.:: 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
Finding place of grenade explosion
Old
  (#1)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Arrow Finding place of grenade explosion - 30-06-2010

Hello!

Here the code.
Code:
const float HalfMapSize (4096.0f);

struct PseudoGrenadeEntityVariables_t
{
	Vector origin;
	int    waterlevel;
	int    flags;	// flags
};

/*
==================
ClipVelocity

Slide off of the impacting object
==================
*/
inline void ClipVelocity (const Vector &in, const Vector &normal, Vector &out, const float overbounce)
{
	#define	STOP_EPSILON	0.1

	float change;
	const float backoff ((in | normal) * overbounce);	// Determine how far along plane to slide based on incoming direction. Scale by overbounce factor.

	for (unsigned char axisIndex (0u); axisIndex < 3u; ++axisIndex)
	{
		change = normal[axisIndex] * backoff;
		out[axisIndex] = in[axisIndex] - change;

		// If out velocity is too small, zero it out.
		if (out[axisIndex] > -STOP_EPSILON && out[axisIndex] < STOP_EPSILON)
			out[axisIndex] = 0.0f;
	}
}

inline const bool VectorCompare (const Vector &v1, const Vector &v2)
{
	for (unsigned char axisIndex (0u); axisIndex < 3u; ++axisIndex)
		if (v1[axisIndex] != v2[axisIndex])
			return false;

	return true;
}

inline const bool IsPointInsideBoundingBox (const Vector &point, const Vector &absmin, const Vector &absoluteMaxs)
{
	return point.x >= absmin.x && point.x <= absoluteMaxs.x && point.y >= absmin.y && point.y <= absoluteMaxs.y && point.z >= absmin.z && point.z <= absoluteMaxs.z;
}

inline const bool IsSmokeGrenade (edict_t *const edict) const
{
	/// @todo NEED TO FIND MORE FASTEST METHOD, IF EXISTS!!!
	return FStrEq (STRING(VARS(pent)->classname) + 9u, "smokegrenade.mdl");
}

void TraceThrownGrenadeToss (const edict_t *const grenade, PseudoGrenadeEntityVariables_t &pseudoGrenadeEntityVariables)
{
	struct PseudoGrenadeEntityVariablesExtended_t : PseudoGrenadeEntityVariables_t
	{
		Vector         velocity;		// current movement direction
		Vector         basevelocity;	// if standing on conveyor, e.g.
		int            watertype;
		edict_t       *groundentity;	// if standing on a entity, the pointer to that entity
		float          friction;		// inverse elasticity of 'MOVETYPE_BOUNCE'
		float          nextthink;		// Time next call BaseEntity::Think() function.

		unsigned char  numberFloorHits;
	} pseudoGrenadeEntityVariablesExtended;

	pseudoGrenadeEntityVariablesExtended.origin = grenade->v.origin;
	pseudoGrenadeEntityVariablesExtended.waterlevel = grenade->v.waterlevel;
	pseudoGrenadeEntityVariablesExtended.flags = grenade->v.flags;
	pseudoGrenadeEntityVariablesExtended.velocity = grenade->v.velocity;
	pseudoGrenadeEntityVariablesExtended.basevelocity = grenade->v.basevelocity;
	pseudoGrenadeEntityVariablesExtended.watertype = grenade->v.watertype;
	pseudoGrenadeEntityVariablesExtended.groundentity = grenade->v.groundentity;
	pseudoGrenadeEntityVariablesExtended.friction = grenade->v.friction;
	pseudoGrenadeEntityVariablesExtended.nextthink = grenade->v.nextthink;
	pseudoGrenadeEntityVariablesExtended.numberFloorHits = 0u;

	const unsigned char maximumFloorHits (10u);

	pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

	if (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin) == CONTENTS_SOLID)
		return;	// grenade is trapped in another solid

	TraceResult traceResult;
	const float pseudoFrameTimeInterval (/*0.05f*/gpGlobals->frameTime);	// Use your own bigger value if you want to reduce CPU work....
	float pseudoTime (gpGlobals->time);
	Vector to;
	const float gravityAdjust (grenade->v.gravity * sv_gravity->value * pseudoFrameTimeInterval);
	vector <edict_t *> touchedBreakables;
	vector <edict_t *> touchedPushables;

	// Run pseudo frames....
	do
	{
		pseudoGrenadeEntityVariablesExtended.basevelocity = pseudoGrenadeEntityVariablesExtended.groundentity != NULL && (pseudoGrenadeEntityVariablesExtended.groundentity->v.flags & FL_CONVEYOR) ? pseudoGrenadeEntityVariablesExtended.groundentity->v.speed * pseudoGrenadeEntityVariablesExtended.groundentity->v.movedir : vec3_origin;

		for (edict_t *pushable (FIND_ENTITY_BY_CLASSNAME (NULL, "trigger_push")); !FNullEnt (pushable); pushable = FIND_ENTITY_BY_CLASSNAME (pushable, "trigger_push"))
		{
			if (pushable->v.solid == SOLID_NOT || !IsPointInsideBoundingBox (pseudoGrenadeEntityVariablesExtended.origin, pushable->v.absmin, pushable->v.absmax))
				continue;

			// Instant trigger, just transfer velocity and remove
			if (pushable->v.spawnflags & SF_TRIG_PUSH_ONCE)
			{
				pseudoGrenadeEntityVariablesExtended.velocity += pushable->v.speed * pushable->v.movedir;

				if (pseudoGrenadeEntityVariablesExtended.velocity.z > 0.0f)
					pseudoGrenadeEntityVariablesExtended.flags &= ~FL_ONGROUND;

				pushable->v.solid = SOLID_NOT;

				touchedPushables.push_back (pushable);
			}
			else
			{	// Push field, transfer to base velocity
				Vector vecPush (pushable->v.speed * pushable->v.movedir);

				if (pseudoGrenadeEntityVariablesExtended.flags & FL_BASEVELOCITY)
					vecPush += pseudoGrenadeEntityVariablesExtended.basevelocity;

				pseudoGrenadeEntityVariablesExtended.basevelocity = vecPush;

				pseudoGrenadeEntityVariablesExtended.flags |= FL_BASEVELOCITY;
			}
		}

		pseudoGrenadeEntityVariablesExtended.waterlevel = 0;
		pseudoGrenadeEntityVariablesExtended.watertype = CONTENTS_EMPTY;
		const int cont (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin));

		if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT)
		{
			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 3;

			if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
			{
				static const Vector current_table[] =
				{
					Vector ( 1.0f,  0.0f,  0.0f),
					Vector ( 0.0f,  1.0f,  0.0f),
					Vector (-1.0f,  0.0f,  0.0f),
					Vector ( 0.0f, -1.0f,  0.0f),
					Vector ( 0.0f,  0.0f,  1.0f),
					Vector ( 0.0f,  0.0f, -1.0f)
				};

				pseudoGrenadeEntityVariablesExtended.basevelocity += pseudoGrenadeEntityVariablesExtended.waterlevel * 50.0f * current_table[CONTENTS_CURRENT_0 - cont];
			}
		}

	// regular thinking
		{
			float thinkTime (pseudoGrenadeEntityVariablesExtended.nextthink);

			if (thinkTime <= pseudoTime + pseudoFrameTimeInterval)
			{
				if
				(
					// check position
					pseudoGrenadeEntityVariablesExtended.origin.x >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.y >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.z >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.x <= -HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.y <= -HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.z <= -HalfMapSize ||
	
					// check speed
					pseudoGrenadeEntityVariablesExtended.velocity.x >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.y >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.z >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.x <= -2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.y <= -2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.z <= -2000.0f
				)
				{
					pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

					pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

					// Restore touched breakables solid types
					for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
						touchedBreakables[index]->v.solid = SOLID_BSP;

					for (unsigned char index (0u); index < touchedPushables.size (); ++index)
						touchedPushables[index]->v.solid = SOLID_TRIGGER;

					return;
				}

				if (thinkTime < pseudoTime)
					thinkTime = pseudoTime;	// don't let things stay in the past.
											// it is possible to start that way
											// by a trigger with a local time.

				pseudoTime = thinkTime;

				pseudoGrenadeEntityVariablesExtended.nextthink = pseudoTime + 0.1f;

				if (IsSmokeGrenade (grenade) && (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND))
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.949f;//0.949999988079071f - value from decompiled swds.dll sources, I think it's would be 0.949f - IDA sometimes wrong, ex: org 0.8 == decompiled 0.800000011920929 - may be I wrong....

				if (pseudoGrenadeEntityVariablesExtended.waterlevel > 0u)
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.5f;
			}
		}

		if (pseudoGrenadeEntityVariablesExtended.velocity.z > 0.0f || pseudoGrenadeEntityVariablesExtended.groundentity == NULL || (pseudoGrenadeEntityVariablesExtended.groundentity->v.flags & FL_CONVEYOR))
			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_ONGROUND;

