thirtyflightsofloving/missionpack/m_q1rotfish.c
Knightmare66 8401c475f6 Improved Tactician Gunner's prox mine aiming in missionpack DLL.
Added powerarmortype field to default Lazaus DLL.  This changes the savegame version.
Added support for blood_type value of 4 to default Lazaurus, missionpack, and Zaero DLLs.
Added support for Lazarus initially dead monsters (health < 0) to missionpack DLL.
Added support for Lazarus monsterjump cvar (berserk, gunner, infantry, mutant, parasite) to missionpack DLL.
Cleaned up surface rendering code from mpolyvertex_t refactoring.
2021-07-31 02:07:06 -04:00

307 lines
7.3 KiB
C

/*
==============================================================================
QUAKE ROTFISH
==============================================================================
*/
#include "g_local.h"
#include "m_q1rotfish.h"
#define Q1_FISH_RUN_SPEED 12
#define Q1_FISH_WALK_SPEED 8
#define Q1_FISH_MELEE_DISTANCE 60
static int sound_chomp;
static int sound_death;
static int sound_idle;
void q1rotfish_idle (edict_t *self)
{
if (random() < 0.5)
gi.sound (self, CHAN_AUTO, sound_idle, 1, ATTN_IDLE, 0);
}
void q1rotfish_stand (edict_t *self);
mframe_t q1rotfish_frames_stand [] =
{
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL
};
mmove_t q1rotfish_move_stand = {FRAME_swim1, FRAME_swim18, q1rotfish_frames_stand, NULL};
void q1rotfish_stand (edict_t *self)
{
self->monsterinfo.currentmove = &q1rotfish_move_stand;
}
mframe_t q1rotfish_frrun_loop [] =
{
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL,
ai_run, Q1_FISH_RUN_SPEED, NULL
};
mmove_t q1rotfish_move_run_loop = {FRAME_swim1, FRAME_swim18, q1rotfish_frrun_loop, NULL};
void q1rotfish_run (edict_t *self)
{
self->monsterinfo.currentmove = &q1rotfish_move_run_loop;
}
/* Standard Swimming */
mframe_t q1rotfish_walk_loop [] =
{
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL,
ai_walk, Q1_FISH_WALK_SPEED, NULL
};
mmove_t q1rotfish_move_walk_loop = {FRAME_swim1, FRAME_swim18, q1rotfish_walk_loop, NULL};
void q1rotfish_walk (edict_t *self)
{
self->monsterinfo.currentmove = &q1rotfish_move_walk_loop;
}
mframe_t q1rotfish_frames_pain1 [] =
{
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL
};
mmove_t q1rotfish_move_pain1 = {FRAME_pain1, FRAME_pain9, q1rotfish_frames_pain1, q1rotfish_run};
void q1rotfish_bite (edict_t *self)
{
vec3_t aim;
if (!self->enemy)
return;
VectorSet (aim, Q1_FISH_MELEE_DISTANCE, 0, 0);
gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0);
fire_hit (self, aim, (random() + random()) * 3, 0);
}
mframe_t q1rotfish_frames_attack [] =
{
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 0, q1rotfish_bite,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 0, q1rotfish_bite,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 0, q1rotfish_bite,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
ai_charge, 10, NULL,
};
mmove_t q1rotfish_move_attack = {FRAME_attack1, FRAME_attack18, q1rotfish_frames_attack, q1rotfish_run};
void q1rotfish_melee(edict_t *self)
{
self->monsterinfo.currentmove = &q1rotfish_move_attack;
}
void q1rotfish_pain (edict_t *self, edict_t *other, float kick, int damage)
{
self->monsterinfo.currentmove = &q1rotfish_move_pain1;
}
void q1rotfish_dead (edict_t *self)
{
VectorSet (self->mins, -16, -16, -24);
VectorSet (self->maxs, 16, 16, -8);
self->gib_health = -10000;
self->movetype = MOVETYPE_TOSS;
self->svflags |= SVF_DEADMONSTER;
gi.linkentity (self);
}
mframe_t q1rotfish_frames_death [] =
{
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
};
mmove_t q1rotfish_move_death = {FRAME_death1, FRAME_death21, q1rotfish_frames_death, q1rotfish_dead};
void q1rotfish_sight (edict_t *self, edict_t *other)
{
}
void q1rotfish_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{
if (self->deadflag == DEAD_DEAD)
return;
// regular death
gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
self->deadflag = DEAD_DEAD;
self->takedamage = DAMAGE_YES;
self->movetype = MOVETYPE_TOSS;
self->monsterinfo.currentmove = &q1rotfish_move_death;
}
//
// SPAWN
//
/*QUAKED monster_q1_rotfish (1 .5 0) (-16 -16 -24) (16 16 24) Ambush Trigger_Spawn Sight
model="models/monsters/q1rotfish/tris.md2"
*/
void SP_monster_q1_rotfish (edict_t *self)
{
if (deathmatch->value)
{
G_FreeEdict (self);
return;
}
sound_death = gi.soundindex ("q1rotfish/death.wav");
sound_chomp = gi.soundindex ("q1rotfish/bite.wav");
sound_idle = gi.soundindex ("q1rotfish/idle.wav");
self->movetype = MOVETYPE_STEP;
self->solid = SOLID_BBOX;
// Lazarus: special purpose skins
if ( self->style )
{
PatchMonsterModel("models/monsters/q1rotfish/tris.md2");
self->s.skinnum = self->style;
}
self->s.modelindex = gi.modelindex ("models/monsters/q1rotfish/tris.md2");
VectorSet (self->mins, -16, -16, -24);
VectorSet (self->maxs, 16, 16, 24);
if (!self->health)
self->health = 25;
// if (!self->gib_health)
self->gib_health = 0;
if (!self->mass)
self->mass = 100;
self->pain = q1rotfish_pain;
self->die = q1rotfish_die;
self->flags |= FL_Q1_MONSTER;
self->monsterinfo.stand = q1rotfish_stand;
self->monsterinfo.walk = q1rotfish_walk;
self->monsterinfo.run = q1rotfish_run;
self->monsterinfo.melee = q1rotfish_melee;
self->monsterinfo.sight = q1rotfish_sight;
if (!self->monsterinfo.flies)
self->monsterinfo.flies = 0.95;
// Lazarus
if (self->powerarmor)
{
if (self->powerarmortype == 1)
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
else
self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
self->monsterinfo.power_armor_power = self->powerarmor;
}
self->common_name = "Rotfish";
self->class_id = ENTITY_MONSTER_Q1_ROTFISH;
gi.linkentity (self);
self->monsterinfo.currentmove = &q1rotfish_move_stand;
if (self->health < 0)
{
mmove_t *deathmoves[] = {&q1rotfish_move_death,
NULL};
M_SetDeath (self, (mmove_t **)&deathmoves);
}
self->monsterinfo.scale = MODEL_SCALE;
swimmonster_start (self);
}