Annotation of quake2/rogue/m_move.c, revision 1.1.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.