Annotation of quake2/rogue/m_move.c, revision 1.1

1.1     ! root        1: // m_move.c -- monster movement
        !             2: 
        !             3: #include "g_local.h"
        !             4: 
        !             5: #define        STEPSIZE        18
        !             6: 
        !             7: // this is used for communications out of sv_movestep to say what entity
        !             8: // is blocking us
        !             9: edict_t                *new_bad;                       //pmm
        !            10: 
        !            11: /*
        !            12: =============
        !            13: M_CheckBottom
        !            14: 
        !            15: Returns false if any part of the bottom of the entity is off an edge that
        !            16: is not a staircase.
        !            17: 
        !            18: =============
        !            19: */
        !            20: int c_yes, c_no;
        !            21: 
        !            22: qboolean M_CheckBottom (edict_t *ent)
        !            23: {
        !            24:        vec3_t  mins, maxs, start, stop;
        !            25:        trace_t trace;
        !            26:        int             x, y;
        !            27:        float   mid, bottom;
        !            28:        
        !            29:        VectorAdd (ent->s.origin, ent->mins, mins);
        !            30:        VectorAdd (ent->s.origin, ent->maxs, maxs);
        !            31: 
        !            32: // if all of the points under the corners are solid world, don't bother
        !            33: // with the tougher checks
        !            34: // the corners must be within 16 of the midpoint
        !            35: 
        !            36: //PGM
        !            37: #ifdef ROGUE_GRAVITY
        !            38:        // FIXME - this will only handle 0,0,1 and 0,0,-1 gravity vectors
        !            39:        start[2] = mins[2] - 1;
        !            40:        if(ent->gravityVector[2] > 0)
        !            41:                start[2] = maxs[2] + 1;
        !            42: #else
        !            43:        start[2] = mins[2] - 1;
        !            44: #endif
        !            45: //PGM
        !            46: 
        !            47:        for     (x=0 ; x<=1 ; x++)
        !            48:                for     (y=0 ; y<=1 ; y++)
        !            49:                {
        !            50:                        start[0] = x ? maxs[0] : mins[0];
        !            51:                        start[1] = y ? maxs[1] : mins[1];
        !            52:                        if (gi.pointcontents (start) != CONTENTS_SOLID)
        !            53:                                goto realcheck;
        !            54:                }
        !            55: 
        !            56:        c_yes++;
        !            57:        return true;            // we got out easy
        !            58: 
        !            59: realcheck:
        !            60:        c_no++;
        !            61: //
        !            62: // check it for real...
        !            63: //
        !            64:        start[2] = mins[2];
        !            65:        
        !            66: // the midpoint must be within 16 of the bottom
        !            67:        start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
        !            68:        start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
        !            69: 
        !            70: //PGM
        !            71: #ifdef ROGUE_GRAVITY
        !            72:        if(ent->gravityVector[2] < 0)
        !            73:        {
        !            74:                start[2] = mins[2];
        !            75:                stop[2] = start[2] - STEPSIZE - STEPSIZE;
        !            76:        }
        !            77:        else
        !            78:        {
        !            79:                start[2] = maxs[2];
        !            80:                stop[2] = start[2] + STEPSIZE + STEPSIZE;
        !            81:        }
        !            82: #else
        !            83:        stop[2] = start[2] - 2*STEPSIZE;
        !            84: #endif
        !            85: //PGM
        !            86: 
        !            87:        trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);
        !            88: 
        !            89:        if (trace.fraction == 1.0)
        !            90:                return false;
        !            91:        mid = bottom = trace.endpos[2];
        !            92:        
        !            93: // the corners must be within 16 of the midpoint       
        !            94:        for     (x=0 ; x<=1 ; x++)
        !            95:                for     (y=0 ; y<=1 ; y++)
        !            96:                {
        !            97:                        start[0] = stop[0] = x ? maxs[0] : mins[0];
        !            98:                        start[1] = stop[1] = y ? maxs[1] : mins[1];
        !            99:                        
        !           100:                        trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);
        !           101: 
        !           102: //PGM
        !           103: #ifdef ROGUE_GRAVITY
        !           104:                        // FIXME - this will only handle 0,0,1 and 0,0,-1 gravity vectors
        !           105:                        if(ent->gravityVector[2] > 0)
        !           106:                        {
        !           107:                                if (trace.fraction != 1.0 && trace.endpos[2] < bottom)
        !           108:                                        bottom = trace.endpos[2];
        !           109:                                if (trace.fraction == 1.0 || trace.endpos[2] - mid > STEPSIZE)
        !           110:                                        return false;
        !           111:                        }
        !           112:                        else
        !           113:                        {
        !           114:                                if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
        !           115:                                        bottom = trace.endpos[2];
        !           116:                                if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
        !           117:                                        return false;
        !           118:                        }
        !           119: #else
        !           120:                        if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
        !           121:                                bottom = trace.endpos[2];
        !           122:                        if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
        !           123:                                return false;
        !           124: #endif
        !           125: //PGM
        !           126:                }
        !           127: 
        !           128:        c_yes++;
        !           129:        return true;
        !           130: }
        !           131: 
        !           132: //============
        !           133: // ROGUE
        !           134: qboolean IsBadAhead (edict_t *self, edict_t *bad)
        !           135: {
        !           136:        vec3_t  dir;
        !           137:        vec3_t  forward;
        !           138: 
        !           139:        VectorSubtract (bad->s.origin, self->s.origin, dir);
        !           140:        VectorNormalize (dir);
        !           141:        AngleVectors (self->s.angles, forward, NULL, NULL);
        !           142:        if(DotProduct(forward, dir) > 0)
        !           143:        {
        !           144: //             gi.dprintf ("bad ahead...\n");
        !           145:                return true;
        !           146:        }
        !           147: 
        !           148: //     gi.dprintf ("bad behind...\n");
        !           149:        return false;
        !           150: }
        !           151: // ROGUE
        !           152: //============
        !           153: 
        !           154: /*
        !           155: =============
        !           156: SV_movestep
        !           157: 
        !           158: Called by monster program code.
        !           159: The move will be adjusted for slopes and stairs, but if the move isn't
        !           160: possible, no move is done, false is returned, and
        !           161: pr_global_struct->trace_normal is set to the normal of the blocking wall
        !           162: =============
        !           163: */
        !           164: //FIXME since we need to test end position contents here, can we avoid doing
        !           165: //it again later in catagorize position?
        !           166: qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
        !           167: {
        !           168:        float           dz;
        !           169:        vec3_t          oldorg, neworg, end;
        !           170:        trace_t         trace;
        !           171:        int                     i;
        !           172:        float           stepsize;
        !           173:        vec3_t          test;
        !           174:        int                     contents;
        !           175:        edict_t         *current_bad;           // PGM
        !           176:        float           minheight;                      // pmm
        !           177: 
        !           178: //======
        !           179: //PGM
        !           180: 
        !           181:        // PMM - who cares about bad areas if you're dead?
        !           182:        if (ent->health > 0)
        !           183:        {
        !           184:                current_bad = CheckForBadArea(ent);
        !           185:                if(current_bad)
        !           186:                {
        !           187:                        ent->bad_area = current_bad;
        !           188:                         
        !           189:                        if(ent->enemy && !strcmp(ent->enemy->classname, "tesla"))
        !           190:                        {
        !           191:                                // if the tesla is in front of us, back up...
        !           192:                                if (IsBadAhead (ent, current_bad))
        !           193:                                        VectorScale(move, -1, move);
        !           194:                        }
        !           195:                }
        !           196:                else if(ent->bad_area)
        !           197:                {
        !           198:                        // if we're no longer in a bad area, get back to business.
        !           199:                        ent->bad_area = NULL;
        !           200:                        if(ent->oldenemy)// && ent->bad_area->owner == ent->enemy)
        !           201:                        {
        !           202:        //                      gi.dprintf("resuming being pissed at %s\n", ent->oldenemy->classname);
        !           203:                                ent->enemy = ent->oldenemy;
        !           204:                                ent->goalentity = ent->oldenemy;
        !           205:                                FoundTarget(ent);
        !           206:        // FIXME - remove this when ready!!!
        !           207:        if (ent->lastMoveTime == level.time)
        !           208:                if ((g_showlogic) && (g_showlogic->value))
        !           209:                        gi.dprintf ("Duplicate move detected for %s, please tell programmers!\n", ent->classname);
        !           210:        ent->lastMoveTime = level.time;
        !           211:        // FIXME
        !           212: 
        !           213:                                return true;
        !           214:                        }
        !           215:                }
        !           216:        }
        !           217: //PGM
        !           218: //======
        !           219: 
        !           220: // try the move        
        !           221:        VectorCopy (ent->s.origin, oldorg);
        !           222:        VectorAdd (ent->s.origin, move, neworg);
        !           223: 
        !           224: // flying monsters don't step up
        !           225:        if ( ent->flags & (FL_SWIM | FL_FLY) )
        !           226:        {
        !           227:        // try one move with vertical motion, then one without
        !           228:                for (i=0 ; i<2 ; i++)
        !           229:                {
        !           230:                        VectorAdd (ent->s.origin, move, neworg);
        !           231:                        if (i == 0 && ent->enemy)
        !           232:                        {
        !           233:                                if (!ent->goalentity)
        !           234:                                        ent->goalentity = ent->enemy;
        !           235:                                dz = ent->s.origin[2] - ent->goalentity->s.origin[2];
        !           236:                                if (ent->goalentity->client)
        !           237:                                {
        !           238:                                        // we want the carrier to stay a certain distance off the ground, to help prevent him
        !           239:                                        // from shooting his fliers, who spawn in below him
        !           240:                                        //
        !           241:                                        if (!strcmp(ent->classname, "monster_carrier"))
        !           242:                                                minheight = 104;
        !           243:                                        else
        !           244:                                                minheight = 40;
        !           245: //                                     if (dz > 40)
        !           246:                                        if (dz > minheight)
        !           247: //     pmm             
        !           248:                                                neworg[2] -= 8;
        !           249:                                        if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2)))
        !           250:                                                if (dz < (minheight - 10))
        !           251:                                                        neworg[2] += 8;
        !           252:                                }
        !           253:                                else
        !           254:                                {
        !           255:                                        if (dz > 8)
        !           256:                                                neworg[2] -= 8;
        !           257:                                        else if (dz > 0)
        !           258:                                                neworg[2] -= dz;
        !           259:                                        else if (dz < -8)
        !           260:                                                neworg[2] += 8;
        !           261:                                        else
        !           262:                                                neworg[2] += dz;
        !           263:                                }
        !           264:                        }
        !           265: 
        !           266:                        trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID);
        !           267:        
        !           268:                        // fly monsters don't enter water voluntarily
        !           269:                        if (ent->flags & FL_FLY)
        !           270:                        {
        !           271:                                if (!ent->waterlevel)
        !           272:                                {
        !           273:                                        test[0] = trace.endpos[0];
        !           274:                                        test[1] = trace.endpos[1];
        !           275:                                        test[2] = trace.endpos[2] + ent->mins[2] + 1;
        !           276:                                        contents = gi.pointcontents(test);
        !           277:                                        if (contents & MASK_WATER)
        !           278:                                                return false;
        !           279:                                }
        !           280:                        }
        !           281: 
        !           282:                        // swim monsters don't exit water voluntarily
        !           283:                        if (ent->flags & FL_SWIM)
        !           284:                        {
        !           285:                                if (ent->waterlevel < 2)
        !           286:                                {
        !           287:                                        test[0] = trace.endpos[0];
        !           288:                                        test[1] = trace.endpos[1];
        !           289:                                        test[2] = trace.endpos[2] + ent->mins[2] + 1;
        !           290:                                        contents = gi.pointcontents(test);
        !           291:                                        if (!(contents & MASK_WATER))
        !           292:                                                return false;
        !           293:                                }
        !           294:                        }
        !           295: 
        !           296: //                     if (trace.fraction == 1)
        !           297: 
        !           298:                        // PMM - changed above to this
        !           299:                        if ((trace.fraction == 1) && (!trace.allsolid) && (!trace.startsolid))
        !           300:                        {
        !           301:                                VectorCopy (trace.endpos, ent->s.origin);
        !           302: //=====
        !           303: //PGM                          
        !           304:                                if(!current_bad && CheckForBadArea(ent))
        !           305:                                {
        !           306: //                                             gi.dprintf("Oooh! Bad Area!\n");
        !           307:                                        VectorCopy (oldorg, ent->s.origin);
        !           308:                                }
        !           309:                                else
        !           310:                                {
        !           311:                                        if (relink)
        !           312:                                        {
        !           313:                                                gi.linkentity (ent);
        !           314:                                                G_TouchTriggers (ent);
        !           315:                                        }
        !           316:        // FIXME - remove this when ready!!!
        !           317:        if (ent->lastMoveTime == level.time)
        !           318:                if ((g_showlogic) && (g_showlogic->value))
        !           319:                        gi.dprintf ("Duplicate move detected for %s, please tell programmers!\n", ent->classname);
        !           320:        ent->lastMoveTime = level.time;
        !           321:        // FIXME
        !           322: 
        !           323:                                        return true;
        !           324:                                }
        !           325: //PGM
        !           326: //=====
        !           327:                        }
        !           328:                        
        !           329:                        if (!ent->enemy)
        !           330:                                break;
        !           331:                }
        !           332:                
        !           333:                return false;
        !           334:        }
        !           335: 
        !           336: // push down from a step height above the wished position
        !           337:        if (!(ent->monsterinfo.aiflags & AI_NOSTEP))
        !           338:                stepsize = STEPSIZE;
        !           339:        else
        !           340:                stepsize = 1;
        !           341: 
        !           342: //PGM
        !           343: #ifdef ROGUE_GRAVITY
        !           344:        // trace from 1 stepsize gravityUp to 2 stepsize gravityDown.
        !           345:        VectorMA(neworg, -1 * stepsize, ent->gravityVector, neworg);
        !           346:        VectorMA(neworg, 2 * stepsize, ent->gravityVector, end);
        !           347: #else
        !           348:        neworg[2] += stepsize;
        !           349:        VectorCopy (neworg, end);
        !           350:        end[2] -= stepsize*2;
        !           351: #endif
        !           352: //PGM
        !           353: 
        !           354:        trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
        !           355: 
        !           356:        if (trace.allsolid)
        !           357:                return false;
        !           358: 
        !           359:        if (trace.startsolid)
        !           360:        {
        !           361:                neworg[2] -= stepsize;
        !           362:                trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
        !           363:                if (trace.allsolid || trace.startsolid)
        !           364:                        return false;
        !           365:        }
        !           366: 
        !           367: 
        !           368:        // don't go in to water
        !           369:        if (ent->waterlevel == 0)
        !           370:        {
        !           371: //PGM
        !           372: #ifdef ROGUE_GRAVITY
        !           373:                test[0] = trace.endpos[0];
        !           374:                test[1] = trace.endpos[1];
        !           375:                if(ent->gravityVector[2] > 0)
        !           376:                        test[2] = trace.endpos[2] + ent->maxs[2] - 1;   
        !           377:                else
        !           378:                        test[2] = trace.endpos[2] + ent->mins[2] + 1;
        !           379: #else
        !           380:                test[0] = trace.endpos[0];
        !           381:                test[1] = trace.endpos[1];
        !           382:                test[2] = trace.endpos[2] + ent->mins[2] + 1;   
        !           383: #endif
        !           384: //PGM
        !           385: 
        !           386:                contents = gi.pointcontents(test);
        !           387: 
        !           388:                if (contents & MASK_WATER)
        !           389:                        return false;
        !           390:        }
        !           391: 
        !           392:        if (trace.fraction == 1)
        !           393:        {
        !           394:        // if monster had the ground pulled out, go ahead and fall
        !           395:                if ( ent->flags & FL_PARTIALGROUND )
        !           396:                {
        !           397:                        VectorAdd (ent->s.origin, move, ent->s.origin);
        !           398:                        if (relink)
        !           399:                        {
        !           400:                                gi.linkentity (ent);
        !           401:                                G_TouchTriggers (ent);
        !           402:                        }
        !           403:                        ent->groundentity = NULL;
        !           404:        // FIXME - remove this when ready!!!
        !           405:        if (ent->lastMoveTime == level.time)
        !           406:                if ((g_showlogic) && (g_showlogic->value))
        !           407:                        gi.dprintf ("Duplicate move detected for %s, please tell programmers!\n", ent->classname);
        !           408:        ent->lastMoveTime = level.time;
        !           409:        // FIXME
        !           410: 
        !           411:                        return true;
        !           412:                }
        !           413:        
        !           414:                return false;           // walked off an edge
        !           415:        }
        !           416: 
        !           417: // check point traces down for dangling corners
        !           418:        VectorCopy (trace.endpos, ent->s.origin);
        !           419: 
        !           420: //PGM
        !           421:        // PMM - don't bother with bad areas if we're dead
        !           422:        if (ent->health > 0)
        !           423:        {
        !           424:                // use AI_BLOCKED to tell the calling layer that we're now mad at a tesla
        !           425:                new_bad = CheckForBadArea(ent);
        !           426:                if(!current_bad && new_bad)
        !           427:                {
        !           428:                        if (new_bad->owner)
        !           429:                        {
        !           430:                                if ((g_showlogic) && (g_showlogic->value))
        !           431:                                        gi.dprintf("Blocked -");
        !           432:                                if (!strcmp(new_bad->owner->classname, "tesla"))
        !           433:                                {
        !           434:                                        if ((g_showlogic) && (g_showlogic->value))
        !           435:                                                gi.dprintf ("it's a tesla -");
        !           436:                                        if ((!(ent->enemy)) || (!(ent->enemy->inuse)))
        !           437:                                        {
        !           438:                                                if ((g_showlogic) && (g_showlogic->value))
        !           439:                                                        gi.dprintf ("I don't have a valid enemy, attacking tesla!\n");
        !           440:                                                TargetTesla (ent, new_bad->owner);
        !           441:                                                ent->monsterinfo.aiflags |= AI_BLOCKED;
        !           442:                                        }
        !           443:                                        else if (!strcmp(ent->enemy->classname, "telsa"))
        !           444:                                        {
        !           445:                                                if ((g_showlogic) && (g_showlogic->value))
        !           446:                                                        gi.dprintf ("but we're already mad at a tesla\n");
        !           447:                                        }
        !           448:                                        else if ((ent->enemy) && (ent->enemy->client))
        !           449:                                        {
        !           450:                                                if ((g_showlogic) && (g_showlogic->value))
        !           451:                                                        gi.dprintf ("we have a player enemy -");
        !           452:                                                if (visible(ent, ent->enemy))
        !           453:                                                {
        !           454:                                                        if ((g_showlogic) && (g_showlogic->value))
        !           455:                                                                gi.dprintf ("we can see him -");
        !           456:                                                }
        !           457:                                                else
        !           458:                                                {
        !           459:                                                        if ((g_showlogic) && (g_showlogic->value))
        !           460:                                                                gi.dprintf ("can't see him, kill the tesla! -");
        !           461:                                                        TargetTesla (ent, new_bad->owner);
        !           462:                                                        ent->monsterinfo.aiflags |= AI_BLOCKED;
        !           463:                                                }
        !           464:                                        }
        !           465:                                        else
        !           466:                                        {
        !           467:                                                if ((g_showlogic) && (g_showlogic->value))
        !           468:                                                        gi.dprintf ("the enemy isn't a player, killing tesla -");
        !           469:                                                TargetTesla (ent, new_bad->owner);
        !           470:                                                ent->monsterinfo.aiflags |= AI_BLOCKED;
        !           471:                                        }
        !           472:                                }
        !           473:                                else if ((g_showlogic) && (g_showlogic->value))
        !           474:                                {
        !           475:                                        gi.dprintf(" by non-tesla bad area!");
        !           476:                                }
        !           477:                        }
        !           478:                        gi.dprintf ("\n");
        !           479: 
        !           480:                        VectorCopy (oldorg, ent->s.origin);
        !           481:                        return false;
        !           482:                }
        !           483:        }
        !           484: //PGM
        !           485: 
        !           486:        if (!M_CheckBottom (ent))
        !           487:        {
        !           488:                if ( ent->flags & FL_PARTIALGROUND )
        !           489:                {       // entity had floor mostly pulled out from underneath it
        !           490:                        // and is trying to correct
        !           491:                        if (relink)
        !           492:                        {
        !           493:                                gi.linkentity (ent);
        !           494:                                G_TouchTriggers (ent);
        !           495:                        }
        !           496:        // FIXME - remove this when ready!!!
        !           497:        if (ent->lastMoveTime == level.time)
        !           498:                if ((g_showlogic) && (g_showlogic->value))
        !           499:                        gi.dprintf ("Duplicate move detected for %s, please tell programmers!\n", ent->classname);
        !           500:        ent->lastMoveTime = level.time;
        !           501:        // FIXME
        !           502: 
        !           503:                        return true;
        !           504:                }
        !           505:                VectorCopy (oldorg, ent->s.origin);
        !           506:                return false;
        !           507:        }
        !           508: 
        !           509:        if ( ent->flags & FL_PARTIALGROUND )
        !           510:        {
        !           511:                ent->flags &= ~FL_PARTIALGROUND;
        !           512:        }
        !           513:        ent->groundentity = trace.ent;
        !           514:        ent->groundentity_linkcount = trace.ent->linkcount;
        !           515: 
        !           516: // the move is ok
        !           517:        if (relink)
        !           518:        {
        !           519:                gi.linkentity (ent);
        !           520:                G_TouchTriggers (ent);
        !           521:        }
        !           522:        // FIXME - remove this when ready!!!
        !           523:        if (ent->lastMoveTime == level.time)
        !           524:                if ((g_showlogic) && (g_showlogic->value))
        !           525:                        gi.dprintf ("Duplicate move detected for %s, please tell programmers!\n", ent->classname);
        !           526:        ent->lastMoveTime = level.time;
        !           527:        // FIXME
        !           528: 
        !           529:        return true;
        !           530: }
        !           531: 
        !           532: 
        !           533: //============================================================================
        !           534: 
        !           535: /*
        !           536: ===============
        !           537: M_ChangeYaw
        !           538: 
        !           539: ===============
        !           540: */
        !           541: void M_ChangeYaw (edict_t *ent)
        !           542: {
        !           543:        float   ideal;
        !           544:        float   current;
        !           545:        float   move;
        !           546:        float   speed;
        !           547:        
        !           548:        current = anglemod(ent->s.angles[YAW]);
        !           549:        ideal = ent->ideal_yaw;
        !           550: 
        !           551:        if (current == ideal)
        !           552:                return;
        !           553: 
        !           554:        move = ideal - current;
        !           555:        speed = ent->yaw_speed;
        !           556:        if (ideal > current)
        !           557:        {
        !           558:                if (move >= 180)
        !           559:                        move = move - 360;
        !           560:        }
        !           561:        else
        !           562:        {
        !           563:                if (move <= -180)
        !           564:                        move = move + 360;
        !           565:        }
        !           566:        if (move > 0)
        !           567:        {
        !           568:                if (move > speed)
        !           569:                        move = speed;
        !           570:        }
        !           571:        else
        !           572:        {
        !           573:                if (move < -speed)
        !           574:                        move = -speed;
        !           575:        }
        !           576:        
        !           577:        ent->s.angles[YAW] = anglemod (current + move);
        !           578: }
        !           579: 
        !           580: 
        !           581: /*
        !           582: ======================
        !           583: SV_StepDirection
        !           584: 
        !           585: Turns to the movement direction, and walks the current distance if
        !           586: facing it.
        !           587: 
        !           588: ======================
        !           589: */
        !           590: qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
        !           591: {
        !           592:        vec3_t          move, oldorigin;
        !           593:        float           delta;
        !           594:        
        !           595:        if(!ent->inuse) return true;            // PGM g_touchtrigger free problem
        !           596: 
        !           597:        ent->ideal_yaw = yaw;
        !           598:        M_ChangeYaw (ent);
        !           599:        
        !           600:        yaw = yaw*M_PI*2 / 360;
        !           601:        move[0] = cos(yaw)*dist;
        !           602:        move[1] = sin(yaw)*dist;
        !           603:        move[2] = 0;
        !           604: 
        !           605:        VectorCopy (ent->s.origin, oldorigin);
        !           606:        if (SV_movestep (ent, move, false))
        !           607:        {
        !           608:                ent->monsterinfo.aiflags &= ~AI_BLOCKED;
        !           609:                if(!ent->inuse) return true;            // PGM g_touchtrigger free problem
        !           610: 
        !           611:                delta = ent->s.angles[YAW] - ent->ideal_yaw;
        !           612:                if (strncmp(ent->classname, "monster_widow", 13))
        !           613:                {
        !           614:                        if (delta > 45 && delta < 315)
        !           615:                        {               // not turned far enough, so don't take the step
        !           616:                                VectorCopy (oldorigin, ent->s.origin);
        !           617:                        }
        !           618:                }
        !           619:                gi.linkentity (ent);
        !           620:                G_TouchTriggers (ent);
        !           621:                return true;
        !           622:        }
        !           623:        gi.linkentity (ent);
        !           624:        G_TouchTriggers (ent);
        !           625:        return false;
        !           626: }
        !           627: 
        !           628: /*
        !           629: ======================
        !           630: SV_FixCheckBottom
        !           631: 
        !           632: ======================
        !           633: */
        !           634: void SV_FixCheckBottom (edict_t *ent)
        !           635: {
        !           636:        ent->flags |= FL_PARTIALGROUND;
        !           637: }
        !           638: 
        !           639: 
        !           640: 
        !           641: /*
        !           642: ================
        !           643: SV_NewChaseDir
        !           644: 
        !           645: ================
        !           646: */
        !           647: #define        DI_NODIR        -1
        !           648: void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
        !           649: {
        !           650:        float   deltax,deltay;
        !           651:        float   d[3];
        !           652:        float   tdir, olddir, turnaround;
        !           653: 
        !           654:        //FIXME: how did we get here with no enemy
        !           655:        if (!enemy)
        !           656:                return;
        !           657: 
        !           658:        olddir = anglemod( (int)(actor->ideal_yaw/45)*45 );
        !           659:        turnaround = anglemod(olddir - 180);
        !           660: 
        !           661:        deltax = enemy->s.origin[0] - actor->s.origin[0];
        !           662:        deltay = enemy->s.origin[1] - actor->s.origin[1];
        !           663:        if (deltax>10)
        !           664:                d[1]= 0;
        !           665:        else if (deltax<-10)
        !           666:                d[1]= 180;
        !           667:        else
        !           668:                d[1]= DI_NODIR;
        !           669:        if (deltay<-10)
        !           670:                d[2]= 270;
        !           671:        else if (deltay>10)
        !           672:                d[2]= 90;
        !           673:        else
        !           674:                d[2]= DI_NODIR;
        !           675: 
        !           676: // try direct route
        !           677:        if (d[1] != DI_NODIR && d[2] != DI_NODIR)
        !           678:        {
        !           679:                if (d[1] == 0)
        !           680:                        tdir = d[2] == 90 ? 45 : 315;
        !           681:                else
        !           682:                        tdir = d[2] == 90 ? 135 : 215;
        !           683:                        
        !           684:                if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
        !           685:                        return;
        !           686:        }
        !           687: 
        !           688: // try other directions
        !           689:        if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
        !           690:        {
        !           691:                tdir=d[1];
        !           692:                d[1]=d[2];
        !           693:                d[2]=tdir;
        !           694:        }
        !           695: 
        !           696:        if (d[1]!=DI_NODIR && d[1]!=turnaround 
        !           697:        && SV_StepDirection(actor, d[1], dist))
        !           698:                        return;
        !           699: 
        !           700:        if (d[2]!=DI_NODIR && d[2]!=turnaround
        !           701:        && SV_StepDirection(actor, d[2], dist))
        !           702:                        return;
        !           703: 
        !           704: //ROGUE
        !           705:        if(actor->monsterinfo.blocked)
        !           706:        {
        !           707:                if ((actor->inuse) && (actor->health > 0))
        !           708:                {
        !           709:                        if((actor->monsterinfo.blocked)(actor, dist))
        !           710:                                return;
        !           711:                }
        !           712:        }
        !           713: //ROGUE
        !           714: 
        !           715: /* there is no direct path to the player, so pick another direction */
        !           716: 
        !           717:        if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
        !           718:                        return;
        !           719: 
        !           720:        if (rand()&1)   /*randomly determine direction of search*/
        !           721:        {
        !           722:                for (tdir=0 ; tdir<=315 ; tdir += 45)
        !           723:                        if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
        !           724:                                        return;
        !           725:        }
        !           726:        else
        !           727:        {
        !           728:                for (tdir=315 ; tdir >=0 ; tdir -= 45)
        !           729:                        if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
        !           730:                                        return;
        !           731:        }
        !           732: 
        !           733:        if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
        !           734:                        return;
        !           735: 
        !           736:        actor->ideal_yaw = olddir;              // can't move
        !           737: 
        !           738: // if a bridge was pulled out from underneath a monster, it may not have
        !           739: // a valid standing position at all
        !           740: 
        !           741:        if (!M_CheckBottom (actor))
        !           742:                SV_FixCheckBottom (actor);
        !           743: }
        !           744: 
        !           745: /*
        !           746: ======================
        !           747: SV_CloseEnough
        !           748: 
        !           749: ======================
        !           750: */
        !           751: qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
        !           752: {
        !           753:        int             i;
        !           754:        
        !           755:        for (i=0 ; i<3 ; i++)
        !           756:        {
        !           757:                if (goal->absmin[i] > ent->absmax[i] + dist)
        !           758:                        return false;
        !           759:                if (goal->absmax[i] < ent->absmin[i] - dist)
        !           760:                        return false;
        !           761:        }
        !           762:        return true;
        !           763: }
        !           764: 
        !           765: /*
        !           766: ======================
        !           767: M_MoveToGoal
        !           768: ======================
        !           769: */
        !           770: void M_MoveToGoal (edict_t *ent, float dist)
        !           771: {
        !           772:        edict_t         *goal;
        !           773:        
        !           774:        goal = ent->goalentity;
        !           775: 
        !           776:        if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
        !           777:                return;
        !           778: 
        !           779: // if the next step hits the enemy, return immediately
        !           780:        if (ent->enemy &&  SV_CloseEnough (ent, ent->enemy, dist) )
        !           781:                return;
        !           782: 
        !           783: // bump around...
        !           784: //     if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist))
        !           785: // PMM - charging monsters (AI_CHARGING) don't deflect unless they have to
        !           786:        if ( (((rand()&3)==1) && !(ent->monsterinfo.aiflags & AI_CHARGING)) || !SV_StepDirection (ent, ent->ideal_yaw, dist))
        !           787:        {
        !           788:                if (ent->monsterinfo.aiflags & AI_BLOCKED)
        !           789:                {
        !           790:                        if ((g_showlogic) && (g_showlogic->value))
        !           791:                                gi.dprintf ("tesla attack detected, not changing direction!\n");
        !           792:                        ent->monsterinfo.aiflags &= ~AI_BLOCKED;
        !           793:                        return;
        !           794:                }
        !           795:                if (ent->inuse)
        !           796:                        SV_NewChaseDir (ent, goal, dist);
        !           797:        }
        !           798: }
        !           799: 
        !           800: 
        !           801: /*
        !           802: ===============
        !           803: M_walkmove
        !           804: ===============
        !           805: */
        !           806: qboolean M_walkmove (edict_t *ent, float yaw, float dist)
        !           807: {
        !           808:        vec3_t  move;
        !           809:        // PMM
        !           810:        qboolean        retval;
        !           811:        
        !           812:        if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
        !           813:                return false;
        !           814: 
        !           815:        yaw = yaw*M_PI*2 / 360;
        !           816:        
        !           817:        move[0] = cos(yaw)*dist;
        !           818:        move[1] = sin(yaw)*dist;
        !           819:        move[2] = 0;
        !           820: 
        !           821:        // PMM
        !           822:        retval = SV_movestep(ent, move, true);
        !           823:        ent->monsterinfo.aiflags &= ~AI_BLOCKED;
        !           824:        return retval;
        !           825:        // pmm
        !           826:        //return SV_movestep(ent, move, true);
        !           827: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.