Beispiel #1
0
//FIXME since we need to test end position contents here, can we avoid doing
//it again later in catagorize position?
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
{
    float		dz;
    vec3_t		oldorg, neworg, end;
    trace_t		trace;
    int			i;
    float		stepsize;
    vec3_t		test;
    int			contents;
    edict_t		*current_bad;		// PGM
    float		minheight;			// pmm

//======
//PGM
    current_bad = CheckForBadArea(ent);
    if(current_bad)
    {
//		gi.dprintf("in bad area\n");
        ent->bad_area = current_bad;

        if(ent->enemy && !strcmp(ent->enemy->classname, "tesla"))
        {
//			gi.dprintf("%s  -->>  ", vtos(move));
            VectorScale(move, -1, move);
//			gi.dprintf("%s\n", vtos(move));
        }
    }
    else if(ent->bad_area)
    {
        // if we're no longer in a bad area, get back to business.
        ent->bad_area = NULL;
        if(ent->oldenemy)// && ent->bad_area->owner == ent->enemy)
        {
//			gi.dprintf("resuming being pissed at %s\n", ent->oldenemy->classname);
            ent->enemy = ent->oldenemy;
            ent->goalentity = ent->oldenemy;
            FoundTarget(ent);
            return true;
        }
    }
//PGM
//======

// try the move
    VectorCopy (ent->s.origin, oldorg);
    VectorAdd (ent->s.origin, move, neworg);

// flying monsters don't step up
    if ( ent->flags & (FL_SWIM | FL_FLY) )
    {
        // try one move with vertical motion, then one without
        for (i=0 ; i<2 ; i++)
        {
            VectorAdd (ent->s.origin, move, neworg);
            if (i == 0 && ent->enemy)
            {
                if (!ent->goalentity)
                    ent->goalentity = ent->enemy;
                dz = ent->s.origin[2] - ent->goalentity->s.origin[2];
                if (ent->goalentity->client)
                {
                    // we want the carrier to stay a certain distance off the ground, to help prevent him
                    // from shooting his fliers, who spawn in below him
                    //
                    if (!strcmp(ent->classname, "monster_carrier"))
                        minheight = 104;
                    else
                        minheight = 40;
//					if (dz > 40)
                    if (dz > minheight)
//	pmm
                        neworg[2] -= 8;
                    if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2)))
                        if (dz < (minheight - 10))
                            neworg[2] += 8;
                }
                else
                {
                    if (dz > 8)
                        neworg[2] -= 8;
                    else if (dz > 0)
                        neworg[2] -= dz;
                    else if (dz < -8)
                        neworg[2] += 8;
                    else
                        neworg[2] += dz;
                }
            }

            trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID);

            // fly monsters don't enter water voluntarily
            if (ent->flags & FL_FLY)
            {
                if (!ent->waterlevel)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (contents & MASK_WATER)
                        return false;
                }
            }

            // swim monsters don't exit water voluntarily
            if (ent->flags & FL_SWIM)
            {
                if (ent->waterlevel < 2)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (!(contents & MASK_WATER))
                        return false;
                }
            }

//			if (trace.fraction == 1)

            // PMM - changed above to this
            if ((trace.fraction == 1) && (!trace.allsolid) && (!trace.startsolid))
            {
                VectorCopy (trace.endpos, ent->s.origin);
//=====
//PGM
                if(!current_bad && CheckForBadArea(ent))
                {
//						gi.dprintf("Oooh! Bad Area!\n");
                    VectorCopy (oldorg, ent->s.origin);
                }
                else
                {
                    if (relink)
                    {
                        gi.linkentity (ent);
                        G_TouchTriggers (ent);
                    }
                    return true;
                }
//PGM
//=====
            }

            if (!ent->enemy)
                break;
        }

        return false;
    }

// push down from a step height above the wished position
    if (!(ent->monsterinfo.aiflags & AI_NOSTEP))
        stepsize = STEPSIZE;
    else
        stepsize = 1;

