|
General Bot Coding See what a pain it is to get those little mechs shooting around
|
|
Member
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
|
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 :'-(
|
|
|
|
|
Member
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
|
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..
|
|
|
|
|
Member
Status: Offline
Posts: 171
Join Date: Nov 2007
Location: Russian Federation
|
Re: Finding place of grenade explosion -
20-08-2010
0.949999988079071f = 0.95f
|
|
|
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
HTML code is Off
|
|
|
Powered by vBulletin® Version 3.8.2 Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
vBulletin Skin developed by: vBStyles.com
|
|