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

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

unix.superglobalmegacorp.com

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