// if onground, return without moving
		if ((pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND) && VectorCompare (pseudoGrenadeEntityVariablesExtended.origin, vec3_origin) && VectorCompare (pseudoGrenadeEntityVariablesExtended.basevelocity, vec3_origin))
		{
			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			continue;
		}

		pseudoGrenadeEntityVariablesExtended.velocity.z -= gravityAdjust;
		pseudoGrenadeEntityVariablesExtended.velocity.z += pseudoGrenadeEntityVariablesExtended.basevelocity.z * pseudoFrameTimeInterval;

		pseudoGrenadeEntityVariablesExtended.basevelocity.z = 0.0f;

// move origin
	// Base velocity is not properly accounted for since this entity will move again after the bounce without taking it into account
		to = pseudoGrenadeEntityVariablesExtended.origin + (pseudoGrenadeEntityVariablesExtended.velocity + pseudoGrenadeEntityVariablesExtended.basevelocity) * pseudoFrameTimeInterval;

		UTIL_TraceHull (pseudoGrenadeEntityVariablesExtended.origin, to, dont_ignore_monsters, point_hull, grenade->v.owner, &traceResult);	/// @note Use TraceHull() function instead of TraceLine() as TraceLine() returns worldspawn entity stored in pHit even if flFraction == 1 !!!!

		if (traceResult.flFraction > 0.0f)
			pseudoGrenadeEntityVariablesExtended.origin = traceResult.vecEndPos;

		if (traceResult.pHit != NULL)
		{
			if (FClassnameIs (traceResult.pHit, "func_breakable") && traceResult.pHit->v.rendermode != kRenderNormal)
			{
				pseudoGrenadeEntityVariablesExtended.velocity *= -2.0f;

				traceResult.pHit->v.solid = SOLID_NOT;

				touchedBreakables.push_back (traceResult.pHit);
			}
			else
			{
				if (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND)
				{
					// add a bit of static friction
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.8f;
				}
				else
				{
					if (pseudoGrenadeEntityVariablesExtended.numberFloorHits >= maximumFloorHits)
					{
						pseudoGrenadeEntityVariablesExtended.groundentity = g_engfuncs.pfnPEntityOfEntIndex (0u);
						pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
						pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
					}

					++pseudoGrenadeEntityVariablesExtended.numberFloorHits;
				}
			}
		}

		if (traceResult.flFraction < 1.0f)
		{
			ClipVelocity (pseudoGrenadeEntityVariablesExtended.velocity, traceResult.vecPlaneNormal, pseudoGrenadeEntityVariablesExtended.velocity, 2.0f - grenade->v.friction);

			// stop if on ground
			if (traceResult.vecPlaneNormal.z > 0.7f)
			{
				Vector move (pseudoGrenadeEntityVariablesExtended.basevelocity + pseudoGrenadeEntityVariablesExtended.velocity);

				if (move.z < sv_gravity->value * pseudoFrameTimeInterval)
				{
					// we're rolling on the ground, add static friction.
					pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
					pseudoGrenadeEntityVariablesExtended.groundentity = traceResult.pHit;
					pseudoGrenadeEntityVariablesExtended.velocity.z = 0.0f;
				}

				if (move.GetLengthSquared () >= 30.0f * 30.0f)
				{
					const float scale ((1.0f - traceResult.flFraction) * pseudoFrameTimeInterval * 0.9f);

					move = scale * pseudoGrenadeEntityVariablesExtended.velocity + scale * pseudoGrenadeEntityVariablesExtended.basevelocity;
					to = pseudoGrenadeEntityVariablesExtended.origin + move;

					UTIL_TraceHull (pseudoGrenadeEntityVariablesExtended.origin, to, dont_ignore_monsters, point_hull, grenade->v.owner, &traceResult);	/// @note I use trace hull as this function returns NULL pointer of pHit when no collides, but trace line wasn't!!!

					if (traceResult.flFraction > 0.0f)
						pseudoGrenadeEntityVariablesExtended.origin = traceResult.vecEndPos;

					if (traceResult.pHit != NULL)
					{
						if (FClassnameIs (traceResult.pHit, "func_breakable") && traceResult.pHit->v.rendermode != kRenderNormal)
						{
							pseudoGrenadeEntityVariablesExtended.velocity *= -2.0f;

							traceResult.pHit->v.solid = SOLID_NOT;

							touchedBreakables.push_back (traceResult.pHit);
						}
						else
						{
							if (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND)
							{
								// add a bit of static friction
								pseudoGrenadeEntityVariablesExtended.velocity *= 0.8f;
							}
							else
							{
								if (pseudoGrenadeEntityVariablesExtended.numberFloorHits >= maximumFloorHits)
								{
									pseudoGrenadeEntityVariablesExtended.groundentity = g_engfuncs.pfnPEntityOfEntIndex (0u);
									pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
									pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
								}

								++pseudoGrenadeEntityVariablesExtended.numberFloorHits;
							}
						}
					}
				}
				else
				{
					pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
					pseudoGrenadeEntityVariablesExtended.groundentity = traceResult.pHit;
					pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
				}
			}
		}

		// check for in water
		const int cont (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin));

		if (pseudoGrenadeEntityVariablesExtended.watertype == 0)
		{	// just spawned here
			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 1;

			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			continue;
		}

		if (cont > CONTENTS_WATER || cont <= CONTENTS_TRANSLUCENT)
		{
			pseudoGrenadeEntityVariablesExtended.watertype = CONTENTS_EMPTY;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 0;
		}
		else
		{
			if (pseudoGrenadeEntityVariablesExtended.watertype == CONTENTS_EMPTY)
			{	// just crossed into water
				pseudoGrenadeEntityVariablesExtended.velocity.z *= 0.5f;
			}

			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 3;
		}

		pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;
	} while (IsSmokeGrenade (grenade) ? grenade->v.dmgtime > (pseudoTime += pseudoFrameTimeInterval) || !(pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND) : grenade->v.dmgtime > (pseudoTime += pseudoFrameTimeInterval));

	pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

	// Restore touched breakables solid types
	for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
		touchedBreakables[index]->v.solid = SOLID_BSP;

	for (unsigned char index (0u); index < touchedPushables.size (); ++index)
		touchedPushables[index]->v.solid = SOLID_TRIGGER;
}
Any offers/questions? - Just write here....

