Annotation of quake2/game/m_tank.c, revision 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.