//PGM
#ifdef ROGUE_GRAVITY
    // trace from 1 stepsize gravityUp to 2 stepsize gravityDown.
    VectorMA(neworg, -1 * stepsize, ent->gravityVector, neworg);
    VectorMA(neworg, 2 * stepsize, ent->gravityVector, end);
#else
    neworg[2] += stepsize;
    VectorCopy (neworg, end);
    end[2] -= stepsize*2;
#endif
//PGM

    trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);

    if (trace.allsolid)
        return false;

    if (trace.startsolid)
    {
        neworg[2] -= stepsize;
        trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
        if (trace.allsolid || trace.startsolid)
            return false;
    }


    // don't go in to water
    if (ent->waterlevel == 0)
    {
//PGM
#ifdef ROGUE_GRAVITY
        test[0] = trace.endpos[0];
        test[1] = trace.endpos[1];
        if(ent->gravityVector[2] > 0)
            test[2] = trace.endpos[2] + ent->maxs[2] - 1;
        else
            test[2] = trace.endpos[2] + ent->mins[2] + 1;
#else
        test[0] = trace.endpos[0];
        test[1] = trace.endpos[1];
        test[2] = trace.endpos[2] + ent->mins[2] + 1;
#endif
//PGM

        contents = gi.pointcontents(test);

        if (contents & MASK_WATER)
            return false;
    }

    if (trace.fraction == 1)
    {
        // if monster had the ground pulled out, go ahead and fall
        if ( ent->flags & FL_PARTIALGROUND )
        {
            VectorAdd (ent->s.origin, move, ent->s.origin);
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            ent->groundentity = NULL;
            return true;
        }

        return false;		// walked off an edge
    }

// check point traces down for dangling corners
    VectorCopy (trace.endpos, ent->s.origin);

//PGM
    new_bad = CheckForBadArea(ent);
    if(!current_bad && new_bad)
    {
        if (new_bad->owner)
        {
            if ((g_showlogic) && (g_showlogic->value))
                gi.dprintf("Blocked -");
            if (!strcmp(new_bad->owner->classname, "tesla"))
            {
                if ((g_showlogic) && (g_showlogic->value))
                    gi.dprintf ("it's a tesla -");
                if ((!(ent->enemy)) || (!(ent->enemy->inuse)))
                {
                    if ((g_showlogic) && (g_showlogic->value))
                        gi.dprintf ("I don't have a valid enemy!\n");
                }
                else if (!strcmp(ent->enemy->classname, "telsa"))
                {
                    if ((g_showlogic) && (g_showlogic->value))
                        gi.dprintf ("but we're already mad at a tesla\n");
                }
                else if ((ent->enemy) && (ent->enemy->client))
                {
                    if ((g_showlogic) && (g_showlogic->value))
                        gi.dprintf ("we have a player enemy -");
                    if (visible(ent, ent->enemy))
                    {
                        if ((g_showlogic) && (g_showlogic->value))
                            gi.dprintf ("we can see him -");
                    }
                    else
                    {
                        if ((g_showlogic) && (g_showlogic->value))
                            gi.dprintf ("can't see him, kill the tesla! -");
                    }
                }
                else
                {
                    if ((g_showlogic) && (g_showlogic->value))
                        gi.dprintf ("the enemy isn't a player -");
                }
            }
        }
        gi.dprintf ("\n");


        VectorCopy (oldorg, ent->s.origin);
        return false;
    }
//PGM

    if (!M_CheckBottom (ent))
    {
        if ( ent->flags & FL_PARTIALGROUND )
        {   // entity had floor mostly pulled out from underneath it
            // and is trying to correct
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            return true;
        }
        VectorCopy (oldorg, ent->s.origin);
        return false;
    }

    if ( ent->flags & FL_PARTIALGROUND )
    {
        ent->flags &= ~FL_PARTIALGROUND;
    }
    ent->groundentity = trace.ent;
    ent->groundentity_linkcount = trace.ent->linkcount;

