|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.