.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Bot Coding (http://forums.bots-united.com/forumdisplay.php?f=24)
-   -   Finding place of grenade explosion (http://forums.bots-united.com/showthread.php?t=7641)

Immortal_BLG 30-06-2010 07:41

Finding place of grenade explosion
 
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 :'-(

Immortal_BLG 07-07-2010 07:14

Re: Finding place of grenade explosion
 
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;
}


Immortal_BLG 20-08-2010 12:55

Re: Finding place of grenade explosion
 
0.949999988079071f = 0.95f


All times are GMT +2. The time now is 19:13.

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