home *** CD-ROM | disk | FTP | other *** search
/ Gambler 19 / GAMBLERCD19.BIN / UTILS / 3D / BRONIE / DUAL_LAU.ZIP / src / m_actor.c < prev    next >
C/C++ Source or Header  |  1997-11-25  |  13KB  |  590 lines

  1. // g_actor.c
  2.  
  3. #include "g_local.h"
  4. #include "m_actor.h"
  5.  
  6. #define    MAX_ACTOR_NAMES        8
  7. char *actor_names[MAX_ACTOR_NAMES] =
  8. {
  9.     "Hellrot",
  10.     "Tokay",
  11.     "Killme",
  12.     "Disruptor",
  13.     "Adrianator",
  14.     "Rambear",
  15.     "Titus",
  16.     "Bitterman"
  17. };
  18.  
  19.  
  20. mframe_t actor_frames_stand [] =
  21. {
  22.     ai_stand, 0, NULL,
  23.     ai_stand, 0, NULL,
  24.     ai_stand, 0, NULL,
  25.     ai_stand, 0, NULL,
  26.     ai_stand, 0, NULL,
  27.     ai_stand, 0, NULL,
  28.     ai_stand, 0, NULL,
  29.     ai_stand, 0, NULL,
  30.     ai_stand, 0, NULL,
  31.     ai_stand, 0, NULL,
  32.  
  33.     ai_stand, 0, NULL,
  34.     ai_stand, 0, NULL,
  35.     ai_stand, 0, NULL,
  36.     ai_stand, 0, NULL,
  37.     ai_stand, 0, NULL,
  38.     ai_stand, 0, NULL,
  39.     ai_stand, 0, NULL,
  40.     ai_stand, 0, NULL,
  41.     ai_stand, 0, NULL,
  42.     ai_stand, 0, NULL,
  43.  
  44.     ai_stand, 0, NULL,
  45.     ai_stand, 0, NULL,
  46.     ai_stand, 0, NULL,
  47.     ai_stand, 0, NULL,
  48.     ai_stand, 0, NULL,
  49.     ai_stand, 0, NULL,
  50.     ai_stand, 0, NULL,
  51.     ai_stand, 0, NULL,
  52.     ai_stand, 0, NULL,
  53.     ai_stand, 0, NULL,
  54.  
  55.     ai_stand, 0, NULL,
  56.     ai_stand, 0, NULL,
  57.     ai_stand, 0, NULL,
  58.     ai_stand, 0, NULL,
  59.     ai_stand, 0, NULL,
  60.     ai_stand, 0, NULL,
  61.     ai_stand, 0, NULL,
  62.     ai_stand, 0, NULL,
  63.     ai_stand, 0, NULL,
  64.     ai_stand, 0, NULL
  65. };
  66. mmove_t actor_move_stand = {FRAME_stand101, FRAME_stand140, actor_frames_stand, NULL};
  67.  
  68. void actor_stand (edict_t *self)
  69. {
  70.     self->monsterinfo.currentmove = &actor_move_stand;
  71.  
  72.     // randomize on startup
  73.     if (level.time < 1.0)
  74.         self->s.frame = self->monsterinfo.currentmove->firstframe + (rand() % (self->monsterinfo.currentmove->lastframe - self->monsterinfo.currentmove->firstframe + 1));
  75. }
  76.  
  77.  
  78. mframe_t actor_frames_walk [] =
  79. {
  80.     ai_walk, 0,  NULL,
  81.     ai_walk, 6,  NULL,
  82.     ai_walk, 10, NULL,
  83.     ai_walk, 3,  NULL,
  84.     ai_walk, 2,  NULL,
  85.     ai_walk, 7,  NULL,
  86.     ai_walk, 10, NULL,
  87.     ai_walk, 1,  NULL,
  88.     ai_walk, 4,  NULL,
  89.     ai_walk, 0,  NULL,
  90.     ai_walk, 0,  NULL
  91. };
  92. mmove_t actor_move_walk = {FRAME_walk01, FRAME_walk08, actor_frames_walk, NULL};
  93.  
  94. void actor_walk (edict_t *self)
  95. {
  96.     self->monsterinfo.currentmove = &actor_move_walk;
  97. }
  98.  
  99.  
  100. mframe_t actor_frames_run [] =
  101. {
  102.     ai_run, 4,  NULL,
  103.     ai_run, 15, NULL,
  104.     ai_run, 15, NULL,
  105.     ai_run, 8,  NULL,
  106.     ai_run, 20, NULL,
  107.     ai_run, 15, NULL,
  108.     ai_run, 8,  NULL,
  109.     ai_run, 17, NULL,
  110.     ai_run, 12, NULL,
  111.     ai_run, -2, NULL,
  112.     ai_run, -2, NULL,
  113.     ai_run, -1, NULL
  114. };
  115. mmove_t actor_move_run = {FRAME_run02, FRAME_run07, actor_frames_run, NULL};
  116.  
  117. void actor_run (edict_t *self)
  118. {
  119.     if ((level.time < self->pain_debounce_time) && (!self->enemy))
  120.     {
  121.         if (self->movetarget)
  122.             actor_walk(self);
  123.         else
  124.             actor_stand(self);
  125.         return;
  126.     }
  127.  
  128.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  129.     {
  130.         actor_stand(self);
  131.         return;
  132.     }
  133.  
  134.     self->monsterinfo.currentmove = &actor_move_run;
  135. }
  136.  
  137.  
  138. mframe_t actor_frames_pain1 [] =
  139. {
  140.     ai_move, -5, NULL,
  141.     ai_move, 4,  NULL,
  142.     ai_move, 1,  NULL
  143. };
  144. mmove_t actor_move_pain1 = {FRAME_pain101, FRAME_pain103, actor_frames_pain1, actor_run};
  145.  
  146. mframe_t actor_frames_pain2 [] =
  147. {
  148.     ai_move, -4, NULL,
  149.     ai_move, 4,  NULL,
  150.     ai_move, 0,  NULL
  151. };
  152. mmove_t actor_move_pain2 = {FRAME_pain201, FRAME_pain203, actor_frames_pain2, actor_run};
  153.  
  154. mframe_t actor_frames_pain3 [] =
  155. {
  156.     ai_move, -1, NULL,
  157.     ai_move, 1,  NULL,
  158.     ai_move, 0,  NULL
  159. };
  160. mmove_t actor_move_pain3 = {FRAME_pain301, FRAME_pain303, actor_frames_pain3, actor_run};
  161.  
  162. mframe_t actor_frames_flipoff [] =
  163. {
  164.     ai_turn, 0,  NULL,
  165.     ai_turn, 0,  NULL,
  166.     ai_turn, 0,  NULL,
  167.     ai_turn, 0,  NULL,
  168.     ai_turn, 0,  NULL,
  169.     ai_turn, 0,  NULL,
  170.     ai_turn, 0,  NULL,
  171.     ai_turn, 0,  NULL,
  172.     ai_turn, 0,  NULL,
  173.     ai_turn, 0,  NULL,
  174.     ai_turn, 0,  NULL,
  175.     ai_turn, 0,  NULL,
  176.     ai_turn, 0,  NULL,
  177.     ai_turn, 0,  NULL
  178. };
  179. mmove_t actor_move_flipoff = {FRAME_flip01, FRAME_flip14, actor_frames_flipoff, actor_run};
  180.  
  181. mframe_t actor_frames_taunt [] =
  182. {
  183.     ai_turn, 0,  NULL,
  184.     ai_turn, 0,  NULL,
  185.     ai_turn, 0,  NULL,
  186.     ai_turn, 0,  NULL,
  187.     ai_turn, 0,  NULL,
  188.     ai_turn, 0,  NULL,
  189.     ai_turn, 0,  NULL,
  190.     ai_turn, 0,  NULL,
  191.     ai_turn, 0,  NULL,
  192.     ai_turn, 0,  NULL,
  193.     ai_turn, 0,  NULL,
  194.     ai_turn, 0,  NULL,
  195.     ai_turn, 0,  NULL,
  196.     ai_turn, 0,  NULL,
  197.     ai_turn, 0,  NULL,
  198.     ai_turn, 0,  NULL,
  199.     ai_turn, 0,  NULL
  200. };
  201. mmove_t actor_move_taunt = {FRAME_taunt01, FRAME_taunt17, actor_frames_taunt, actor_run};
  202.  
  203. char *messages[] =
  204. {
  205.     "Watch it",
  206.     "#$@*&",
  207.     "Idiot",
  208.     "Check your targets"
  209. };
  210.  
  211. void actor_pain (edict_t *self, edict_t *other, float kick, int damage)
  212. {
  213.     int        n;
  214.  
  215.     if (self->health < (self->max_health / 2))
  216.         self->s.skinnum = 1;
  217.  
  218.     if (level.time < self->pain_debounce_time)
  219.         return;
  220.  
  221.     self->pain_debounce_time = level.time + 3;
  222. //    gi.sound (self, CHAN_VOICE, actor.sound_pain, 1, ATTN_NORM, 0);
  223.  
  224.     if ((other->client) && (random() < 0.4))
  225.     {
  226.         vec3_t    v;
  227.         char    *name;
  228.  
  229.         VectorSubtract (other->s.origin, self->s.origin, v);
  230.         self->ideal_yaw = vectoyaw (v);
  231.         if (random() < 0.5)
  232.             self->monsterinfo.currentmove = &actor_move_flipoff;
  233.         else
  234.             self->monsterinfo.currentmove = &actor_move_taunt;
  235.         name = actor_names[(self - g_edicts)%MAX_ACTOR_NAMES];
  236.         gi.cprintf (other, PRINT_CHAT, "%s: %s!\n", name, messages[rand()%3]);
  237.         return;
  238.     }
  239.  
  240.     n = rand() % 3;
  241.     if (n == 0)
  242.         self->monsterinfo.currentmove = &actor_move_pain1;
  243.     else if (n == 1)
  244.         self->monsterinfo.currentmove = &actor_move_pain2;
  245.     else
  246.         self->monsterinfo.currentmove = &actor_move_pain3;
  247. }
  248.  
  249.  
  250. void actorMachineGun (edict_t *self)
  251. {
  252.     vec3_t    start, target;
  253.     vec3_t    forward, right;
  254.  
  255.     AngleVectors (self->s.angles, forward, right, NULL);
  256.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_ACTOR_MACHINEGUN_1], forward, right, start);
  257.     if (self->enemy)
  258.     {
  259.         if (self->enemy->health > 0)
  260.         {
  261.             VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  262.             target[2] += self->enemy->viewheight;
  263.         }
  264.         else
  265.         {
  266.             VectorCopy (self->enemy->absmin, target);
  267.             target[2] += (self->enemy->size[2] / 2);
  268.         }
  269.         VectorSubtract (target, start, forward);
  270.         VectorNormalize (forward);
  271.     }
  272.     else
  273.     {
  274.         AngleVectors (self->s.angles, forward, NULL, NULL);
  275.     }
  276.     monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_ACTOR_MACHINEGUN_1);
  277. }
  278.  
  279.  
  280. void actor_dead (edict_t *self)
  281. {
  282.     VectorSet (self->mins, -16, -16, -24);
  283.     VectorSet (self->maxs, 16, 16, -8);
  284.     self->movetype = MOVETYPE_TOSS;
  285.     self->nextthink = 0;
  286.     gi.linkentity (self);
  287. }
  288.  
  289. mframe_t actor_frames_death1 [] =
  290. {
  291.     ai_move, 0,   NULL,
  292.     ai_move, 0,   NULL,
  293.     ai_move, -13, NULL,
  294.     ai_move, 14,  NULL,
  295.     ai_move, 3,   NULL,
  296.     ai_move, -2,  NULL,
  297.     ai_move, 1,   NULL
  298. };
  299. mmove_t actor_move_death1 = {FRAME_death101, FRAME_death107, actor_frames_death1, actor_dead};
  300.  
  301. mframe_t actor_frames_death2 [] =
  302. {
  303.     ai_move, 0,   NULL,
  304.     ai_move, 7,   NULL,
  305.     ai_move, -6,  NULL,
  306.     ai_move, -5,  NULL,
  307.     ai_move, 1,   NULL,
  308.     ai_move, 0,   NULL,
  309.     ai_move, -1,  NULL,
  310.     ai_move, -2,  NULL,
  311.     ai_move, -1,  NULL,
  312.     ai_move, -9,  NULL,
  313.     ai_move, -13, NULL,
  314.     ai_move, -13, NULL,
  315.     ai_move, 0,   NULL
  316. };
  317. mmove_t actor_move_death2 = {FRAME_death201, FRAME_death213, actor_frames_death2, actor_dead};
  318.  
  319. void actor_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  320. {
  321.     int        n;
  322.  
  323. // check for gib
  324.     if (self->health <= -80)
  325.     {
  326. //        gi.sound (self, CHAN_VOICE, actor.sound_gib, 1, ATTN_NORM, 0);
  327.         for (n= 0; n < 2; n++)
  328.             ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  329.         for (n= 0; n < 4; n++)
  330.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  331.         ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  332.         self->deadflag = DEAD_DEAD;
  333.         return;
  334.     }
  335.  
  336.     if (self->deadflag == DEAD_DEAD)
  337.         return;
  338.  
  339. // regular death
  340. //    gi.sound (self, CHAN_VOICE, actor.sound_die, 1, ATTN_NORM, 0);
  341.     self->deadflag = DEAD_DEAD;
  342.     self->takedamage = DAMAGE_YES;
  343.  
  344.     n = rand() % 2;
  345.     if (n == 0)
  346.         self->monsterinfo.currentmove = &actor_move_death1;
  347.     else
  348.         self->monsterinfo.currentmove = &actor_move_death2;
  349. }
  350.  
  351.  
  352. void actor_fire (edict_t *self)
  353. {
  354.     actorMachineGun (self);
  355.  
  356.     if (level.time >= self->monsterinfo.pausetime)
  357.         self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  358.     else
  359.         self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  360. }
  361.  
  362. mframe_t actor_frames_attack [] =
  363. {
  364.     ai_charge, -2,  actor_fire,
  365.     ai_charge, -2,  NULL,
  366.     ai_charge, 3,   NULL,
  367.     ai_charge, 2,   NULL
  368. };
  369. mmove_t actor_move_attack = {FRAME_attak01, FRAME_attak04, actor_frames_attack, actor_run};
  370.  
  371. void actor_attack(edict_t *self)
  372. {
  373.     int        n;
  374.  
  375.     self->monsterinfo.currentmove = &actor_move_attack;
  376.     n = (rand() & 15) + 3 + 7;
  377.     self->monsterinfo.pausetime = level.time + n * FRAMETIME;
  378. }
  379.  
  380.  
  381. void actor_use (edict_t *self, edict_t *other, edict_t *activator)
  382. {
  383.     vec3_t        v;
  384.  
  385.     self->goalentity = self->movetarget = G_PickTarget(self->target);
  386.     if ((!self->movetarget) || (strcmp(self->movetarget->classname, "target_actor") != 0))
  387.     {
  388.         gi.dprintf ("%s has bad target %s at %s\n", self->classname, self->target, vtos(self->s.origin));
  389.         self->target = NULL;
  390.         self->monsterinfo.pausetime = 100000000;
  391.         self->monsterinfo.stand (self);
  392.         return;
  393.     }
  394.  
  395.     VectorSubtract (self->goalentity->s.origin, self->s.origin, v);
  396.     self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v);
  397.     self->monsterinfo.walk (self);
  398.     self->target = NULL;
  399. }
  400.  
  401.  
  402. /*QUAKED misc_actor (1 .5 0) (-16 -16 -24) (16 16 32)
  403. */
  404.  
  405. void SP_misc_actor (edict_t *self)
  406. {
  407.     if (deathmatch->value)
  408.     {
  409.         G_FreeEdict (self);
  410.         return;
  411.     }
  412.  
  413.     if (!self->targetname)
  414.     {
  415.         gi.dprintf("untargeted %s at %s\n", self->classname, vtos(self->s.origin));
  416.         G_FreeEdict (self);
  417.         return;
  418.     }
  419.  
  420.     if (!self->target)
  421.     {
  422.         gi.dprintf("%s with no target at %s\n", self->classname, vtos(self->s.origin));
  423.         G_FreeEdict (self);
  424.         return;
  425.     }
  426.  
  427.     self->movetype = MOVETYPE_STEP;
  428.     self->solid = SOLID_BBOX;
  429.     self->s.modelindex = gi.modelindex("players/male/tris.md2");
  430.     VectorSet (self->mins, -16, -16, -24);
  431.     VectorSet (self->maxs, 16, 16, 32);
  432.  
  433.     if (!self->health)
  434.         self->health = 100;
  435.     self->mass = 200;
  436.  
  437.     self->pain = actor_pain;
  438.     self->die = actor_die;
  439.  
  440.     self->monsterinfo.stand = actor_stand;
  441.     self->monsterinfo.walk = actor_walk;
  442.     self->monsterinfo.run = actor_run;
  443.     self->monsterinfo.attack = actor_attack;
  444.     self->monsterinfo.melee = NULL;
  445.     self->monsterinfo.sight = NULL;
  446.  
  447.     self->monsterinfo.aiflags |= AI_GOOD_GUY;
  448.  
  449.     gi.linkentity (self);
  450.  
  451.     self->monsterinfo.currentmove = &actor_move_stand;
  452.     self->monsterinfo.scale = MODEL_SCALE;
  453.  
  454.     walkmonster_start (self);
  455.  
  456.     // actors always start in a dormant state, they *must* be used to get going
  457.     self->use = actor_use;
  458. }
  459.  
  460.  
  461. /*QUAKED target_actor (.5 .3 0) (-8 -8 -8) (8 8 8) JUMP SHOOT ATTACK x HOLD BRUTAL
  462. JUMP            jump in set direction upon reaching this target
  463. SHOOT            take a single shot at the pathtarget
  464. ATTACK            attack pathtarget until it or actor is dead 
  465.  
  466. "target"        next target_actor
  467. "pathtarget"    target of any action to be taken at this point
  468. "wait"            amount of time actor should pause at this point
  469. "message"        actor will "say" this to the player
  470.  
  471. for JUMP only:
  472. "speed"            speed thrown forward (default 200)
  473. "height"        speed thrown upwards (default 200)
  474. */
  475.  
  476. void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
  477. {
  478.     vec3_t    v;
  479.  
  480.     if (other->movetarget != self)
  481.         return;
  482.     
  483.     if (other->enemy)
  484.         return;
  485.  
  486.     other->goalentity = other->movetarget = NULL;
  487.  
  488.     if (self->message)
  489.     {
  490.         int        n;
  491.         edict_t    *ent;
  492.  
  493.         for (n = 1; n <= game.maxclients; n++)
  494.         {
  495.             ent = &g_edicts[n];
  496.             if (!ent->inuse)
  497.                 continue;
  498.             gi.cprintf (ent, PRINT_CHAT, "%s: %s\n", actor_names[(other - g_edicts)%MAX_ACTOR_NAMES], self->message);
  499.         }
  500.     }
  501.  
  502.     if (self->spawnflags & 1)        //jump
  503.     {
  504.         other->velocity[0] = self->movedir[0] * self->speed;
  505.         other->velocity[1] = self->movedir[1] * self->speed;
  506.         
  507.         if (other->groundentity)
  508.         {
  509.             other->groundentity = NULL;
  510.             other->velocity[2] = self->movedir[2];
  511.             gi.sound(other, CHAN_VOICE, gi.soundindex("player/male/jump1.wav"), 1, ATTN_NORM, 0);
  512.         }
  513.     }
  514.  
  515.     if (self->spawnflags & 2)    //shoot
  516.     {
  517.     }
  518.     else if (self->spawnflags & 4)    //attack
  519.     {
  520.         other->enemy = G_PickTarget(self->pathtarget);
  521.         if (other->enemy)
  522.         {
  523.             other->goalentity = other->enemy;
  524.             if (self->spawnflags & 32)
  525.                 other->monsterinfo.aiflags |= AI_BRUTAL;
  526.             if (self->spawnflags & 16)
  527.             {
  528.                 other->monsterinfo.aiflags |= AI_STAND_GROUND;
  529.                 actor_stand (other);
  530.             }
  531.             else
  532.             {
  533.                 actor_run (other);
  534.             }
  535.         }
  536.     }
  537.  
  538.     if (!(self->spawnflags & 6) && (self->pathtarget))
  539.     {
  540.         char *savetarget;
  541.  
  542.         savetarget = self->target;
  543.         self->target = self->pathtarget;
  544.         G_UseTargets (self, other);
  545.         self->target = savetarget;
  546.     }
  547.  
  548.     other->movetarget = G_PickTarget(self->target);
  549.  
  550.     if (!other->goalentity)
  551.         other->goalentity = other->movetarget;
  552.  
  553.     if (!other->movetarget && !other->enemy)
  554.     {
  555.         other->monsterinfo.pausetime = level.time + 100000000;
  556.         other->monsterinfo.stand (other);
  557.     }
  558.     else if (other->movetarget == other->goalentity)
  559.     {
  560.         VectorSubtract (other->movetarget->s.origin, other->s.origin, v);
  561.         other->ideal_yaw = vectoyaw (v);
  562.     }
  563. }
  564.  
  565. void SP_target_actor (edict_t *self)
  566. {
  567.     if (!self->targetname)
  568.         gi.dprintf ("%s with no targetname at %s\n", self->classname, vtos(self->s.origin));
  569.  
  570.     self->solid = SOLID_TRIGGER;
  571.     self->touch = target_actor_touch;
  572.     VectorSet (self->mins, -8, -8, -8);
  573.     VectorSet (self->maxs, 8, 8, 8);
  574.     self->svflags = SVF_NOCLIENT;
  575.  
  576.     if (self->spawnflags & 1)
  577.     {
  578.         if (!self->speed)
  579.             self->speed = 200;
  580.         if (!st.height)
  581.             st.height = 200;
  582.         if (self->s.angles[YAW] == 0)
  583.             self->s.angles[YAW] = 360;
  584.         G_SetMovedir (self->s.angles, self->movedir);
  585.         self->movedir[2] = st.height;
  586.     }
  587.  
  588.     gi.linkentity (self);
  589. }
  590.