mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-25 22:10:59 +00:00
game: Add ReRelease Guardian Monster
This commit is contained in:
parent
145027c240
commit
1151c91069
10 changed files with 1043 additions and 17 deletions
1
Makefile
1
Makefile
|
@ -909,6 +909,7 @@ GAME_OBJS_ = \
|
|||
src/game/monster/gekk/gekk.o \
|
||||
src/game/monster/gladiator/gladb.o \
|
||||
src/game/monster/gladiator/gladiator.o \
|
||||
src/game/monster/guardian/guardian.o \
|
||||
src/game/monster/gunner/gunner.o \
|
||||
src/game/monster/hover/hover.o \
|
||||
src/game/monster/infantry/infantry.o \
|
||||
|
|
|
@ -50,18 +50,19 @@ SZ_GetSpace(sizebuf_t *buf, int length)
|
|||
{
|
||||
if (!buf->allowoverflow)
|
||||
{
|
||||
Com_Error(ERR_FATAL, "SZ_GetSpace: overflow without allowoverflow set");
|
||||
Com_Error(ERR_FATAL, "%s: overflow without allowoverflow set",
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (length > buf->maxsize)
|
||||
{
|
||||
Com_Error(ERR_FATAL, "SZ_GetSpace: %i is > full buffer size",
|
||||
length);
|
||||
Com_Error(ERR_FATAL, "%s: %i is > full buffer size",
|
||||
__func__, length);
|
||||
}
|
||||
|
||||
SZ_Clear(buf);
|
||||
buf->overflowed = true;
|
||||
Com_Printf("SZ_GetSpace: overflow\n");
|
||||
Com_Printf("%s: overflow\n", __func__);
|
||||
}
|
||||
|
||||
data = buf->data + buf->cursize;
|
||||
|
|
|
@ -193,7 +193,7 @@ gib_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unu
|
|||
}
|
||||
|
||||
void
|
||||
ThrowGib(edict_t *self, char *gibname, int damage, int type)
|
||||
ThrowGib(edict_t *self, const char *gibname, int damage, int type)
|
||||
{
|
||||
edict_t *gib;
|
||||
vec3_t vd;
|
||||
|
@ -262,7 +262,7 @@ ThrowGib(edict_t *self, char *gibname, int damage, int type)
|
|||
}
|
||||
|
||||
void
|
||||
ThrowHead(edict_t *self, char *gibname, int damage, int type)
|
||||
ThrowHead(edict_t *self, const char *gibname, int damage, int type)
|
||||
{
|
||||
vec3_t vd;
|
||||
float vscale;
|
||||
|
@ -319,7 +319,7 @@ ThrowHead(edict_t *self, char *gibname, int damage, int type)
|
|||
}
|
||||
|
||||
void
|
||||
ThrowGibACID(edict_t *self, char *gibname, int damage, int type)
|
||||
ThrowGibACID(edict_t *self, const char *gibname, int damage, int type)
|
||||
{
|
||||
edict_t *gib;
|
||||
vec3_t vd;
|
||||
|
@ -387,7 +387,7 @@ ThrowGibACID(edict_t *self, char *gibname, int damage, int type)
|
|||
}
|
||||
|
||||
void
|
||||
ThrowHeadACID(edict_t *self, char *gibname, int damage, int type)
|
||||
ThrowHeadACID(edict_t *self, const char *gibname, int damage, int type)
|
||||
{
|
||||
vec3_t vd;
|
||||
float vscale;
|
||||
|
|
|
@ -135,6 +135,7 @@ void SP_monster_berserk(edict_t *self);
|
|||
void SP_monster_gladiator(edict_t *self);
|
||||
void SP_monster_gunner(edict_t *self);
|
||||
void SP_monster_guncmdr(edict_t *self);
|
||||
void SP_monster_guardian(edict_t *self);
|
||||
void SP_monster_infantry(edict_t *self);
|
||||
void SP_monster_soldier_light(edict_t *self);
|
||||
void SP_monster_soldier(edict_t *self);
|
||||
|
@ -328,6 +329,7 @@ static spawn_t spawns[] = {
|
|||
{"monster_gladiator", SP_monster_gladiator},
|
||||
{"monster_gunner", SP_monster_gunner},
|
||||
{"monster_guncmdr", SP_monster_guncmdr},
|
||||
{"monster_guardian", SP_monster_guardian},
|
||||
{"monster_infantry", SP_monster_infantry},
|
||||
{"monster_soldier_light", SP_monster_soldier_light},
|
||||
{"monster_soldier", SP_monster_soldier},
|
||||
|
|
|
@ -878,12 +878,12 @@ void stationarymonster_start(edict_t *self);
|
|||
void monster_done_dodge(edict_t *self);
|
||||
|
||||
/* g_misc.c */
|
||||
void ThrowHead(edict_t *self, char *gibname, int damage, int type);
|
||||
void ThrowHead(edict_t *self, const char *gibname, int damage, int type);
|
||||
void ThrowClientHead(edict_t *self, int damage);
|
||||
void ThrowGib(edict_t *self, char *gibname, int damage, int type);
|
||||
void ThrowGib(edict_t *self, const char *gibname, int damage, int type);
|
||||
void BecomeExplosion1(edict_t *self);
|
||||
void ThrowHeadACID(edict_t *self, char *gibname, int damage, int type);
|
||||
void ThrowGibACID(edict_t *self, char *gibname, int damage, int type);
|
||||
void ThrowHeadACID(edict_t *self, const char *gibname, int damage, int type);
|
||||
void ThrowGibACID(edict_t *self, const char *gibname, int damage, int type);
|
||||
|
||||
/* g_ai.c */
|
||||
void AI_SetSightClient(void);
|
||||
|
|
776
src/game/monster/guardian/guardian.c
Normal file
776
src/game/monster/guardian/guardian.c
Normal file
|
@ -0,0 +1,776 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Copyright (c) ZeniMax Media Inc.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* The Guardian.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "../../header/local.h"
|
||||
#include "guardian.h"
|
||||
|
||||
void BossExplode(edict_t *self);
|
||||
|
||||
static int sound_charge;
|
||||
static int sound_spin_loop;
|
||||
|
||||
//
|
||||
// stand
|
||||
//
|
||||
|
||||
static mframe_t guardian_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},
|
||||
{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 guardian_move_stand =
|
||||
{
|
||||
FRAME_idle1,
|
||||
FRAME_idle52,
|
||||
guardian_frames_stand,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
guardian_stand(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_stand;
|
||||
}
|
||||
|
||||
//
|
||||
// walk
|
||||
//
|
||||
|
||||
static int sound_step;
|
||||
|
||||
void guardian_footstep(edict_t *self)
|
||||
{
|
||||
gi.sound(self, CHAN_BODY, sound_step, 1.f, ATTN_NORM, 0.0f);
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_walk[] = {
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, guardian_footstep},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, guardian_footstep},
|
||||
{ai_walk, 8, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_walk =
|
||||
{
|
||||
FRAME_walk1,
|
||||
FRAME_walk19,
|
||||
guardian_frames_walk,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
guardian_walk(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_walk;
|
||||
}
|
||||
|
||||
//
|
||||
// run
|
||||
//
|
||||
|
||||
static mframe_t guardian_frames_run[] = {
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, guardian_footstep},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, guardian_footstep},
|
||||
{ai_run, 8, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_run =
|
||||
{
|
||||
FRAME_walk1,
|
||||
FRAME_walk19,
|
||||
guardian_frames_run,
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
guardian_run(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
|
||||
{
|
||||
self->monsterinfo.currentmove = &guardian_move_stand;
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_run;
|
||||
}
|
||||
|
||||
//
|
||||
// pain
|
||||
//
|
||||
|
||||
static mframe_t guardian_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}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_pain1 =
|
||||
{
|
||||
FRAME_pain1_1,
|
||||
FRAME_pain1_8,
|
||||
guardian_frames_pain1,
|
||||
guardian_run
|
||||
};
|
||||
|
||||
void
|
||||
guardian_pain(edict_t *self, edict_t *other /* other */,
|
||||
float kick /* other */, int damage)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (damage <= 10)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.time < self->pain_debounce_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (damage <= 75)
|
||||
{
|
||||
if (random() > 0.2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* don't go into pain while attacking */
|
||||
if ((self->s.frame >= FRAME_atk1_spin1) && (self->s.frame <= FRAME_atk1_spin15))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((self->s.frame >= FRAME_atk2_fire1) && (self->s.frame <= FRAME_atk2_fire4))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((self->s.frame >= FRAME_kick_in1) && (self->s.frame <= FRAME_kick_in13))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->pain_debounce_time = level.time + 3;
|
||||
|
||||
if (skill->value == SKILL_HARDPLUS)
|
||||
{
|
||||
return; /* no pain anims in nightmare */
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_pain1;
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_atk1_out[] = {
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_atk1_out =
|
||||
{
|
||||
FRAME_atk1_out1,
|
||||
FRAME_atk1_out3,
|
||||
guardian_frames_atk1_out,
|
||||
guardian_run
|
||||
};
|
||||
|
||||
void guardian_atk1_finish(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_atk1_out;
|
||||
}
|
||||
|
||||
void guardian_atk1_charge(edict_t *self)
|
||||
{
|
||||
gi.sound(self, CHAN_WEAPON, sound_charge, 1.f, ATTN_NORM, 0.f);
|
||||
}
|
||||
|
||||
void guardian_fire_blaster(edict_t *self)
|
||||
{
|
||||
vec3_t forward, right, target;
|
||||
vec3_t start;
|
||||
int id = MZ2_TANK_BLASTER_1;
|
||||
|
||||
AngleVectors(self->s.angles, forward, right, NULL);
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[id], forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, target);
|
||||
target[2] += self->enemy->viewheight;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
target[i] += (randk() % 10) - 5.f;
|
||||
}
|
||||
|
||||
/* calc direction to where we targeted */
|
||||
VectorSubtract(target, start, forward);
|
||||
VectorNormalize(forward);
|
||||
|
||||
monster_fire_blaster(self, start, forward, 2, 1000, id, (self->s.frame % 4) ? 0 : EF_HYPERBLASTER);
|
||||
|
||||
if (self->enemy && self->enemy->health > 0 &&
|
||||
self->s.frame == FRAME_atk1_spin12 && self->timestamp > level.time && visible(self, self->enemy))
|
||||
self->monsterinfo.nextframe = FRAME_atk1_spin5;
|
||||
}
|
||||
|
||||
void
|
||||
guardian_hyper_sound(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gi.sound(self, CHAN_WEAPON, sound_spin_loop, 1.f, ATTN_NORM, 0.f);
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_atk1_spin[] = {
|
||||
{ai_charge, 0, guardian_atk1_charge},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_hyper_sound},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0, guardian_fire_blaster},
|
||||
{ai_charge, 0},
|
||||
{ai_charge, 0},
|
||||
{ai_charge, 0}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_atk1_spin =
|
||||
{
|
||||
FRAME_atk1_spin1,
|
||||
FRAME_atk1_spin15,
|
||||
guardian_frames_atk1_spin,
|
||||
guardian_atk1_finish
|
||||
};
|
||||
|
||||
void guardian_atk1(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_atk1_spin;
|
||||
self->timestamp = level.time + 0.650f + (randk() % 10 ) / 10.f * 1.5f;
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_atk1_in[] = {
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_atk1_in =
|
||||
{
|
||||
FRAME_atk1_in1,
|
||||
FRAME_atk1_in3,
|
||||
guardian_frames_atk1_in,
|
||||
guardian_atk1
|
||||
};
|
||||
|
||||
static mframe_t guardian_frames_atk2_out[] = {
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_atk2_out =
|
||||
{
|
||||
FRAME_atk2_out1,
|
||||
FRAME_atk2_out7,
|
||||
guardian_frames_atk2_out,
|
||||
guardian_run
|
||||
};
|
||||
|
||||
void guardian_atk2_out(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_atk2_out;
|
||||
}
|
||||
|
||||
static int sound_laser;
|
||||
|
||||
static vec3_t laser_positions[] = {
|
||||
{ 125.0f, -70.f, 60.f},
|
||||
{ 112.0f, -62.f, 60.f }
|
||||
};
|
||||
|
||||
void guardian_laser_fire(edict_t *self)
|
||||
{
|
||||
vec3_t forward, right, up;
|
||||
vec3_t tempang, start;
|
||||
vec3_t dir, angles, end;
|
||||
vec3_t tempvec;
|
||||
edict_t *ent;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gi.sound(self, CHAN_WEAPON, sound_laser, 1.f, ATTN_NORM, 0.f);
|
||||
|
||||
if (random() > 0.8)
|
||||
{
|
||||
gi.sound(self, CHAN_AUTO, gi.soundindex("misc/lasfly.wav"), 1, ATTN_STATIC, 0);
|
||||
}
|
||||
|
||||
VectorCopy(self->s.origin, start);
|
||||
VectorCopy(self->enemy->s.origin, end);
|
||||
VectorSubtract(end, start, dir);
|
||||
vectoangles(dir, angles);
|
||||
VectorCopy(laser_positions[1 - (self->s.frame & 1)], tempvec);
|
||||
|
||||
ent = G_Spawn();
|
||||
VectorCopy(self->s.origin, ent->s.origin);
|
||||
VectorCopy(angles, tempang);
|
||||
AngleVectors(tempang, forward, right, up);
|
||||
VectorCopy(tempang, ent->s.angles);
|
||||
VectorCopy(ent->s.origin, start);
|
||||
|
||||
VectorMA(start, tempvec[0] + 2, right, start);
|
||||
VectorMA(start, tempvec[2] + 8, up, start);
|
||||
VectorMA(start, tempvec[1], forward, start);
|
||||
|
||||
VectorCopy(start, ent->s.origin);
|
||||
ent->enemy = self->enemy;
|
||||
ent->owner = self;
|
||||
|
||||
ent->dmg = 25;
|
||||
|
||||
monster_dabeam(ent);
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_atk2_fire[] = {
|
||||
{ai_charge, 0, guardian_laser_fire},
|
||||
{ai_charge, 0, guardian_laser_fire},
|
||||
{ai_charge, 0, guardian_laser_fire},
|
||||
{ai_charge, 0, guardian_laser_fire }
|
||||
};
|
||||
|
||||
mmove_t guardian_move_atk2_fire =
|
||||
{
|
||||
FRAME_atk2_fire1,
|
||||
FRAME_atk2_fire4,
|
||||
guardian_frames_atk2_fire,
|
||||
guardian_atk2_out
|
||||
};
|
||||
|
||||
void guardian_atk2(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_atk2_fire;
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_atk2_in[] = {
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_atk2_in =
|
||||
{
|
||||
FRAME_atk2_in1,
|
||||
FRAME_atk2_in12,
|
||||
guardian_frames_atk2_in,
|
||||
guardian_atk2
|
||||
};
|
||||
|
||||
void
|
||||
guardian_kick(edict_t *self)
|
||||
{
|
||||
vec3_t aim = {MELEE_DISTANCE, 0, -80};
|
||||
fire_hit(self, aim, 85, 700);
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_kick[] =
|
||||
{
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_kick},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, guardian_footstep},
|
||||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_kick =
|
||||
{
|
||||
FRAME_kick_in1,
|
||||
FRAME_kick_in13,
|
||||
guardian_frames_kick,
|
||||
guardian_run
|
||||
};
|
||||
|
||||
void
|
||||
guardian_attack(edict_t *self)
|
||||
{
|
||||
float r;
|
||||
|
||||
if (!self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
r = realrange(self, self->enemy);
|
||||
|
||||
if (r > RANGE_NEAR)
|
||||
{
|
||||
self->monsterinfo.currentmove = &guardian_move_atk2_in;
|
||||
}
|
||||
else if (r < 120.f)
|
||||
{
|
||||
self->monsterinfo.currentmove = &guardian_move_kick;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->monsterinfo.currentmove = &guardian_move_atk1_in;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// death
|
||||
//
|
||||
|
||||
void guardian_explode(edict_t *self)
|
||||
{
|
||||
vec3_t start, pos;
|
||||
int i;
|
||||
|
||||
VectorAdd(self->s.origin, self->mins, start);
|
||||
|
||||
VectorCopy(self->size, pos);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
pos[i] *= random();
|
||||
}
|
||||
|
||||
VectorAdd(start, pos, pos);
|
||||
|
||||
gi.WriteByte(svc_temp_entity);
|
||||
gi.WriteByte(TE_EXPLOSION1_BIG);
|
||||
gi.WritePosition(pos);
|
||||
gi.multicast(self->s.origin, MULTICAST_ALL);
|
||||
}
|
||||
|
||||
static const char *gibs[] = {
|
||||
"models/monsters/guardian/gib1.md2",
|
||||
"models/monsters/guardian/gib2.md2",
|
||||
"models/monsters/guardian/gib3.md2",
|
||||
"models/monsters/guardian/gib4.md2",
|
||||
"models/monsters/guardian/gib5.md2",
|
||||
"models/monsters/guardian/gib6.md2",
|
||||
"models/monsters/guardian/gib7.md2"
|
||||
};
|
||||
|
||||
void guardian_dead(edict_t *self)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
guardian_explode(self);
|
||||
}
|
||||
|
||||
for (n = 0; n < 2; n++)
|
||||
{
|
||||
ThrowGib(self, "models/objects/gibs/sm_meat/tris.md2",
|
||||
125, GIB_ORGANIC);
|
||||
}
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
ThrowGib(self, "models/objects/gibs/sm_metal/tris.md2",
|
||||
125, GIB_METALLIC);
|
||||
}
|
||||
|
||||
for (n = 0; n < 6; n++)
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
ThrowGib(self, gibs[n], 125, GIB_METALLIC);
|
||||
}
|
||||
}
|
||||
|
||||
ThrowHead(self, gibs[6], 125, GIB_METALLIC);
|
||||
}
|
||||
|
||||
static mframe_t guardian_frames_death1[FRAME_death26 - FRAME_death1 + 1] = {
|
||||
{ai_move, 0, BossExplode},
|
||||
{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},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t guardian_move_death =
|
||||
{
|
||||
FRAME_death1,
|
||||
FRAME_death26,
|
||||
guardian_frames_death1,
|
||||
guardian_dead
|
||||
};
|
||||
|
||||
void
|
||||
guardian_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */,
|
||||
int damage, vec3_t point /* unused */)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* regular death */
|
||||
self->deadflag = true;
|
||||
self->takedamage = true;
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_death;
|
||||
}
|
||||
|
||||
//
|
||||
// monster_tank
|
||||
//
|
||||
|
||||
/*
|
||||
* QUAKED monster_guardian (1 .5 0) (-96 -96 -66) (96 96 62) Ambush Trigger_Spawn Sight
|
||||
*/
|
||||
void
|
||||
SP_monster_guardian(edict_t *self)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (deathmatch->value)
|
||||
{
|
||||
G_FreeEdict(self);
|
||||
return;
|
||||
}
|
||||
|
||||
sound_step = gi.soundindex("zortemp/step.wav");
|
||||
sound_charge = gi.soundindex("weapons/hyprbu1a.wav");
|
||||
sound_spin_loop = gi.soundindex("weapons/hyprbl1a.wav");
|
||||
sound_laser = gi.soundindex("weapons/laser2.wav");
|
||||
|
||||
for(i = 0; i < sizeof(gibs) / sizeof(*gibs); i++)
|
||||
{
|
||||
gi.modelindex(gibs[i]);
|
||||
}
|
||||
|
||||
self->s.modelindex = gi.modelindex("models/monsters/guardian/tris.md2");
|
||||
VectorSet(self->mins, -96, -96, -66);
|
||||
VectorSet(self->maxs, 96, 96, 62);
|
||||
self->movetype = MOVETYPE_STEP;
|
||||
self->solid = SOLID_BBOX;
|
||||
|
||||
self->health = 2500;
|
||||
self->gib_health = -200;
|
||||
|
||||
self->monsterinfo.scale = MODEL_SCALE;
|
||||
|
||||
self->mass = 850;
|
||||
|
||||
self->pain = guardian_pain;
|
||||
self->die = guardian_die;
|
||||
self->monsterinfo.stand = guardian_stand;
|
||||
self->monsterinfo.walk = guardian_walk;
|
||||
self->monsterinfo.run = guardian_run;
|
||||
self->monsterinfo.attack = guardian_attack;
|
||||
|
||||
gi.linkentity(self);
|
||||
|
||||
self->monsterinfo.currentmove = &guardian_move_stand;
|
||||
|
||||
walkmonster_start(self);
|
||||
}
|
244
src/game/monster/guardian/guardian.h
Normal file
244
src/game/monster/guardian/guardian.h
Normal file
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software Inc.
|
||||
* Copyright (c) ZeniMax Media Inc.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not write to the Free Software
|
||||
* Foundation Inc. 59 Temple Place - Suite 330 Boston MA
|
||||
* 02111-1307 USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Guardian animations.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#define FRAME_sleep1 0
|
||||
#define FRAME_sleep2 1
|
||||
#define FRAME_sleep3 2
|
||||
#define FRAME_sleep4 3
|
||||
#define FRAME_sleep5 4
|
||||
#define FRAME_sleep6 5
|
||||
#define FRAME_sleep7 6
|
||||
#define FRAME_sleep8 7
|
||||
#define FRAME_sleep9 8
|
||||
#define FRAME_sleep10 9
|
||||
#define FRAME_sleep11 10
|
||||
#define FRAME_sleep12 11
|
||||
#define FRAME_sleep13 12
|
||||
#define FRAME_sleep14 13
|
||||
#define FRAME_death1 14
|
||||
#define FRAME_death2 15
|
||||
#define FRAME_death3 16
|
||||
#define FRAME_death4 17
|
||||
#define FRAME_death5 18
|
||||
#define FRAME_death6 19
|
||||
#define FRAME_death7 20
|
||||
#define FRAME_death8 21
|
||||
#define FRAME_death9 22
|
||||
#define FRAME_death10 23
|
||||
#define FRAME_death11 24
|
||||
#define FRAME_death12 25
|
||||
#define FRAME_death13 26
|
||||
#define FRAME_death14 27
|
||||
#define FRAME_death15 28
|
||||
#define FRAME_death16 29
|
||||
#define FRAME_death17 30
|
||||
#define FRAME_death18 31
|
||||
#define FRAME_death19 32
|
||||
#define FRAME_death20 33
|
||||
#define FRAME_death21 34
|
||||
#define FRAME_death22 35
|
||||
#define FRAME_death23 36
|
||||
#define FRAME_death24 37
|
||||
#define FRAME_death25 38
|
||||
#define FRAME_death26 39
|
||||
#define FRAME_atk1_out1 40
|
||||
#define FRAME_atk1_out2 41
|
||||
#define FRAME_atk1_out3 42
|
||||
#define FRAME_atk2_out1 43
|
||||
#define FRAME_atk2_out2 44
|
||||
#define FRAME_atk2_out3 45
|
||||
#define FRAME_atk2_out4 46
|
||||
#define FRAME_atk2_out5 47
|
||||
#define FRAME_atk2_out6 48
|
||||
#define FRAME_atk2_out7 49
|
||||
#define FRAME_kick_out1 50
|
||||
#define FRAME_kick_out2 51
|
||||
#define FRAME_kick_out3 52
|
||||
#define FRAME_kick_out4 53
|
||||
#define FRAME_kick_out5 54
|
||||
#define FRAME_kick_out6 55
|
||||
#define FRAME_kick_out7 56
|
||||
#define FRAME_kick_out8 57
|
||||
#define FRAME_kick_out9 58
|
||||
#define FRAME_kick_out10 59
|
||||
#define FRAME_kick_out11 60
|
||||
#define FRAME_kick_out12 61
|
||||
#define FRAME_pain1_1 62
|
||||
#define FRAME_pain1_2 63
|
||||
#define FRAME_pain1_3 64
|
||||
#define FRAME_pain1_4 65
|
||||
#define FRAME_pain1_5 66
|
||||
#define FRAME_pain1_6 67
|
||||
#define FRAME_pain1_7 68
|
||||
#define FRAME_pain1_8 69
|
||||
#define FRAME_idle1 70
|
||||
#define FRAME_idle2 71
|
||||
#define FRAME_idle3 72
|
||||
#define FRAME_idle4 73
|
||||
#define FRAME_idle5 74
|
||||
#define FRAME_idle6 75
|
||||
#define FRAME_idle7 76
|
||||
#define FRAME_idle8 77
|
||||
#define FRAME_idle9 78
|
||||
#define FRAME_idle10 79
|
||||
#define FRAME_idle11 80
|
||||
#define FRAME_idle12 81
|
||||
#define FRAME_idle13 82
|
||||
#define FRAME_idle14 83
|
||||
#define FRAME_idle15 84
|
||||
#define FRAME_idle16 85
|
||||
#define FRAME_idle17 86
|
||||
#define FRAME_idle18 87
|
||||
#define FRAME_idle19 88
|
||||
#define FRAME_idle20 89
|
||||
#define FRAME_idle21 90
|
||||
#define FRAME_idle22 91
|
||||
#define FRAME_idle23 92
|
||||
#define FRAME_idle24 93
|
||||
#define FRAME_idle25 94
|
||||
#define FRAME_idle26 95
|
||||
#define FRAME_idle27 96
|
||||
#define FRAME_idle28 97
|
||||
#define FRAME_idle29 98
|
||||
#define FRAME_idle30 99
|
||||
#define FRAME_idle31 100
|
||||
#define FRAME_idle32 101
|
||||
#define FRAME_idle33 102
|
||||
#define FRAME_idle34 103
|
||||
#define FRAME_idle35 104
|
||||
#define FRAME_idle36 105
|
||||
#define FRAME_idle37 106
|
||||
#define FRAME_idle38 107
|
||||
#define FRAME_idle39 108
|
||||
#define FRAME_idle40 109
|
||||
#define FRAME_idle41 110
|
||||
#define FRAME_idle42 111
|
||||
#define FRAME_idle43 112
|
||||
#define FRAME_idle44 113
|
||||
#define FRAME_idle45 114
|
||||
#define FRAME_idle46 115
|
||||
#define FRAME_idle47 116
|
||||
#define FRAME_idle48 117
|
||||
#define FRAME_idle49 118
|
||||
#define FRAME_idle50 119
|
||||
#define FRAME_idle51 120
|
||||
#define FRAME_idle52 121
|
||||
#define FRAME_atk1_in1 122
|
||||
#define FRAME_atk1_in2 123
|
||||
#define FRAME_atk1_in3 124
|
||||
#define FRAME_kick_in1 125
|
||||
#define FRAME_kick_in2 126
|
||||
#define FRAME_kick_in3 127
|
||||
#define FRAME_kick_in4 128
|
||||
#define FRAME_kick_in5 129
|
||||
#define FRAME_kick_in6 130
|
||||
#define FRAME_kick_in7 131
|
||||
#define FRAME_kick_in8 132
|
||||
#define FRAME_kick_in9 133
|
||||
#define FRAME_kick_in10 134
|
||||
#define FRAME_kick_in11 135
|
||||
#define FRAME_kick_in12 136
|
||||
#define FRAME_kick_in13 137
|
||||
#define FRAME_walk1 138
|
||||
#define FRAME_walk2 139
|
||||
#define FRAME_walk3 140
|
||||
#define FRAME_walk4 141
|
||||
#define FRAME_walk5 142
|
||||
#define FRAME_walk6 143
|
||||
#define FRAME_walk7 144
|
||||
#define FRAME_walk8 145
|
||||
#define FRAME_walk9 146
|
||||
#define FRAME_walk10 147
|
||||
#define FRAME_walk11 148
|
||||
#define FRAME_walk12 149
|
||||
#define FRAME_walk13 150
|
||||
#define FRAME_walk14 151
|
||||
#define FRAME_walk15 152
|
||||
#define FRAME_walk16 153
|
||||
#define FRAME_walk17 154
|
||||
#define FRAME_walk18 155
|
||||
#define FRAME_walk19 156
|
||||
#define FRAME_wake1 157
|
||||
#define FRAME_wake2 158
|
||||
#define FRAME_wake3 159
|
||||
#define FRAME_wake4 160
|
||||
#define FRAME_wake5 161
|
||||
#define FRAME_atk1_spin1 162
|
||||
#define FRAME_atk1_spin2 163
|
||||
#define FRAME_atk1_spin3 164
|
||||
#define FRAME_atk1_spin4 165
|
||||
#define FRAME_atk1_spin5 166
|
||||
#define FRAME_atk1_spin6 167
|
||||
#define FRAME_atk1_spin7 168
|
||||
#define FRAME_atk1_spin8 169
|
||||
#define FRAME_atk1_spin9 170
|
||||
#define FRAME_atk1_spin10 171
|
||||
#define FRAME_atk1_spin11 172
|
||||
#define FRAME_atk1_spin12 173
|
||||
#define FRAME_atk1_spin13 174
|
||||
#define FRAME_atk1_spin14 175
|
||||
#define FRAME_atk1_spin15 176
|
||||
#define FRAME_atk2_fire1 177
|
||||
#define FRAME_atk2_fire2 178
|
||||
#define FRAME_atk2_fire3 179
|
||||
#define FRAME_atk2_fire4 180
|
||||
#define FRAME_turnl_1 181
|
||||
#define FRAME_turnl_2 182
|
||||
#define FRAME_turnl_3 183
|
||||
#define FRAME_turnl_4 184
|
||||
#define FRAME_turnl_5 185
|
||||
#define FRAME_turnl_6 186
|
||||
#define FRAME_turnl_7 187
|
||||
#define FRAME_turnl_8 188
|
||||
#define FRAME_turnl_9 189
|
||||
#define FRAME_turnl_10 190
|
||||
#define FRAME_turnl_11 191
|
||||
#define FRAME_turnr_1 192
|
||||
#define FRAME_turnr_2 193
|
||||
#define FRAME_turnr_3 194
|
||||
#define FRAME_turnr_4 195
|
||||
#define FRAME_turnr_5 196
|
||||
#define FRAME_turnr_6 197
|
||||
#define FRAME_turnr_7 198
|
||||
#define FRAME_turnr_8 199
|
||||
#define FRAME_turnr_9 200
|
||||
#define FRAME_turnr_10 201
|
||||
#define FRAME_turnr_11 202
|
||||
#define FRAME_atk2_in1 203
|
||||
#define FRAME_atk2_in2 204
|
||||
#define FRAME_atk2_in3 205
|
||||
#define FRAME_atk2_in4 206
|
||||
#define FRAME_atk2_in5 207
|
||||
#define FRAME_atk2_in6 208
|
||||
#define FRAME_atk2_in7 209
|
||||
#define FRAME_atk2_in8 210
|
||||
#define FRAME_atk2_in9 211
|
||||
#define FRAME_atk2_in10 212
|
||||
#define FRAME_atk2_in11 213
|
||||
#define FRAME_atk2_in12 214
|
||||
|
||||
#define MODEL_SCALE 1.000000
|
|
@ -2630,7 +2630,7 @@ soldierh_laserbeam(edict_t *self, int flash_index)
|
|||
VectorCopy(tempang, ent->s.angles);
|
||||
VectorCopy(ent->s.origin, start);
|
||||
|
||||
if (flash_index == 85)
|
||||
if (flash_index == MZ2_SOLDIER_MACHINEGUN_3)
|
||||
{
|
||||
VectorMA(start, tempvec[0] - 14, right, start);
|
||||
VectorMA(start, tempvec[2] + 8, up, start);
|
||||
|
|
|
@ -235,6 +235,7 @@ extern void ThrowWidowGibLoc ( edict_t * self , char * gibname , int damage , in
|
|||
extern void ThrowWidowGib ( edict_t * self , char * gibname , int damage , int type ) ;
|
||||
extern void widow_gib_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
|
||||
extern void WidowVelocityForDamage ( int damage , vec3_t v ) ;
|
||||
extern void SP_monster_guardian(edict_t *self);
|
||||
extern void SP_monster_widow2 ( edict_t * self ) ;
|
||||
extern void Widow2Precache ( void ) ;
|
||||
extern qboolean Widow2_CheckAttack ( edict_t * self ) ;
|
||||
|
@ -1499,10 +1500,10 @@ extern void BecomeExplosion1 ( edict_t * self ) ;
|
|||
extern void ThrowDebris ( edict_t * self , char * modelname , float speed , vec3_t origin ) ;
|
||||
extern void debris_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void ThrowClientHead ( edict_t * self , int damage ) ;
|
||||
extern void ThrowHeadACID ( edict_t * self , char * gibname , int damage , int type ) ;
|
||||
extern void ThrowGibACID ( edict_t * self , char * gibname , int damage , int type ) ;
|
||||
extern void ThrowHead ( edict_t * self , char * gibname , int damage , int type ) ;
|
||||
extern void ThrowGib ( edict_t * self , char * gibname , int damage , int type ) ;
|
||||
extern void ThrowHeadACID ( edict_t * self , const char * gibname , int damage , int type ) ;
|
||||
extern void ThrowGibACID ( edict_t * self , const char * gibname , int damage , int type ) ;
|
||||
extern void ThrowHead ( edict_t * self , const char * gibname , int damage , int type ) ;
|
||||
extern void ThrowGib ( edict_t * self , const char * gibname , int damage , int type ) ;
|
||||
extern void gib_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void gib_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ;
|
||||
extern void gib_think ( edict_t * self ) ;
|
||||
|
|
|
@ -237,6 +237,7 @@
|
|||
{"ThrowWidowGib", (byte *)ThrowWidowGib},
|
||||
{"widow_gib_touch", (byte *)widow_gib_touch},
|
||||
{"WidowVelocityForDamage", (byte *)WidowVelocityForDamage},
|
||||
{"SP_monster_guardian", (byte *)SP_monster_guardian},
|
||||
{"SP_monster_widow2", (byte *)SP_monster_widow2},
|
||||
{"Widow2Precache", (byte *)Widow2Precache},
|
||||
{"Widow2_CheckAttack", (byte *)Widow2_CheckAttack},
|
||||
|
|
Loading…
Reference in a new issue