mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-14 16:40:57 +00:00
add4c7cc46
Added new SCR_DrawPic() variants in cl_screen.c. Added new graphics for text fields and sliders in menus. Improved mouse interaction for menu sliders. Added resettargets developer command to default Lazarus and missionpack DLLs. Added hint_test developer command to missionpack DLL. Fixed freeze developer command in default Lazarus and missionpack DLLs so it can be used more than once. More tweaks to Tactician Gunner prox mine safety checks in misssionpack DLL.
738 lines
16 KiB
C
738 lines
16 KiB
C
/*
|
|
==============================================================================
|
|
|
|
hound
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#include "g_local.h"
|
|
#include "z_hound.h"
|
|
|
|
|
|
static int sound_pain1;
|
|
static int sound_pain2;
|
|
static int sound_die;
|
|
static int sound_launch;
|
|
static int sound_impact;
|
|
static int sound_sight;
|
|
static int sound_bite;
|
|
static int sound_bitemiss;
|
|
static int sound_jump;
|
|
|
|
|
|
void hound_stand (edict_t *self);
|
|
void hound_run (edict_t *self);
|
|
void hound_walk (edict_t *self);
|
|
|
|
|
|
void hound_launch (edict_t *self)
|
|
{
|
|
gi.sound (self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void hound_sight (edict_t *self, edict_t *other)
|
|
{
|
|
gi.sound (self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
//
|
|
// STAND
|
|
//
|
|
|
|
|
|
mframe_t hound_frames_stand1 [] =
|
|
{
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL, // 10
|
|
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL
|
|
};
|
|
mmove_t hound_stand1 = {FRAME_stand1start, FRAME_stand1end, hound_frames_stand1, hound_stand};
|
|
|
|
|
|
|
|
mframe_t hound_frames_stand2 [] =
|
|
{
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL, // 10
|
|
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL,
|
|
ai_schoolStand, 0, NULL, // 20
|
|
|
|
ai_schoolStand, 0, NULL
|
|
};
|
|
mmove_t hound_stand2 = {FRAME_stand2start, FRAME_stand2end, hound_frames_stand2, hound_stand};
|
|
|
|
|
|
|
|
void hound_stand (edict_t *self)
|
|
{
|
|
if (random() < 0.8)
|
|
{
|
|
self->monsterinfo.currentmove = &hound_stand1;
|
|
}
|
|
else
|
|
{
|
|
self->monsterinfo.currentmove = &hound_stand2;
|
|
}
|
|
}
|
|
|
|
//
|
|
// RUN
|
|
//
|
|
|
|
|
|
mframe_t hound_frames_run [] =
|
|
{
|
|
ai_schoolRun, 60, NULL,
|
|
ai_schoolRun, 60, NULL,
|
|
ai_schoolRun, 40, NULL,
|
|
ai_schoolRun, 30, NULL,
|
|
ai_schoolRun, 30, NULL,
|
|
ai_schoolRun, 30, NULL,
|
|
ai_schoolRun, 40, NULL
|
|
};
|
|
mmove_t hound_move_run = {FRAME_runStart, FRAME_runEnd, hound_frames_run, NULL};
|
|
|
|
|
|
void hound_run (edict_t *self)
|
|
{
|
|
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
|
|
hound_stand(self);
|
|
else
|
|
self->monsterinfo.currentmove = &hound_move_run;
|
|
}
|
|
|
|
|
|
//
|
|
// WALK
|
|
//
|
|
|
|
mframe_t hound_frames_walk [] =
|
|
{
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL,
|
|
ai_schoolWalk, 7, NULL
|
|
};
|
|
mmove_t hound_move_walk = {FRAME_walkStart, FRAME_walkEnd, hound_frames_walk, hound_walk};
|
|
|
|
|
|
void hound_walk (edict_t *self)
|
|
{
|
|
self->monsterinfo.currentmove = &hound_move_walk;
|
|
}
|
|
|
|
|
|
//
|
|
// PAIN
|
|
//
|
|
|
|
|
|
mframe_t hound_frames_pain1 [] =
|
|
{
|
|
ai_move, 6, NULL,
|
|
ai_move, 16, NULL,
|
|
ai_move, -6, NULL,
|
|
ai_move, -7, NULL,
|
|
};
|
|
mmove_t hound_move_pain1 = {FRAME_pain1Start, FRAME_pain1End, hound_frames_pain1, hound_run};
|
|
|
|
mframe_t hound_frames_pain2 [] =
|
|
{
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 6, NULL,
|
|
ai_move, 16, NULL,
|
|
ai_move, -6, NULL,
|
|
ai_move, -7, NULL,
|
|
ai_move, 0, NULL,
|
|
};
|
|
mmove_t hound_move_pain2 = {FRAME_pain2Start, FRAME_pain2End, hound_frames_pain2, hound_run};
|
|
|
|
|
|
void hound_pain (edict_t *self, edict_t *other, float kick, int damage)
|
|
{
|
|
if (self->health < (self->max_health / 2))
|
|
self->s.skinnum |= 1;
|
|
|
|
if (random() < 0.5)
|
|
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
|
|
else
|
|
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
|
|
|
|
if (level.time < self->pain_debounce_time)
|
|
return;
|
|
|
|
self->pain_debounce_time = level.time + 3;
|
|
|
|
if (skill->value == 3)
|
|
return; // no pain anims in nightmare
|
|
|
|
if (random() < 0.5)
|
|
self->monsterinfo.currentmove = &hound_move_pain1;
|
|
else
|
|
self->monsterinfo.currentmove = &hound_move_pain2;
|
|
}
|
|
|
|
//
|
|
// MELEE
|
|
//
|
|
|
|
|
|
void hound_bite (edict_t *self)
|
|
{
|
|
vec3_t aim;
|
|
|
|
VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
|
|
if (fire_hit (self, aim, (30 + (rand() %5)), 100))
|
|
gi.sound (self, CHAN_WEAPON, sound_bite, 1, ATTN_NORM, 0);
|
|
else
|
|
gi.sound (self, CHAN_WEAPON, sound_bitemiss, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void hound_bite2 (edict_t *self)
|
|
{
|
|
vec3_t aim;
|
|
|
|
VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
|
|
fire_hit (self, aim, (30 + (rand() %5)), 100);
|
|
}
|
|
|
|
|
|
|
|
mframe_t hound_frames_attack1 [] =
|
|
{
|
|
ai_schoolCharge, 0, hound_launch,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, hound_bite,
|
|
ai_schoolCharge, 0, hound_bite2
|
|
};
|
|
mmove_t hound_move_attack1 = {FRAME_attack1Start, FRAME_attack1End, hound_frames_attack1, hound_run};
|
|
|
|
|
|
mframe_t hound_frames_attack2 [] =
|
|
{
|
|
ai_schoolCharge, 0, hound_launch,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, NULL,
|
|
ai_schoolCharge, 0, hound_bite,
|
|
ai_schoolCharge, 0, hound_bite2,
|
|
ai_schoolCharge, 0, hound_bite2,
|
|
ai_schoolCharge, 0, hound_bite2,
|
|
ai_schoolCharge, 0, NULL,
|
|
};
|
|
mmove_t hound_move_attack2 = {FRAME_attack2Start, FRAME_attack2End, hound_frames_attack2, hound_run};
|
|
|
|
|
|
void hound_attack (edict_t *self)
|
|
{
|
|
if (random() < 0.6)
|
|
{
|
|
self->monsterinfo.currentmove = &hound_move_attack1;
|
|
}
|
|
else
|
|
{
|
|
self->monsterinfo.currentmove = &hound_move_attack2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// ATTACK
|
|
//
|
|
|
|
|
|
void hound_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
|
{
|
|
if (self->health <= 0)
|
|
{
|
|
self->touch = NULL;
|
|
return;
|
|
}
|
|
|
|
if (other->takedamage && strcmp(self->classname, other->classname) != 0)
|
|
{
|
|
if (VectorLength(self->velocity) > 400)
|
|
{
|
|
vec3_t point;
|
|
vec3_t normal;
|
|
int damage;
|
|
|
|
VectorCopy (self->velocity, normal);
|
|
VectorNormalize(normal);
|
|
VectorMA (self->s.origin, self->maxs[0], normal, point);
|
|
damage = 40 + 10 * random();
|
|
T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_UNKNOWN);
|
|
}
|
|
}
|
|
|
|
if (!M_CheckBottom (self))
|
|
{
|
|
if (self->groundentity)
|
|
{
|
|
self->monsterinfo.nextframe = FRAME_leapLoop;
|
|
self->touch = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
self->touch = NULL;
|
|
}
|
|
|
|
void hound_jump_takeoff (edict_t *self)
|
|
{
|
|
vec3_t forward;
|
|
|
|
gi.sound (self, CHAN_VOICE, sound_jump, 1, ATTN_NORM, 0);
|
|
AngleVectors (self->s.angles, forward, NULL, NULL);
|
|
self->s.origin[2] += 1;
|
|
VectorScale (forward, 400, self->velocity);
|
|
self->velocity[2] = 200;
|
|
self->groundentity = NULL;
|
|
// self->monsterinfo.aiflags |= AI_JUMPING;
|
|
self->monsterinfo.attack_finished = level.time + 3;
|
|
self->touch = hound_jump_touch;
|
|
}
|
|
|
|
void hound_check_landing (edict_t *self)
|
|
{
|
|
if (self->groundentity)
|
|
{
|
|
gi.sound (self, CHAN_WEAPON, sound_impact, 1, ATTN_NORM, 0);
|
|
self->monsterinfo.attack_finished = 0;
|
|
// self->monsterinfo.aiflags &= ~AI_JUMPING;
|
|
return;
|
|
}
|
|
|
|
if (level.time > self->monsterinfo.attack_finished)
|
|
self->monsterinfo.nextframe = FRAME_leapLoop;
|
|
else
|
|
self->monsterinfo.nextframe = FRAME_leapEndStart;
|
|
}
|
|
|
|
void hound_check_landing2 (edict_t *self)
|
|
{
|
|
self->owner = NULL;
|
|
|
|
if (self->groundentity)
|
|
{
|
|
gi.sound (self, CHAN_WEAPON, sound_impact, 1, ATTN_NORM, 0);
|
|
self->monsterinfo.attack_finished = 0;
|
|
// self->monsterinfo.aiflags &= ~AI_JUMPING;
|
|
return;
|
|
}
|
|
|
|
if (level.time > self->monsterinfo.attack_finished)
|
|
self->monsterinfo.nextframe = FRAME_hattack1Loop;
|
|
else
|
|
self->monsterinfo.nextframe = FRAME_hattack1LoopEnd;
|
|
}
|
|
|
|
|
|
mframe_t hound_frames_handlerjump [] =
|
|
{
|
|
ai_charge, 0, NULL,
|
|
ai_charge, 20, hound_jump_takeoff,
|
|
ai_move, 40, NULL,
|
|
ai_move, 30, hound_check_landing2,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
};
|
|
|
|
|
|
mmove_t hound_move_handlerjump = {FRAME_hattack1Sep, FRAME_hattack1End, hound_frames_handlerjump, hound_run};
|
|
|
|
|
|
|
|
mframe_t hound_frames_jump [] =
|
|
{
|
|
ai_charge, 20, NULL,
|
|
ai_charge, 20, hound_jump_takeoff,
|
|
ai_move, 40, NULL,
|
|
ai_move, 30, hound_check_landing,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL
|
|
};
|
|
mmove_t hound_move_jump = {FRAME_leapStart, FRAME_leapEnd, hound_frames_jump, hound_run};
|
|
|
|
void hound_jump (edict_t *self)
|
|
{
|
|
self->monsterinfo.currentmove = &hound_move_jump;
|
|
}
|
|
|
|
|
|
/*
|
|
===
|
|
attack check routines
|
|
===
|
|
*/
|
|
|
|
|
|
|
|
qboolean hound_check_melee (edict_t *self)
|
|
{
|
|
if (range (self, self->enemy) == RANGE_MELEE)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
qboolean hound_check_jump (edict_t *self)
|
|
{
|
|
vec3_t v;
|
|
float distance;
|
|
|
|
if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2]))
|
|
return false;
|
|
|
|
if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2]))
|
|
return false;
|
|
|
|
v[0] = self->s.origin[0] - self->enemy->s.origin[0];
|
|
v[1] = self->s.origin[1] - self->enemy->s.origin[1];
|
|
v[2] = 0;
|
|
distance = VectorLength(v);
|
|
|
|
if (distance < 100)
|
|
return false;
|
|
if (distance > 100)
|
|
{
|
|
if (random() < 0.9)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
qboolean hound_checkattack (edict_t *self)
|
|
{
|
|
if (!self->enemy || self->enemy->health <= 0)
|
|
return false;
|
|
|
|
if (hound_check_melee(self))
|
|
{
|
|
self->monsterinfo.attack_state = AS_MELEE;
|
|
return true;
|
|
}
|
|
|
|
if (hound_check_jump(self))
|
|
{
|
|
self->monsterinfo.attack_state = AS_MISSILE;
|
|
// FIXME play a jump sound here
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
===
|
|
Death Stuff Starts
|
|
===
|
|
*/
|
|
|
|
void hound_dead (edict_t *self)
|
|
{
|
|
// Lazarus: Stupid... if flies aren't set by M_FlyCheck, monster_think
|
|
// will cause us to come back here over and over and over
|
|
// until flies ARE set or monster is gibbed.
|
|
// This line fixes that:
|
|
self->nextthink = 0;
|
|
|
|
VectorSet (self->mins, -16, -16, -24);
|
|
VectorSet (self->maxs, 16, 16, -8);
|
|
self->movetype = MOVETYPE_TOSS;
|
|
self->svflags |= SVF_DEADMONSTER;
|
|
self->nextthink = 0;
|
|
gi.linkentity (self);
|
|
M_FlyCheck (self);
|
|
|
|
// Lazarus monster fade
|
|
if (world->effects & FX_WORLDSPAWN_CORPSEFADE)
|
|
{
|
|
self->think = FadeDieSink;
|
|
self->nextthink = level.time+corpse_fadetime->value;
|
|
}
|
|
}
|
|
|
|
mframe_t hound_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
|
|
};
|
|
mmove_t hound_move_death = {FRAME_die1Start, FRAME_die1End, hound_frames_death, hound_dead};
|
|
|
|
void hound_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
|
{
|
|
int n;
|
|
|
|
// check for gib
|
|
if (self->health <= self->gib_health && !(self->spawnflags & SF_MONSTER_NOGIB))
|
|
{
|
|
gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
|
|
for (n = 0; n < 2; n++)
|
|
ThrowGib (self, "models/objects/gibs/bone/tris.md2", 0, 0, damage, GIB_ORGANIC);
|
|
for (n = 0; n < 4; n++)
|
|
ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", 0, 0, damage, GIB_ORGANIC);
|
|
ThrowHead (self, "models/objects/gibs/head2/tris.md2", 0, 0, damage, GIB_ORGANIC);
|
|
self->deadflag = DEAD_DEAD;
|
|
return;
|
|
}
|
|
|
|
if (self->deadflag == DEAD_DEAD)
|
|
return;
|
|
|
|
// regular death
|
|
gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
|
|
self->s.skinnum |= 1;
|
|
self->deadflag = DEAD_DEAD;
|
|
self->takedamage = DAMAGE_YES;
|
|
self->monsterinfo.currentmove = &hound_move_death;
|
|
}
|
|
|
|
|
|
/*
|
|
===
|
|
End Death Stuff
|
|
===
|
|
*/
|
|
|
|
void SP_monster_hound_precache(void)
|
|
{
|
|
sound_pain1 = gi.soundindex ("monsters/hound/hpain1.wav");
|
|
sound_pain2 = gi.soundindex ("monsters/hound/hpain2.wav");
|
|
sound_die = gi.soundindex ("monsters/hound/hdeth1.wav");
|
|
sound_launch = gi.soundindex("monsters/hound/hlaunch.wav");
|
|
sound_impact = gi.soundindex("monsters/hound/himpact.wav");
|
|
sound_sight = gi.soundindex("monsters/hound/hsight1.wav");
|
|
sound_jump = gi.soundindex("monsters/hound/hjump.wav");
|
|
sound_bite = gi.soundindex("monsters/hound/hbite1.wav");
|
|
sound_bitemiss = gi.soundindex("monsters/hound/hbite2.wav");
|
|
}
|
|
|
|
|
|
/*QUAKED monster_hound (1 .5 0) (-16 -16 -24) (16 16 24) Ambush Trigger_Spawn Sight GoodGuy NoGib
|
|
model="models/monsters/guard/hound/"
|
|
*/
|
|
void SP_monster_hound (edict_t *self)
|
|
{
|
|
if (deathmatch->value)
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
|
|
SP_monster_hound_precache();
|
|
|
|
// Lazarus: special purpose skins
|
|
if ( self->style )
|
|
{
|
|
PatchMonsterModel("models/monsters/guard/hound/tris.md2");
|
|
self->s.skinnum = self->style * 2;
|
|
}
|
|
|
|
self->s.modelindex = gi.modelindex ("models/monsters/guard/hound/tris.md2");
|
|
VectorSet (self->mins, -16, -16, -24);
|
|
VectorSet (self->maxs, 16, 16, 24);
|
|
self->movetype = MOVETYPE_STEP;
|
|
self->solid = SOLID_BBOX;
|
|
self->yaw_speed = 30;
|
|
|
|
if (!self->health)
|
|
self->health = 175;
|
|
if (!self->gib_health)
|
|
self->gib_health = -50;
|
|
if (!self->mass)
|
|
self->mass = 250;
|
|
|
|
self->pain = hound_pain;
|
|
self->die = hound_die;
|
|
|
|
if (self->spawnflags & 0x8)
|
|
{
|
|
self->monsterinfo.aiflags2 = AI2_SCHOOLING;
|
|
}
|
|
|
|
self->monsterinfo.zSchoolSightRadius = 500;
|
|
self->monsterinfo.zSchoolMaxSpeed = 4;
|
|
self->monsterinfo.zSchoolMinSpeed = 3;
|
|
self->monsterinfo.zSpeedStandMax = 1;
|
|
self->monsterinfo.zSpeedWalkMax = 3;
|
|
self->monsterinfo.zSchoolDecayRate = 0.95;
|
|
self->monsterinfo.zSchoolMinimumDistance = 100;
|
|
|
|
self->monsterinfo.stand = hound_stand;
|
|
self->monsterinfo.walk = hound_walk;
|
|
self->monsterinfo.run = hound_run;
|
|
self->monsterinfo.attack = hound_jump;
|
|
self->monsterinfo.melee = hound_attack;
|
|
self->monsterinfo.sight = hound_sight;
|
|
self->monsterinfo.idle = hound_stand;
|
|
self->monsterinfo.checkattack = hound_checkattack;
|
|
|
|
if (!self->monsterinfo.flies)
|
|
self->monsterinfo.flies = 0.60;
|
|
|
|
// 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 = "HellHound";
|
|
self->class_id = ENTITY_MONSTER_HOUND;
|
|
|
|
gi.linkentity (self);
|
|
|
|
self->monsterinfo.currentmove = &hound_stand1;
|
|
if (self->health < 0)
|
|
{
|
|
mmove_t *deathmoves[] = {&hound_move_death,
|
|
NULL};
|
|
M_SetDeath (self, (mmove_t **)&deathmoves);
|
|
}
|
|
self->monsterinfo.scale = MODEL_SCALE;
|
|
|
|
walkmonster_start (self);
|
|
}
|
|
|
|
void monster_think (edict_t *self);
|
|
qboolean monster_start (edict_t *self);
|
|
void hound_createHound (edict_t *self, float healthPercent)
|
|
{
|
|
edict_t *hound;
|
|
|
|
hound = G_Spawn();
|
|
|
|
//*hound = *self;
|
|
|
|
hound->classname = "monster_hound";
|
|
hound->s.modelindex = gi.modelindex ("models/monsters/guard/hound/tris.md2");
|
|
VectorSet (hound->mins, -16, -16, -24);
|
|
VectorSet (hound->maxs, 16, 16, 24);
|
|
VectorCopy(self->s.origin, hound->s.origin);
|
|
VectorCopy(self->s.old_origin, hound->s.old_origin);
|
|
VectorCopy(self->s.angles, hound->s.angles);
|
|
hound->movetype = MOVETYPE_STEP;
|
|
hound->solid = SOLID_BBOX;
|
|
hound->takedamage = DAMAGE_YES;
|
|
hound->svflags |= SVF_MONSTER;
|
|
hound->svflags &= ~SVF_DEADMONSTER;
|
|
hound->s.renderfx |= RF_FRAMELERP;
|
|
hound->clipmask = MASK_MONSTERSOLID;
|
|
hound->deadflag = DEAD_NO;
|
|
hound->owner = self;
|
|
hound->yaw_speed = 30;
|
|
hound->enemy = self->enemy;
|
|
hound->ideal_yaw = self->ideal_yaw;
|
|
|
|
hound->health = 175.0 * healthPercent;
|
|
hound->gib_health = -50;
|
|
hound->mass = 250;
|
|
|
|
hound->pain = hound_pain;
|
|
hound->die = hound_die;
|
|
|
|
hound->monsterinfo.stand = hound_stand;
|
|
hound->monsterinfo.walk = hound_walk;
|
|
hound->monsterinfo.run = hound_run;
|
|
hound->monsterinfo.attack = hound_jump;
|
|
hound->monsterinfo.melee = hound_attack;
|
|
hound->monsterinfo.sight = hound_sight;
|
|
hound->monsterinfo.idle = hound_stand;
|
|
hound->monsterinfo.checkattack = hound_checkattack;
|
|
|
|
hound->monsterinfo.currentmove = &hound_move_handlerjump;
|
|
hound->monsterinfo.scale = MODEL_SCALE;
|
|
|
|
hound->think = monster_think;
|
|
hound->nextthink = level.time + FRAMETIME;
|
|
|
|
// Lazarus
|
|
hound->powerarmor = self->powerarmor;
|
|
if (hound->powerarmor)
|
|
{
|
|
if (hound->powerarmortype == 1)
|
|
hound->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
|
|
else
|
|
hound->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
|
|
hound->monsterinfo.power_armor_power = self->powerarmor;
|
|
}
|
|
|
|
hound->monsterinfo.flies = self->monsterinfo.flies;
|
|
if (!hound->monsterinfo.flies)
|
|
hound->monsterinfo.flies = 0.60;
|
|
|
|
hound->common_name = "HellHound";
|
|
hound->class_id = ENTITY_MONSTER_HOUND;
|
|
|
|
// monster_start(hound);
|
|
|
|
gi.linkentity (hound);
|
|
|
|
// move the fucker now!!!
|
|
ai_move (hound, 20);
|
|
}
|