.:: Bots United ::.  
filebase forums discord server github wiki web
cubebot epodbot fritzbot gravebot grogbot hpbbot ivpbot jkbotti joebot
meanmod podbotmm racc rcbot realbot sandbot shrikebot soulfathermaps yapb

Go Back   .:: Bots United ::. > Developer's Farm > General Bot Coding
General Bot Coding See what a pain it is to get those little mechs shooting around

Reply
 
Thread Tools
code to get the illumination at any point on the map
Old
  (#1)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Idea code to get the illumination at any point on the map - 03-02-2012

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!!!!!!!!!!!!!!!!!
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#2)
The Storm
Council Member / E[POD]bot developer
 
The Storm's Avatar
 
Status: Offline
Posts: 1,620
Join Date: Jul 2004
Location: Bulgaria
Default Re: code to get the illumination at any point on the map - 04-02-2012

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.
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#3)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Default Re: code to get the illumination at any point on the map - 04-02-2012

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.....
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#4)
The Storm
Council Member / E[POD]bot developer
 
The Storm's Avatar
 
Status: Offline
Posts: 1,620
Join Date: Jul 2004
Location: Bulgaria
Default Re: code to get the illumination at any point on the map - 05-02-2012

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.
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#5)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Default Re: code to get the illumination at any point on the map - 06-02-2012

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
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#6)
SamPlay
Member
 
Status: Offline
Posts: 46
Join Date: Jan 2006
Default Re: code to get the illumination at any point on the map - 12-02-2012

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.
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#7)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Default Re: code to get the illumination at any point on the map - 13-02-2012

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!
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#8)
KWo
Developer of PODBot mm
 
KWo's Avatar
 
Status: Offline
Posts: 3,425
Join Date: Apr 2004
Default Re: code to get the illumination at any point on the map - 25-02-2012

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?
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#9)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Default Re: code to get the illumination at any point on the map - 27-02-2012

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....
  
Reply With Quote
Re: code to get the illumination at any point on the map
Old
  (#10)
KWo
Developer of PODBot mm
 
KWo's Avatar
 
Status: Offline
Posts: 3,425
Join Date: Apr 2004
Default Re: code to get the illumination at any point on the map - 12-03-2012

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?
  
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
vBulletin Skin developed by: vBStyles.com