Annotation of quake2/xatrix/m_fixbot.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        fixbot.c
                      3: */
                      4: 
                      5: 
                      6: #include "g_local.h"
                      7: #include "m_fixbot.h"
                      8: 
                      9: 
                     10: #define MZ2_fixbot_BLASTER_1                           MZ2_HOVER_BLASTER_1
                     11: 
                     12: qboolean visible (edict_t *self, edict_t *other);
                     13: qboolean infront (edict_t *self, edict_t *other);
                     14: 
                     15: static int     sound_pain1;
                     16: static int     sound_die;
                     17: static int  sound_weld1;
                     18: static int  sound_weld2;
                     19: static int  sound_weld3;
                     20: 
                     21: void fixbot_run (edict_t *self);
                     22: void fixbot_stand (edict_t *self);
                     23: void fixbot_dead (edict_t *self);
                     24: void fixbot_attack (edict_t *self);
                     25: void fixbot_fire_blaster (edict_t *self);
                     26: void fixbot_fire_welder (edict_t *self);
                     27: void fixbot_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
                     28: 
                     29: void use_scanner (edict_t *self);
                     30: void change_to_roam (edict_t *self);
                     31: void fly_vertical (edict_t *self);
                     32: 
                     33: extern mmove_t fixbot_move_forward;
                     34: extern mmove_t fixbot_move_stand;
                     35: extern mmove_t fixbot_move_stand2;
                     36: extern mmove_t fixbot_move_roamgoal;
                     37: 
                     38: extern mmove_t fixbot_move_weld_start;
                     39: extern mmove_t fixbot_move_weld;
                     40: extern mmove_t fixbot_move_weld_end;
                     41: extern mmove_t fixbot_move_takeoff;
                     42: extern mmove_t fixbot_move_landing;
                     43: extern mmove_t fixbot_move_turn;
                     44: 
                     45: extern void roam_goal (edict_t *self);
                     46: void ED_CallSpawn (edict_t *ent);
                     47: 
                     48: float crand(void)
                     49: {
                     50:        return (rand()&32767)*(2.0/32767)-1;    
                     51: };
                     52: 
                     53: edict_t *fixbot_FindDeadMonster (edict_t *self)
                     54: {
                     55:        edict_t *ent = NULL;
                     56:        edict_t *best = NULL;
                     57: 
                     58:        while ((ent = findradius(ent, self->s.origin, 1024)) != NULL)
                     59:        {
                     60:                if (ent == self)
                     61:                        continue;
                     62:                if (!(ent->svflags & SVF_MONSTER))
                     63:                        continue;
                     64:                if (ent->monsterinfo.aiflags & AI_GOOD_GUY)
                     65:                        continue;
                     66:                if (ent->owner)
                     67:                        continue;
                     68:                if (ent->health > 0)
                     69:                        continue;
                     70:                if (ent->nextthink)
                     71:                        continue;
                     72:                if (!visible(self, ent))
                     73:                        continue;
                     74:                if (!best)
                     75:                {
                     76:                        best = ent;
                     77:                        continue;
                     78:                }
                     79:                if (ent->max_health <= best->max_health)
                     80:                        continue;
                     81:                best = ent;
                     82:        }
                     83: 
                     84:        return best;
                     85: }
                     86: 
                     87: 
                     88: int fixbot_search (edict_t *self)
                     89: {
                     90:        edict_t *ent;
                     91: 
                     92:        if (!self->goalentity)
                     93:        {
                     94:                ent = fixbot_FindDeadMonster(self);
                     95:                if (ent)
                     96:                {
                     97:                        self->oldenemy = self->enemy;
                     98:                        self->enemy = ent;
                     99:                        self->enemy->owner = self;
                    100:                        self->monsterinfo.aiflags |= AI_MEDIC;
                    101:                        FoundTarget (self);
                    102:                        return (1);
                    103:                }
                    104:        }
                    105:        return (0);
                    106: }
                    107: 
                    108: void landing_goal (edict_t *self)
                    109: {
                    110:        trace_t tr;
                    111:        vec3_t forward, right, up;
                    112:        vec3_t end;
                    113:        edict_t *ent;
                    114:        
                    115:        ent = G_Spawn ();       
                    116:        ent->classname = "bot_goal";
                    117:        ent->solid = SOLID_BBOX;
                    118:        ent->owner = self;
                    119:        gi.linkentity (ent);
                    120:        
                    121:        VectorSet (ent->mins, -32, -32, -24);
                    122:        VectorSet (ent->maxs, 32, 32, 24);
                    123:        
                    124:        AngleVectors (self->s.angles, forward, right, up);
                    125:        VectorMA (self->s.origin, 32, forward, end);
                    126:        VectorMA (self->s.origin, -8096, up, end);
                    127:                
                    128:        tr = gi.trace (self->s.origin, ent->mins, ent->maxs, end, self, MASK_MONSTERSOLID);
                    129: 
                    130:        VectorCopy (tr.endpos, ent->s.origin);
                    131:        
                    132:        self->goalentity = self->enemy = ent;
                    133:        self->monsterinfo.currentmove = &fixbot_move_landing;           
                    134:        
                    135: 
                    136: }
                    137: 
                    138: 
                    139: void takeoff_goal (edict_t *self)
                    140: {
                    141:        trace_t tr;
                    142:        vec3_t forward, right, up;
                    143:        vec3_t end;
                    144:        edict_t *ent;
                    145:        
                    146:        ent = G_Spawn ();       
                    147:        ent->classname = "bot_goal";
                    148:        ent->solid = SOLID_BBOX;
                    149:        ent->owner = self;
                    150:        gi.linkentity (ent);
                    151:        
                    152:        VectorSet (ent->mins, -32, -32, -24);
                    153:        VectorSet (ent->maxs, 32, 32, 24);
                    154:        
                    155:                
                    156:        AngleVectors (self->s.angles, forward, right, up);
                    157:        VectorMA (self->s.origin, 32, forward, end);
                    158:        VectorMA (self->s.origin, 128, up, end);
                    159:                
                    160:        tr = gi.trace (self->s.origin, ent->mins, ent->maxs, end, self, MASK_MONSTERSOLID);
                    161: 
                    162:        VectorCopy (tr.endpos, ent->s.origin);
                    163:        
                    164:        self->goalentity = self->enemy = ent;
                    165:        self->monsterinfo.currentmove = &fixbot_move_takeoff;           
                    166:        
                    167: 
                    168: }
                    169: 
                    170: void change_to_roam (edict_t *self)
                    171: {
                    172:        
                    173:        if (fixbot_search(self))
                    174:                return;
                    175: 
                    176:        self->monsterinfo.currentmove = &fixbot_move_roamgoal;
                    177: 
                    178:        
                    179:        if (self->spawnflags & 16)
                    180:        {
                    181:                landing_goal (self);
                    182:                self->monsterinfo.currentmove = &fixbot_move_landing;
                    183:                self->spawnflags &= ~16;
                    184:                self->spawnflags = 32;
                    185:        }
                    186:        if (self->spawnflags & 8) 
                    187:        {
                    188:                takeoff_goal (self);
                    189:                self->monsterinfo.currentmove = &fixbot_move_takeoff;
                    190:                self->spawnflags &= ~8;
                    191:                self->spawnflags = 32;
                    192:        }
                    193:        if (self->spawnflags & 4)
                    194:        {
                    195:                self->monsterinfo.currentmove = &fixbot_move_roamgoal;
                    196:                self->spawnflags &= ~4;
                    197:                self->spawnflags = 32;
                    198:        }
                    199:        if (!self->spawnflags)
                    200:        {
                    201:                self->monsterinfo.currentmove = &fixbot_move_stand2;
                    202:        }
                    203: 
                    204: }
                    205: 
                    206: 
                    207: void roam_goal (edict_t *self)
                    208: {
                    209: 
                    210:        trace_t         tr;
                    211:        vec3_t          forward, right, up;
                    212:        vec3_t          end;
                    213:        edict_t         *ent;
                    214:        vec3_t          dang;
                    215:        int                     len, oldlen, whichi, i;
                    216:        vec3_t          vec;
                    217:        vec3_t          whichvec;
                    218:                
                    219:        ent = G_Spawn ();       
                    220:        ent->classname = "bot_goal";
                    221:        ent->solid = SOLID_BBOX;
                    222:        ent->owner = self;
                    223:        gi.linkentity (ent);
                    224: 
                    225:        oldlen = 0;
                    226:        whichi = 0;
                    227:        for (i=0; i<12; i++) 
                    228:        {
                    229:                
                    230:                VectorCopy (self->s.angles, dang);
                    231: 
                    232:                if (i < 6)
                    233:                        dang[YAW] += 30 * i;
                    234:                else 
                    235:                        dang[YAW] -= 30 * (i-6);
                    236: 
                    237:                AngleVectors (dang, forward, right, up);
                    238:                VectorMA (self->s.origin, 8192, forward, end);
                    239:                
                    240:                tr = gi.trace (self->s.origin, NULL, NULL, end, self, MASK_SHOT);
                    241: 
                    242:                VectorSubtract (self->s.origin, tr.endpos, vec);
                    243:                len = VectorNormalize (vec);
                    244:                
                    245:                if (len > oldlen)
                    246:                {
                    247:                        oldlen=len;
                    248:                        VectorCopy (tr.endpos, whichvec);
                    249:                }
                    250:                
                    251:        }
                    252:        
                    253:        VectorCopy (whichvec, ent->s.origin);
                    254:        self->goalentity = self->enemy = ent;
                    255:        
                    256:        self->monsterinfo.currentmove = &fixbot_move_turn;              
                    257: 
                    258: 
                    259: }
                    260: 
                    261: void use_scanner (edict_t *self)
                    262: {
                    263:        edict_t *ent = NULL;
                    264:        
                    265:        float   radius = 1024;
                    266:        vec3_t  vec;
                    267:        
                    268:        int len;
                    269:        int oldlen = 0x10000;
                    270:        edict_t *tempent = NULL; 
                    271: 
                    272: 
                    273:        while ((ent = findradius(ent, self->s.origin, radius)) != NULL)
                    274:        {
                    275:                if (ent->health >= 100)
                    276:                {
                    277:                        if (strcmp (ent->classname, "object_repair") == 0)
                    278:                        {
                    279:                                if (visible(self, ent))
                    280:                                {       
                    281:                                        // remove the old one
                    282:                                        if (strcmp (self->goalentity->classname, "bot_goal") == 0)
                    283:                                        {
                    284:                                                self->goalentity->nextthink = level.time + 0.1;
                    285:                                                self->goalentity->think = G_FreeEdict;
                    286:                                        }       
                    287:                                        
                    288:                                        self->goalentity = self->enemy = ent;
                    289:                                        
                    290:                                        VectorSubtract (self->s.origin, self->goalentity->s.origin, vec);
                    291:                                        len = VectorNormalize (vec);
                    292: 
                    293:                                        if (len < 32)
                    294:                                        {
                    295:                                                self->monsterinfo.currentmove = &fixbot_move_weld_start;
                    296:                                                return;
                    297:                                        }
                    298:                                return;
                    299:                                }
                    300:                        }
                    301:                }
                    302:        }
                    303: 
                    304:        VectorSubtract (self->s.origin, self->goalentity->s.origin, vec);
                    305:        len = VectorLength (vec);
                    306: 
                    307:        if (len < 32)
                    308:        {
                    309:                if (strcmp (self->goalentity->classname, "object_repair") == 0)
                    310:                {
                    311:                        self->monsterinfo.currentmove = &fixbot_move_weld_start;
                    312:                }
                    313:                else 
                    314:                {
                    315:                        self->goalentity->nextthink = level.time + 0.1;
                    316:                        self->goalentity->think = G_FreeEdict;
                    317:                        self->goalentity = self->enemy = NULL;
                    318:                        self->monsterinfo.currentmove = &fixbot_move_stand;
                    319:                }
                    320:                return;
                    321:        }
                    322: 
                    323:        VectorSubtract (self->s.origin, self->s.old_origin, vec);
                    324:        len = VectorLength (vec);
                    325: 
                    326:        /* 
                    327:          bot is stuck get new goalentity
                    328:        */
                    329:        if (len == 0)
                    330:        {
                    331:                if (strcmp (self->goalentity->classname , "object_repair") == 0)
                    332:                {
                    333:                        self->monsterinfo.currentmove = &fixbot_move_stand;
                    334:                }
                    335:                else 
                    336:                {
                    337:                        self->goalentity->nextthink = level.time + 0.1;
                    338:                        self->goalentity->think = G_FreeEdict;
                    339:                        self->goalentity = self->enemy = NULL;
                    340:                        self->monsterinfo.currentmove = &fixbot_move_stand;
                    341:                }
                    342:        }
                    343: 
                    344: }
                    345: 
                    346: 
                    347: /*
                    348:        when the bot has found a landing pad
                    349:        it will proceed to its goalentity
                    350:        just above the landing pad and
                    351:        decend translated along the z the current
                    352:        frames are at 10fps
                    353: */ 
                    354: void blastoff (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread)
                    355: {
                    356:        trace_t         tr;
                    357:        vec3_t          dir;
                    358:        vec3_t          forward, right, up;
                    359:        vec3_t          end;
                    360:        float           r;
                    361:        float           u;
                    362:        vec3_t          water_start;
                    363:        qboolean        water = false;
                    364:        int                     content_mask = MASK_SHOT | MASK_WATER;
                    365: 
                    366:        hspread+= (self->s.frame - FRAME_takeoff_01);
                    367:        vspread+= (self->s.frame - FRAME_takeoff_01);
                    368: 
                    369:        tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
                    370:        if (!(tr.fraction < 1.0))
                    371:        {
                    372:                vectoangles (aimdir, dir);
                    373:                AngleVectors (dir, forward, right, up);
                    374: 
                    375:                r = crandom()*hspread;
                    376:                u = crandom()*vspread;
                    377:                VectorMA (start, 8192, forward, end);
                    378:                VectorMA (end, r, right, end);
                    379:                VectorMA (end, u, up, end);
                    380: 
                    381:                if (gi.pointcontents (start) & MASK_WATER)
                    382:                {
                    383:                        water = true;
                    384:                        VectorCopy (start, water_start);
                    385:                        content_mask &= ~MASK_WATER;
                    386:                }
                    387: 
                    388:                tr = gi.trace (start, NULL, NULL, end, self, content_mask);
                    389: 
                    390:                // see if we hit water
                    391:                if (tr.contents & MASK_WATER)
                    392:                {
                    393:                        int             color;
                    394: 
                    395:                        water = true;
                    396:                        VectorCopy (tr.endpos, water_start);
                    397: 
                    398:                        if (!VectorCompare (start, tr.endpos))
                    399:                        {
                    400:                                if (tr.contents & CONTENTS_WATER)
                    401:                                {
                    402:                                        if (strcmp(tr.surface->name, "*brwater") == 0)
                    403:                                                color = SPLASH_BROWN_WATER;
                    404:                                        else
                    405:                                                color = SPLASH_BLUE_WATER;
                    406:                                }
                    407:                                else if (tr.contents & CONTENTS_SLIME)
                    408:                                        color = SPLASH_SLIME;
                    409:                                else if (tr.contents & CONTENTS_LAVA)
                    410:                                        color = SPLASH_LAVA;
                    411:                                else
                    412:                                        color = SPLASH_UNKNOWN;
                    413: 
                    414:                                if (color != SPLASH_UNKNOWN)
                    415:                                {
                    416:                                        gi.WriteByte (svc_temp_entity);
                    417:                                        gi.WriteByte (TE_SPLASH);
                    418:                                        gi.WriteByte (8);
                    419:                                        gi.WritePosition (tr.endpos);
                    420:                                        gi.WriteDir (tr.plane.normal);
                    421:                                        gi.WriteByte (color);
                    422:                                        gi.multicast (tr.endpos, MULTICAST_PVS);
                    423:                                }
                    424: 
                    425:                                // change bullet's course when it enters water
                    426:                                VectorSubtract (end, start, dir);
                    427:                                vectoangles (dir, dir);
                    428:                                AngleVectors (dir, forward, right, up);
                    429:                                r = crandom()*hspread*2;
                    430:                                u = crandom()*vspread*2;
                    431:                                VectorMA (water_start, 8192, forward, end);
                    432:                                VectorMA (end, r, right, end);
                    433:                                VectorMA (end, u, up, end);
                    434:                        }
                    435: 
                    436:                        // re-trace ignoring water this time
                    437:                        tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
                    438:                }
                    439:        }
                    440: 
                    441:        // send gun puff / flash
                    442:        if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
                    443:        {
                    444:                if (tr.fraction < 1.0)
                    445:                {
                    446:                        if (tr.ent->takedamage)
                    447:                        {
                    448:                                T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, MOD_BLASTOFF);
                    449:                        }
                    450:                        else
                    451:                        {
                    452:                                if (strncmp (tr.surface->name, "sky", 3) != 0)
                    453:                                {
                    454:                                        gi.WriteByte (svc_temp_entity);
                    455:                                        gi.WriteByte (te_impact);
                    456:                                        gi.WritePosition (tr.endpos);
                    457:                                        gi.WriteDir (tr.plane.normal);
                    458:                                        gi.multicast (tr.endpos, MULTICAST_PVS);
                    459: 
                    460:                                        if (self->client)
                    461:                                                PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
                    462:                                }
                    463:                        }
                    464:                }
                    465:        }
                    466: 
                    467:        // if went through water, determine where the end and make a bubble trail
                    468:        if (water)
                    469:        {
                    470:                vec3_t  pos;
                    471: 
                    472:                VectorSubtract (tr.endpos, water_start, dir);
                    473:                VectorNormalize (dir);
                    474:                VectorMA (tr.endpos, -2, dir, pos);
                    475:                if (gi.pointcontents (pos) & MASK_WATER)
                    476:                        VectorCopy (pos, tr.endpos);
                    477:                else
                    478:                        tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
                    479: 
                    480:                VectorAdd (water_start, tr.endpos, pos);
                    481:                VectorScale (pos, 0.5, pos);
                    482: 
                    483:                gi.WriteByte (svc_temp_entity);
                    484:                gi.WriteByte (TE_BUBBLETRAIL);
                    485:                gi.WritePosition (water_start);
                    486:                gi.WritePosition (tr.endpos);
                    487:                gi.multicast (pos, MULTICAST_PVS);
                    488:        }
                    489: }
                    490: 
                    491: 
                    492: void fly_vertical (edict_t *self)
                    493: {
                    494:        int i;
                    495:        vec3_t v;
                    496:        vec3_t forward, right, up;
                    497:        vec3_t start;
                    498:        vec3_t tempvec;
                    499:        
                    500:        VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
                    501:        self->ideal_yaw = vectoyaw(v);  
                    502:        M_ChangeYaw (self);
                    503:        
                    504:        if (self->s.frame == FRAME_landing_58 || self->s.frame == FRAME_takeoff_16)
                    505:        {
                    506:                self->goalentity->nextthink = level.time + 0.1;
                    507:                self->goalentity->think = G_FreeEdict;
                    508:                self->monsterinfo.currentmove = &fixbot_move_stand;
                    509:                self->goalentity = self->enemy = NULL;
                    510:        }
                    511: 
                    512:        // kick up some particles
                    513:        VectorCopy (self->s.angles, tempvec);
                    514:        tempvec[PITCH] += 90;
                    515: 
                    516:        AngleVectors (tempvec, forward, right, up);
                    517:        VectorCopy (self->s.origin, start);
                    518:        
                    519:        for (i=0; i< 10; i++)
                    520:                blastoff (self, start, forward, 2, 1, TE_SHOTGUN, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD);
                    521: 
                    522:        // needs sound
                    523: }
                    524: 
                    525: 
                    526: void fly_vertical2 (edict_t *self)
                    527: {
                    528:        vec3_t v;
                    529:        int len;
                    530:        
                    531:        VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
                    532:        len = VectorLength (v);
                    533:        self->ideal_yaw = vectoyaw(v);  
                    534:        M_ChangeYaw (self);
                    535:        
                    536:        if (len < 32)
                    537:        {
                    538:                self->goalentity->nextthink = level.time + 0.1;
                    539:                self->goalentity->think = G_FreeEdict;
                    540:                self->monsterinfo.currentmove = &fixbot_move_stand;
                    541:                self->goalentity = self->enemy = NULL;
                    542:        }
                    543:                
                    544:        // needs sound
                    545: }
                    546: 
                    547: mframe_t fixbot_frames_landing [] =
                    548: {
                    549:        ai_move, 0,  NULL,
                    550:        ai_move, 0, fly_vertical2,
                    551:        ai_move, 0, fly_vertical2,
                    552:        ai_move, 0, fly_vertical2,
                    553:        ai_move, 0, fly_vertical2,
                    554:        ai_move, 0, fly_vertical2,
                    555:        ai_move, 0, fly_vertical2,
                    556:        ai_move, 0, fly_vertical2,
                    557:        ai_move, 0, fly_vertical2,
                    558:        ai_move, 0, fly_vertical2,
                    559: 
                    560:        ai_move, 0, fly_vertical2,
                    561:        ai_move, 0, fly_vertical2,
                    562:        ai_move, 0, fly_vertical2,
                    563:        ai_move, 0, fly_vertical2,
                    564:        ai_move, 0, fly_vertical2,
                    565:        ai_move, 0, fly_vertical2,
                    566:        ai_move, 0, fly_vertical2,
                    567:        ai_move, 0, fly_vertical2,
                    568:        ai_move, 0, fly_vertical2,
                    569:        ai_move, 0, fly_vertical2,
                    570: 
                    571:        ai_move, 0, fly_vertical2,
                    572:        ai_move, 0, fly_vertical2,
                    573:        ai_move, 0, fly_vertical2,
                    574:        ai_move, 0, fly_vertical2,
                    575:        ai_move, 0, fly_vertical2,
                    576:        ai_move, 0, fly_vertical2,
                    577:        ai_move, 0, fly_vertical2,
                    578:        ai_move, 0, fly_vertical2,
                    579:        ai_move, 0, fly_vertical2,
                    580:        ai_move, 0, fly_vertical2,
                    581: 
                    582:        ai_move, 0, fly_vertical2,
                    583:        ai_move, 0, fly_vertical2,
                    584:        ai_move, 0, fly_vertical2,
                    585:        ai_move, 0, fly_vertical2,
                    586:        ai_move, 0, fly_vertical2,
                    587:        ai_move, 0, fly_vertical2,
                    588:        ai_move, 0, fly_vertical2,
                    589:        ai_move, 0, fly_vertical2,
                    590:        ai_move, 0, fly_vertical2,
                    591:        ai_move, 0, fly_vertical2,
                    592: 
                    593:        ai_move, 0, fly_vertical2,
                    594:        ai_move, 0, fly_vertical2,
                    595:        ai_move, 0, fly_vertical2,
                    596:        ai_move, 0, fly_vertical2,
                    597:        ai_move, 0, fly_vertical2,
                    598:        ai_move, 0, fly_vertical2,
                    599:        ai_move, 0, fly_vertical2,
                    600:        ai_move, 0, fly_vertical2,
                    601:        ai_move, 0, fly_vertical2,
                    602:        ai_move, 0, fly_vertical2,
                    603: 
                    604:        ai_move, 0, fly_vertical2,
                    605:        ai_move, 0, fly_vertical2,
                    606:        ai_move, 0, fly_vertical2,
                    607:        ai_move, 0, fly_vertical2,
                    608:        ai_move, 0, fly_vertical2,
                    609:        ai_move, 0, fly_vertical2,
                    610:        ai_move, 0, fly_vertical2,
                    611:        ai_move, 0, fly_vertical2
                    612: };
                    613: mmove_t fixbot_move_landing = { FRAME_landing_01, FRAME_landing_58, fixbot_frames_landing, NULL };
                    614: 
                    615: /*
                    616:        generic ambient stand
                    617: */
                    618: mframe_t fixbot_frames_stand [] =
                    619: {
                    620:        ai_move, 0, NULL,
                    621:        ai_move, 0, NULL,
                    622:        ai_move, 0, NULL,
                    623:        ai_move, 0, NULL,
                    624:        ai_move, 0, NULL,
                    625:        ai_move, 0, NULL,
                    626:        ai_move, 0, NULL,
                    627:        ai_move, 0, NULL,
                    628:        ai_move, 0, NULL,
                    629:        ai_move, 0, NULL,
                    630: 
                    631:        ai_move, 0, NULL,
                    632:        ai_move, 0, NULL,
                    633:        ai_move, 0, NULL,
                    634:        ai_move, 0, NULL,
                    635:        ai_move, 0, NULL,
                    636:        ai_move, 0, NULL,
                    637:        ai_move, 0, NULL,
                    638:        ai_move, 0, NULL,
                    639:        ai_move, 0, change_to_roam
                    640:        
                    641: };
                    642: mmove_t        fixbot_move_stand = {FRAME_ambient_01, FRAME_ambient_19, fixbot_frames_stand, NULL};
                    643: 
                    644: mframe_t fixbot_frames_stand2 [] =
                    645: {
                    646:        
                    647:        ai_stand, 0, NULL,
                    648:        ai_stand, 0, NULL,
                    649:        ai_stand, 0, NULL,
                    650:        ai_stand, 0, NULL,
                    651:        ai_stand, 0, NULL,
                    652:        ai_stand, 0, NULL,
                    653:        ai_stand, 0, NULL,
                    654:        ai_stand, 0, NULL,
                    655:        ai_stand, 0, NULL,
                    656:        ai_stand, 0, NULL,
                    657: 
                    658:        ai_stand, 0, NULL,
                    659:        ai_stand, 0, NULL,
                    660:        ai_stand, 0, NULL,
                    661:        ai_stand, 0, NULL,
                    662:        ai_stand, 0, NULL,
                    663:        ai_stand, 0, NULL,
                    664:        ai_stand, 0, NULL,
                    665:        ai_stand, 0, NULL,
                    666:        ai_stand, 0, NULL
                    667:        
                    668: };
                    669: mmove_t        fixbot_move_stand2 = {FRAME_ambient_01, FRAME_ambient_19, fixbot_frames_stand2, NULL};
                    670: 
                    671: 
                    672: /*
                    673:        will need the pickup offset for the front pincers
                    674:        object will need to stop forward of the object 
                    675:        and take the object with it ( this may require a variant of liftoff and landing )
                    676: */
                    677: mframe_t fixbot_frames_pickup [] =
                    678: {
                    679:        ai_move, 0, NULL,
                    680:        ai_move, 0, NULL,
                    681:        ai_move, 0, NULL,
                    682:        ai_move, 0, NULL,
                    683:        ai_move, 0, NULL,
                    684:        ai_move, 0, NULL,
                    685:        ai_move, 0, NULL,
                    686:        ai_move, 0, NULL,
                    687:        ai_move, 0, NULL,
                    688:        ai_move, 0, NULL,
                    689: 
                    690:        ai_move, 0, NULL,
                    691:        ai_move, 0, NULL,
                    692:        ai_move, 0, NULL,
                    693:        ai_move, 0, NULL,
                    694:        ai_move, 0, NULL,
                    695:        ai_move, 0, NULL,
                    696:        ai_move, 0, NULL,
                    697:        ai_move, 0, NULL,
                    698:        ai_move, 0, NULL,
                    699:        ai_move, 0, NULL,
                    700: 
                    701:        ai_move, 0, NULL,
                    702:        ai_move, 0, NULL,
                    703:        ai_move, 0, NULL,
                    704:        ai_move, 0, NULL,
                    705:        ai_move, 0, NULL,
                    706:        ai_move, 0, NULL,
                    707:        ai_move, 0, NULL
                    708:        
                    709: };
                    710: mmove_t fixbot_move_pickup = { FRAME_pickup_01, FRAME_pickup_27, fixbot_frames_pickup, NULL};
                    711: 
                    712: /*
                    713:        generic frame to move bot
                    714: */
                    715: mframe_t fixbot_frames_roamgoal [] =
                    716: {
                    717:        ai_move, 0, roam_goal
                    718: };
                    719: mmove_t fixbot_move_roamgoal = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_roamgoal, NULL};
                    720: 
                    721: 
                    722: void ai_facing (edict_t *self, float dist)
                    723: {
                    724:        vec3_t v;
                    725: 
                    726:        if (infront (self, self->goalentity))
                    727:                self->monsterinfo.currentmove = &fixbot_move_forward;
                    728:        else
                    729:        {
                    730:                VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
                    731:                self->ideal_yaw = vectoyaw(v);  
                    732:                M_ChangeYaw (self);
                    733:        }
                    734: 
                    735: };
                    736: 
                    737: mframe_t fixbot_frames_turn [] =
                    738: {
                    739:        ai_facing,      0,      NULL
                    740: };
                    741: mmove_t fixbot_move_turn = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_turn, NULL};
                    742: 
                    743: 
                    744: void go_roam (edict_t *self)
                    745: {
                    746:        self->monsterinfo.currentmove = &fixbot_move_stand;     
                    747: }
                    748: 
                    749: 
                    750: /*
                    751:        takeoff
                    752: */
                    753: mframe_t fixbot_frames_takeoff [] =
                    754: {
                    755:        ai_move,        0.01,   fly_vertical,
                    756:        ai_move,        0.01,   fly_vertical,
                    757:        ai_move,        0.01,   fly_vertical,
                    758:        ai_move,        0.01,   fly_vertical,
                    759:        ai_move,        0.01,   fly_vertical,
                    760:        ai_move,        0.01,   fly_vertical,
                    761:        ai_move,        0.01,   fly_vertical,
                    762:        ai_move,        0.01,   fly_vertical,
                    763:        ai_move,        0.01,   fly_vertical,
                    764:        ai_move,        0.01,   fly_vertical,
                    765: 
                    766:        ai_move,        0.01,   fly_vertical,
                    767:        ai_move,        0.01,   fly_vertical,
                    768:        ai_move,        0.01,   fly_vertical,
                    769:        ai_move,        0.01,   fly_vertical,
                    770:        ai_move,        0.01,   fly_vertical,
                    771:        ai_move,        0.01,   fly_vertical
                    772: };
                    773: mmove_t fixbot_move_takeoff = {FRAME_takeoff_01, FRAME_takeoff_16, fixbot_frames_takeoff, NULL};
                    774: 
                    775: 
                    776: /* findout what this is */
                    777: mframe_t fixbot_frames_paina [] =
                    778: {
                    779:        ai_move, 0, NULL,
                    780:        ai_move, 0, NULL,
                    781:        ai_move, 0, NULL,
                    782:        ai_move, 0, NULL,
                    783:        ai_move, 0, NULL,
                    784:        ai_move, 0, NULL
                    785: };
                    786: mmove_t fixbot_move_paina = {FRAME_paina_01, FRAME_paina_06, fixbot_frames_paina, fixbot_run};
                    787: 
                    788: /* findout what this is */
                    789: mframe_t fixbot_frames_painb [] =
                    790: {
                    791:        ai_move, 0, NULL,
                    792:        ai_move, 0, NULL,
                    793:        ai_move, 0, NULL,
                    794:        ai_move, 0, NULL,
                    795:        ai_move, 0, NULL,
                    796:        ai_move, 0, NULL,
                    797:        ai_move, 0, NULL,
                    798:        ai_move, 0, NULL
                    799: };
                    800: mmove_t fixbot_move_painb = {FRAME_painb_01, FRAME_painb_08, fixbot_frames_painb, fixbot_run};
                    801: 
                    802: /*
                    803:        backup from pain
                    804:        call a generic painsound
                    805:        some spark effects
                    806: */
                    807: mframe_t fixbot_frames_pain3 [] =
                    808: {
                    809:        ai_move,        -1,     NULL
                    810: };
                    811: mmove_t fixbot_move_pain3 = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_pain3, fixbot_run};
                    812: 
                    813: /*
                    814:        bot has compleated landing
                    815:        and is now on the grownd
                    816:        ( may need second land if the bot is releasing jib into jib vat )
                    817: */
                    818: mframe_t fixbot_frames_land [] =
                    819: {
                    820:        ai_move,        0,      NULL
                    821: };
                    822: mmove_t fixbot_move_land = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_land, NULL};
                    823: 
                    824: 
                    825: void M_MoveToGoal (edict_t *ent, float dist);
                    826: 
                    827: void ai_movetogoal (edict_t *self, float dist)
                    828: {
                    829:        M_MoveToGoal (self, dist);
                    830: }
                    831: /*
                    832:        
                    833: */
                    834: mframe_t fixbot_frames_forward [] =
                    835: {
                    836:        ai_movetogoal,  5,      use_scanner
                    837: };
                    838: mmove_t fixbot_move_forward = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_forward, NULL};
                    839: 
                    840: 
                    841: /*
                    842:        
                    843: */
                    844: mframe_t fixbot_frames_walk [] =
                    845: {
                    846:        ai_walk,        5,      NULL
                    847: };
                    848: mmove_t fixbot_move_walk = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_walk, NULL};
                    849: 
                    850: 
                    851: /*
                    852:        
                    853: */
                    854: mframe_t fixbot_frames_run [] =
                    855: {
                    856:        ai_run, 10,     NULL
                    857: };
                    858: mmove_t fixbot_move_run = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_run, NULL};
                    859: 
                    860: /*
                    861:        raf
                    862:        note to self
                    863:        they could have a timer that will cause
                    864:        the bot to explode on countdown
                    865: */
                    866: mframe_t fixbot_frames_death1 [] =
                    867: {
                    868:        ai_move,        0,      NULL
                    869: };
                    870: mmove_t fixbot_move_death1 = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_death1, fixbot_dead};
                    871: 
                    872: //
                    873: mframe_t fixbot_frames_backward [] =
                    874: {
                    875:        ai_move,        0,      NULL
                    876: };
                    877: mmove_t fixbot_move_backward = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_backward, NULL};
                    878: 
                    879: //
                    880: mframe_t fixbot_frames_start_attack [] =
                    881: {
                    882:        ai_charge,      0,      NULL
                    883: };
                    884: mmove_t fixbot_move_start_attack = {FRAME_freeze_01, FRAME_freeze_01, fixbot_frames_start_attack, fixbot_attack};
                    885: 
                    886: /*
                    887:        TBD: 
                    888:        need to get laser attack anim
                    889:        attack with the laser blast
                    890: */
                    891: mframe_t fixbot_frames_attack1 [] =
                    892: {
                    893:        ai_charge,      0,      NULL,
                    894:        ai_charge,      0,      NULL,
                    895:        ai_charge,      0,      NULL,
                    896:        ai_charge,      0,      NULL,
                    897:        ai_charge,      0,      NULL,
                    898:        ai_charge,      -10,  fixbot_fire_blaster
                    899: };
                    900: mmove_t fixbot_move_attack1 = {FRAME_shoot_01, FRAME_shoot_06, fixbot_frames_attack1, NULL};
                    901: 
                    902: 
                    903: int check_telefrag (edict_t *self)
                    904: {
                    905:        vec3_t  start = { 0, 0, 0 };
                    906:        vec3_t  forward, right, up;
                    907:        trace_t tr;
                    908: 
                    909:        AngleVectors (self->enemy->s.angles, forward, right, up);
                    910:        VectorMA (start, 48, up, start);
                    911:        tr = gi.trace (self->enemy->s.origin, self->enemy->mins, self->enemy->maxs, start, self, MASK_MONSTERSOLID);
                    912:        if (tr.ent->takedamage)
                    913:        {
                    914:                tr.ent->health = -1000;
                    915:                return (0);
                    916:        }
                    917:                        
                    918:        return (1);
                    919: }
                    920: 
                    921: void fixbot_fire_laser (edict_t *self)
                    922: {
                    923:  
                    924:        vec3_t forward, right, up;
                    925:        vec3_t tempang, start;
                    926:        vec3_t  dir, angles, end;
                    927:        edict_t *ent;
                    928: 
                    929:        // critter dun got blown up while bein' fixed
                    930:        if (self->enemy->health <= self->enemy->gib_health)
                    931:        {
                    932:                self->monsterinfo.currentmove = &fixbot_move_stand;
                    933:                self->monsterinfo.aiflags &= ~AI_MEDIC;
                    934:                return;
                    935:        }
                    936: 
                    937:        gi.sound(self, CHAN_AUTO, gi.soundindex("misc/lasfly.wav"), 1, ATTN_STATIC, 0);
                    938: 
                    939:        VectorCopy (self->s.origin, start);
                    940:        VectorCopy (self->enemy->s.origin, end);
                    941:        VectorSubtract (end, start, dir);
                    942:        vectoangles (dir, angles);
                    943:        
                    944:        ent = G_Spawn ();
                    945:        VectorCopy (self->s.origin, ent->s.origin);
                    946:        VectorCopy (angles, tempang);
                    947:        AngleVectors (tempang, forward, right, up);
                    948:        VectorCopy (tempang, ent->s.angles);
                    949:        VectorCopy (ent->s.origin, start);
                    950:        
                    951:        VectorMA (start, 16, forward, start);
                    952:        
                    953:        VectorCopy (start, ent->s.origin);
                    954:        ent->enemy = self->enemy;
                    955:        ent->owner = self;
                    956:        ent->dmg = -1;
                    957:        monster_dabeam (ent);
                    958: 
                    959:        if (self->enemy->health > (self->enemy->mass/10))
                    960:        {
                    961:                // sorry guys but had to fix the problem this way
                    962:                // if it doesn't do this then two creatures can share the same space
                    963:                // and its real bad.
                    964:                if (check_telefrag (self)) 
                    965:                {
                    966:                        self->enemy->spawnflags = 0;
                    967:                        self->enemy->monsterinfo.aiflags = 0;
                    968:                        self->enemy->target = NULL;
                    969:                        self->enemy->targetname = NULL;
                    970:                        self->enemy->combattarget = NULL;
                    971:                        self->enemy->deathtarget = NULL;
                    972:                        self->enemy->owner = self;
                    973:                        ED_CallSpawn (self->enemy);
                    974:                        self->enemy->owner = NULL;
                    975:                        self->s.origin[2] += 1;
                    976:                
                    977:                        self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
                    978: 
                    979:                        self->monsterinfo.currentmove = &fixbot_move_stand;
                    980:                        self->monsterinfo.aiflags &= ~AI_MEDIC;
                    981: 
                    982:                }
                    983:        }
                    984:        else
                    985:                self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
                    986: }
                    987: 
                    988: mframe_t fixbot_frames_laserattack [] =
                    989: {
                    990:        ai_charge,      0,      fixbot_fire_laser,
                    991:        ai_charge,      0,      fixbot_fire_laser,
                    992:        ai_charge,      0,      fixbot_fire_laser,
                    993:        ai_charge,      0,      fixbot_fire_laser,
                    994:        ai_charge,      0,      fixbot_fire_laser,
                    995:        ai_charge,      0,  fixbot_fire_laser
                    996: };
                    997: mmove_t fixbot_move_laserattack = {FRAME_shoot_01, FRAME_shoot_06, fixbot_frames_laserattack, NULL};
                    998: 
                    999: 
                   1000: /*
                   1001:        need to get forward translation data
                   1002:        for the charge attack
                   1003: */
                   1004: mframe_t fixbot_frames_attack2 [] =
                   1005: {
                   1006:        ai_charge,      0,      NULL,
                   1007:        ai_charge,  0,  NULL,
                   1008:        ai_charge,      0,      NULL,
                   1009:        ai_charge,  0,  NULL,
                   1010:        ai_charge,      0,      NULL,
                   1011:        ai_charge,  0,  NULL,
                   1012:        ai_charge,      0,      NULL,
                   1013:        ai_charge,  0,  NULL,
                   1014:        ai_charge,      0,      NULL,
                   1015:        ai_charge,  0,  NULL,
                   1016: 
                   1017:        ai_charge,      -10, NULL,
                   1018:        ai_charge,  -10, NULL,
                   1019:        ai_charge,      -10, NULL,
                   1020:        ai_charge,  -10, NULL,
                   1021:        ai_charge,      -10, NULL,
                   1022:        ai_charge,  -10, NULL,
                   1023:        ai_charge,      -10, NULL,
                   1024:        ai_charge,  -10, NULL,
                   1025:        ai_charge,      -10, NULL,
                   1026:        ai_charge,  -10, NULL,
                   1027: 
                   1028:        ai_charge,      0,      fixbot_fire_blaster,
                   1029:        ai_charge,  0,  NULL,
                   1030:        ai_charge,      0,      NULL,
                   1031:        ai_charge,  0,  NULL,
                   1032:        ai_charge,      0,      NULL,
                   1033:        ai_charge,  0,  NULL,
                   1034:        ai_charge,      0,      NULL,
                   1035:        ai_charge,  0,  NULL,
                   1036:        ai_charge,  0,  NULL,
                   1037:        ai_charge,  0,  NULL,
                   1038: 
                   1039:        ai_charge,  0,  NULL
                   1040: };
                   1041: mmove_t fixbot_move_attack2 = {FRAME_charging_01, FRAME_charging_31, fixbot_frames_attack2, fixbot_run};
                   1042: 
                   1043: void weldstate (edict_t *self)
                   1044: {
                   1045:        if (self->s.frame == FRAME_weldstart_10)
                   1046:                self->monsterinfo.currentmove = &fixbot_move_weld;
                   1047:        else if (self->s.frame == FRAME_weldmiddle_07)
                   1048:        {
                   1049:                if (self->goalentity->health < 0) 
                   1050:                {
                   1051:                        self->enemy->owner = NULL;
                   1052:                        self->monsterinfo.currentmove = &fixbot_move_weld_end;
                   1053:                }
                   1054:                else
                   1055:                        self->goalentity->health-=10;
                   1056:        }
                   1057:        else
                   1058:        {
                   1059:                self->goalentity = self->enemy = NULL;
                   1060:                self->monsterinfo.currentmove = &fixbot_move_stand;
                   1061:        }
                   1062: }
                   1063: 
                   1064: void ai_move2 (edict_t *self, float dist)
                   1065: {
                   1066:        vec3_t v;
                   1067:        
                   1068:        if (dist)
                   1069:                M_walkmove (self, self->s.angles[YAW], dist);
                   1070: 
                   1071:        VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
                   1072:        self->ideal_yaw = vectoyaw(v);  
                   1073:        M_ChangeYaw (self);
                   1074: };
                   1075: 
                   1076: mframe_t fixbot_frames_weld_start [] = 
                   1077: {
                   1078:        ai_move2, 0, NULL,
                   1079:        ai_move2, 0, NULL,
                   1080:        ai_move2, 0, NULL,
                   1081:        ai_move2, 0, NULL,
                   1082:        ai_move2, 0, NULL,
                   1083:        ai_move2, 0, NULL,
                   1084:        ai_move2, 0, NULL,
                   1085:        ai_move2, 0, NULL,
                   1086:        ai_move2, 0, NULL,
                   1087:        ai_move2, 0, weldstate
                   1088: };
                   1089: mmove_t fixbot_move_weld_start = {FRAME_weldstart_01, FRAME_weldstart_10, fixbot_frames_weld_start, NULL};
                   1090: 
                   1091: mframe_t fixbot_frames_weld [] =
                   1092: {
                   1093:        ai_move2, 0, fixbot_fire_welder,
                   1094:        ai_move2, 0, fixbot_fire_welder,
                   1095:        ai_move2, 0, fixbot_fire_welder,
                   1096:        ai_move2, 0, fixbot_fire_welder,
                   1097:        ai_move2, 0, fixbot_fire_welder,
                   1098:        ai_move2, 0, fixbot_fire_welder,
                   1099:        ai_move2, 0, weldstate
                   1100: };
                   1101: mmove_t fixbot_move_weld = {FRAME_weldmiddle_01, FRAME_weldmiddle_07, fixbot_frames_weld, NULL};
                   1102: 
                   1103: mframe_t fixbot_frames_weld_end [] =
                   1104: {
                   1105:        ai_move2, -2, NULL,
                   1106:        ai_move2, -2, NULL,
                   1107:        ai_move2, -2, NULL,
                   1108:        ai_move2, -2, NULL,
                   1109:        ai_move2, -2, NULL,
                   1110:        ai_move2, -2, NULL,
                   1111:        ai_move2, -2, weldstate
                   1112: };
                   1113: mmove_t fixbot_move_weld_end = {FRAME_weldend_01, FRAME_weldend_07, fixbot_frames_weld_end, NULL};
                   1114: 
                   1115: 
                   1116: void fixbot_fire_welder (edict_t *self)
                   1117: {
                   1118:        vec3_t  start;
                   1119:        vec3_t  forward, right, up;
                   1120:        vec3_t  end;
                   1121:        vec3_t  dir;
                   1122:        int             count = 2;
                   1123:        vec3_t  vec;
                   1124:        float   r;
                   1125:        
                   1126:        if (!self->enemy)
                   1127:                return;
                   1128: 
                   1129: 
                   1130:        vec[0]=24.0;
                   1131:        vec[1]=-0.8;
                   1132:        vec[2]=-10.0;
                   1133: 
                   1134:        AngleVectors (self->s.angles, forward, right, up);
                   1135:        G_ProjectSource (self->s.origin, vec, forward, right, start);
                   1136: 
                   1137:        VectorCopy (self->enemy->s.origin, end);
                   1138:        
                   1139:        VectorSubtract (end, start, dir);
                   1140: 
                   1141:        gi.WriteByte (svc_temp_entity);
                   1142:        gi.WriteByte (TE_WELDING_SPARKS);
                   1143:        gi.WriteByte (10);
                   1144:        gi.WritePosition (start);
                   1145:        gi.WriteDir (vec3_origin);
                   1146:        gi.WriteByte (0xe0 + (rand()&7));
                   1147:        gi.multicast (self->s.origin, MULTICAST_PVS);
                   1148: 
                   1149: 
                   1150:        if (random() > 0.8)
                   1151:        {
                   1152:                r = random();
                   1153: 
                   1154:                if (r < 0.33)
                   1155:                        gi.sound (self, CHAN_VOICE, sound_weld1, 1, ATTN_IDLE, 0);
                   1156:                else if (r < 0.66)
                   1157:                        gi.sound (self, CHAN_VOICE, sound_weld2, 1, ATTN_IDLE, 0);
                   1158:                else
                   1159:                        gi.sound (self, CHAN_VOICE, sound_weld3, 1, ATTN_IDLE, 0);
                   1160:        }
                   1161: }
                   1162: 
                   1163: void fixbot_fire_blaster (edict_t *self)
                   1164: {
                   1165:        vec3_t  start;
                   1166:        vec3_t  forward, right, up;
                   1167:        vec3_t  end;
                   1168:        vec3_t  dir;
                   1169: 
                   1170:        if (!visible(self, self->enemy))
                   1171:        {
                   1172:                self->monsterinfo.currentmove = &fixbot_move_run;       
                   1173:        }
                   1174:        
                   1175:        AngleVectors (self->s.angles, forward, right, up);
                   1176:        G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_fixbot_BLASTER_1], forward, right, start);
                   1177: 
                   1178:        VectorCopy (self->enemy->s.origin, end);
                   1179:        end[2] += self->enemy->viewheight;
                   1180:        VectorSubtract (end, start, dir);
                   1181: 
                   1182:        monster_fire_blaster (self, start, dir, 15, 1000, MZ2_fixbot_BLASTER_1, EF_BLASTER);
                   1183:        
                   1184: }
                   1185: 
                   1186: void fixbot_stand (edict_t *self)
                   1187: {
                   1188:        self->monsterinfo.currentmove = &fixbot_move_stand;
                   1189: }
                   1190: 
                   1191: void fixbot_run (edict_t *self)
                   1192: {
                   1193:        if (self->monsterinfo.aiflags & AI_STAND_GROUND)
                   1194:                self->monsterinfo.currentmove = &fixbot_move_stand;
                   1195:        else
                   1196:                self->monsterinfo.currentmove = &fixbot_move_run;
                   1197: }
                   1198: 
                   1199: void fixbot_walk (edict_t *self)
                   1200: {
                   1201:        vec3_t  vec;
                   1202:        int             len;
                   1203: 
                   1204:        if (strcmp (self->goalentity->classname, "object_repair") == 0)
                   1205:        {
                   1206:                VectorSubtract (self->s.origin, self->goalentity->s.origin, vec);
                   1207:                len = VectorLength (vec);
                   1208:                if (len < 32)
                   1209:                {
                   1210:                        self->monsterinfo.currentmove = &fixbot_move_weld_start;
                   1211:                        return;
                   1212:                }
                   1213:        }
                   1214:        self->monsterinfo.currentmove = &fixbot_move_walk;
                   1215: }
                   1216: 
                   1217: void fixbot_start_attack (edict_t *self)
                   1218: {
                   1219:        self->monsterinfo.currentmove = &fixbot_move_start_attack;
                   1220: }
                   1221: 
                   1222: void fixbot_attack(edict_t *self)
                   1223: {
                   1224:        vec3_t  vec;
                   1225:        int             len;
                   1226:        
                   1227:        if (self->monsterinfo.aiflags & AI_MEDIC)
                   1228:        {
                   1229:                if (!visible (self, self->goalentity))
                   1230:                        return;
                   1231:                VectorSubtract (self->s.origin, self->enemy->s.origin, vec);
                   1232:                len = VectorLength(vec);
                   1233:                if (len > 128)
                   1234:                        return;
                   1235:                else
                   1236:                        self->monsterinfo.currentmove = &fixbot_move_laserattack;
                   1237:        }
                   1238:        else
                   1239:                self->monsterinfo.currentmove = &fixbot_move_attack2;
                   1240:        
                   1241: }
                   1242: 
                   1243: 
                   1244: void fixbot_pain (edict_t *self, edict_t *other, float kick, int damage)
                   1245: {
                   1246: //     if (self->health < (self->max_health / 2))
                   1247: //             self->s.skinnum = 1;
                   1248:        // gi.dprintf("pain\n");
                   1249: 
                   1250:        if (level.time < self->pain_debounce_time)
                   1251:                return;
                   1252: 
                   1253:        self->pain_debounce_time = level.time + 3;
                   1254:        gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
                   1255: 
                   1256:        if (damage <= 10)
                   1257:                self->monsterinfo.currentmove = &fixbot_move_pain3;
                   1258:        else if (damage <= 25)
                   1259:                self->monsterinfo.currentmove = &fixbot_move_painb;
                   1260:        else
                   1261:                self->monsterinfo.currentmove = &fixbot_move_paina;
                   1262: }
                   1263: 
                   1264: void fixbot_dead (edict_t *self)
                   1265: {
                   1266:        VectorSet (self->mins, -16, -16, -24);
                   1267:        VectorSet (self->maxs, 16, 16, -8);
                   1268:        self->movetype = MOVETYPE_TOSS;
                   1269:        self->svflags |= SVF_DEADMONSTER;
                   1270:        self->nextthink = 0;
                   1271:        gi.linkentity (self);
                   1272: }
                   1273: 
                   1274: void fixbot_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
                   1275: {
                   1276:        gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
                   1277:        BecomeExplosion1(self);
                   1278: 
                   1279:        // shards
                   1280:        
                   1281: }
                   1282: 
                   1283: /*QUAKED monster_fixbot (1 .5 0) (-32 -32 -24) (32 32 24) Ambush Trigger_Spawn Fixit Takeoff Landing
                   1284: */
                   1285: void SP_monster_fixbot (edict_t *self)
                   1286: {
                   1287:        if (deathmatch->value)
                   1288:        {
                   1289:                G_FreeEdict (self);
                   1290:                return;
                   1291:        }
                   1292: 
                   1293:        sound_pain1 = gi.soundindex ("flyer/flypain1.wav");
                   1294:        sound_die = gi.soundindex ("flyer/flydeth1.wav");
                   1295: 
                   1296:        sound_weld1 = gi.soundindex ("misc/welder1.wav");
                   1297:        sound_weld2 = gi.soundindex ("misc/welder2.wav");
                   1298:        sound_weld3 = gi.soundindex ("misc/welder3.wav");
                   1299: 
                   1300:        self->s.modelindex = gi.modelindex ("models/monsters/fixbot/tris.md2");
                   1301:        
                   1302:        VectorSet (self->mins, -32, -32, -24);
                   1303:        VectorSet (self->maxs, 32, 32, 24);
                   1304:        
                   1305:        self->movetype = MOVETYPE_STEP;
                   1306:        self->solid = SOLID_BBOX;
                   1307: 
                   1308:        self->health = 150;
                   1309:        self->mass = 150;
                   1310: 
                   1311:        self->pain = fixbot_pain;
                   1312:        self->die = fixbot_die;
                   1313: 
                   1314:        self->monsterinfo.stand = fixbot_stand;
                   1315:        self->monsterinfo.walk = fixbot_walk;
                   1316:        self->monsterinfo.run = fixbot_run;
                   1317:        self->monsterinfo.attack = fixbot_attack;
                   1318:        
                   1319:        gi.linkentity (self);
                   1320: 
                   1321:        self->monsterinfo.currentmove = &fixbot_move_stand;     
                   1322:        self->monsterinfo.scale = MODEL_SCALE;
                   1323:                        
                   1324:        flymonster_start (self);
                   1325:                                
                   1326: }
                   1327: 
                   1328: 

unix.superglobalmegacorp.com

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