Annotation of quake2/rogue/m_chick.c, revision 1.1.1.1

1.1       root        1: /*
                      2: ==============================================================================
                      3: 
                      4: chick
                      5: 
                      6: ==============================================================================
                      7: */
                      8: 
                      9: #include "g_local.h"
                     10: #include "m_chick.h"
                     11: 
                     12: // ROGUE
                     13: #define LEAD_TARGET            1
                     14: // ROGUE
                     15: 
                     16: qboolean visible (edict_t *self, edict_t *other);
                     17: 
                     18: void chick_stand (edict_t *self);
                     19: void chick_run (edict_t *self);
                     20: void chick_reslash(edict_t *self);
                     21: void chick_rerocket(edict_t *self);
                     22: void chick_attack1(edict_t *self);
                     23: 
                     24: static int     sound_missile_prelaunch;
                     25: static int     sound_missile_launch;
                     26: static int     sound_melee_swing;
                     27: static int     sound_melee_hit;
                     28: static int     sound_missile_reload;
                     29: static int     sound_death1;
                     30: static int     sound_death2;
                     31: static int     sound_fall_down;
                     32: static int     sound_idle1;
                     33: static int     sound_idle2;
                     34: static int     sound_pain1;
                     35: static int     sound_pain2;
                     36: static int     sound_pain3;
                     37: static int     sound_sight;
                     38: static int     sound_search;
                     39: 
                     40: void ChickMoan (edict_t *self)
                     41: {
                     42:        if (random() < 0.5)
                     43:                gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);
                     44:        else
                     45:                gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0);
                     46: }
                     47: 
                     48: mframe_t chick_frames_fidget [] =
                     49: {
                     50:        ai_stand, 0,  NULL,
                     51:        ai_stand, 0,  NULL,
                     52:        ai_stand, 0,  NULL,
                     53:        ai_stand, 0,  NULL,
                     54:        ai_stand, 0,  NULL,
                     55:        ai_stand, 0,  NULL,
                     56:        ai_stand, 0,  NULL,
                     57:        ai_stand, 0,  NULL,
                     58:        ai_stand, 0,  ChickMoan,
                     59:        ai_stand, 0,  NULL,
                     60:        ai_stand, 0,  NULL,
                     61:        ai_stand, 0,  NULL,
                     62:        ai_stand, 0,  NULL,
                     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: };
                     81: mmove_t chick_move_fidget = {FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand};
                     82: 
                     83: void chick_fidget (edict_t *self)
                     84: {
                     85:        if (self->monsterinfo.aiflags & AI_STAND_GROUND)
                     86:                return;
                     87:        if (random() <= 0.3)
                     88:                self->monsterinfo.currentmove = &chick_move_fidget;
                     89: }
                     90: 
                     91: mframe_t chick_frames_stand [] =
                     92: {
                     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:        ai_stand, 0, NULL,
                    113:        ai_stand, 0, NULL,
                    114:        ai_stand, 0, NULL,
                    115:        ai_stand, 0, NULL,
                    116:        ai_stand, 0, NULL,
                    117:        ai_stand, 0, NULL,
                    118:        ai_stand, 0, NULL,
                    119:        ai_stand, 0, NULL,
                    120:        ai_stand, 0, NULL,
                    121:        ai_stand, 0, NULL,
                    122:        ai_stand, 0, chick_fidget,
                    123: 
                    124: };
                    125: mmove_t chick_move_stand = {FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL};
                    126: 
                    127: void chick_stand (edict_t *self)
                    128: {
                    129:        self->monsterinfo.currentmove = &chick_move_stand;
                    130: }
                    131: 
                    132: mframe_t chick_frames_start_run [] =
                    133: {
                    134:        ai_run, 1,  NULL,
                    135:        ai_run, 0,  NULL,
                    136:        ai_run, 0,       NULL,
                    137:        ai_run, -1, NULL, 
                    138:        ai_run, -1, NULL, 
                    139:        ai_run, 0,  NULL,
                    140:        ai_run, 1,  NULL,
                    141:        ai_run, 3,  NULL,
                    142:        ai_run, 6,       NULL,
                    143:        ai_run, 3,       NULL
                    144: };
                    145: mmove_t chick_move_start_run = {FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run};
                    146: 
                    147: mframe_t chick_frames_run [] =
                    148: {
                    149:        ai_run, 6,      NULL,
                    150:        ai_run, 8,  NULL,
                    151:        ai_run, 13, NULL,
                    152:        ai_run, 5,  monster_done_dodge,  // make sure to clear dodge bit
                    153:        ai_run, 7,  NULL,
                    154:        ai_run, 4,  NULL,
                    155:        ai_run, 11, NULL,
                    156:        ai_run, 5,  NULL,
                    157:        ai_run, 9,  NULL,
                    158:        ai_run, 7,  NULL
                    159: };
                    160: 
                    161: mmove_t chick_move_run = {FRAME_walk11, FRAME_walk20, chick_frames_run, NULL};
                    162: 
                    163: mframe_t chick_frames_walk [] =
                    164: {
                    165:        ai_walk, 6,      NULL,
                    166:        ai_walk, 8,  NULL,
                    167:        ai_walk, 13, NULL,
                    168:        ai_walk, 5,  NULL,
                    169:        ai_walk, 7,  NULL,
                    170:        ai_walk, 4,  NULL,
                    171:        ai_walk, 11, NULL,
                    172:        ai_walk, 5,  NULL,
                    173:        ai_walk, 9,  NULL,
                    174:        ai_walk, 7,  NULL
                    175: };
                    176: 
                    177: mmove_t chick_move_walk = {FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL};
                    178: 
                    179: void chick_walk (edict_t *self)
                    180: {
                    181:        self->monsterinfo.currentmove = &chick_move_walk;
                    182: }
                    183: 
                    184: void chick_run (edict_t *self)
                    185: {
                    186:        monster_done_dodge (self);
                    187: 
                    188:        if (self->monsterinfo.aiflags & AI_STAND_GROUND)
                    189:        {
                    190:                self->monsterinfo.currentmove = &chick_move_stand;
                    191:                return;
                    192:        }
                    193: 
                    194:        if (self->monsterinfo.currentmove == &chick_move_walk ||
                    195:                self->monsterinfo.currentmove == &chick_move_start_run)
                    196:        {
                    197:                self->monsterinfo.currentmove = &chick_move_run;
                    198:        }
                    199:        else
                    200:        {
                    201:                self->monsterinfo.currentmove = &chick_move_start_run;
                    202:        }
                    203: }
                    204: 
                    205: mframe_t chick_frames_pain1 [] =
                    206: {
                    207:        ai_move, 0, NULL,
                    208:        ai_move, 0, NULL,
                    209:        ai_move, 0, NULL,
                    210:        ai_move, 0, NULL,
                    211:        ai_move, 0, NULL
                    212: };
                    213: mmove_t chick_move_pain1 = {FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run};
                    214: 
                    215: mframe_t chick_frames_pain2 [] =
                    216: {
                    217:        ai_move, 0, NULL,
                    218:        ai_move, 0, NULL,
                    219:        ai_move, 0, NULL,
                    220:        ai_move, 0, NULL,
                    221:        ai_move, 0, NULL
                    222: };
                    223: mmove_t chick_move_pain2 = {FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run};
                    224: 
                    225: mframe_t chick_frames_pain3 [] =
                    226: {
                    227:        ai_move, 0,             NULL,
                    228:        ai_move, 0,             NULL,
                    229:        ai_move, -6,    NULL,
                    230:        ai_move, 3,             NULL,
                    231:        ai_move, 11,    NULL,
                    232:        ai_move, 3,             NULL,
                    233:        ai_move, 0,             NULL,
                    234:        ai_move, 0,             NULL,
                    235:        ai_move, 4,             NULL,
                    236:        ai_move, 1,             NULL,
                    237:        ai_move, 0,             NULL,
                    238:        ai_move, -3,    NULL,
                    239:        ai_move, -4,    NULL,
                    240:        ai_move, 5,             NULL,
                    241:        ai_move, 7,             NULL,
                    242:        ai_move, -2,    NULL,
                    243:        ai_move, 3,             NULL,
                    244:        ai_move, -5,    NULL,
                    245:        ai_move, -2,    NULL,
                    246:        ai_move, -8,    NULL,
                    247:        ai_move, 2,             NULL
                    248: };
                    249: mmove_t chick_move_pain3 = {FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run};
                    250: 
                    251: void chick_pain (edict_t *self, edict_t *other, float kick, int damage)
                    252: {
                    253:        float   r;
                    254: 
                    255:        monster_done_dodge(self);
                    256: 
                    257:        if (self->health < (self->max_health / 2))
                    258:                self->s.skinnum = 1;
                    259: 
                    260:        if (level.time < self->pain_debounce_time)
                    261:                return;
                    262: 
                    263:        self->pain_debounce_time = level.time + 3;
                    264: 
                    265:        r = random();
                    266:        if (r < 0.33)
                    267:                gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
                    268:        else if (r < 0.66)
                    269:                gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
                    270:        else
                    271:                gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0);
                    272: 
                    273:        if (skill->value == 3)
                    274:                return;         // no pain anims in nightmare
                    275: 
                    276:        // PMM - clear this from blindfire
                    277:        self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
                    278: 
                    279:        if (damage <= 10)
                    280:                self->monsterinfo.currentmove = &chick_move_pain1;
                    281:        else if (damage <= 25)
                    282:                self->monsterinfo.currentmove = &chick_move_pain2;
                    283:        else
                    284:                self->monsterinfo.currentmove = &chick_move_pain3;
                    285: 
                    286:        // PMM - clear duck flag
                    287:        if (self->monsterinfo.aiflags & AI_DUCKED)
                    288:                monster_duck_up(self);
                    289: }
                    290: 
                    291: void chick_dead (edict_t *self)
                    292: {
                    293:        VectorSet (self->mins, -16, -16, 0);
                    294:        VectorSet (self->maxs, 16, 16, 16);
                    295:        self->movetype = MOVETYPE_TOSS;
                    296:        self->svflags |= SVF_DEADMONSTER;
                    297:        self->nextthink = 0;
                    298:        gi.linkentity (self);
                    299: }
                    300: 
                    301: mframe_t chick_frames_death2 [] =
                    302: {
                    303:        ai_move, -6, NULL,
                    304:        ai_move, 0,  NULL,
                    305:        ai_move, -1,  NULL,
                    306:        ai_move, -5, NULL,
                    307:        ai_move, 0, NULL,
                    308:        ai_move, -1,  NULL,
                    309:        ai_move, -2,  NULL,
                    310:        ai_move, 1,  NULL,
                    311:        ai_move, 10, NULL,
                    312:        ai_move, 2,  NULL,
                    313:        ai_move, 3,  NULL,
                    314:        ai_move, 1,  NULL,
                    315:        ai_move, 2, NULL,
                    316:        ai_move, 0,  NULL,
                    317:        ai_move, 3,  NULL,
                    318:        ai_move, 3,  NULL,
                    319:        ai_move, 1,  NULL,
                    320:        ai_move, -3,  NULL,
                    321:        ai_move, -5, NULL,
                    322:        ai_move, 4, NULL,
                    323:        ai_move, 15, NULL,
                    324:        ai_move, 14, NULL,
                    325:        ai_move, 1, NULL
                    326: };
                    327: mmove_t chick_move_death2 = {FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead};
                    328: 
                    329: mframe_t chick_frames_death1 [] =
                    330: {
                    331:        ai_move, 0,  NULL,
                    332:        ai_move, 0,  NULL,
                    333:        ai_move, -7, NULL,
                    334:        ai_move, 4,  NULL,
                    335:        ai_move, 11, NULL,
                    336:        ai_move, 0,  NULL,
                    337:        ai_move, 0,  NULL,
                    338:        ai_move, 0,  NULL,
                    339:        ai_move, 0,  NULL,
                    340:        ai_move, 0,  NULL,
                    341:        ai_move, 0,  NULL,
                    342:        ai_move, 0,  NULL
                    343:        
                    344: };
                    345: mmove_t chick_move_death1 = {FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead};
                    346: 
                    347: void chick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
                    348: {
                    349:        int             n;
                    350: 
                    351: // check for gib
                    352:        if (self->health <= self->gib_health)
                    353:        {
                    354:                gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
                    355:                for (n= 0; n < 2; n++)
                    356:                        ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
                    357:                for (n= 0; n < 4; n++)
                    358:                        ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
                    359:                ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
                    360:                self->deadflag = DEAD_DEAD;
                    361:                return;
                    362:        }
                    363: 
                    364:        if (self->deadflag == DEAD_DEAD)
                    365:                return;
                    366: 
                    367: // regular death
                    368:        self->deadflag = DEAD_DEAD;
                    369:        self->takedamage = DAMAGE_YES;
                    370: 
                    371:        n = rand() % 2;
                    372:        if (n == 0)
                    373:        {
                    374:                self->monsterinfo.currentmove = &chick_move_death1;
                    375:                gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
                    376:        }
                    377:        else
                    378:        {
                    379:                self->monsterinfo.currentmove = &chick_move_death2;
                    380:                gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0);
                    381:        }
                    382: }
                    383: 
                    384: // PMM - changes to duck code for new dodge
                    385: 
                    386: mframe_t chick_frames_duck [] =
                    387: {
                    388:        ai_move, 0, monster_duck_down,
                    389:        ai_move, 1, NULL,
                    390:        ai_move, 4, monster_duck_hold,
                    391:        ai_move, -4,  NULL,
                    392:        ai_move, -5,  monster_duck_up,
                    393:        ai_move, 3, NULL,
                    394:        ai_move, 1,  NULL
                    395: };
                    396: mmove_t chick_move_duck = {FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run};
                    397: 
                    398: /*
                    399: void chick_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
                    400: {
                    401: // begin orig code
                    402:        if (random() > 0.25)
                    403:                return;
                    404: 
                    405:        if (!self->enemy)
                    406:                self->enemy = attacker;
                    407: 
                    408:        self->monsterinfo.currentmove = &chick_move_duck;
                    409: // end
                    410: 
                    411:        float   r;
                    412:        float   height;
                    413:        int             shooting = 0;
                    414: 
                    415:        if (!self->enemy)
                    416:        {
                    417:                self->enemy = attacker;
                    418:                FoundTarget (self);
                    419:        }
                    420: 
                    421:        // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
                    422:        // seeing numbers like 13 and 14)
                    423:        if ((eta < 0.1) || (eta > 5))
                    424:                return;
                    425: 
                    426:        r = random();
                    427:        if (r > (0.25*((skill->value)+1)))
                    428:                return;
                    429: 
                    430:        if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
                    431:                (self->monsterinfo.currentmove == &chick_move_attack1))
                    432:        {
                    433:                shooting = 1;
                    434:        }
                    435:        if (self->monsterinfo.aiflags & AI_DODGING)
                    436:        {
                    437:                height = self->absmax[2];
                    438:        }
                    439:        else
                    440:        {
                    441:                height = self->absmax[2]-32-1;  // the -1 is because the absmax is s.origin + maxs + 1
                    442:        }
                    443: 
                    444:        // check to see if it makes sense to duck
                    445:        if (tr->endpos[2] <= height)
                    446:        {
                    447:                vec3_t right, diff;
                    448:                if (shooting)
                    449:                {
                    450:                        self->monsterinfo.attack_state = AS_SLIDING;
                    451:                        return;
                    452:                }
                    453:                AngleVectors (self->s.angles, NULL, right, NULL);
                    454:                VectorSubtract (tr->endpos, self->s.origin, diff);
                    455:                if (DotProduct (right, diff) < 0)
                    456:                {
                    457:                        self->monsterinfo.lefty = 1;
                    458:                }
                    459:                // if it doesn't sense to duck, try to strafe away
                    460:                monster_done_dodge (self);
                    461:                self->monsterinfo.currentmove = &chick_move_run;
                    462:                self->monsterinfo.attack_state = AS_SLIDING;
                    463:                return;
                    464:        }
                    465: 
                    466:        if (skill->value == 0)
                    467:        {
                    468:                self->monsterinfo.currentmove = &chick_move_duck;
                    469:                // PMM - stupid dodge
                    470:                self->monsterinfo.duck_wait_time = level.time + eta + 1;
                    471:                self->monsterinfo.aiflags |= AI_DODGING;
                    472:                return;
                    473:        }
                    474: 
                    475:        if (!shooting)
                    476:        {
                    477:                self->monsterinfo.currentmove = &chick_move_duck;
                    478:                self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
                    479:                self->monsterinfo.aiflags |= AI_DODGING;
                    480:        }
                    481:        return;
                    482: 
                    483: }
                    484: */
                    485: void ChickSlash (edict_t *self)
                    486: {
                    487:        vec3_t  aim;
                    488: 
                    489:        VectorSet (aim, MELEE_DISTANCE, self->mins[0], 10);
                    490:        gi.sound (self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0);
                    491:        fire_hit (self, aim, (10 + (rand() %6)), 100);
                    492: }
                    493: 
                    494: 
                    495: void ChickRocket (edict_t *self)
                    496: {
                    497:        vec3_t  forward, right;
                    498:        vec3_t  start;
                    499:        vec3_t  dir;
                    500:        vec3_t  vec;
                    501:        trace_t trace;  // PMM - check target
                    502:        int             rocketSpeed;
                    503:        float   dist;
                    504:        // pmm - blindfire
                    505:        vec3_t  target;
                    506:        qboolean blindfire = false;
                    507: 
                    508:        if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
                    509:                blindfire = true;
                    510:        else
                    511:                blindfire = false;
                    512: 
                    513:        if(!self->enemy || !self->enemy->inuse)         //PGM
                    514:                return;                                                                 //PGM
                    515: 
                    516:        AngleVectors (self->s.angles, forward, right, NULL);
                    517:        G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start);
                    518: 
                    519:        rocketSpeed = 500 + (100 * skill->value);       // PGM rock & roll.... :)
                    520: 
                    521:        // put a debug trail from start to endpoint, confirm that the start point is
                    522:        // correct for the trace
                    523: 
                    524:        // PMM
                    525:        if (blindfire)
                    526:                VectorCopy (self->monsterinfo.blind_fire_target, target);
                    527:        else
                    528:                VectorCopy (self->enemy->s.origin, target);
                    529:        // pmm
                    530: //PGM
                    531:        // PMM - blindfire shooting
                    532:        if (blindfire)
                    533:        {
                    534:                VectorCopy (target, vec);
                    535:                VectorSubtract (vec, start, dir);
                    536:        }
                    537:        // pmm
                    538:        // don't shoot at feet if they're above where i'm shooting from.
                    539:        else if(random() < 0.33 || (start[2] < self->enemy->absmin[2]))
                    540:        {
                    541: //             gi.dprintf("normal shot\n");
                    542:                VectorCopy (target, vec);
                    543:                vec[2] += self->enemy->viewheight;
                    544:                VectorSubtract (vec, start, dir);
                    545:        }
                    546:        else
                    547:        {
                    548: //             gi.dprintf("shooting at feet!\n");
                    549:                VectorCopy (target, vec);
                    550:                vec[2] = self->enemy->absmin[2];
                    551:                VectorSubtract (vec, start, dir);
                    552:        }
                    553: //PGM
                    554: 
                    555: //======
                    556: //PMM - lead target  (not when blindfiring)
                    557:        // 20, 35, 50, 65 chance of leading
                    558:        if((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15)))))
                    559:        {
                    560:                float   time;
                    561: 
                    562: //             gi.dprintf ("leading target\n");
                    563:                dist = VectorLength (dir);
                    564:                time = dist/rocketSpeed;
                    565:                VectorMA(vec, time, self->enemy->velocity, vec);
                    566:                VectorSubtract(vec, start, dir);
                    567:        }
                    568: //PMM - lead target
                    569: //======
                    570: 
                    571:        VectorNormalize (dir);
                    572: 
                    573:        // pmm blindfire doesn't check target (done in checkattack)
                    574:        // paranoia, make sure we're not shooting a target right next to us
                    575:        trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
                    576:        if (blindfire)
                    577:        {
                    578:                // blindfire has different fail criteria for the trace
                    579:                if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
                    580:                        monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
                    581:                else 
                    582:                {
                    583:                        // geez, this is bad.  she's avoiding about 80% of her blindfires due to hitting things.
                    584:                        // hunt around for a good shot
                    585:                        // try shifting the target to the left a little (to help counter her large offset)
                    586:                        VectorCopy (target, vec);
                    587:                        VectorMA (vec, -10, right, vec);
                    588:                        VectorSubtract(vec, start, dir);
                    589:                        VectorNormalize (dir);
                    590:                        trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
                    591:                        if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
                    592:                                monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
                    593:                        else 
                    594:                        {
                    595:                                // ok, that failed.  try to the right
                    596:                                VectorCopy (target, vec);
                    597:                                VectorMA (vec, 10, right, vec);
                    598:                                VectorSubtract(vec, start, dir);
                    599:                                VectorNormalize (dir);
                    600:                                trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
                    601:                                if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
                    602:                                        monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
                    603:                                else if ((g_showlogic) && (g_showlogic->value))
                    604:                                        // ok, I give up
                    605:                                        gi.dprintf ("chick avoiding blindfire shot\n");
                    606:                        }
                    607:                }
                    608:        }
                    609:        else
                    610:        {
                    611:                trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
                    612:                if(trace.ent == self->enemy || trace.ent == world)
                    613:                {
                    614:                        if(trace.fraction > 0.5 || (trace.ent && trace.ent->client))
                    615:                                monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
                    616:        //              else
                    617:        //                      gi.dprintf("didn't make it halfway to target...aborting\n");
                    618:                }
                    619:        }
                    620: }      
                    621: 
                    622: void Chick_PreAttack1 (edict_t *self)
                    623: {
                    624:        gi.sound (self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0);
                    625: }
                    626: 
                    627: void ChickReload (edict_t *self)
                    628: {
                    629:        gi.sound (self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0);
                    630: }
                    631: 
                    632: 
                    633: mframe_t chick_frames_start_attack1 [] =
                    634: {
                    635:        ai_charge, 0,   Chick_PreAttack1,
                    636:        ai_charge, 0,   NULL,
                    637:        ai_charge, 0,   NULL,
                    638:        ai_charge, 4,   NULL,
                    639:        ai_charge, 0,   NULL,
                    640:        ai_charge, -3,  NULL,
                    641:        ai_charge, 3,   NULL,
                    642:        ai_charge, 5,   NULL,
                    643:        ai_charge, 7,   NULL,
                    644:        ai_charge, 0,   NULL,
                    645:        ai_charge, 0,   NULL,
                    646:        ai_charge, 0,   NULL,
                    647:        ai_charge, 0,   chick_attack1
                    648: };
                    649: mmove_t chick_move_start_attack1 = {FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL};
                    650: 
                    651: 
                    652: mframe_t chick_frames_attack1 [] =
                    653: {
                    654:        ai_charge, 19,  ChickRocket,
                    655:        ai_charge, -6,  NULL,
                    656:        ai_charge, -5,  NULL,
                    657:        ai_charge, -2,  NULL,
                    658:        ai_charge, -7,  NULL,
                    659:        ai_charge, 0,   NULL,
                    660:        ai_charge, 1,   NULL,
                    661:        ai_charge, 10,  ChickReload,
                    662:        ai_charge, 4,   NULL,
                    663:        ai_charge, 5,   NULL,
                    664:        ai_charge, 6,   NULL,
                    665:        ai_charge, 6,   NULL,
                    666:        ai_charge, 4,   NULL,
                    667:        ai_charge, 3,   chick_rerocket
                    668: 
                    669: };
                    670: mmove_t chick_move_attack1 = {FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL};
                    671: 
                    672: mframe_t chick_frames_end_attack1 [] =
                    673: {
                    674:        ai_charge, -3,  NULL,
                    675:        ai_charge, 0,   NULL,
                    676:        ai_charge, -6,  NULL,
                    677:        ai_charge, -4,  NULL,
                    678:        ai_charge, -2,  NULL
                    679: };
                    680: mmove_t chick_move_end_attack1 = {FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run};
                    681: 
                    682: void chick_rerocket(edict_t *self)
                    683: {
                    684:        if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
                    685:        {
                    686:                self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
                    687:                self->monsterinfo.currentmove = &chick_move_end_attack1;
                    688:                return;
                    689:        }
                    690:        if (self->enemy->health > 0)
                    691:        {
                    692:                if (range (self, self->enemy) > RANGE_MELEE)
                    693:                        if ( visible (self, self->enemy) )
                    694:                                if (random() <= (0.6 + (0.05*((float)skill->value))))
                    695:                                {
                    696:                                        self->monsterinfo.currentmove = &chick_move_attack1;
                    697:                                        return;
                    698:                                }
                    699:        }       
                    700:        self->monsterinfo.currentmove = &chick_move_end_attack1;
                    701: }
                    702: 
                    703: void chick_attack1(edict_t *self)
                    704: {
                    705:        self->monsterinfo.currentmove = &chick_move_attack1;
                    706: }
                    707: 
                    708: mframe_t chick_frames_slash [] =
                    709: {
                    710:        ai_charge, 1,   NULL,
                    711:        ai_charge, 7,   ChickSlash,
                    712:        ai_charge, -7,  NULL,
                    713:        ai_charge, 1,   NULL,
                    714:        ai_charge, -1,  NULL,
                    715:        ai_charge, 1,   NULL,
                    716:        ai_charge, 0,   NULL,
                    717:        ai_charge, 1,   NULL,
                    718:        ai_charge, -2,  chick_reslash
                    719: };
                    720: mmove_t chick_move_slash = {FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL};
                    721: 
                    722: mframe_t chick_frames_end_slash [] =
                    723: {
                    724:        ai_charge, -6,  NULL,
                    725:        ai_charge, -1,  NULL,
                    726:        ai_charge, -6,  NULL,
                    727:        ai_charge, 0,   NULL
                    728: };
                    729: mmove_t chick_move_end_slash = {FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run};
                    730: 
                    731: 
                    732: void chick_reslash(edict_t *self)
                    733: {
                    734:        if (self->enemy->health > 0)
                    735:        {
                    736:                if (range (self, self->enemy) == RANGE_MELEE)
                    737:                        if (random() <= 0.9)
                    738:                        {                               
                    739:                                self->monsterinfo.currentmove = &chick_move_slash;
                    740:                                return;
                    741:                        }
                    742:                        else
                    743:                        {
                    744:                                self->monsterinfo.currentmove = &chick_move_end_slash;
                    745:                                return;
                    746:                        }
                    747:        }
                    748:        self->monsterinfo.currentmove = &chick_move_end_slash;
                    749: }
                    750: 
                    751: void chick_slash(edict_t *self)
                    752: {
                    753:        self->monsterinfo.currentmove = &chick_move_slash;
                    754: }
                    755: 
                    756: 
                    757: mframe_t chick_frames_start_slash [] =
                    758: {      
                    759:        ai_charge, 1,   NULL,
                    760:        ai_charge, 8,   NULL,
                    761:        ai_charge, 3,   NULL
                    762: };
                    763: mmove_t chick_move_start_slash = {FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash};
                    764: 
                    765: 
                    766: 
                    767: void chick_melee(edict_t *self)
                    768: {
                    769:        self->monsterinfo.currentmove = &chick_move_start_slash;
                    770: }
                    771: 
                    772: 
                    773: void chick_attack(edict_t *self)
                    774: {
                    775:        float r, chance;
                    776: 
                    777:        monster_done_dodge (self);
                    778: 
                    779:        // PMM 
                    780:        if (self->monsterinfo.attack_state == AS_BLIND)
                    781:        {
                    782:                // setup shot probabilities
                    783:                if (self->monsterinfo.blind_fire_delay < 1.0)
                    784:                        chance = 1.0;
                    785:                else if (self->monsterinfo.blind_fire_delay < 7.5)
                    786:                        chance = 0.4;
                    787:                else
                    788:                        chance = 0.1;
                    789: 
                    790:                r = random();
                    791: 
                    792:                gi.dprintf ("chance = %2.2f, roll = %2.2f\n", chance, r);
                    793: 
                    794:                // minimum of 2 seconds, plus 0-3, after the shots are done
                    795:                self->monsterinfo.blind_fire_delay += 4.0 + 1.5 + random();
                    796: 
                    797:                // don't shoot at the origin
                    798:                if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
                    799:                        return;
                    800: 
                    801:                // don't shoot if the dice say not to
                    802:                if (r > chance)
                    803:                {
                    804:                        if ((g_showlogic) && (g_showlogic->value))
                    805:                                gi.dprintf ("blindfire - NO SHOT\n");
                    806:                        return;
                    807:                }
                    808: 
                    809:                // turn on manual steering to signal both manual steering and blindfire
                    810:                self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
                    811:                self->monsterinfo.currentmove = &chick_move_start_attack1;
                    812:                self->monsterinfo.attack_finished = level.time + 2*random();
                    813:                return;
                    814:        }
                    815:        // pmm
                    816: 
                    817:        self->monsterinfo.currentmove = &chick_move_start_attack1;
                    818: }
                    819: 
                    820: void chick_sight(edict_t *self, edict_t *other)
                    821: {
                    822:        gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
                    823: }
                    824: 
                    825: //===========
                    826: //PGM
                    827: qboolean chick_blocked (edict_t *self, float dist)
                    828: {
                    829:        if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
                    830:                return true;
                    831: 
                    832:        if(blocked_checkplat (self, dist))
                    833:                return true;
                    834: 
                    835:        return false;
                    836: }
                    837: //PGM
                    838: //===========
                    839: 
                    840: void chick_duck (edict_t *self, float eta)
                    841: {
                    842:        if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
                    843:                (self->monsterinfo.currentmove == &chick_move_attack1))
                    844:        {
                    845:                // if we're shooting, and not on easy, don't dodge
                    846:                if (skill->value)
                    847:                {
                    848:                        self->monsterinfo.aiflags &= ~AI_DUCKED;
                    849:                        return;
                    850:                }
                    851:        }
                    852: 
                    853:        if (skill->value == 0)
                    854:                // PMM - stupid dodge
                    855:                self->monsterinfo.duck_wait_time = level.time + eta + 1;
                    856:        else
                    857:                self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
                    858: 
                    859:        // has to be done immediately otherwise she can get stuck
                    860:        monster_duck_down(self);
                    861: 
                    862:        self->monsterinfo.nextframe = FRAME_duck01;
                    863:        self->monsterinfo.currentmove = &chick_move_duck;
                    864:        return;
                    865: }
                    866: 
                    867: void chick_sidestep (edict_t *self)
                    868: {
                    869:        if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
                    870:                (self->monsterinfo.currentmove == &chick_move_attack1))
                    871:        {
                    872:                // if we're shooting, and not on easy, don't dodge
                    873:                if (skill->value)
                    874:                {
                    875:                        self->monsterinfo.aiflags &= ~AI_DODGING;
                    876:                        return;
                    877:                }
                    878:        }
                    879: 
                    880:        if (self->monsterinfo.currentmove != &chick_move_run)
                    881:                self->monsterinfo.currentmove = &chick_move_run;
                    882: }
                    883: 
                    884: /*QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
                    885: */
                    886: void SP_monster_chick (edict_t *self)
                    887: {
                    888:        if (deathmatch->value)
                    889:        {
                    890:                G_FreeEdict (self);
                    891:                return;
                    892:        }
                    893: 
                    894:        sound_missile_prelaunch = gi.soundindex ("chick/chkatck1.wav"); 
                    895:        sound_missile_launch    = gi.soundindex ("chick/chkatck2.wav"); 
                    896:        sound_melee_swing               = gi.soundindex ("chick/chkatck3.wav"); 
                    897:        sound_melee_hit                 = gi.soundindex ("chick/chkatck4.wav"); 
                    898:        sound_missile_reload    = gi.soundindex ("chick/chkatck5.wav"); 
                    899:        sound_death1                    = gi.soundindex ("chick/chkdeth1.wav"); 
                    900:        sound_death2                    = gi.soundindex ("chick/chkdeth2.wav"); 
                    901:        sound_fall_down                 = gi.soundindex ("chick/chkfall1.wav"); 
                    902:        sound_idle1                             = gi.soundindex ("chick/chkidle1.wav"); 
                    903:        sound_idle2                             = gi.soundindex ("chick/chkidle2.wav"); 
                    904:        sound_pain1                             = gi.soundindex ("chick/chkpain1.wav"); 
                    905:        sound_pain2                             = gi.soundindex ("chick/chkpain2.wav"); 
                    906:        sound_pain3                             = gi.soundindex ("chick/chkpain3.wav"); 
                    907:        sound_sight                             = gi.soundindex ("chick/chksght1.wav"); 
                    908:        sound_search                    = gi.soundindex ("chick/chksrch1.wav"); 
                    909: 
                    910:        self->movetype = MOVETYPE_STEP;
                    911:        self->solid = SOLID_BBOX;
                    912:        self->s.modelindex = gi.modelindex ("models/monsters/bitch2/tris.md2");
                    913:        VectorSet (self->mins, -16, -16, 0);
                    914:        VectorSet (self->maxs, 16, 16, 56);
                    915: 
                    916:        self->health = 175;
                    917:        self->gib_health = -70;
                    918:        self->mass = 200;
                    919: 
                    920:        self->pain = chick_pain;
                    921:        self->die = chick_die;
                    922: 
                    923:        self->monsterinfo.stand = chick_stand;
                    924:        self->monsterinfo.walk = chick_walk;
                    925:        self->monsterinfo.run = chick_run;
                    926:        // pmm
                    927:        self->monsterinfo.dodge = M_MonsterDodge;
                    928:        self->monsterinfo.duck = chick_duck;
                    929:        self->monsterinfo.unduck = monster_duck_up;
                    930:        self->monsterinfo.sidestep = chick_sidestep;
                    931: //     self->monsterinfo.dodge = chick_dodge;
                    932:        // pmm
                    933:        self->monsterinfo.attack = chick_attack;
                    934:        self->monsterinfo.melee = chick_melee;
                    935:        self->monsterinfo.sight = chick_sight;
                    936:        self->monsterinfo.blocked = chick_blocked;              // PGM
                    937: 
                    938:        gi.linkentity (self);
                    939: 
                    940:        self->monsterinfo.currentmove = &chick_move_stand;
                    941:        self->monsterinfo.scale = MODEL_SCALE;
                    942: 
                    943:        // PMM
                    944:        self->monsterinfo.blindfire = true;
                    945:        // pmm
                    946:        walkmonster_start (self);
                    947: }
                    948: 

unix.superglobalmegacorp.com

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