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