Here the DLL of my bot with example of this function, just throw grenade and find green 3D cross of explosion origin.... - should work

P.S. AGAIN SORRY FOR BAD ENGLISH :'-(
  
Reply With Quote
Re: Finding place of grenade explosion
Old
  (#2)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Warning Re: Finding place of grenade explosion - 07-07-2010

EDIT: Function TraceThrownGrenadeToss() is a bit rewritten.
REMOVED BLOCK:
Code:
if (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin) == CONTENTS_SOLID)
		return;	// grenade is trapped in another solid
ADDED:
Code:
pseudoGrenadeEntityVariablesExtended.flags |= FL_KILLME;
if (!IsInWorld (grenade)) - to check whether grenade will be removed.
ADDED BLOCK:
Code:
if (traceResult.fAllSolid)
		{
			// grenade is trapped in another solid
			pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;

			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

			// Restore touched breakables solid types
			for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
				touchedBreakables[index]->v.solid = SOLID_BSP;

			for (unsigned char index (0u); index < touchedPushables.size (); ++index)
				touchedPushables[index]->v.solid = SOLID_TRIGGER;

			return;
		}
NOTE: Function does not always returns right explosion origin vector, if grenade is collided with player!!!

Full function code:
Code:
void TraceThrownGrenadeToss (const edict_t *const grenade, PseudoGrenadeEntityVariables_t &pseudoGrenadeEntityVariables)
{
	struct PseudoGrenadeEntityVariablesExtended_t : PseudoGrenadeEntityVariables_t
	{
		Vector         velocity;		// current movement direction
		Vector         basevelocity;	// if standing on conveyor, e.g.
		int            watertype;
		edict_t       *groundentity;	// if standing on a entity, the pointer to that entity
		float          friction;		// inverse elasticity of 'MOVETYPE_BOUNCE'
		float          nextthink;		// Time next call BaseEntity::Think() function.

		unsigned char  numberFloorHits;
	} pseudoGrenadeEntityVariablesExtended;

	pseudoGrenadeEntityVariablesExtended.origin = grenade->v.origin;
	pseudoGrenadeEntityVariablesExtended.waterlevel = grenade->v.waterlevel;
	pseudoGrenadeEntityVariablesExtended.flags = grenade->v.flags;
	pseudoGrenadeEntityVariablesExtended.velocity = grenade->v.velocity;
	pseudoGrenadeEntityVariablesExtended.basevelocity = grenade->v.basevelocity;
	pseudoGrenadeEntityVariablesExtended.watertype = grenade->v.watertype;
	pseudoGrenadeEntityVariablesExtended.groundentity = grenade->v.groundentity;
	pseudoGrenadeEntityVariablesExtended.friction = grenade->v.friction;
	pseudoGrenadeEntityVariablesExtended.nextthink = grenade->v.nextthink;
	pseudoGrenadeEntityVariablesExtended.numberFloorHits = 0u;

	const unsigned char maximumFloorHits (10u);

	pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

	TraceResult traceResult;
	const float pseudoFrameTimeInterval (/*0.05f*/gpGlobals->frameTime);	// Use your own bigger value if you want to reduce CPU work....
	float pseudoTime (gpGlobals->time);
	Vector to;
	const float gravityAdjust (grenade->v.gravity * sv_gravity->value * pseudoFrameTimeInterval);
	vector <edict_t *> touchedBreakables;
	vector <edict_t *> touchedPushables;

	// Run pseudo frames....
	do
	{
		pseudoGrenadeEntityVariablesExtended.basevelocity = pseudoGrenadeEntityVariablesExtended.groundentity != NULL && (pseudoGrenadeEntityVariablesExtended.groundentity->v.flags & FL_CONVEYOR) ? pseudoGrenadeEntityVariablesExtended.groundentity->v.speed * pseudoGrenadeEntityVariablesExtended.groundentity->v.movedir : vec3_origin;

		for (edict_t *pushable (FIND_ENTITY_BY_CLASSNAME (NULL, "trigger_push")); !FNullEnt (pushable); pushable = FIND_ENTITY_BY_CLASSNAME (pushable, "trigger_push"))
		{
			if (pushable->v.solid == SOLID_NOT || !IsPointInsideBoundingBox (pseudoGrenadeEntityVariablesExtended.origin, pushable->v.absmin, pushable->v.absmax))
				continue;

			// Instant trigger, just transfer velocity and remove
			if (pushable->v.spawnflags & SF_TRIG_PUSH_ONCE)
			{
				pseudoGrenadeEntityVariablesExtended.velocity += pushable->v.speed * pushable->v.movedir;

				if (pseudoGrenadeEntityVariablesExtended.velocity.z > 0.0f)
					pseudoGrenadeEntityVariablesExtended.flags &= ~FL_ONGROUND;

				pushable->v.solid = SOLID_NOT;

				touchedPushables.push_back (pushable);
			}
			else
			{	// Push field, transfer to base velocity
				Vector vecPush (pushable->v.speed * pushable->v.movedir);

				if (pseudoGrenadeEntityVariablesExtended.flags & FL_BASEVELOCITY)
					vecPush += pseudoGrenadeEntityVariablesExtended.basevelocity;

				pseudoGrenadeEntityVariablesExtended.basevelocity = vecPush;

				pseudoGrenadeEntityVariablesExtended.flags |= FL_BASEVELOCITY;
			}
		}

		pseudoGrenadeEntityVariablesExtended.waterlevel = 0;
		pseudoGrenadeEntityVariablesExtended.watertype = CONTENTS_EMPTY;
		const int cont (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin));

		if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT)
		{
			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 3;

			if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
			{
				static const Vector current_table[] =
				{
					Vector ( 1.0f,  0.0f,  0.0f),
					Vector ( 0.0f,  1.0f,  0.0f),
					Vector (-1.0f,  0.0f,  0.0f),
					Vector ( 0.0f, -1.0f,  0.0f),
					Vector ( 0.0f,  0.0f,  1.0f),
					Vector ( 0.0f,  0.0f, -1.0f)
				};

				pseudoGrenadeEntityVariablesExtended.basevelocity += pseudoGrenadeEntityVariablesExtended.waterlevel * 50.0f * current_table[CONTENTS_CURRENT_0 - cont];
			}
		}

	// regular thinking
		{
			float thinkTime (pseudoGrenadeEntityVariablesExtended.nextthink);

			if (thinkTime <= pseudoTime + pseudoFrameTimeInterval)
			{
				if
				(
					// check position
					pseudoGrenadeEntityVariablesExtended.origin.x >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.y >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.z >=  HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.x <= -HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.y <= -HalfMapSize ||
					pseudoGrenadeEntityVariablesExtended.origin.z <= -HalfMapSize ||
	
					// check speed
					pseudoGrenadeEntityVariablesExtended.velocity.x >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.y >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.z >=  2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.x <= -2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.y <= -2000.0f ||
					pseudoGrenadeEntityVariablesExtended.velocity.z <= -2000.0f
				)
				{
					pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;
					pseudoGrenadeEntityVariablesExtended.flags |= FL_KILLME;

					pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

					// Restore touched breakables solid types
					for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
						touchedBreakables[index]->v.solid = SOLID_BSP;

					for (unsigned char index (0u); index < touchedPushables.size (); ++index)
						touchedPushables[index]->v.solid = SOLID_TRIGGER;

					return;
				}

				if (thinkTime < pseudoTime)
					thinkTime = pseudoTime;	// don't let things stay in the past.
											// it is possible to start that way
											// by a trigger with a local time.

				pseudoTime = thinkTime;

				pseudoGrenadeEntityVariablesExtended.nextthink = pseudoTime + 0.1f;

				if (IsSmokeGrenade (grenade) && (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND))
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.949f;//0.949999988079071f - value from decompiled swds.dll sources, I think it's would be 0.949f - IDA sometimes wrong, ex: org 0.8 == decompiled 0.800000011920929 - may be I wrong....

				if (pseudoGrenadeEntityVariablesExtended.waterlevel > 0u)
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.5f;
			}
		}

		if (pseudoGrenadeEntityVariablesExtended.velocity.z > 0.0f || pseudoGrenadeEntityVariablesExtended.groundentity == NULL || (pseudoGrenadeEntityVariablesExtended.groundentity->v.flags & FL_CONVEYOR))
			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_ONGROUND;

