Annotation of quake2/game/m_tank.c, revision 1.1.1.1

1.1       root        1: /*
                      2: ==============================================================================
                      3: 
                      4: TANK
                      5: 
                      6: ==============================================================================
                      7: */
                      8: 
                      9: #include "g_local.h"
                     10: #include "m_tank.h"
                     11: 
                     12: 
                     13: void tank_refire_rocket (edict_t *self);
                     14: void tank_doattack_rocket (edict_t *self);
                     15: void tank_reattack_blaster (edict_t *self);
                     16: 
                     17: static int     sound_thud;
                     18: static int     sound_pain;
                     19: static int     sound_idle;
                     20: static int     sound_die;
                     21: static int     sound_step;
                     22: static int     sound_sight;
                     23: static int     sound_windup;
                     24: static int     sound_strike;
                     25: 
                     26: //
                     27: // misc
                     28: //
                     29: 
                     30: void tank_sight (edict_t *self, edict_t *other)
                     31: {
                     32:        gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
                     33: }
                     34: 
                     35: 
                     36: void tank_footstep (edict_t *self)
                     37: {
                     38:        gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
                     39: }
                     40: 
                     41: void tank_thud (edict_t *self)
                     42: {
                     43:        gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0);
                     44: }
                     45: 
                     46: void tank_windup (edict_t *self)
                     47: {
                     48:        gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0);
                     49: }
                     50: 
                     51: void tank_idle (edict_t *self)
                     52: {
                     53:        gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
                     54: }
                     55: 
                     56: 
                     57: //
                     58: // stand
                     59: //
                     60: 
                     61: mframe_t tank_frames_stand []=
                     62: {
                     63:        ai_stand, 0, NULL,
                     64:        ai_stand, 0, NULL,
                     65:        ai_stand, 0, NULL,
                     66:        ai_stand, 0, NULL,
                     67:        ai_stand, 0, NULL,
                     68:        ai_stand, 0, NULL,
                     69:        ai_stand, 0, NULL,
                     70:        ai_stand, 0, NULL,
                     71:        ai_stand, 0, NULL,
                     72:        ai_stand, 0, NULL,
                     73:        ai_stand, 0, NULL,
                     74:        ai_stand, 0, NULL,
                     75:        ai_stand, 0, NULL,
                     76:        ai_stand, 0, NULL,
                     77:        ai_stand, 0, NULL,
                     78:        ai_stand, 0, NULL,
                     79:        ai_stand, 0, NULL,
                     80:        ai_stand, 0, NULL,
                     81:        ai_stand, 0, NULL,
                     82:        ai_stand, 0, NULL,
                     83:        ai_stand, 0, NULL,
                     84:        ai_stand, 0, NULL,
                     85:        ai_stand, 0, NULL,
                     86:        ai_stand, 0, NULL,
                     87:        ai_stand, 0, NULL,
                     88:        ai_stand, 0, NULL,
                     89:        ai_stand, 0, NULL,
                     90:        ai_stand, 0, NULL,
                     91:        ai_stand, 0, NULL,
                     92:        ai_stand, 0, NULL
                     93: };
                     94: mmove_t        tank_move_stand = {FRAME_stand01, FRAME_stand30, tank_frames_stand, NULL};
                     95:        
                     96: void tank_stand (edict_t *self)
                     97: {
                     98:        self->monsterinfo.currentmove = &tank_move_stand;
                     99: }
                    100: 
                    101: 
                    102: //
                    103: // walk
                    104: //
                    105: 
                    106: void tank_walk (edict_t *self);
                    107: 
                    108: mframe_t tank_frames_start_walk [] =
                    109: {
                    110:        ai_walk,  0, NULL,
                    111:        ai_walk,  6, NULL,
                    112:        ai_walk,  6, NULL,
                    113:        ai_walk, 11, tank_footstep
                    114: };
                    115: mmove_t        tank_move_start_walk = {FRAME_walk01, FRAME_walk04, tank_frames_start_walk, tank_walk};
                    116: 
                    117: mframe_t tank_frames_walk [] =
                    118: {
                    119:        ai_walk, 4,     NULL,
                    120:        ai_walk, 5,     NULL,
                    121:        ai_walk, 3,     NULL,
                    122:        ai_walk, 2,     NULL,
                    123:        ai_walk, 5,     NULL,
                    124:        ai_walk, 5,     NULL,
                    125:        ai_walk, 4,     NULL,
                    126:        ai_walk, 4,     tank_footstep,
                    127:        ai_walk, 3,     NULL,
                    128:        ai_walk, 5,     NULL,
                    129:        ai_walk, 4,     NULL,
                    130:        ai_walk, 5,     NULL,
                    131:        ai_walk, 7,     NULL,
                    132:        ai_walk, 7,     NULL,
                    133:        ai_walk, 6,     NULL,
                    134:        ai_walk, 6,     tank_footstep
                    135: };
                    136: mmove_t        tank_move_walk = {FRAME_walk05, FRAME_walk20, tank_frames_walk, NULL};
                    137: 
                    138: mframe_t tank_frames_stop_walk [] =
                    139: {
                    140:        ai_walk,  3, NULL,
                    141:        ai_walk,  3, NULL,
                    142:        ai_walk,  2, NULL,
                    143:        ai_walk,  2, NULL,
                    144:        ai_walk,  4, tank_footstep
                    145: };
                    146: mmove_t        tank_move_stop_walk = {FRAME_walk21, FRAME_walk25, tank_frames_stop_walk, tank_stand};
                    147: 
                    148: void tank_walk (edict_t *self)
                    149: {
                    150:                self->monsterinfo.currentmove = &tank_move_walk;
                    151: }
                    152: 
                    153: 
                    154: //
                    155: // run
                    156: //
                    157: 
                    158: void tank_run (edict_t *self);
                    159: 
                    160: mframe_t tank_frames_start_run [] =
                    161: {
                    162:        ai_run,  0, NULL,
                    163:        ai_run,  6, NULL,
                    164:        ai_run,  6, NULL,
                    165:        ai_run, 11, tank_footstep
                    166: };
                    167: mmove_t        tank_move_start_run = {FRAME_walk01, FRAME_walk04, tank_frames_start_run, tank_run};
                    168: 
                    169: mframe_t tank_frames_run [] =
                    170: {
                    171:        ai_run, 4,      NULL,
                    172:        ai_run, 5,      NULL,
                    173:        ai_run, 3,      NULL,
                    174:        ai_run, 2,      NULL,
                    175:        ai_run, 5,      NULL,
                    176:        ai_run, 5,      NULL,
                    177:        ai_run, 4,      NULL,
                    178:        ai_run, 4,      tank_footstep,
                    179:        ai_run, 3,      NULL,
                    180:        ai_run, 5,      NULL,
                    181:        ai_run, 4,      NULL,
                    182:        ai_run, 5,      NULL,
                    183:        ai_run, 7,      NULL,
                    184:        ai_run, 7,      NULL,
                    185:        ai_run, 6,      NULL,
                    186:        ai_run, 6,      tank_footstep
                    187: };
                    188: mmove_t        tank_move_run = {FRAME_walk05, FRAME_walk20, tank_frames_run, NULL};
                    189: 
                    190: mframe_t tank_frames_stop_run [] =
                    191: {
                    192:        ai_run,  3, NULL,
                    193:        ai_run,  3, NULL,
                    194:        ai_run,  2, NULL,
                    195:        ai_run,  2, NULL,
                    196:        ai_run,  4, tank_footstep
                    197: };
                    198: mmove_t        tank_move_stop_run = {FRAME_walk21, FRAME_walk25, tank_frames_stop_run, tank_walk};
                    199: 
                    200: void tank_run (edict_t *self)
                    201: {
                    202:        if (self->enemy && self->enemy->client)
                    203:                self->monsterinfo.aiflags |= AI_BRUTAL;
                    204:        else
                    205:                self->monsterinfo.aiflags &= ~AI_BRUTAL;
                    206: 
                    207:        if (self->monsterinfo.aiflags & AI_STAND_GROUND)
                    208:        {
                    209:                self->monsterinfo.currentmove = &tank_move_stand;
                    210:                return;
                    211:        }
                    212: 
                    213:        if (self->monsterinfo.currentmove == &tank_move_walk ||
                    214:                self->monsterinfo.currentmove == &tank_move_start_run)
                    215:        {
                    216:                self->monsterinfo.currentmove = &tank_move_run;
                    217:        }
                    218:        else
                    219:        {
                    220:                self->monsterinfo.currentmove = &tank_move_start_run;
                    221:        }
                    222: }
                    223: 
                    224: //
                    225: // pain
                    226: //
                    227: 
                    228: mframe_t tank_frames_pain1 [] =
                    229: {
                    230:        ai_move, 0, NULL,
                    231:        ai_move, 0, NULL,
                    232:        ai_move, 0, NULL,
                    233:        ai_move, 0, NULL
                    234: };
                    235: mmove_t tank_move_pain1 = {FRAME_pain101, FRAME_pain104, tank_frames_pain1, tank_run};
                    236: 
                    237: mframe_t tank_frames_pain2 [] =
                    238: {
                    239:        ai_move, 0, NULL,
                    240:        ai_move, 0, NULL,
                    241:        ai_move, 0, NULL,
                    242:        ai_move, 0, NULL,
                    243:        ai_move, 0, NULL
                    244: };
                    245: mmove_t tank_move_pain2 = {FRAME_pain201, FRAME_pain205, tank_frames_pain2, tank_run};
                    246: 
                    247: mframe_t tank_frames_pain3 [] =
                    248: {
                    249:        ai_move, -7, NULL,
                    250:        ai_move, 0,  NULL,
                    251:        ai_move, 0,  NULL,
                    252:        ai_move, 0,  NULL,
                    253:        ai_move, 2,  NULL,
                    254:        ai_move, 0,  NULL,
                    255:        ai_move, 0,  NULL,
                    256:        ai_move, 3,  NULL,
                    257:        ai_move, 0,  NULL,
                    258:        ai_move, 2,  NULL,
                    259:        ai_move, 0,  NULL,
                    260:        ai_move, 0,  NULL,
                    261:        ai_move, 0,  NULL,
                    262:        ai_move, 0,  NULL,
                    263:        ai_move, 0,  NULL,
                    264:        ai_move, 0,  tank_footstep
                    265: };
                    266: mmove_t        tank_move_pain3 = {FRAME_pain301, FRAME_pain316, tank_frames_pain3, tank_run};
                    267: 
                    268: 
                    269: void tank_pain (edict_t *self, edict_t *other, float kick, int damage)
                    270: {
                    271:        if (self->health < (self->max_health / 2))
                    272:                        self->s.skinnum |= 1;
                    273: 
                    274:        if (damage <= 10)
                    275:                return;
                    276: 
                    277:        if (level.time < self->pain_debounce_time)
                    278:                        return;
                    279: 
                    280:        if (damage <= 30)
                    281:                if (random() > 0.2)
                    282:                        return;
                    283:        
                    284:        // If hard or nightmare, don't go into pain while attacking
                    285:        if ( skill->value >= 2)
                    286:        {
                    287:                if ( (self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330) )
                    288:                        return;
                    289:                if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116) )
                    290:                        return;
                    291:        }
                    292: 
                    293:        self->pain_debounce_time = level.time + 3;
                    294:        gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
                    295: 
                    296:        if (skill->value == 3)
                    297:                return;         // no pain anims in nightmare
                    298: 
                    299:        if (damage <= 30)
                    300:                self->monsterinfo.currentmove = &tank_move_pain1;
                    301:        else if (damage <= 60)
                    302:                self->monsterinfo.currentmove = &tank_move_pain2;
                    303:        else
                    304:                self->monsterinfo.currentmove = &tank_move_pain3;
                    305: };
                    306: 
                    307: 
                    308: //
                    309: // attacks
                    310: //
                    311: 
                    312: void TankBlaster (edict_t *self)
                    313: {
                    314:        vec3_t  forward, right;
                    315:        vec3_t  start;
                    316:        vec3_t  end;
                    317:        vec3_t  dir;
                    318:        int             flash_number;
                    319: 
                    320:        if (self->s.frame == FRAME_attak110)
                    321:                flash_number = MZ2_TANK_BLASTER_1;
                    322:        else if (self->s.frame == FRAME_attak113)
                    323:                flash_number = MZ2_TANK_BLASTER_2;
                    324:        else // (self->s.frame == FRAME_attak116)
                    325:                flash_number = MZ2_TANK_BLASTER_3;
                    326: 
                    327:        AngleVectors (self->s.angles, forward, right, NULL);
                    328:        G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
                    329: 
                    330:        VectorCopy (self->enemy->s.origin, end);
                    331:        end[2] += self->enemy->viewheight;
                    332:        VectorSubtract (end, start, dir);
                    333: 
                    334:        monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER);
                    335: }      
                    336: 
                    337: void TankStrike (edict_t *self)
                    338: {
                    339:        gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0);
                    340: }      
                    341: 
                    342: void TankRocket (edict_t *self)
                    343: {
                    344:        vec3_t  forward, right;
                    345:        vec3_t  start;
                    346:        vec3_t  dir;
                    347:        vec3_t  vec;
                    348:        int             flash_number;
                    349: 
                    350:        if (self->s.frame == FRAME_attak324)
                    351:                flash_number = MZ2_TANK_ROCKET_1;
                    352:        else if (self->s.frame == FRAME_attak327)
                    353:                flash_number = MZ2_TANK_ROCKET_2;
                    354:        else // (self->s.frame == FRAME_attak330)
                    355:                flash_number = MZ2_TANK_ROCKET_3;
                    356: 
                    357:        AngleVectors (self->s.angles, forward, right, NULL);
                    358:        G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
                    359: 
                    360:        VectorCopy (self->enemy->s.origin, vec);
                    361:        vec[2] += self->enemy->viewheight;
                    362:        VectorSubtract (vec, start, dir);
                    363:        VectorNormalize (dir);
                    364: 
                    365:        monster_fire_rocket (self, start, dir, 50, 550, flash_number);
                    366: }      
                    367: 
                    368: void TankMachineGun (edict_t *self)
                    369: {
                    370:        vec3_t  dir;
                    371:        vec3_t  vec;
                    372:        vec3_t  start;
                    373:        vec3_t  forward, right;
                    374:        int             flash_number;
                    375: 
                    376:        flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406);
                    377: 
                    378:        AngleVectors (self->s.angles, forward, right, NULL);
                    379:        G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
                    380: 
                    381:        if (self->enemy)
                    382:        {
                    383:                VectorCopy (self->enemy->s.origin, vec);
                    384:                vec[2] += self->enemy->viewheight;
                    385:                VectorSubtract (vec, start, vec);
                    386:                vectoangles (vec, vec);
                    387:                dir[0] = vec[0];
                    388:        }
                    389:        else
                    390:        {
                    391:                dir[0] = 0;
                    392:        }
                    393:        if (self->s.frame <= FRAME_attak415)
                    394:                dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411);
                    395:        else
                    396:                dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419);
                    397:        dir[2] = 0;
                    398: 
                    399:        AngleVectors (dir, forward, NULL, NULL);
                    400: 
                    401:        monster_fire_bullet (self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
                    402: }      
                    403: 
                    404: 
                    405: mframe_t tank_frames_attack_blast [] =
                    406: {
                    407:        ai_charge, 0,   NULL,
                    408:        ai_charge, 0,   NULL,
                    409:        ai_charge, 0,   NULL,
                    410:        ai_charge, 0,   NULL,
                    411:        ai_charge, -1,  NULL,
                    412:        ai_charge, -2,  NULL,
                    413:        ai_charge, -1,  NULL,
                    414:        ai_charge, -1,  NULL,
                    415:        ai_charge, 0,   NULL,
                    416:        ai_charge, 0,   TankBlaster,            // 10
                    417:        ai_charge, 0,   NULL,
                    418:        ai_charge, 0,   NULL,
                    419:        ai_charge, 0,   TankBlaster,
                    420:        ai_charge, 0,   NULL,
                    421:        ai_charge, 0,   NULL,
                    422:        ai_charge, 0,   TankBlaster                     // 16
                    423: };
                    424: mmove_t tank_move_attack_blast = {FRAME_attak101, FRAME_attak116, tank_frames_attack_blast, tank_reattack_blaster};
                    425: 
                    426: mframe_t tank_frames_reattack_blast [] =
                    427: {
                    428:        ai_charge, 0,   NULL,
                    429:        ai_charge, 0,   NULL,
                    430:        ai_charge, 0,   TankBlaster,
                    431:        ai_charge, 0,   NULL,
                    432:        ai_charge, 0,   NULL,
                    433:        ai_charge, 0,   TankBlaster                     // 16
                    434: };
                    435: mmove_t tank_move_reattack_blast = {FRAME_attak111, FRAME_attak116, tank_frames_reattack_blast, tank_reattack_blaster};
                    436: 
                    437: mframe_t tank_frames_attack_post_blast [] =    
                    438: {
                    439:        ai_move, 0,             NULL,                           // 17
                    440:        ai_move, 0,             NULL,
                    441:        ai_move, 2,             NULL,
                    442:        ai_move, 3,             NULL,
                    443:        ai_move, 2,             NULL,
                    444:        ai_move, -2,    tank_footstep           // 22
                    445: };
                    446: mmove_t tank_move_attack_post_blast = {FRAME_attak117, FRAME_attak122, tank_frames_attack_post_blast, tank_run};
                    447: 
                    448: void tank_reattack_blaster (edict_t *self)
                    449: {
                    450:        if (skill->value >= 2)
                    451:                if (visible (self, self->enemy))
                    452:                        if (self->enemy->health > 0)
                    453:                                if (random() <= 0.6)
                    454:                                {
                    455:                                        self->monsterinfo.currentmove = &tank_move_reattack_blast;
                    456:                                        return;
                    457:                                }
                    458:        self->monsterinfo.currentmove = &tank_move_attack_post_blast;
                    459: }
                    460: 
                    461: 
                    462: void tank_poststrike (edict_t *self)
                    463: {
                    464:        self->enemy = NULL;
                    465:        tank_run (self);
                    466: }
                    467: 
                    468: mframe_t tank_frames_attack_strike [] =
                    469: {
                    470:        ai_move, 3,   NULL,
                    471:        ai_move, 2,   NULL,
                    472:        ai_move, 2,   NULL,
                    473:        ai_move, 1,   NULL,
                    474:        ai_move, 6,   NULL,
                    475:        ai_move, 7,   NULL,
                    476:        ai_move, 9,   tank_footstep,
                    477:        ai_move, 2,   NULL,
                    478:        ai_move, 1,   NULL,
                    479:        ai_move, 2,   NULL,
                    480:        ai_move, 2,   tank_footstep,
                    481:        ai_move, 2,   NULL,
                    482:        ai_move, 0,   NULL,
                    483:        ai_move, 0,   NULL,
                    484:        ai_move, 0,   NULL,
                    485:        ai_move, 0,   NULL,
                    486:        ai_move, -2,  NULL,
                    487:        ai_move, -2,  NULL,
                    488:        ai_move, 0,   tank_windup,
                    489:        ai_move, 0,   NULL,
                    490:        ai_move, 0,   NULL,
                    491:        ai_move, 0,   NULL,
                    492:        ai_move, 0,   NULL,
                    493:        ai_move, 0,   NULL,
                    494:        ai_move, 0,   NULL,
                    495:        ai_move, 0,   TankStrike,
                    496:        ai_move, 0,   NULL,
                    497:        ai_move, -1,  NULL,
                    498:        ai_move, -1,  NULL,
                    499:        ai_move, -1,  NULL,
                    500:        ai_move, -1,  NULL,
                    501:        ai_move, -1,  NULL,
                    502:        ai_move, -3,  NULL,
                    503:        ai_move, -10, NULL,
                    504:        ai_move, -10, NULL,
                    505:        ai_move, -2,  NULL,
                    506:        ai_move, -3,  NULL,
                    507:        ai_move, -2,  tank_footstep
                    508: };
                    509: mmove_t tank_move_attack_strike = {FRAME_attak201, FRAME_attak238, tank_frames_attack_strike, tank_poststrike};
                    510: 
                    511: mframe_t tank_frames_attack_pre_rocket [] =
                    512: {
                    513:        ai_charge, 0,  NULL,
                    514:        ai_charge, 0,  NULL,
                    515:        ai_charge, 0,  NULL,
                    516:        ai_charge, 0,  NULL,
                    517:        ai_charge, 0,  NULL,
                    518:        ai_charge, 0,  NULL,
                    519:        ai_charge, 0,  NULL,
                    520:        ai_charge, 0,  NULL,
                    521:        ai_charge, 0,  NULL,
                    522:        ai_charge, 0,  NULL,                    // 10
                    523: 
                    524:        ai_charge, 0,  NULL,
                    525:        ai_charge, 1,  NULL,
                    526:        ai_charge, 2,  NULL,
                    527:        ai_charge, 7,  NULL,
                    528:        ai_charge, 7,  NULL,
                    529:        ai_charge, 7,  tank_footstep,
                    530:        ai_charge, 0,  NULL,
                    531:        ai_charge, 0,  NULL,
                    532:        ai_charge, 0,  NULL,
                    533:        ai_charge, 0,  NULL,                    // 20
                    534: 
                    535:        ai_charge, -3, NULL
                    536: };
                    537: mmove_t tank_move_attack_pre_rocket = {FRAME_attak301, FRAME_attak321, tank_frames_attack_pre_rocket, tank_doattack_rocket};
                    538: 
                    539: mframe_t tank_frames_attack_fire_rocket [] =
                    540: {
                    541:        ai_charge, -3, NULL,                    // Loop Start   22 
                    542:        ai_charge, 0,  NULL,
                    543:        ai_charge, 0,  TankRocket,              // 24
                    544:        ai_charge, 0,  NULL,
                    545:        ai_charge, 0,  NULL,
                    546:        ai_charge, 0,  TankRocket,
                    547:        ai_charge, 0,  NULL,
                    548:        ai_charge, 0,  NULL,
                    549:        ai_charge, -1, TankRocket               // 30   Loop End
                    550: };
                    551: mmove_t tank_move_attack_fire_rocket = {FRAME_attak322, FRAME_attak330, tank_frames_attack_fire_rocket, tank_refire_rocket};
                    552: 
                    553: mframe_t tank_frames_attack_post_rocket [] =
                    554: {      
                    555:        ai_charge, 0,  NULL,                    // 31
                    556:        ai_charge, -1, NULL,
                    557:        ai_charge, -1, NULL,
                    558:        ai_charge, 0,  NULL,
                    559:        ai_charge, 2,  NULL,
                    560:        ai_charge, 3,  NULL,
                    561:        ai_charge, 4,  NULL,
                    562:        ai_charge, 2,  NULL,
                    563:        ai_charge, 0,  NULL,
                    564:        ai_charge, 0,  NULL,                    // 40
                    565: 
                    566:        ai_charge, 0,  NULL,
                    567:        ai_charge, -9, NULL,
                    568:        ai_charge, -8, NULL,
                    569:        ai_charge, -7, NULL,
                    570:        ai_charge, -1, NULL,
                    571:        ai_charge, -1, tank_footstep,
                    572:        ai_charge, 0,  NULL,
                    573:        ai_charge, 0,  NULL,
                    574:        ai_charge, 0,  NULL,
                    575:        ai_charge, 0,  NULL,                    // 50
                    576: 
                    577:        ai_charge, 0,  NULL,
                    578:        ai_charge, 0,  NULL,
                    579:        ai_charge, 0,  NULL
                    580: };
                    581: mmove_t tank_move_attack_post_rocket = {FRAME_attak331, FRAME_attak353, tank_frames_attack_post_rocket, tank_run};
                    582: 
                    583: mframe_t tank_frames_attack_chain [] =
                    584: {
                    585:        ai_charge, 0, NULL,
                    586:        ai_charge, 0, NULL,
                    587:        ai_charge, 0, NULL,
                    588:        ai_charge, 0, NULL,
                    589:        ai_charge, 0, NULL,
                    590:        NULL,      0, TankMachineGun,
                    591:        NULL,      0, TankMachineGun,
                    592:        NULL,      0, TankMachineGun,
                    593:        NULL,      0, TankMachineGun,
                    594:        NULL,      0, TankMachineGun,
                    595:        NULL,      0, TankMachineGun,
                    596:        NULL,      0, TankMachineGun,
                    597:        NULL,      0, TankMachineGun,
                    598:        NULL,      0, TankMachineGun,
                    599:        NULL,      0, TankMachineGun,
                    600:        NULL,      0, TankMachineGun,
                    601:        NULL,      0, TankMachineGun,
                    602:        NULL,      0, TankMachineGun,
                    603:        NULL,      0, TankMachineGun,
                    604:        NULL,      0, TankMachineGun,
                    605:        NULL,      0, TankMachineGun,
                    606:        NULL,      0, TankMachineGun,
                    607:        NULL,      0, TankMachineGun,
                    608:        NULL,      0, TankMachineGun,
                    609:        ai_charge, 0, NULL,
                    610:        ai_charge, 0, NULL,
                    611:        ai_charge, 0, NULL,
                    612:        ai_charge, 0, NULL,
                    613:        ai_charge, 0, NULL
                    614: };
                    615: mmove_t tank_move_attack_chain = {FRAME_attak401, FRAME_attak429, tank_frames_attack_chain, tank_run};
                    616: 
                    617: void tank_refire_rocket (edict_t *self)
                    618: {
                    619:        // Only on hard or nightmare
                    620:        if ( skill->value >= 2 )
                    621:                if (self->enemy->health > 0)
                    622:                        if (visible(self, self->enemy) )
                    623:                                if (random() <= 0.4)
                    624:                                {
                    625:                                        self->monsterinfo.currentmove = &tank_move_attack_fire_rocket;
                    626:                                        return;
                    627:                                }
                    628:        self->monsterinfo.currentmove = &tank_move_attack_post_rocket;
                    629: }
                    630: 
                    631: void tank_doattack_rocket (edict_t *self)
                    632: {
                    633:        self->monsterinfo.currentmove = &tank_move_attack_fire_rocket;
                    634: }
                    635: 
                    636: void tank_attack(edict_t *self)
                    637: {
                    638:        vec3_t  vec;
                    639:        float   range;
                    640:        float   r;
                    641: 
                    642:        if (self->enemy->health < 0)
                    643:        {
                    644:                self->monsterinfo.currentmove = &tank_move_attack_strike;
                    645:                self->monsterinfo.aiflags &= ~AI_BRUTAL;
                    646:                return;
                    647:        }
                    648: 
                    649:        VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
                    650:        range = VectorLength (vec);
                    651: 
                    652:        r = random();
                    653: 
                    654:        if (range <= 125)
                    655:        {
                    656:                if (r < 0.4)
                    657:                        self->monsterinfo.currentmove = &tank_move_attack_chain;
                    658:                else 
                    659:                        self->monsterinfo.currentmove = &tank_move_attack_blast;
                    660:        }
                    661:        else if (range <= 250)
                    662:        {
                    663:                if (r < 0.5)
                    664:                        self->monsterinfo.currentmove = &tank_move_attack_chain;
                    665:                else
                    666:                        self->monsterinfo.currentmove = &tank_move_attack_blast;
                    667:        }
                    668:        else
                    669:        {
                    670:                if (r < 0.33)
                    671:                        self->monsterinfo.currentmove = &tank_move_attack_chain;
                    672:                else if (r < 0.66)
                    673:                {
                    674:                        self->monsterinfo.currentmove = &tank_move_attack_pre_rocket;
                    675:                        self->pain_debounce_time = level.time + 5.0;    // no pain for a while
                    676:                }
                    677:                else
                    678:                        self->monsterinfo.currentmove = &tank_move_attack_blast;
                    679:        }
                    680: }
                    681: 
                    682: 
                    683: //
                    684: // death
                    685: //
                    686: 
                    687: void tank_dead (edict_t *self)
                    688: {
                    689:        VectorSet (self->mins, -16, -16, -16);
                    690:        VectorSet (self->maxs, 16, 16, -0);
                    691:        self->movetype = MOVETYPE_TOSS;
                    692:        self->svflags |= SVF_DEADMONSTER;
                    693:        self->nextthink = 0;
                    694:        gi.linkentity (self);
                    695: }
                    696: 
                    697: mframe_t tank_frames_death1 [] =
                    698: {
                    699:        ai_move, -7,  NULL,
                    700:        ai_move, -2,  NULL,
                    701:        ai_move, -2,  NULL,
                    702:        ai_move, 1,   NULL,
                    703:        ai_move, 3,   NULL,
                    704:        ai_move, 6,   NULL,
                    705:        ai_move, 1,   NULL,
                    706:        ai_move, 1,   NULL,
                    707:        ai_move, 2,   NULL,
                    708:        ai_move, 0,   NULL,
                    709:        ai_move, 0,   NULL,
                    710:        ai_move, 0,   NULL,
                    711:        ai_move, -2,  NULL,
                    712:        ai_move, 0,   NULL,
                    713:        ai_move, 0,   NULL,
                    714:        ai_move, -3,  NULL,
                    715:        ai_move, 0,   NULL,
                    716:        ai_move, 0,   NULL,
                    717:        ai_move, 0,   NULL,
                    718:        ai_move, 0,   NULL,
                    719:        ai_move, 0,   NULL,
                    720:        ai_move, 0,   NULL,
                    721:        ai_move, -4,  NULL,
                    722:        ai_move, -6,  NULL,
                    723:        ai_move, -4,  NULL,
                    724:        ai_move, -5,  NULL,
                    725:        ai_move, -7,  NULL,
                    726:        ai_move, -15, tank_thud,
                    727:        ai_move, -5,  NULL,
                    728:        ai_move, 0,   NULL,
                    729:        ai_move, 0,   NULL,
                    730:        ai_move, 0,   NULL
                    731: };
                    732: mmove_t        tank_move_death = {FRAME_death101, FRAME_death132, tank_frames_death1, tank_dead};
                    733: 
                    734: void tank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
                    735: {
                    736:        int             n;
                    737: 
                    738: // check for gib
                    739:        if (self->health <= self->gib_health)
                    740:        {
                    741:                gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
                    742:                for (n= 0; n < 1 /*4*/; n++)
                    743:                        ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
                    744:                for (n= 0; n < 4; n++)
                    745:                        ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
                    746:                ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
                    747:                ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
                    748:                self->deadflag = DEAD_DEAD;
                    749:                return;
                    750:        }
                    751: 
                    752:        if (self->deadflag == DEAD_DEAD)
                    753:                return;
                    754: 
                    755: // regular death
                    756:        gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
                    757:        self->deadflag = DEAD_DEAD;
                    758:        self->takedamage = DAMAGE_YES;
                    759: 
                    760:        self->monsterinfo.currentmove = &tank_move_death;
                    761:        
                    762: }
                    763: 
                    764: 
                    765: //
                    766: // monster_tank
                    767: //
                    768: 
                    769: /*QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
                    770: */
                    771: /*QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
                    772: */
                    773: void SP_monster_tank (edict_t *self)
                    774: {
                    775:        if (deathmatch->value)
                    776:        {
                    777:                G_FreeEdict (self);
                    778:                return;
                    779:        }
                    780: 
                    781:        self->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2");
                    782:        VectorSet (self->mins, -32, -32, -16);
                    783:        VectorSet (self->maxs, 32, 32, 72);
                    784:        self->movetype = MOVETYPE_STEP;
                    785:        self->solid = SOLID_BBOX;
                    786: 
                    787:        sound_pain = gi.soundindex ("tank/tnkpain2.wav");
                    788:        sound_thud = gi.soundindex ("tank/tnkdeth2.wav");
                    789:        sound_idle = gi.soundindex ("tank/tnkidle1.wav");
                    790:        sound_die = gi.soundindex ("tank/death.wav");
                    791:        sound_step = gi.soundindex ("tank/step.wav");
                    792:        sound_windup = gi.soundindex ("tank/tnkatck4.wav");
                    793:        sound_strike = gi.soundindex ("tank/tnkatck5.wav");
                    794:        sound_sight = gi.soundindex ("tank/sight1.wav");
                    795: 
                    796:        gi.soundindex ("tank/tnkatck1.wav");
                    797:        gi.soundindex ("tank/tnkatk2a.wav");
                    798:        gi.soundindex ("tank/tnkatk2b.wav");
                    799:        gi.soundindex ("tank/tnkatk2c.wav");
                    800:        gi.soundindex ("tank/tnkatk2d.wav");
                    801:        gi.soundindex ("tank/tnkatk2e.wav");
                    802:        gi.soundindex ("tank/tnkatck3.wav");
                    803: 
                    804:        if (strcmp(self->classname, "monster_tank_commander") == 0)
                    805:        {
                    806:                self->health = 1000;
                    807:                self->gib_health = -225;
                    808:        }
                    809:        else
                    810:        {
                    811:                self->health = 750;
                    812:                self->gib_health = -200;
                    813:        }
                    814: 
                    815:        self->mass = 500;
                    816: 
                    817:        self->pain = tank_pain;
                    818:        self->die = tank_die;
                    819:        self->monsterinfo.stand = tank_stand;
                    820:        self->monsterinfo.walk = tank_walk;
                    821:        self->monsterinfo.run = tank_run;
                    822:        self->monsterinfo.dodge = NULL;
                    823:        self->monsterinfo.attack = tank_attack;
                    824:        self->monsterinfo.melee = NULL;
                    825:        self->monsterinfo.sight = tank_sight;
                    826:        self->monsterinfo.idle = tank_idle;
                    827: 
                    828:        gi.linkentity (self);
                    829:        
                    830:        self->monsterinfo.currentmove = &tank_move_stand;
                    831:        self->monsterinfo.scale = MODEL_SCALE;
                    832: 
                    833:        walkmonster_start(self);
                    834: 
                    835:        if (strcmp(self->classname, "monster_tank_commander") == 0)
                    836:                self->s.skinnum = 2;
                    837: }

unix.superglobalmegacorp.com

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