// the move is ok
    if (relink)
    {
        gi.linkentity (ent);
        G_TouchTriggers (ent);
    }
    return true;
}
Beispiel #2
0
//FIXME since we need to test end position contents here, can we avoid doing
//it again later in catagorize position?
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
{
    float		dz;
    vec3_t		oldorg, neworg, end;
    trace_t		trace;
    int			i;
    float		stepsize;
    vec3_t		test;
    int			contents;
    edict_t		*current_bad = NULL;		// PGM
    float		minheight;			// pmm

    //======
    //PGM

    // PMM - who cares about bad areas if you're dead?
    if (ent->health > 0)
    {
        current_bad = CheckForBadArea(ent);
        if(current_bad)
        {
            ent->bad_area = current_bad;

            if(ent->enemy && !strcmp(ent->enemy->classname, "tesla"))
            {
                // if the tesla is in front of us, back up...
                if (IsBadAhead (ent, current_bad, move))
                    VectorScale(move, -1, move);
            }
        }
        else if(ent->bad_area)
        {
            // if we're no longer in a bad area, get back to business.
            ent->bad_area = NULL;
            if(ent->oldenemy)// && ent->bad_area->owner == ent->enemy)
            {
                ent->enemy = ent->oldenemy;
                ent->goalentity = ent->oldenemy;
                FoundTarget(ent);
                return true;
            }
        }
    }
    //PGM
    //======

    // try the move
    VectorCopy (ent->s.origin, oldorg);
    VectorAdd (ent->s.origin, move, neworg);

    // flying monsters don't step up
    if ( ent->flags & (FL_SWIM | FL_FLY) )
    {
        // try one move with vertical motion, then one without
        for (i=0 ; i<2 ; i++)
        {
            VectorAdd (ent->s.origin, move, neworg);
            if (i == 0 && ent->enemy)
            {
                if (!ent->goalentity)
                    ent->goalentity = ent->enemy;
                dz = ent->s.origin[2] - ent->goalentity->s.origin[2];
                if (ent->goalentity->client)
                {
                    // we want the carrier to stay a certain distance off the ground, to help prevent him
                    // from shooting his fliers, who spawn in below him
                    //
                    if (!strcmp(ent->classname, "monster_carrier"))
                        minheight = 104;
                    else
                        minheight = 40;
                    if (dz > minheight)
                        //	pmm
                        neworg[2] -= 8;
                    if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2)))
                        if (dz < (minheight - 10))
                            neworg[2] += 8;
                }
                else
                {
                    if (dz > 8)
                        neworg[2] -= 8;
                    else if (dz > 0)
                        neworg[2] -= dz;
                    else if (dz < -8)
                        neworg[2] += 8;
                    else
                        neworg[2] += dz;
                }
            }

            trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID);

            // fly monsters don't enter water voluntarily
            if (ent->flags & FL_FLY)
            {
                if (!ent->waterlevel)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (contents & MASK_WATER)
                        return false;
                }
            }

            // swim monsters don't exit water voluntarily
            if (ent->flags & FL_SWIM)
            {
                if (ent->waterlevel < 2)
                {
                    test[0] = trace.endpos[0];
                    test[1] = trace.endpos[1];
                    test[2] = trace.endpos[2] + ent->mins[2] + 1;
                    contents = gi.pointcontents(test);
                    if (!(contents & MASK_WATER))
                        return false;
                }
            }

            // PMM - changed above to this
            if ((trace.fraction == 1) && (!trace.allsolid) && (!trace.startsolid))
            {
                VectorCopy (trace.endpos, ent->s.origin);
                //=====
                //PGM
                if(!current_bad && CheckForBadArea(ent))
                {
                    VectorCopy (oldorg, ent->s.origin);
                }
                else
                {
                    if (relink)
                    {
                        gi.linkentity (ent);
                        G_TouchTriggers (ent);
                    }
                    return true;
                }
                //PGM
                //=====
            }

            if (!ent->enemy)
                break;
        }

        return false;
    }

    // push down from a step height above the wished position
    if (!(ent->monsterinfo.aiflags & AI_NOSTEP))
        stepsize = STEPSIZE;
    else
        stepsize = 1;

    //PGM
    // trace from 1 stepsize gravityUp to 2 stepsize gravityDown.
    VectorMA(neworg, -1 * stepsize, ent->gravityVector, neworg);
    VectorMA(neworg, 2 * stepsize, ent->gravityVector, end);
    //PGM

    trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);

    if (trace.allsolid)
        return false;

    if (trace.startsolid)
    {
        neworg[2] -= stepsize;
        trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
        if (trace.allsolid || trace.startsolid)
            return false;
    }


    // don't go in to water
    if (ent->waterlevel == 0)
    {
        //PGM
        test[0] = trace.endpos[0];
        test[1] = trace.endpos[1];
        if(ent->gravityVector[2] > 0)
            test[2] = trace.endpos[2] + ent->maxs[2] - 1;
        else
            test[2] = trace.endpos[2] + ent->mins[2] + 1;
        //PGM

        contents = gi.pointcontents(test);

        if (contents & MASK_WATER)
            return false;
    }

    if (trace.fraction == 1)
    {
        // if monster had the ground pulled out, go ahead and fall
        if ( ent->flags & FL_PARTIALGROUND )
        {
            VectorAdd (ent->s.origin, move, ent->s.origin);
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            ent->groundentity = NULL;

            return true;
        }

        return false;		// walked off an edge
    }

    // check point traces down for dangling corners
    VectorCopy (trace.endpos, ent->s.origin);

    //PGM
    // PMM - don't bother with bad areas if we're dead
    if (ent->health > 0)
    {
        // use AI_BLOCKED to tell the calling layer that we're now mad at a tesla
        new_bad = CheckForBadArea(ent);
        if(!current_bad && new_bad)
        {
            if (new_bad->owner)
            {
                if (!strcmp(new_bad->owner->classname, "tesla"))
                {
                    if ((!(ent->enemy)) || (!(ent->enemy->inuse)))
                    {
                        TargetTesla (ent, new_bad->owner);
                        ent->monsterinfo.aiflags |= AI_BLOCKED;
                    }
                    else if (!strcmp(ent->enemy->classname, "telsa"))
                    {
                    }
                    else if ((ent->enemy) && (ent->enemy->client))
                    {
                        if (visible(ent, ent->enemy))
                        {
                        }
                        else
                        {
                            TargetTesla (ent, new_bad->owner);
                            ent->monsterinfo.aiflags |= AI_BLOCKED;
                        }
                    }
                    else
                    {
                        TargetTesla (ent, new_bad->owner);
                        ent->monsterinfo.aiflags |= AI_BLOCKED;
                    }
                }
            }

            VectorCopy (oldorg, ent->s.origin);
            return false;
        }
    }
    //PGM

    if (!M_CheckBottom (ent))
    {
        if ( ent->flags & FL_PARTIALGROUND )
        {   // entity had floor mostly pulled out from underneath it
            // and is trying to correct
            if (relink)
            {
                gi.linkentity (ent);
                G_TouchTriggers (ent);
            }
            return true;
        }
        VectorCopy (oldorg, ent->s.origin);
        return false;
    }

    if ( ent->flags & FL_PARTIALGROUND )
    {
        ent->flags &= ~FL_PARTIALGROUND;
    }
    ent->groundentity = trace.ent;
    ent->groundentity_linkcount = trace.ent->linkcount;

    if (relink)
    {
        gi.linkentity (ent);
        G_TouchTriggers (ent);
    }
    return true;
}