// if onground, return without moving
		if ((pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND) && VectorCompare (pseudoGrenadeEntityVariablesExtended.origin, vec3_origin) && VectorCompare (pseudoGrenadeEntityVariablesExtended.basevelocity, vec3_origin))
		{
			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			continue;
		}

		pseudoGrenadeEntityVariablesExtended.velocity.z -= gravityAdjust;
		pseudoGrenadeEntityVariablesExtended.velocity.z += pseudoGrenadeEntityVariablesExtended.basevelocity.z * pseudoFrameTimeInterval;

		pseudoGrenadeEntityVariablesExtended.basevelocity.z = 0.0f;

// move origin
	// Base velocity is not properly accounted for since this entity will move again after the bounce without taking it into account
		to = pseudoGrenadeEntityVariablesExtended.origin + (pseudoGrenadeEntityVariablesExtended.velocity + pseudoGrenadeEntityVariablesExtended.basevelocity) * pseudoFrameTimeInterval;

		UTIL_TraceHull (pseudoGrenadeEntityVariablesExtended.origin, to, dont_ignore_monsters, point_hull, grenade->v.owner, &traceResult);	/// @note Use TraceHull() function instead of TraceLine() as TraceLine() returns worldspawn entity stored in pHit even if flFraction == 1 !!!!

		if (traceResult.flFraction > 0.0f)
			pseudoGrenadeEntityVariablesExtended.origin = traceResult.vecEndPos;

		if (traceResult.pHit != NULL)
		{
			if (FClassnameIs (traceResult.pHit, "func_breakable") && traceResult.pHit->v.rendermode != kRenderNormal)
			{
				pseudoGrenadeEntityVariablesExtended.velocity *= -2.0f;

				traceResult.pHit->v.solid = SOLID_NOT;

				touchedBreakables.push_back (traceResult.pHit);
			}
			else
			{
				if (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND)
				{
					// add a bit of static friction
					pseudoGrenadeEntityVariablesExtended.velocity *= 0.8f;
				}
				else
				{
					if (pseudoGrenadeEntityVariablesExtended.numberFloorHits >= maximumFloorHits)
					{
						pseudoGrenadeEntityVariablesExtended.groundentity = g_engfuncs.pfnPEntityOfEntIndex (0u);
						pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
						pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
					}

					++pseudoGrenadeEntityVariablesExtended.numberFloorHits;
				}
			}
		}

		if (traceResult.fAllSolid)
		{
			// grenade is trapped in another solid
			pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;

			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

			// Restore touched breakables solid types
			for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
				touchedBreakables[index]->v.solid = SOLID_BSP;

			for (unsigned char index (0u); index < touchedPushables.size (); ++index)
				touchedPushables[index]->v.solid = SOLID_TRIGGER;

			return;
		}

		if (traceResult.flFraction < 1.0f)
		{
			ClipVelocity (pseudoGrenadeEntityVariablesExtended.velocity, traceResult.vecPlaneNormal, pseudoGrenadeEntityVariablesExtended.velocity, 2.0f - grenade->v.friction);

			// stop if on ground
			if (traceResult.vecPlaneNormal.z > 0.7f)
			{
				Vector move (pseudoGrenadeEntityVariablesExtended.basevelocity + pseudoGrenadeEntityVariablesExtended.velocity);

				if (move.z < sv_gravity->value * pseudoFrameTimeInterval)
				{
					// we're rolling on the ground, add static friction.
					pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
					pseudoGrenadeEntityVariablesExtended.groundentity = traceResult.pHit;
					pseudoGrenadeEntityVariablesExtended.velocity.z = 0.0f;
				}

				if (move.GetLengthSquared () >= 30.0f * 30.0f)
				{
					const float scale ((1.0f - traceResult.flFraction) * pseudoFrameTimeInterval * 0.9f);

					move = scale * pseudoGrenadeEntityVariablesExtended.velocity + scale * pseudoGrenadeEntityVariablesExtended.basevelocity;
					to = pseudoGrenadeEntityVariablesExtended.origin + move;

					UTIL_TraceHull (pseudoGrenadeEntityVariablesExtended.origin, to, dont_ignore_monsters, point_hull, grenade->v.owner, &traceResult);	/// @note I use trace hull as this function returns NULL pointer of pHit when no collides, but trace line wasn't!!!

					if (traceResult.flFraction > 0.0f)
						pseudoGrenadeEntityVariablesExtended.origin = traceResult.vecEndPos;

					if (traceResult.pHit != NULL)
					{
						if (FClassnameIs (traceResult.pHit, "func_breakable") && traceResult.pHit->v.rendermode != kRenderNormal)
						{
							pseudoGrenadeEntityVariablesExtended.velocity *= -2.0f;

							traceResult.pHit->v.solid = SOLID_NOT;

							touchedBreakables.push_back (traceResult.pHit);
						}
						else
						{
							if (pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND)
							{
								// add a bit of static friction
								pseudoGrenadeEntityVariablesExtended.velocity *= 0.8f;
							}
							else
							{
								if (pseudoGrenadeEntityVariablesExtended.numberFloorHits >= maximumFloorHits)
								{
									pseudoGrenadeEntityVariablesExtended.groundentity = g_engfuncs.pfnPEntityOfEntIndex (0u);
									pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
									pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
								}

								++pseudoGrenadeEntityVariablesExtended.numberFloorHits;
							}
						}
					}
				}
				else
				{
					pseudoGrenadeEntityVariablesExtended.flags |= FL_ONGROUND;
					pseudoGrenadeEntityVariablesExtended.groundentity = traceResult.pHit;
					pseudoGrenadeEntityVariablesExtended.velocity = vec3_origin;
				}
			}
		}

		// check for in water
		const int cont (UTIL_PointContents (pseudoGrenadeEntityVariablesExtended.origin));

		if (pseudoGrenadeEntityVariablesExtended.watertype == 0)
		{	// just spawned here
			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 1;

			pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;

			continue;
		}

		if (cont > CONTENTS_WATER || cont <= CONTENTS_TRANSLUCENT)
		{
			pseudoGrenadeEntityVariablesExtended.watertype = CONTENTS_EMPTY;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 0;
		}
		else
		{
			if (pseudoGrenadeEntityVariablesExtended.watertype == CONTENTS_EMPTY)
			{	// just crossed into water
				pseudoGrenadeEntityVariablesExtended.velocity.z *= 0.5f;
			}

			pseudoGrenadeEntityVariablesExtended.watertype = cont;
			pseudoGrenadeEntityVariablesExtended.waterlevel = 3;
		}

		pseudoGrenadeEntityVariablesExtended.flags &= ~FL_BASEVELOCITY;
	} while (IsSmokeGrenade (grenade) ? grenade->v.dmgtime > (pseudoTime += pseudoFrameTimeInterval) || !(pseudoGrenadeEntityVariablesExtended.flags & FL_ONGROUND) : grenade->v.dmgtime > (pseudoTime += pseudoFrameTimeInterval));

	pseudoGrenadeEntityVariables = pseudoGrenadeEntityVariablesExtended;

	// Restore touched breakables solid types
	for (unsigned char index (0u); index < touchedBreakables.size (); ++index)
		touchedBreakables[index]->v.solid = SOLID_BSP;

	for (unsigned char index (0u); index < touchedPushables.size (); ++index)
		touchedPushables[index]->v.solid = SOLID_TRIGGER;
}

Last edited by Immortal_BLG; 07-07-2010 at 08:41..
  
Reply With Quote
Re: Finding place of grenade explosion
Old
  (#3)
Immortal_BLG
Member
 
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
Default Re: Finding place of grenade explosion - 20-08-2010

0.949999988079071f = 0.95f
  
Reply With Quote
Reply


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

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