.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Bot Coding (http://forums.bots-united.com/forumdisplay.php?f=24)
-   -   code to get the illumination at any point on the map (http://forums.bots-united.com/showthread.php?t=9005)

Immortal_BLG 03-02-2012 05:05

code to get the illumination at any point on the map
 
Here a code which will help to receive value of illumination of any point on the map.
Also you will open for yourselves some changes in such structures as 'texture_t', 'mleaf_t', 'msurface_t' and 'mnode_t' which Valve hasn't found time to update in HLSDK....

NOTE: The code is working, but in that kind in which it is placed here wasn't checked.
NOTE2: Engine functions (GiveFnptrsToDll, StartFrame, LightStyle and PM_Move) in a code are placed simply for descriptive reasons.

Code:

#undef texture_t
#undef mleaf_t
#undef msurface_t
#undef mnode_t

struct texture_t        // NOT USED BY LIGHTING CODE, BUT STILL AS BONUS
{
/*! Off=0(0)*/        char                name[16];
/*! Off=16(4)*/        unsigned int        width, height;
/*! Off=24(6)*/        unsigned int UNKNOWN[2u];
/*! Off=32(8)*/        int                        anim_total;                                // total tenths in sequence (0 = no)
/*! Off=36(9)*/        int                        anim_min, anim_max;                // time for this frame min <=time< max
/*! Off=44(11)*/        texture_t *anim_next;                // in the animation sequence
/*! Off=48(12)*/        texture_t *alternate_anims;        // bmodels in frame 1 use these
/*! Off=52(13)*/        unsigned int        offsets[MIPLEVELS];                // four mip maps stored
/*! Off=68(17)*/        unsigned int        paloffset;
};        // sizeof (texture_t) == 72 (18)
struct mleaf_t        // NOT USED BY LIGHTING CODE, BUT STILL HERE AS A BONUS
{
// common with node
/*! Off=0(0)*/        int                        contents;                // wil be a negative contents number
/*! Off=4(1)*/        int                        visframe;                // node needs to be traversed if current

/*! Off=8(2)*/        Vector                mins, maxs;                // for bounding box culling

/*! Off=32(8)*/        mnode_t        *parent;

// leaf specific
/*! Off=36(9)*/        unsigned char                *compressed_vis;
/*! Off=40(10)*/        efrag_t        *efrags;

/*! Off=44(11)*/        msurface_t        **firstmarksurface;
/*! Off=48(12)*/        int                        nummarksurfaces;
/*! Off=52(13)*/        int                        key;                        // BSP sequence number for leaf's contents
/*! Off=56(14)*/        unsigned char                ambient_sound_level[NUM_AMBIENTS];
};        // sizeof (mleaf_t) == 60 (15)
struct msurface_t
{
/*off=0(0)*/        int                        visframe;                // should be drawn when node is crossed
/*off=4(1)*/        mplane_t        *plane;                        // pointer to shared plane
/*off=8(2)*/        int                        flags;                        // see SURF_* #defines

/*off=12(3)*/        int                        firstedge;        // look up in model->surfedges[], negative numbers are backwards edges
/*off=16(4)*/        int                        numedges;

/*off=20(5)*/        short                texturemins[2]; // smallest s/t position on the surface.
/*off=24(6)*/        short                extents[2];                // ?? s/t texture size, 1..256 for all non-sky surfaces

/*off=28(7)*/        int                        light_s, light_t;        // gl lightmap coordinates
/*off=36(9)*/        struct glpoly_t        *polys;                                // multiple if warped
/*off=40(10)*/        msurface_t        *texturechain;
/*off=44(11)*/        mtexinfo_t        *texinfo;

// lighting info
/*off=48(12)*/        int                        dlightframe;        // last frame the surface was checked by an animated light
/*off=52(13)*/        int                        dlightbits;                // dynamically generated. Indicates if the surface illumination
                                                                // is modified by an animated light.
/*off=56(14)*/        int                        lightmaptexturenum;
/*off=60(15)*/        unsigned char                styles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights
                                                                          // no one surface can be effected by more than 4
                                                                          // animated lights.

/*off=64(16)*/        int                        cached_light[MAXLIGHTMAPS];        // values currently used in lightmap
/*off=80(20)*/        BOOL        cached_dlight;                                // true if dynamic light in cache

/*off=84(21)*/        color24                *samples;        // [numstyles*surfsize]

/*off=88(22)*/        decal_t                *pdecals;
};        // sizeof (msurface_t) == 92 (23)
struct mnode_t
{
        enum ChildrenType_t
        {
                ChildrenType_Front,
                ChildrenType_Back,

                ChildrenType_Total
        };

// common with leaf
/*! Off=0(0)*/        int                        contents;                // 0, to differentiate from leafs
/*! Off=4(1)*/        int                        visframe;                // node needs to be traversed if current

/*! Off=8(2)*/        Vector                mins, maxs;                // for bounding box culling

/*! Off=32(8)*/        mnode_t        *parent;

// node specific
/*! Off=36(9)*/        mplane_t        *plane;
/*! Off=40(10)*/        mnode_t        *children[ChildrenType_Total];

/*! Off=48(12)*/        unsigned short                firstsurface;
/*! Off=52(13)*/        unsigned short                numsurfaces;
};        // sizeof (mnode_t) == 52 (13)

#define        MAX_LIGHTSTYLES        64
#define        MAX_LIGHTSTYLEVALUE        256

struct lightstyle_t
{
        int  length;
        char map[MAX_LIGHTSTYLES];
};

lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
int          d_lightstylevalue[MAX_LIGHTSTYLEVALUE];        // 8.8 fraction of base light value
model_t    *sv_worldmodel (NULL);        // Analog of sv.worldmodel.

static inline void SetupLightStyles (void)
{
        // Setup lighting information....

        // reset all light styles
        for (unsigned char index (0u); index < MAX_LIGHTSTYLES; ++index)
        {
                cl_lightstyle.length = 0u;
                cl_lightstyle.map[0u] = '\0';
        }

        for (unsigned short index (0u); index < MAX_LIGHTSTYLEVALUE; ++index)
                d_lightstylevalue[index] = 264;        // normal light value
}

static inline void R_AnimateLight (void)
{
        // light animations
        // 'm' is normal light, 'a' is no light, 'z' is double bright
        const int i (static_cast <int> (gpGlobals->time * 10.0f));
        int k;

        for (unsigned char j (0u); j < MAX_LIGHTSTYLES; ++j)
        {
                if (cl_lightstyle[j].length == 0u)
                {
                        d_lightstylevalue[j] = 256;

                        continue;
                }

                k = cl_lightstyle[j].map[i % cl_lightstyle[j].length] - 'a';
                k *= 22;

                d_lightstylevalue[j] = k;
        }       
}

static inline void CallbackLightStyle (const unsigned char style, char *const value)
{
        if (style >= MAX_LIGHTSTYLES)
        {
                g_engfuncs.ServerPrintf ("SVC_LIGHTSTYLE > MAX_LIGHTSTYLES\n");

                return;
        }

        // OCCURS!
        if (value == NULL)
        {
                cl_lightstyle[style].length = 0u;
                cl_lightstyle[style].map[0u] = '\0';

                return;
        }

        const unsigned short maximumCopyAmount (sizeof (cl_lightstyle[style].map) - sizeof ('\0'));

        strncpy (cl_lightstyle[style].map, value, maximumCopyAmount);

        cl_lightstyle[style].map[maximumCopyAmount] = '\0';

        cl_lightstyle[style].length = strlen (cl_lightstyle[style].map);
}
static inline void CallbackStartFrame (void)
{
        R_AnimateLight ();

        inline void ShowMagic (void);

        ShowMagic ();
}
static inline void CallbackPM_Move (playermove_t *const playerMove, const bool server)
{
        // Reliability checks.
        assert (playerMove != NULL);
        assert (server == true);        // ALWAYS SHOULD BE TRUE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        // Honestly this is need only once per changelevel, but....
        sv_worldmodel = playerMove->physents[0u].model;        // Always point at sv.worldmodel!

        // Reliability check.
        assert (sv_worldmodel != NULL);
}

static WINAPI GiveFnptrsToDll (enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals)
{
        // get the engine functions from the engine...
        memcpy (&g_engfuncs, pengfuncsFromEngine, sizeof (g_engfuncs));
        gpGlobals = pGlobals;
 
        SetupLightStyles ();
}
static void pfnLightStyle (int style, char *value)
{
        LIGHT_STYLE (style, value);
        or ->>---------->>------------->>---------------------->>-------------------|
                                                                                                                                                                |
        // Update light style for fake clients....                                                                        |
        CallbackLightStyle (static_cast <const unsigned char> (style), value);                |
                                                                                                                                                                |
        RETURN_META (MRES_IGNORED);        <------------------<<------------<<-------------|
}
static void pfnStartFrame (void)
{
        // this function starts a video frame. It is called once per video frame by the engine. If
        // you run Half-Life at 90 fps, this function will then be called 90 times per second. By
        // placing a hook on it, we have a good place to do things that should be done continuously
        // during the game, for example making the bots think (yes, because no Think() function exists
        // for the bots by the MOD side, remember). Also here we have control on the bot population,
        // for example if a new player joins the server, we should disconnect a bot, and if the
        // player population decreases, we should fill the server with other bots.

        CallbackStartFrame ();

        (*g_engfuncs.pfnStartFrame) ();
        or
        RETURN_META (MRES_IGNORED);
}
static void PM_Move (playermove_t *playerMove, BOOL server)
{
        // this is the player movement code clients run to predict things when the server can't update
        // them often enough (or doesn't want to). The server runs exactly the same function for
        // moving players. There is normally no distinction between them, else client-side prediction
        // wouldn't work properly (and it doesn't work that well, already...)

        CallbackPM_Move (playerMove, server == TRUE);

        (*g_engfuncs.pfnPM_Move) (playerMove, server);
        or
        RETURN_META (MRES_IGNORED);
}

struct Color
{
        int red;
        int green;
        int blue;

        inline      void        Reset  (void)      { red = green = blue = 0; }
        inline const unsigned int GetAvg (void) const { return (red + green + blue) / (sizeof (Color) / sizeof (int)); }
};

/*
=============================================================================

LIGHT SAMPLING

=============================================================================
*/
namespace Light
{
//static const mplane_t *lightplane (NULL);
//static Vector lightspot;
static Color g_pointColor;

static const bool RecursiveLightPoint (const mnode_t *const node, const Vector &start, const Vector &end)
{
        float front, back, frac;
        int side;
        mplane_t *plane;
        Vector mid;
        msurface_t *surf;
        int s, t, ds, dt;
        int i;
        mtexinfo_t *tex;
        color24 *lightmap;
        unsigned int scale;
        unsigned char maps;

        // Reliability check.
        assert (node != NULL);

        if (node->contents < 0)
                return false;        // didn't hit anything

        // Determine which side of the node plane our points are on
        // FIXME: optimize for axial
        plane = node->plane;
        front = (start | plane->normal) - plane->dist;
        back = (end | plane->normal) - plane->dist;
        side = front < 0.0f;

        // If they're both on the same side of the plane, don't bother to split just check the appropriate child
        if ((back < 0.0f) == side)
                return RecursiveLightPoint (node->children[side], start, end);

        // calculate mid point
        frac = front / (front - back);
        mid = start + (end - start) * frac;

        // go down front side       
        if (RecursiveLightPoint (node->children[side], start, mid))
                return true;        // hit something

        // Blow it off if it doesn't split the plane...
        if ((back < 0.0f) == side)
                return false;        // didn't hit anything

        // check for impact on this node
//        lightspot = mid;
//        lightplane = plane;

        surf = sv_worldmodel->surfaces + node->firstsurface;
        for (i = 0; i < node->numsurfaces; ++i, ++surf)
        {
                if (surf->flags & SURF_DRAWTILED)
                        continue;        // no lightmaps

                tex = surf->texinfo;

                // See where in lightmap space our intersection point is
                s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
                t = static_cast <int> ((mid | Vector (tex->vecs[1])) + tex->vecs[1][3]);

                // Not in the bounds of our lightmap? punt...
                if (s < surf->texturemins[0] || t < surf->texturemins[1])
                        continue;

                // assuming a square lightmap (FIXME: which ain't always the case),
                // lets see if it lies in that rectangle. If not, punt...
                ds = s - surf->texturemins[0];
                dt = t - surf->texturemins[1];

                if (ds > surf->extents[0] || dt > surf->extents[1])
                        continue;

                if (surf->samples == NULL)
                        return true;

                ds >>= 4;
                dt >>= 4;

                g_pointColor.Reset ();        // Reset point color.

                const int smax ((surf->extents[0] >> 4) + 1);
                const int tmax ((surf->extents[1] >> 4) + 1);
                const int size (smax * tmax);

                lightmap = surf->samples + dt * smax + ds;

                // Compute the lightmap color at a particular point
                for (maps = 0u; maps < MAXLIGHTMAPS && surf->styles[maps] != 255u; ++maps)
                {
                        scale = d_lightstylevalue[surf->styles[maps]];

                        g_pointColor.red += lightmap->r * scale;
                        g_pointColor.green += lightmap->g * scale;
                        g_pointColor.blue += lightmap->b * scale;

                        lightmap += size;        // skip to next lightmap
                }

                g_pointColor.red >>= 8u;
                g_pointColor.green >>= 8u;
                g_pointColor.blue >>= 8u;

                return true;
        }

        // go down back side
        return RecursiveLightPoint (node->children[!side], mid, end);
}

static inline const unsigned char R_LightPoint (const Vector &p)
{
        // Reliability check.
        assert (sv_worldmodel != NULL);

        if (sv_worldmodel->lightdata == NULL)
                return 255u;

        Vector end (p);

        end.z -= 2048.0f;

        return RecursiveLightPoint (sv_worldmodel->nodes, p, end) == false ? 0u : static_cast <unsigned char> (g_pointColor.GetAvg ());
}
}

static inline const char *const FormatBuffer (const char *const format, ...)
{
        static char string[4096u];

        va_list argumentPointer;

        // Concatenate all the arguments in one string....
        va_start (argumentPointer, format);
                vsnprintf (string, sizeof (string), format, argumentPointer);
        va_end (argumentPointer);

        return string;
}

inline void ShowMagic (void)
{
        const edict_t *const hostPlayerEdict (INDEXENT (1u));

        if (hostPlayerEdict == NULL || hostPlayerEdict->free)
                return;

        CLIENT_PRINTF (hostPlayerEdict, print_chat, FormatBuffer ("ShowMagic(): \"%s\"->v.light_level=%i, R_LightPoint(hostOrg)=%i\n", STRING (hostPlayerEdict->v.netname), hostPlayerEdict->v.light_level, Light::R_LightPoint (hostPlayerEdict->v.origin)));
}

Now bots don't need to create fakeIlluminationEntity for illumination reception!!!!!!!!!!!!!!!!!

The Storm 04-02-2012 11:52

Re: code to get the illumination at any point on the map
 
Thank you again for your time in discovering/reversing what Valve should give us by default.

I didn't look at the code very deeply, so sorry if my question is obvious.
Is it PM_Move requred? Because actually this is only valid in Listen server mode.

Immortal_BLG 04-02-2012 12:50

Re: code to get the illumination at any point on the map
 
Quote:

Originally Posted by The Storm
Is it PM_Move requred? Because actually this is only valid in Listen server mode.

You're 100 percent right, but I started from the fact that the server will be present, or the person editing the waypoints (for example exposing the illumination for waypoints), or bots, for which in fact I posted the code because I wanted to have it replaced illuminationEntity for bots.

IMPORTANT NOTE that I forgot to write in the first post: The code will work if at least one client will be present on the server!!!

P.S. Why I have made reception 'sv.worldmodel' of structure 'playermove_t'? Because this is probably the only way without the use of wild hooks.....

The Storm 05-02-2012 12:39

Re: code to get the illumination at any point on the map
 
Ok, but I think there is anoder fall. It is bad ides to save illumination in waypoits, because of the many mods that exists( like AMXX ) that depending on some condition can change the light level in some area. Then if the waypoits are holding such data it will become invalid.

Immortal_BLG 06-02-2012 02:21

Re: code to get the illumination at any point on the map
 
It was a simple example.

And now about the actual fall :)
Now I have understood, why the Valve haven't changed structure which I posted.
The reason is that the structures which are currently in HLSDK intended for a dedicated server (swds.dll), and those structures that I have posted are used in the listen server (hw.dll) to work with openGL.

Well now that in this situation will have to take into account the type of server (listen/dedicated) and on the basis of it to choose structure.... :(

So modified code is here (The prefix "GL_" for names of structures is added, has replaced 'GL_texture_t::UNKNOWN[2u]' to original members, fixed offset for 'GL_mnode_t::numsurfaces', function RecursiveLightPoint() now a template, added function ActualRecursiveLightPoint(), the call in function 'R_LightPoint' of function 'RecursiveLightPoint' has been changed to a call 'ActualRecursiveLightPoint')

Code:

struct GL_texture_t        // NOT USED BY LIGHTING CODE, BUT STILL AS BONUS
{
/*! Off=0(0)*/        char                name[16];
/*! Off=16(4)*/        unsigned int        width, height;
/*! Off=24(6)*/        int                        gl_texturenum;
/*! Off=28(7)*/        msurface_t        *texturechain;        // for gl_texsort drawing
/*! Off=32(8)*/        int                        anim_total;                                // total tenths in sequence (0 = no)
/*! Off=36(9)*/        int                        anim_min, anim_max;                // time for this frame min <=time< max
/*! Off=44(11)*/        texture_t *anim_next;                // in the animation sequence
/*! Off=48(12)*/        texture_t *alternate_anims;        // bmodels in frame 1 use these
/*! Off=52(13)*/        unsigned int        offsets[MIPLEVELS];                // four mip maps stored
/*! Off=68(17)*/        unsigned int        paloffset;
};        // sizeof (GL_texture_t) == 72 (18)
struct GL_mleaf_t        // NOT USED BY LIGHTING CODE, BUT STILL HERE AS A BONUS
{
// common with node
/*! Off=0(0)*/        int                        contents;                // wil be a negative contents number
/*! Off=4(1)*/        int                        visframe;                // node needs to be traversed if current

/*! Off=8(2)*/        Vector                mins, maxs;                // for bounding box culling

/*! Off=32(8)*/        mnode_t        *parent;

// leaf specific
/*! Off=36(9)*/        unsigned char                *compressed_vis;
/*! Off=40(10)*/        efrag_t        *efrags;

/*! Off=44(11)*/        msurface_t        **firstmarksurface;
/*! Off=48(12)*/        int                        nummarksurfaces;
/*! Off=52(13)*/        int                        key;                        // BSP sequence number for leaf's contents
/*! Off=56(14)*/        unsigned char                ambient_sound_level[NUM_AMBIENTS];
};        // sizeof (GL_mleaf_t) == 60 (15)
struct GL_msurface_t
{
/*off=0(0)*/        int                        visframe;                // should be drawn when node is crossed
/*off=4(1)*/        mplane_t        *plane;                        // pointer to shared plane
/*off=8(2)*/        int                        flags;                        // see SURF_* #defines

/*off=12(3)*/        int                        firstedge;        // look up in model->surfedges[], negative numbers are backwards edges
/*off=16(4)*/        int                        numedges;

/*off=20(5)*/        short                texturemins[2]; // smallest s/t position on the surface.
/*off=24(6)*/        short                extents[2];                // ?? s/t texture size, 1..256 for all non-sky surfaces

/*off=28(7)*/        int                        light_s, light_t;        // gl lightmap coordinates
/*off=36(9)*/        struct glpoly_t        *polys;                                // multiple if warped
/*off=40(10)*/        msurface_t        *texturechain;
/*off=44(11)*/        mtexinfo_t        *texinfo;

// lighting info
/*off=48(12)*/        int                        dlightframe;        // last frame the surface was checked by an animated light
/*off=52(13)*/        int                        dlightbits;                // dynamically generated. Indicates if the surface illumination
                                                                // is modified by an animated light.
/*off=56(14)*/        int                        lightmaptexturenum;
/*off=60(15)*/        unsigned char                styles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights
                                                                          // no one surface can be effected by more than 4
                                                                          // animated lights.

/*off=64(16)*/        int                        cached_light[MAXLIGHTMAPS];        // values currently used in lightmap
/*off=80(20)*/        BOOL        cached_dlight;                                // true if dynamic light in cache

/*off=84(21)*/        color24                *samples;        // [numstyles*surfsize]

/*off=88(22)*/        decal_t                *pdecals;
};        // sizeof (GL_msurface_t) == 92 (23)
struct GL_mnode_t
{
        enum ChildrenType_t
        {
                ChildrenType_Front,
                ChildrenType_Back,

                ChildrenType_Total
        };

// common with leaf
/*! Off=0(0)*/        int                        contents;                // 0, to differentiate from leafs
/*! Off=4(1)*/        int                        visframe;                // node needs to be traversed if current

/*! Off=8(2)*/        Vector                mins, maxs;                // for bounding box culling

/*! Off=32(8)*/        mnode_t        *parent;

// node specific
/*! Off=36(9)*/        mplane_t        *plane;
/*! Off=40(10)*/        mnode_t        *children[ChildrenType_Total];

/*! Off=48(12)*/        unsigned short                firstsurface;
/*! Off=50(12.5)*/        unsigned short                numsurfaces;
};        // sizeof (GL_mnode_t) == 52 (13)

#define        MAX_LIGHTSTYLES        64
#define        MAX_LIGHTSTYLEVALUE        256

struct lightstyle_t
{
        int  length;
        char map[MAX_LIGHTSTYLES];
};

lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
int          d_lightstylevalue[MAX_LIGHTSTYLEVALUE];        // 8.8 fraction of base light value
model_t    *sv_worldmodel (NULL);        // Analog of sv.worldmodel.

static inline void SetupLightStyles (void)
{
        // Setup lighting information....

        // reset all light styles
        for (unsigned char index (0u); index < MAX_LIGHTSTYLES; ++index)
        {
                cl_lightstyle.length = 0u;
                cl_lightstyle.map[0u] = '\0';
        }

        for (unsigned short index (0u); index < MAX_LIGHTSTYLEVALUE; ++index)
                d_lightstylevalue[index] = 264;        // normal light value
}

static inline void R_AnimateLight (void)
{
        // light animations
        // 'm' is normal light, 'a' is no light, 'z' is double bright
        const int i (static_cast <int> (gpGlobals->time * 10.0f));
        int k;

        for (unsigned char j (0u); j < MAX_LIGHTSTYLES; ++j)
        {
                if (cl_lightstyle[j].length == 0u)
                {
                        d_lightstylevalue[j] = 256;

                        continue;
                }

                k = cl_lightstyle[j].map[i % cl_lightstyle[j].length] - 'a';
                k *= 22;

                d_lightstylevalue[j] = k;
        }       
}

static inline void CallbackLightStyle (const unsigned char style, char *const value)
{
        if (style >= MAX_LIGHTSTYLES)
        {
                g_engfuncs.ServerPrintf ("SVC_LIGHTSTYLE > MAX_LIGHTSTYLES\n");

                return;
        }

        // OCCURS!
        if (value == NULL)
        {
                cl_lightstyle[style].length = 0u;
                cl_lightstyle[style].map[0u] = '\0';

                return;
        }

        const unsigned short maximumCopyAmount (sizeof (cl_lightstyle[style].map) - sizeof ('\0'));

        strncpy (cl_lightstyle[style].map, value, maximumCopyAmount);

        cl_lightstyle[style].map[maximumCopyAmount] = '\0';

        cl_lightstyle[style].length = strlen (cl_lightstyle[style].map);
}
static inline void CallbackStartFrame (void)
{
        R_AnimateLight ();

        inline void ShowMagic (void);

        ShowMagic ();
}
static inline void CallbackPM_Move (playermove_t *const playerMove, const bool server)
{
        // Reliability checks.
        assert (playerMove != NULL);
        assert (server == true);        // ALWAYS SHOULD BE TRUE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        // Honestly this is need only once per changelevel, but....
        sv_worldmodel = playerMove->physents[0u].model;        // Always point at sv.worldmodel!

        // Reliability check.
        assert (sv_worldmodel != NULL);
}

static WINAPI GiveFnptrsToDll (enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals)
{
        // get the engine functions from the engine...
        memcpy (&g_engfuncs, pengfuncsFromEngine, sizeof (g_engfuncs));
        gpGlobals = pGlobals;
 
        SetupLightStyles ();
}
static void pfnLightStyle (int style, char *value)
{
        LIGHT_STYLE (style, value);
        or ->>---------->>------------->>---------------------->>-------------------|
                                                                                                                                                                |
        // Update light style for fake clients....                                                                        |
        CallbackLightStyle (static_cast <const unsigned char> (style), value);                |
                                                                                                                                                                |
        RETURN_META (MRES_IGNORED);        <------------------<<------------<<-------------|
}
static void pfnStartFrame (void)
{
        // this function starts a video frame. It is called once per video frame by the engine. If
        // you run Half-Life at 90 fps, this function will then be called 90 times per second. By
        // placing a hook on it, we have a good place to do things that should be done continuously
        // during the game, for example making the bots think (yes, because no Think() function exists
        // for the bots by the MOD side, remember). Also here we have control on the bot population,
        // for example if a new player joins the server, we should disconnect a bot, and if the
        // player population decreases, we should fill the server with other bots.

        CallbackStartFrame ();

        (*g_engfuncs.pfnStartFrame) ();
        or
        RETURN_META (MRES_IGNORED);
}
static void PM_Move (playermove_t *playerMove, BOOL server)
{
        // this is the player movement code clients run to predict things when the server can't update
        // them often enough (or doesn't want to). The server runs exactly the same function for
        // moving players. There is normally no distinction between them, else client-side prediction
        // wouldn't work properly (and it doesn't work that well, already...)

        CallbackPM_Move (playerMove, server == TRUE);

        (*g_engfuncs.pfnPM_Move) (playerMove, server);
        or
        RETURN_META (MRES_IGNORED);
}

struct Color
{
        int red;
        int green;
        int blue;

        inline      void        Reset  (void)      { red = green = blue = 0; }
        inline const unsigned int GetAvg (void) const { return (red + green + blue) / (sizeof (Color) / sizeof (int)); }
};

/*
=============================================================================

LIGHT SAMPLING

=============================================================================
*/
namespace Light
{
//static const mplane_t *lightplane (NULL);
//static Vector lightspot;
static Color g_pointColor;

template <typename nodeType, typename surfaceType> static const bool RecursiveLightPoint (const nodeType *const node, const Vector &start, const Vector &end)
{
        float front, back, frac;
        int side;
        mplane_t *plane;
        Vector mid;
        surfaceType *surf;
        int s, t, ds, dt;
        int i;
        mtexinfo_t *tex;
        color24 *lightmap;
        unsigned int scale;
        unsigned char maps;

        // Reliability check.
        assert (node != NULL);

        if (node->contents < 0)
                return false;        // didn't hit anything

        // Determine which side of the node plane our points are on
        // FIXME: optimize for axial
        plane = node->plane;
        front = (start | plane->normal) - plane->dist;
        back = (end | plane->normal) - plane->dist;
        side = front < 0.0f;

        // If they're both on the same side of the plane, don't bother to split just check the appropriate child
        if ((back < 0.0f) == side)
                return RecursiveLightPoint <nodeType, surfaceType> (reinterpret_cast <nodeType *> (node->children[side]), start, end);

        // calculate mid point
        frac = front / (front - back);
        mid = start + (end - start) * frac;

        // go down front side       
        if (RecursiveLightPoint <nodeType, surfaceType> (reinterpret_cast <nodeType *> (node->children[side]), start, mid))
                return true;        // hit something

        // Blow it off if it doesn't split the plane...
        if ((back < 0.0f) == side)
                return false;        // didn't hit anything

        // check for impact on this node
//        lightspot = mid;
//        lightplane = plane;

        surf = reinterpret_cast <surfaceType *> (sv_worldmodel->surfaces) + node->firstsurface;
        for (i = 0; i < node->numsurfaces; ++i, ++surf)
        {
                if (surf->flags & SURF_DRAWTILED)
                        continue;        // no lightmaps

                tex = surf->texinfo;

                // See where in lightmap space our intersection point is
                s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
                t = static_cast <int> ((mid | Vector (tex->vecs[1])) + tex->vecs[1][3]);

                // Not in the bounds of our lightmap? punt...
                if (s < surf->texturemins[0] || t < surf->texturemins[1])
                        continue;

                // assuming a square lightmap (FIXME: which ain't always the case),
                // lets see if it lies in that rectangle. If not, punt...
                ds = s - surf->texturemins[0];
                dt = t - surf->texturemins[1];

                if (ds > surf->extents[0] || dt > surf->extents[1])
                        continue;

                if (surf->samples == NULL)
                        return true;

                ds >>= 4;
                dt >>= 4;

                g_pointColor.Reset ();        // Reset point color.

                const int smax ((surf->extents[0] >> 4) + 1);
                const int tmax ((surf->extents[1] >> 4) + 1);
                const int size (smax * tmax);

                lightmap = surf->samples + dt * smax + ds;

                // Compute the lightmap color at a particular point
                for (maps = 0u; maps < MAXLIGHTMAPS && surf->styles[maps] != 255u; ++maps)
                {
                        scale = d_lightstylevalue[surf->styles[maps]];

                        g_pointColor.red += lightmap->r * scale;
                        g_pointColor.green += lightmap->g * scale;
                        g_pointColor.blue += lightmap->b * scale;

                        lightmap += size;        // skip to next lightmap
                }

                g_pointColor.red >>= 8u;
                g_pointColor.green >>= 8u;
                g_pointColor.blue >>= 8u;

                return true;
        }

        // go down back side
        return RecursiveLightPoint <nodeType, surfaceType> (reinterpret_cast <nodeType *> (node->children[!side]), mid, end);
}
const bool ActualRecursiveLightPoint (const Math::Vector3D &start, const Math::Vector3D &end)
{
        return IS_DEDICATED_SERVER () ?
                RecursiveLightPoint <mnode_t, msurface_t> (sv_worldmodel->nodes, start, end) :
                RecursiveLightPoint <GL_mnode_t, GL_msurface_t> (reinterpret_cast <GL_mnode_t *> (sv_worldmodel->nodes), start, end);
}

static inline const unsigned char R_LightPoint (const Vector &p)
{
        // Reliability check.
        assert (sv_worldmodel != NULL);

        if (sv_worldmodel->lightdata == NULL)
                return 255u;

        Vector end (p);

        end.z -= 2048.0f;

        return ActualRecursiveLightPoint (p, end) == false ? 0u : static_cast <unsigned char> (g_pointColor.GetAvg ());
}
}

static inline const char *const FormatBuffer (const char *const format, ...)
{
        static char string[4096u];

        va_list argumentPointer;

        // Concatenate all the arguments in one string....
        va_start (argumentPointer, format);
                vsnprintf (string, sizeof (string), format, argumentPointer);
        va_end (argumentPointer);

        return string;
}

inline void ShowMagic (void)
{
        const edict_t *const hostPlayerEdict (INDEXENT (1u));

        if (hostPlayerEdict == NULL || hostPlayerEdict->free)
                return;

        CLIENT_PRINTF (hostPlayerEdict, print_chat, FormatBuffer ("ShowMagic(): \"%s\"->v.light_level=%i, R_LightPoint(hostOrg)=%i\n", STRING (hostPlayerEdict->v.netname), hostPlayerEdict->v.light_level, Light::R_LightPoint (hostPlayerEdict->v.origin)));
}

P.S. Excuse if that and also sorry for bad english

SamPlay 12-02-2012 12:19

Re: code to get the illumination at any point on the map
 
Hi,
I think that looking at the modified common/com_model.h file in the hlsdk23_msvc2008.zip downloadable from
http://www.moddb.com/games/half-life/downloads/half-life-sdk-v23-for-visual-studio-2008
will provide you with useful information on data structure you addressed.
regards.

Immortal_BLG 13-02-2012 03:54

Re: code to get the illumination at any point on the map
 
It seems that Mr. "Gary_McTaggart" has already made it long before me. :) I on the computer had this archive, however I have missed these changes. Thanks!

KWo 25-02-2012 19:43

Re: code to get the illumination at any point on the map
 
After very fast look at Your code (of course without understanding it) I haven't seen the call for this function:
#define GETENTITYILLUM (*g_engfuncs.pfnGetEntityIllum)
I don't know it this is no longer needed or what. But I had troubles with that function - it works perfectly on a windows server, but it always gives 0 as a return value on a linux server. So - did You check if Your code is working on both - linux and windows server?

Immortal_BLG 27-02-2012 01:28

Re: code to get the illumination at any point on the map
 
Hello KWo!

Quote:

Originally Posted by KWo
I had troubles with that function - it works perfectly on a windows server, but it always gives 0 as a return value on a linux server.

Fairly I admit - I don't know why on LINUX function GetEntityIllum always returns 0 and also how to solve this problem, all that I can is to show code of function GetEntityIllum to you:
Code:

//----- (01D82AE0) --------------------------------------------------------
int GetEntityIllum (edict_t *const edict)
{
        if (edict == NULL)
                return -1;

        const unsigned int edictIndex (NUM_FOR_EDICT (edict));

        if (edictIndex <= svs.maxclients)
                return edict->v.light_level;        // player has more precision light level that come from client-side

        if (cls.state == 3/*! MAYBE 'ca_connected', BUT NOT SHURE!!! */ || cls.state == 4/*! MAYBE 'ca_active', BUT NOT SHURE!!! */ || cls.state == 5/*! @warning DON'T KNOW!!! */)
        {
                const colorVec &cvFloorColor (cl_entities[edictIndex].cvFloorColor);

                return (cvFloorColor.r + cvFloorColor.g + cvFloorColor.b) / 3u;
        }

        return 128;
}

And 'edict->v.light_level' is assigned approximately so:
edict->v.light_level = R_LightPoint (edict->v.origin);

Quote:

Originally Posted by KWo
did You check if Your code is working on both - linux and windows server?

The answer is no, because I do not have LINUX. However, I think that everything should work. The only thing I want to recommend - is to change line
Code:

assert (sv_worldmodel != NULL);
to
Code:

if (sv_worldmodel == NULL)
        return 0u;

in the beginning of function R_LightPoint() just in case.

And one more: it is necessary to replace in function "ActualRecursiveLightPoint()" call "IsSoftwareDrawingMode()" instead of a call of function "IS_DEDICATED_SERVER()" and to define this function so:
Code:

inline const bool IsSoftwareDrawingMode (void)
{
        static const bool isSoftwareDrawingMode (IS_DEDICATED_SERVER () || GetModuleHandle ("sw.dll") != NULL);

        return isSoftwareDrawingMode;
}

It is made that the client could play without crashing on software mode. Sorry forgot about it....

KWo 12-03-2012 20:20

Re: code to get the illumination at any point on the map
 
OK - I'm getting confused after reading that. What should I do in HLSDK files, and what in bot code files? I mean which changes should be applied to HLSDK files and which should be applied to bot cpp/h files?


All times are GMT +2. The time now is 21:52.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.