mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2025-01-18 22:41:49 +00:00
d16b46e3cf
Overhauled child entity movement in default Lazarus DLL. Added bbox versions of various triggers to default Lazarus DLL. Added level.maptype field to default Lazarus DLL. Added entity class IDs to default Lazarus DLL. Incremented savegame version for default Lazarus DLL.
729 lines
16 KiB
C
729 lines
16 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
Copyright (C) 2000-2002 Mr. Hyde and Mad Dog
|
|
|
|
This file is part of Lazarus Quake 2 Mod source code.
|
|
|
|
Lazarus Quake 2 Mod source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Lazarus Quake 2 Mod source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Lazarus Quake 2 Mod source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
/*
|
|
==============================================================================
|
|
|
|
brain
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#include "g_local.h"
|
|
#include "m_brain.h"
|
|
|
|
|
|
static int sound_chest_open;
|
|
static int sound_tentacles_extend;
|
|
static int sound_tentacles_retract;
|
|
static int sound_death;
|
|
static int sound_idle1;
|
|
static int sound_idle2;
|
|
static int sound_idle3;
|
|
static int sound_pain1;
|
|
static int sound_pain2;
|
|
static int sound_sight;
|
|
static int sound_search;
|
|
static int sound_melee1;
|
|
static int sound_melee2;
|
|
static int sound_melee3;
|
|
|
|
|
|
void brain_sight (edict_t *self, edict_t *other)
|
|
{
|
|
gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_search (edict_t *self)
|
|
{
|
|
gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
|
|
void brain_run (edict_t *self);
|
|
void brain_dead (edict_t *self);
|
|
|
|
|
|
//
|
|
// STAND
|
|
//
|
|
|
|
mframe_t brain_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,
|
|
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 brain_move_stand = {FRAME_stand01, FRAME_stand30, brain_frames_stand, NULL};
|
|
|
|
void brain_stand (edict_t *self)
|
|
{
|
|
self->monsterinfo.currentmove = &brain_move_stand;
|
|
}
|
|
|
|
|
|
//
|
|
// IDLE
|
|
//
|
|
|
|
mframe_t brain_frames_idle [] =
|
|
{
|
|
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,
|
|
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 brain_move_idle = {FRAME_stand31, FRAME_stand60, brain_frames_idle, brain_stand};
|
|
|
|
void brain_idle (edict_t *self)
|
|
{
|
|
if (!(self->spawnflags & SF_MONSTER_AMBUSH)) //Knightmare- play all 3 idle sounds
|
|
{
|
|
float r = random();
|
|
|
|
if (r < 0.33)
|
|
gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);
|
|
else if (r < 0.67)
|
|
gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0);
|
|
else
|
|
gi.sound (self, CHAN_VOICE, sound_idle3, 1, ATTN_IDLE, 0); //Knightmare- changed channel
|
|
}
|
|
self->monsterinfo.currentmove = &brain_move_idle;
|
|
}
|
|
|
|
|
|
//
|
|
// WALK
|
|
//
|
|
mframe_t brain_frames_walk1 [] =
|
|
{
|
|
ai_walk, 7, NULL,
|
|
ai_walk, 2, NULL,
|
|
ai_walk, 3, NULL,
|
|
ai_walk, 3, NULL,
|
|
ai_walk, 1, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 9, NULL,
|
|
ai_walk, -4, NULL,
|
|
ai_walk, -1, NULL,
|
|
ai_walk, 2, NULL
|
|
};
|
|
mmove_t brain_move_walk1 = {FRAME_walk101, FRAME_walk111, brain_frames_walk1, NULL};
|
|
|
|
// walk2 is FUBAR, do not use
|
|
#if 0
|
|
void brain_walk2_cycle (edict_t *self)
|
|
{
|
|
if (random() > 0.1)
|
|
self->monsterinfo.nextframe = FRAME_walk220;
|
|
}
|
|
|
|
mframe_t brain_frames_walk2 [] =
|
|
{
|
|
ai_walk, 3, NULL,
|
|
ai_walk, -2, NULL,
|
|
ai_walk, -4, NULL,
|
|
ai_walk, -3, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 1, NULL,
|
|
ai_walk, 12, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, -3, NULL,
|
|
ai_walk, 0, NULL,
|
|
|
|
ai_walk, -2, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 1, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 10, NULL, // Cycle Start
|
|
|
|
ai_walk, -1, NULL,
|
|
ai_walk, 7, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 3, NULL,
|
|
ai_walk, -3, NULL,
|
|
ai_walk, 2, NULL,
|
|
ai_walk, 4, NULL,
|
|
ai_walk, -3, NULL,
|
|
ai_walk, 2, NULL,
|
|
ai_walk, 0, NULL,
|
|
|
|
ai_walk, 4, brain_walk2_cycle,
|
|
ai_walk, -1, NULL,
|
|
ai_walk, -1, NULL,
|
|
ai_walk, -8, NULL,
|
|
ai_walk, 0, NULL,
|
|
ai_walk, 1, NULL,
|
|
ai_walk, 5, NULL,
|
|
ai_walk, 2, NULL,
|
|
ai_walk, -1, NULL,
|
|
ai_walk, -5, NULL
|
|
};
|
|
//mmove_t brain_move_walk2 = {FRAME_walk201, FRAME_walk240, brain_frames_walk2, NULL};
|
|
#endif
|
|
|
|
void brain_walk (edict_t *self)
|
|
{
|
|
// if (random() <= 0.5)
|
|
self->monsterinfo.currentmove = &brain_move_walk1;
|
|
// else
|
|
// self->monsterinfo.currentmove = &brain_move_walk2;
|
|
}
|
|
|
|
|
|
|
|
mframe_t brain_frames_defense [] =
|
|
{
|
|
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 brain_move_defense = {FRAME_defens01, FRAME_defens08, brain_frames_defense, NULL};
|
|
|
|
mframe_t brain_frames_pain3 [] =
|
|
{
|
|
ai_move, -2, NULL,
|
|
ai_move, 2, NULL,
|
|
ai_move, 1, NULL,
|
|
ai_move, 3, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, -4, NULL
|
|
};
|
|
mmove_t brain_move_pain3 = {FRAME_pain301, FRAME_pain306, brain_frames_pain3, brain_run};
|
|
|
|
mframe_t brain_frames_pain2 [] =
|
|
{
|
|
ai_move, -2, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 3, NULL,
|
|
ai_move, 1, NULL,
|
|
ai_move, -2, NULL
|
|
};
|
|
mmove_t brain_move_pain2 = {FRAME_pain201, FRAME_pain208, brain_frames_pain2, brain_run};
|
|
|
|
mframe_t brain_frames_pain1 [] =
|
|
{
|
|
ai_move, -6, NULL,
|
|
ai_move, -2, NULL,
|
|
ai_move, -6, 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, 2, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 2, NULL,
|
|
ai_move, 1, NULL,
|
|
ai_move, 7, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 3, NULL,
|
|
ai_move, -1, NULL
|
|
};
|
|
mmove_t brain_move_pain1 = {FRAME_pain101, FRAME_pain121, brain_frames_pain1, brain_run};
|
|
|
|
|
|
//
|
|
// DUCK
|
|
//
|
|
|
|
void brain_duck_down (edict_t *self)
|
|
{
|
|
if (self->monsterinfo.aiflags & AI_DUCKED)
|
|
return;
|
|
self->monsterinfo.aiflags |= AI_DUCKED;
|
|
self->maxs[2] -= 32;
|
|
self->takedamage = DAMAGE_YES;
|
|
gi.linkentity (self);
|
|
}
|
|
|
|
void brain_duck_hold (edict_t *self)
|
|
{
|
|
if (level.time >= self->monsterinfo.pausetime)
|
|
self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
|
|
else
|
|
self->monsterinfo.aiflags |= AI_HOLD_FRAME;
|
|
}
|
|
|
|
void brain_duck_up (edict_t *self)
|
|
{
|
|
self->monsterinfo.aiflags &= ~AI_DUCKED;
|
|
self->maxs[2] += 32;
|
|
self->takedamage = DAMAGE_AIM;
|
|
gi.linkentity (self);
|
|
}
|
|
|
|
mframe_t brain_frames_duck [] =
|
|
{
|
|
ai_move, 0, NULL,
|
|
ai_move, -2, brain_duck_down,
|
|
ai_move, 17, brain_duck_hold,
|
|
ai_move, -3, NULL,
|
|
ai_move, -1, brain_duck_up,
|
|
ai_move, -5, NULL,
|
|
ai_move, -6, NULL,
|
|
ai_move, -6, NULL
|
|
};
|
|
mmove_t brain_move_duck = {FRAME_duck01, FRAME_duck08, brain_frames_duck, brain_run};
|
|
|
|
void brain_dodge (edict_t *self, edict_t *attacker, float eta)
|
|
{
|
|
if (random() > 0.25)
|
|
return;
|
|
|
|
if (!self->enemy)
|
|
self->enemy = attacker;
|
|
|
|
self->monsterinfo.pausetime = level.time + eta + 0.5;
|
|
self->monsterinfo.currentmove = &brain_move_duck;
|
|
}
|
|
|
|
mframe_t brain_frames_death2 [] =
|
|
{
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, 9, NULL,
|
|
ai_move, 0, NULL
|
|
};
|
|
mmove_t brain_move_death2 = {FRAME_death201, FRAME_death205, brain_frames_death2, brain_dead};
|
|
|
|
mframe_t brain_frames_death1 [] =
|
|
{
|
|
ai_move, 0, NULL,
|
|
ai_move, 0, NULL,
|
|
ai_move, -2, NULL,
|
|
ai_move, 9, 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 brain_move_death1 = {FRAME_death101, FRAME_death118, brain_frames_death1, brain_dead};
|
|
|
|
|
|
//
|
|
// MELEE
|
|
//
|
|
|
|
void brain_swing_right (edict_t *self)
|
|
{
|
|
gi.sound (self, CHAN_BODY, sound_melee1, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_hit_right (edict_t *self)
|
|
{
|
|
vec3_t aim;
|
|
|
|
VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8);
|
|
if (fire_hit (self, aim, (15 + (rand() %5)), 40))
|
|
gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_swing_left (edict_t *self)
|
|
{
|
|
gi.sound (self, CHAN_BODY, sound_melee2, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_hit_left (edict_t *self)
|
|
{
|
|
vec3_t aim;
|
|
|
|
VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
|
|
if (fire_hit (self, aim, (15 + (rand() %5)), 40))
|
|
gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
mframe_t brain_frames_attack1 [] =
|
|
{
|
|
ai_charge, 8, NULL,
|
|
ai_charge, 3, NULL,
|
|
ai_charge, 5, NULL,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, -3, brain_swing_right,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, -5, NULL,
|
|
ai_charge, -7, brain_hit_right,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, 6, brain_swing_left,
|
|
ai_charge, 1, NULL,
|
|
ai_charge, 2, brain_hit_left,
|
|
ai_charge, -3, NULL,
|
|
ai_charge, 6, NULL,
|
|
ai_charge, -1, NULL,
|
|
ai_charge, -3, NULL,
|
|
ai_charge, 2, NULL,
|
|
ai_charge, -11,NULL
|
|
};
|
|
mmove_t brain_move_attack1 = {FRAME_attak101, FRAME_attak118, brain_frames_attack1, brain_run};
|
|
|
|
void brain_chest_open (edict_t *self)
|
|
{
|
|
self->spawnflags &= ~65536;
|
|
self->monsterinfo.power_armor_type = POWER_ARMOR_NONE;
|
|
gi.sound (self, CHAN_BODY, sound_chest_open, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_tentacle_attack (edict_t *self)
|
|
{
|
|
vec3_t aim;
|
|
|
|
VectorSet (aim, MELEE_DISTANCE, 0, 8);
|
|
if (fire_hit (self, aim, (10 + (rand() %5)), -600) && skill->value > 0)
|
|
self->spawnflags |= 65536;
|
|
gi.sound (self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0);
|
|
}
|
|
|
|
void brain_chest_closed (edict_t *self)
|
|
{
|
|
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
|
|
if (self->spawnflags & 65536)
|
|
{
|
|
self->spawnflags &= ~65536;
|
|
self->monsterinfo.currentmove = &brain_move_attack1;
|
|
}
|
|
}
|
|
|
|
mframe_t brain_frames_attack2 [] =
|
|
{
|
|
ai_charge, 5, NULL,
|
|
ai_charge, -4, NULL,
|
|
ai_charge, -4, NULL,
|
|
ai_charge, -3, NULL,
|
|
ai_charge, 0, brain_chest_open,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, 13, brain_tentacle_attack,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, 2, NULL,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, -9, brain_chest_closed,
|
|
ai_charge, 0, NULL,
|
|
ai_charge, 4, NULL,
|
|
ai_charge, 3, NULL,
|
|
ai_charge, 2, NULL,
|
|
ai_charge, -3, NULL,
|
|
ai_charge, -6, NULL
|
|
};
|
|
mmove_t brain_move_attack2 = {FRAME_attak201, FRAME_attak217, brain_frames_attack2, brain_run};
|
|
|
|
void brain_melee(edict_t *self)
|
|
{
|
|
if (random() <= 0.5)
|
|
self->monsterinfo.currentmove = &brain_move_attack1;
|
|
else
|
|
self->monsterinfo.currentmove = &brain_move_attack2;
|
|
}
|
|
|
|
|
|
//
|
|
// RUN
|
|
//
|
|
|
|
mframe_t brain_frames_run [] =
|
|
{
|
|
ai_run, 9, NULL,
|
|
ai_run, 2, NULL,
|
|
ai_run, 3, NULL,
|
|
ai_run, 3, NULL,
|
|
ai_run, 1, NULL,
|
|
ai_run, 0, NULL,
|
|
ai_run, 0, NULL,
|
|
ai_run, 10, NULL,
|
|
ai_run, -4, NULL,
|
|
ai_run, -1, NULL,
|
|
ai_run, 2, NULL
|
|
};
|
|
mmove_t brain_move_run = {FRAME_walk101, FRAME_walk111, brain_frames_run, NULL};
|
|
|
|
void brain_run (edict_t *self)
|
|
{
|
|
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
|
|
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
|
|
self->monsterinfo.currentmove = &brain_move_stand;
|
|
else
|
|
self->monsterinfo.currentmove = &brain_move_run;
|
|
}
|
|
|
|
|
|
void brain_pain (edict_t *self, edict_t *other, float kick, int damage)
|
|
{
|
|
float r;
|
|
|
|
if (self->health < (self->max_health / 2))
|
|
self->s.skinnum |= 1;
|
|
|
|
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
|
|
|
|
r = random();
|
|
if (r < 0.33)
|
|
{
|
|
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
|
|
self->monsterinfo.currentmove = &brain_move_pain1;
|
|
}
|
|
else if (r < 0.66)
|
|
{
|
|
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
|
|
self->monsterinfo.currentmove = &brain_move_pain2;
|
|
}
|
|
else
|
|
{
|
|
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
|
|
self->monsterinfo.currentmove = &brain_move_pain3;
|
|
}
|
|
}
|
|
|
|
void brain_dead (edict_t *self)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void brain_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
|
{
|
|
int n;
|
|
|
|
self->s.effects = 0;
|
|
self->monsterinfo.power_armor_type = POWER_ARMOR_NONE;
|
|
|
|
self->s.skinnum |= 1;
|
|
|
|
// 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", damage, GIB_ORGANIC);
|
|
for (n= 0; n < 4; n++)
|
|
ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
|
|
ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
|
|
self->deadflag = DEAD_DEAD;
|
|
return;
|
|
}
|
|
|
|
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;
|
|
if (random() <= 0.5)
|
|
self->monsterinfo.currentmove = &brain_move_death1;
|
|
else
|
|
self->monsterinfo.currentmove = &brain_move_death2;
|
|
}
|
|
|
|
/*QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
|
|
*/
|
|
void SP_monster_brain (edict_t *self)
|
|
{
|
|
if (deathmatch->value)
|
|
{
|
|
G_FreeEdict (self);
|
|
return;
|
|
}
|
|
|
|
sound_chest_open = gi.soundindex ("brain/brnatck1.wav");
|
|
sound_tentacles_extend = gi.soundindex ("brain/brnatck2.wav");
|
|
sound_tentacles_retract = gi.soundindex ("brain/brnatck3.wav");
|
|
sound_death = gi.soundindex ("brain/brndeth1.wav");
|
|
sound_idle1 = gi.soundindex ("brain/brnidle1.wav");
|
|
sound_idle2 = gi.soundindex ("brain/brnidle2.wav");
|
|
sound_idle3 = gi.soundindex ("brain/brnlens1.wav");
|
|
sound_pain1 = gi.soundindex ("brain/brnpain1.wav");
|
|
sound_pain2 = gi.soundindex ("brain/brnpain2.wav");
|
|
sound_sight = gi.soundindex ("brain/brnsght1.wav");
|
|
sound_search = gi.soundindex ("brain/brnsrch1.wav");
|
|
sound_melee1 = gi.soundindex ("brain/melee1.wav");
|
|
sound_melee2 = gi.soundindex ("brain/melee2.wav");
|
|
sound_melee3 = gi.soundindex ("brain/melee3.wav");
|
|
|
|
self->movetype = MOVETYPE_STEP;
|
|
self->solid = SOLID_BBOX;
|
|
|
|
// Lazarus: special purpose skins
|
|
if ( self->style )
|
|
{
|
|
PatchMonsterModel("models/monsters/brain/tris.md2");
|
|
self->s.skinnum = self->style * 2;
|
|
}
|
|
|
|
self->s.modelindex = gi.modelindex ("models/monsters/brain/tris.md2");
|
|
VectorSet (self->mins, -16, -16, -24);
|
|
VectorSet (self->maxs, 16, 16, 32);
|
|
|
|
// Lazarus: mapper-configurable health
|
|
if (!self->health)
|
|
self->health = 300;
|
|
if (!self->gib_health)
|
|
self->gib_health = -150;
|
|
if (!self->mass)
|
|
self->mass = 400;
|
|
|
|
self->pain = brain_pain;
|
|
self->die = brain_die;
|
|
|
|
self->monsterinfo.stand = brain_stand;
|
|
self->monsterinfo.walk = brain_walk;
|
|
self->monsterinfo.run = brain_run;
|
|
self->monsterinfo.dodge = brain_dodge;
|
|
// self->monsterinfo.attack = brain_attack;
|
|
self->monsterinfo.melee = brain_melee;
|
|
self->monsterinfo.sight = brain_sight;
|
|
self->monsterinfo.search = brain_search;
|
|
self->monsterinfo.idle = brain_idle;
|
|
|
|
self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
|
|
self->monsterinfo.power_armor_power = 100;
|
|
|
|
if (!self->monsterinfo.flies)
|
|
self->monsterinfo.flies = 0.10;
|
|
|
|
// self->common_name = "Brains";
|
|
self->common_name = "Brain";
|
|
self->class_id = ENTITY_MONSTER_BRAIN;
|
|
|
|
// Knightmare- added sparks and blood type
|
|
if (!self->blood_type)
|
|
self->blood_type = 3; // sparks and blood
|
|
|
|
gi.linkentity (self);
|
|
|
|
self->monsterinfo.currentmove = &brain_move_stand;
|
|
if (self->health < 0)
|
|
{
|
|
mmove_t *deathmoves[] = {&brain_move_death1,
|
|
&brain_move_death2,
|
|
NULL};
|
|
M_SetDeath(self,(mmove_t **)&deathmoves);
|
|
}
|
|
self->monsterinfo.scale = MODEL_SCALE;
|
|
|
|
walkmonster_start (self);
|
|
}
|