mirror of
https://github.com/yquake2/rogue.git
synced 2024-11-10 06:42:21 +00:00
Merge branch 'master' into pvs
This commit is contained in:
commit
51b1eeb6a9
11 changed files with 770 additions and 126 deletions
|
@ -1113,7 +1113,7 @@ ai_run_slide(edict_t *self, float distance)
|
|||
/* clamp maximum sideways move for non flyers to make them look less jerky */
|
||||
if (!(self->flags & FL_FLY))
|
||||
{
|
||||
distance = min(distance, 0.8);
|
||||
distance = min(distance, 8.0);
|
||||
}
|
||||
|
||||
if (M_walkmove(self, self->ideal_yaw + ofs, distance))
|
||||
|
|
|
@ -159,7 +159,7 @@ mframe_t berserk_frames_run1[] = {
|
|||
{ai_run, 21, NULL},
|
||||
{ai_run, 11, NULL},
|
||||
{ai_run, 21, NULL},
|
||||
{ai_run, 25, NULL},
|
||||
{ai_run, 25, monster_done_dodge},
|
||||
{ai_run, 18, NULL},
|
||||
{ai_run, 19, NULL}
|
||||
};
|
||||
|
@ -179,6 +179,8 @@ berserk_run(edict_t *self)
|
|||
return;
|
||||
}
|
||||
|
||||
monster_done_dodge(self);
|
||||
|
||||
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_stand;
|
||||
|
@ -303,6 +305,8 @@ berserk_melee(edict_t *self)
|
|||
return;
|
||||
}
|
||||
|
||||
monster_done_dodge(self);
|
||||
|
||||
if ((rand() % 2) == 0)
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_attack_spike;
|
||||
|
@ -383,6 +387,8 @@ berserk_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage)
|
|||
return; /* no pain anims in nightmare */
|
||||
}
|
||||
|
||||
monster_done_dodge(self);
|
||||
|
||||
if ((damage < 20) || (random() < 0.5))
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_pain1;
|
||||
|
@ -499,6 +505,158 @@ berserk_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
berserk_jump_now(edict_t *self)
|
||||
{
|
||||
vec3_t forward, up;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
monster_jump_start(self);
|
||||
|
||||
AngleVectors(self->s.angles, forward, NULL, up);
|
||||
VectorMA(self->velocity, 100, forward, self->velocity);
|
||||
VectorMA(self->velocity, 300, up, self->velocity);
|
||||
}
|
||||
|
||||
void
|
||||
berserk_jump2_now(edict_t *self)
|
||||
{
|
||||
vec3_t forward,up;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
monster_jump_start(self);
|
||||
|
||||
AngleVectors(self->s.angles, forward, NULL, up);
|
||||
VectorMA(self->velocity, 150, forward, self->velocity);
|
||||
VectorMA(self->velocity, 400, up, self->velocity);
|
||||
}
|
||||
|
||||
void
|
||||
berserk_jump_wait_land(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->groundentity == NULL)
|
||||
{
|
||||
self->monsterinfo.nextframe = self->s.frame;
|
||||
|
||||
if (monster_jump_finished(self))
|
||||
{
|
||||
self->monsterinfo.nextframe = self->s.frame + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->monsterinfo.nextframe = self->s.frame + 1;
|
||||
}
|
||||
}
|
||||
|
||||
mframe_t berserk_frames_jump[] = {
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, berserk_jump_now},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, berserk_jump_wait_land},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t berserk_move_jump = {
|
||||
FRAME_jump1,
|
||||
FRAME_jump9,
|
||||
berserk_frames_jump,
|
||||
berserk_run
|
||||
};
|
||||
|
||||
mframe_t berserk_frames_jump2[] = {
|
||||
{ai_move, -8, NULL},
|
||||
{ai_move, -4, NULL},
|
||||
{ai_move, -4, NULL},
|
||||
{ai_move, 0, berserk_jump_now},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, berserk_jump_wait_land},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t berserk_move_jump2 = {
|
||||
FRAME_jump1,
|
||||
FRAME_jump9,
|
||||
berserk_frames_jump2,
|
||||
berserk_run
|
||||
};
|
||||
|
||||
void
|
||||
berserk_jump(edict_t *self)
|
||||
{
|
||||
if (!self || !self->enemy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
monster_done_dodge(self);
|
||||
|
||||
if (self->enemy->s.origin[2] > self->s.origin[2])
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_jump2;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_jump;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean
|
||||
berserk_blocked(edict_t *self, float dist)
|
||||
{
|
||||
if (blocked_checkjump(self, dist, 256, 40))
|
||||
{
|
||||
berserk_jump(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blocked_checkplat(self, dist))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
berserk_sidestep(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((self->monsterinfo.currentmove == &berserk_move_jump) ||
|
||||
(self->monsterinfo.currentmove == &berserk_move_jump2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.currentmove != &berserk_move_run1)
|
||||
{
|
||||
self->monsterinfo.currentmove = &berserk_move_run1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* QUAKED monster_berserk (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
|
||||
*/
|
||||
|
@ -540,11 +698,13 @@ SP_monster_berserk(edict_t *self)
|
|||
self->monsterinfo.stand = berserk_stand;
|
||||
self->monsterinfo.walk = berserk_walk;
|
||||
self->monsterinfo.run = berserk_run;
|
||||
self->monsterinfo.dodge = NULL;
|
||||
self->monsterinfo.dodge = M_MonsterDodge;
|
||||
self->monsterinfo.sidestep = berserk_sidestep;
|
||||
self->monsterinfo.attack = NULL;
|
||||
self->monsterinfo.melee = berserk_melee;
|
||||
self->monsterinfo.sight = berserk_sight;
|
||||
self->monsterinfo.search = berserk_search;
|
||||
self->monsterinfo.blocked = berserk_blocked;
|
||||
|
||||
self->monsterinfo.currentmove = &berserk_move_stand;
|
||||
self->monsterinfo.scale = MODEL_SCALE;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "../../header/local.h"
|
||||
#include "boss2.h"
|
||||
|
||||
#define BOSS2_ROCKET_SPEED 750
|
||||
|
||||
qboolean infront(edict_t *self, edict_t *other);
|
||||
void BossExplode(edict_t *self);
|
||||
void boss2_run(edict_t *self);
|
||||
|
@ -39,52 +41,125 @@ boss2_search(edict_t *self)
|
|||
}
|
||||
|
||||
void
|
||||
Boss2Rocket(edict_t *self)
|
||||
Boss2PredictiveRocket(edict_t *self)
|
||||
{
|
||||
vec3_t forward, right;
|
||||
vec3_t start;
|
||||
vec3_t dir;
|
||||
vec3_t vec;
|
||||
vec3_t forward, right;
|
||||
vec3_t start;
|
||||
vec3_t dir;
|
||||
vec3_t vec;
|
||||
float time, dist;
|
||||
|
||||
if (!self)
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AngleVectors(self->s.angles, forward, right, NULL);
|
||||
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1],
|
||||
forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
//1
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start);
|
||||
VectorSubtract(self->enemy->s.origin, start, dir);
|
||||
dist = VectorLength(dir);
|
||||
time = dist / BOSS2_ROCKET_SPEED;
|
||||
VectorMA(self->enemy->s.origin, time-0.3, self->enemy->velocity, vec);
|
||||
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_1);
|
||||
|
||||
//2
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start);
|
||||
VectorSubtract(self->enemy->s.origin, start, dir);
|
||||
dist = VectorLength(dir);
|
||||
time = dist / BOSS2_ROCKET_SPEED;
|
||||
VectorMA(self->enemy->s.origin, time-0.15, self->enemy->velocity, vec);
|
||||
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_2);
|
||||
|
||||
//3
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start);
|
||||
VectorSubtract(self->enemy->s.origin, start, dir);
|
||||
dist = VectorLength(dir);
|
||||
time = dist / BOSS2_ROCKET_SPEED;
|
||||
VectorMA(self->enemy->s.origin, time, self->enemy->velocity, vec);
|
||||
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_3);
|
||||
|
||||
//4
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
|
||||
VectorSubtract(self->enemy->s.origin, start, dir);
|
||||
dist = VectorLength(dir);
|
||||
time = dist / BOSS2_ROCKET_SPEED;
|
||||
VectorMA(self->enemy->s.origin, time+0.15, self->enemy->velocity, vec);
|
||||
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_4);
|
||||
}
|
||||
|
||||
void
|
||||
Boss2Rocket(edict_t *self)
|
||||
{
|
||||
vec3_t forward, right;
|
||||
vec3_t start;
|
||||
vec3_t dir;
|
||||
vec3_t vec;
|
||||
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->enemy->client && random() < 0.9)
|
||||
{
|
||||
Boss2PredictiveRocket(self);
|
||||
return;
|
||||
}
|
||||
|
||||
AngleVectors (self->s.angles, forward, right, NULL);
|
||||
|
||||
//1
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] -= 15;
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
VectorMA(dir, 0.4, right, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1);
|
||||
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2],
|
||||
forward, right, start);
|
||||
//2
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
VectorMA(dir, 0.025, right, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2);
|
||||
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3],
|
||||
forward, right, start);
|
||||
//3
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
VectorMA(dir, -0.025, right, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3);
|
||||
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4],
|
||||
forward, right, start);
|
||||
//4
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
vec[2] -= 15;
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
VectorMA(dir, -0.4, right, dir);
|
||||
VectorNormalize(dir);
|
||||
monster_fire_rocket(self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
boss2_firebullet_right(edict_t *self)
|
||||
|
@ -101,12 +176,12 @@ boss2_firebullet_right(edict_t *self)
|
|||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1],
|
||||
forward, right, start);
|
||||
|
||||
VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target);
|
||||
VectorMA(self->enemy->s.origin, 0.2, self->enemy->velocity, target);
|
||||
target[2] += self->enemy->viewheight;
|
||||
VectorSubtract(target, start, forward);
|
||||
VectorNormalize(forward);
|
||||
|
||||
monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD,
|
||||
monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3,
|
||||
DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1);
|
||||
}
|
||||
|
||||
|
@ -125,13 +200,13 @@ boss2_firebullet_left(edict_t *self)
|
|||
G_ProjectSource(self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1],
|
||||
forward, right, start);
|
||||
|
||||
VectorMA(self->enemy->s.origin, -0.2, self->enemy->velocity, target);
|
||||
VectorMA(self->enemy->s.origin, 0.2, self->enemy->velocity, target);
|
||||
|
||||
target[2] += self->enemy->viewheight;
|
||||
VectorSubtract(target, start, forward);
|
||||
VectorNormalize(forward);
|
||||
|
||||
monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD,
|
||||
monster_fire_bullet(self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3,
|
||||
DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1);
|
||||
}
|
||||
|
||||
|
@ -219,26 +294,26 @@ mmove_t boss2_move_fidget = {
|
|||
};
|
||||
|
||||
mframe_t boss2_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, 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, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL},
|
||||
{ai_walk, 8, NULL}
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL},
|
||||
{ai_walk, 10, NULL}
|
||||
};
|
||||
|
||||
mmove_t boss2_move_walk = {
|
||||
|
@ -249,26 +324,26 @@ mmove_t boss2_move_walk = {
|
|||
};
|
||||
|
||||
mframe_t boss2_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, 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, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL},
|
||||
{ai_run, 8, NULL}
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL},
|
||||
{ai_run, 10, NULL}
|
||||
};
|
||||
|
||||
mmove_t boss2_move_run = {
|
||||
|
@ -279,15 +354,15 @@ mmove_t boss2_move_run = {
|
|||
};
|
||||
|
||||
mframe_t boss2_frames_attack_pre_mg[] = {
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, boss2_attack_mg}
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, boss2_attack_mg}
|
||||
};
|
||||
|
||||
mmove_t boss2_move_attack_pre_mg = {
|
||||
|
@ -299,12 +374,12 @@ mmove_t boss2_move_attack_pre_mg = {
|
|||
|
||||
/* Loop this */
|
||||
mframe_t boss2_frames_attack_mg[] = {
|
||||
{ai_charge, 1, Boss2MachineGun},
|
||||
{ai_charge, 1, Boss2MachineGun},
|
||||
{ai_charge, 1, Boss2MachineGun},
|
||||
{ai_charge, 1, Boss2MachineGun},
|
||||
{ai_charge, 1, Boss2MachineGun},
|
||||
{ai_charge, 1, boss2_reattack_mg}
|
||||
{ai_charge, 2, Boss2MachineGun},
|
||||
{ai_charge, 2, Boss2MachineGun},
|
||||
{ai_charge, 2, Boss2MachineGun},
|
||||
{ai_charge, 2, Boss2MachineGun},
|
||||
{ai_charge, 2, Boss2MachineGun},
|
||||
{ai_charge, 2, boss2_reattack_mg}
|
||||
};
|
||||
|
||||
mmove_t boss2_move_attack_mg = {
|
||||
|
@ -315,10 +390,10 @@ mmove_t boss2_move_attack_mg = {
|
|||
};
|
||||
|
||||
mframe_t boss2_frames_attack_post_mg[] = {
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL}
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
@ -330,27 +405,27 @@ mmove_t boss2_move_attack_post_mg = {
|
|||
};
|
||||
|
||||
mframe_t boss2_frames_attack_rocket[] = {
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_move, -20, Boss2Rocket},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL},
|
||||
{ai_charge, 1, NULL}
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_move, -5, Boss2Rocket},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL},
|
||||
{ai_charge, 2, NULL}
|
||||
};
|
||||
|
||||
mmove_t boss2_move_attack_rocket = {FRAME_attack20,
|
||||
|
@ -666,7 +741,11 @@ Boss2_CheckAttack(edict_t *self)
|
|||
/* do we have a clear shot? */
|
||||
if (tr.ent != self->enemy)
|
||||
{
|
||||
return false;
|
||||
/* we want them to go ahead and shoot at info_notnulls if they can */
|
||||
if (self->enemy->solid != SOLID_NOT || tr.fraction < 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -724,7 +803,7 @@ Boss2_CheckAttack(edict_t *self)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (random() < chance)
|
||||
if ((random() < chance) || (self->enemy->solid == SOLID_NOT))
|
||||
{
|
||||
self->monsterinfo.attack_state = AS_MISSILE;
|
||||
self->monsterinfo.attack_finished = level.time + 2 * random();
|
||||
|
|
|
@ -54,7 +54,7 @@ floater_fire_blaster(edict_t *self)
|
|||
vec3_t dir;
|
||||
int effect;
|
||||
|
||||
if (!self)
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -285,6 +285,31 @@ mmove_t floater_move_attack1 = {
|
|||
floater_run
|
||||
};
|
||||
|
||||
/* circle strafe frames */
|
||||
mframe_t floater_frames_attack1a[] = {
|
||||
{ai_charge, 10, NULL}, // Blaster attack
|
||||
{ai_charge, 10, NULL},
|
||||
{ai_charge, 10, NULL},
|
||||
{ai_charge, 10, floater_fire_blaster}, // BOOM (0, -25.8, 32.5) -- LOOP Starts
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, floater_fire_blaster},
|
||||
{ai_charge, 10, NULL},
|
||||
{ai_charge, 10, NULL},
|
||||
{ai_charge, 10, NULL},
|
||||
{ai_charge, 10, NULL} // -- LOOP Ends
|
||||
};
|
||||
|
||||
mmove_t floater_move_attack1a = {
|
||||
FRAME_attak101,
|
||||
FRAME_attak114,
|
||||
floater_frames_attack1a,
|
||||
floater_run
|
||||
};
|
||||
|
||||
mframe_t floater_frames_attack2[] = {
|
||||
{ai_charge, 0, NULL}, /* Claws */
|
||||
{ai_charge, 0, NULL},
|
||||
|
@ -640,7 +665,7 @@ floater_zap(edict_t *self)
|
|||
gi.WriteByte(1); /* sparks */
|
||||
gi.multicast(origin, MULTICAST_PVS);
|
||||
|
||||
if (range(self, self->enemy) && infront(self, self->enemy) &&
|
||||
if (range(self, self->enemy) == RANGE_MELEE && infront(self, self->enemy) &&
|
||||
visible(self, self->enemy))
|
||||
{
|
||||
T_Damage(self->enemy, self, self, dir, self->enemy->s.origin,
|
||||
|
@ -651,12 +676,41 @@ floater_zap(edict_t *self)
|
|||
void
|
||||
floater_attack(edict_t *self)
|
||||
{
|
||||
float chance;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.currentmove = &floater_move_attack1;
|
||||
// 0% chance of circle in easy
|
||||
// 50% chance in normal
|
||||
// 75% chance in hard
|
||||
// 86.67% chance in nightmare
|
||||
if (!skill->value)
|
||||
{
|
||||
chance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chance = 1.0 - (0.5/(float)(skill->value));
|
||||
}
|
||||
|
||||
if (random() > chance)
|
||||
{
|
||||
self->monsterinfo.attack_state = AS_STRAIGHT;
|
||||
self->monsterinfo.currentmove = &floater_move_attack1;
|
||||
}
|
||||
else // circle strafe
|
||||
{
|
||||
if (random () <= 0.5) // switch directions
|
||||
{
|
||||
self->monsterinfo.lefty = 1 - self->monsterinfo.lefty;
|
||||
}
|
||||
|
||||
self->monsterinfo.attack_state = AS_SLIDING;
|
||||
self->monsterinfo.currentmove = &floater_move_attack1a;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -747,6 +801,22 @@ floater_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
|
|||
BecomeExplosion1(self);
|
||||
}
|
||||
|
||||
qboolean
|
||||
floater_blocked(edict_t *self, float dist)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blocked_checkshot(self, 0.25 + (0.05 * skill->value)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUAKED monster_floater (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
|
||||
*/
|
||||
|
@ -796,6 +866,7 @@ SP_monster_floater(edict_t *self)
|
|||
self->monsterinfo.melee = floater_melee;
|
||||
self->monsterinfo.sight = floater_sight;
|
||||
self->monsterinfo.idle = floater_idle;
|
||||
self->monsterinfo.blocked = floater_blocked;
|
||||
|
||||
gi.linkentity(self);
|
||||
|
||||
|
|
|
@ -466,6 +466,27 @@ gladiator_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker
|
|||
self->monsterinfo.currentmove = &gladiator_move_death;
|
||||
}
|
||||
|
||||
qboolean
|
||||
gladiator_blocked(edict_t *self, float dist)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blocked_checkplat(self, dist))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUAKED monster_gladiator (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight
|
||||
*/
|
||||
|
@ -516,6 +537,7 @@ SP_monster_gladiator(edict_t *self)
|
|||
self->monsterinfo.sight = gladiator_sight;
|
||||
self->monsterinfo.idle = gladiator_idle;
|
||||
self->monsterinfo.search = gladiator_search;
|
||||
self->monsterinfo.blocked = gladiator_blocked;
|
||||
|
||||
gi.linkentity(self);
|
||||
self->monsterinfo.currentmove = &gladiator_move_stand;
|
||||
|
|
|
@ -804,6 +804,117 @@ mutant_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /*
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
mutant_jump_down(edict_t *self)
|
||||
{
|
||||
vec3_t forward, up;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AngleVectors(self->s.angles, forward, NULL, up);
|
||||
VectorMA(self->velocity, 100, forward, self->velocity);
|
||||
VectorMA(self->velocity, 300, up, self->velocity);
|
||||
}
|
||||
|
||||
void
|
||||
mutant_jump_up(edict_t *self)
|
||||
{
|
||||
vec3_t forward, up;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AngleVectors(self->s.angles, forward, NULL, up);
|
||||
VectorMA(self->velocity, 200, forward, self->velocity);
|
||||
VectorMA(self->velocity, 450, up, self->velocity);
|
||||
}
|
||||
|
||||
void
|
||||
mutant_jump_wait_land(edict_t *self)
|
||||
{
|
||||
if (self->groundentity == NULL)
|
||||
{
|
||||
self->monsterinfo.nextframe = self->s.frame;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->monsterinfo.nextframe = self->s.frame + 1;
|
||||
}
|
||||
}
|
||||
|
||||
mframe_t mutant_frames_jump_up[] = {
|
||||
{ai_move, -8, NULL},
|
||||
{ai_move, -8, mutant_jump_up},
|
||||
{ai_move, 0, mutant_jump_wait_land},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t mutant_move_jump_up = {
|
||||
FRAME_jump01,
|
||||
FRAME_jump05,
|
||||
mutant_frames_jump_up,
|
||||
mutant_run
|
||||
};
|
||||
|
||||
mframe_t mutant_frames_jump_down[] = {
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, mutant_jump_down},
|
||||
{ai_move, 0, mutant_jump_wait_land},
|
||||
{ai_move, 0, NULL},
|
||||
{ai_move, 0, NULL}
|
||||
};
|
||||
|
||||
mmove_t mutant_move_jump_down = {
|
||||
FRAME_jump01,
|
||||
FRAME_jump05,
|
||||
mutant_frames_jump_down,
|
||||
mutant_run
|
||||
};
|
||||
|
||||
void
|
||||
mutant_jump_updown(edict_t *self)
|
||||
{
|
||||
if (!self || !self->enemy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->enemy->s.origin[2] > self->s.origin[2])
|
||||
{
|
||||
self->monsterinfo.currentmove = &mutant_move_jump_up;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->monsterinfo.currentmove = &mutant_move_jump_down;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean
|
||||
mutant_blocked(edict_t *self, float dist)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blocked_checkjump(self, dist, 256, 68))
|
||||
{
|
||||
mutant_jump_updown(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blocked_checkplat(self, dist))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUAKED monster_mutant (1 .5 0) (-32 -32 -24) (32 32 32) Ambush Trigger_Spawn Sight
|
||||
*/
|
||||
|
@ -858,6 +969,7 @@ SP_monster_mutant(edict_t *self)
|
|||
self->monsterinfo.search = mutant_search;
|
||||
self->monsterinfo.idle = mutant_idle;
|
||||
self->monsterinfo.checkattack = mutant_checkattack;
|
||||
self->monsterinfo.blocked = mutant_blocked;
|
||||
|
||||
gi.linkentity(self);
|
||||
|
||||
|
|
|
@ -394,6 +394,8 @@ tank_pain(edict_t *self, edict_t *other /* unused */, float kick, int damage)
|
|||
return; /* no pain anims in nightmare */
|
||||
}
|
||||
|
||||
self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
|
||||
|
||||
if (damage <= 30)
|
||||
{
|
||||
self->monsterinfo.currentmove = &tank_move_pain1;
|
||||
|
@ -465,12 +467,25 @@ TankRocket(edict_t *self)
|
|||
vec3_t dir;
|
||||
vec3_t vec;
|
||||
int flash_number;
|
||||
trace_t trace;
|
||||
int rocketSpeed;
|
||||
vec3_t target;
|
||||
qboolean blindfire = false;
|
||||
|
||||
if (!self)
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
|
||||
{
|
||||
blindfire = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
blindfire = false;
|
||||
}
|
||||
|
||||
if (self->s.frame == FRAME_attak324)
|
||||
{
|
||||
flash_number = MZ2_TANK_ROCKET_1;
|
||||
|
@ -485,15 +500,111 @@ TankRocket(edict_t *self)
|
|||
}
|
||||
|
||||
AngleVectors(self->s.angles, forward, right, NULL);
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward,
|
||||
right, start);
|
||||
G_ProjectSource(self->s.origin, monster_flash_offset[flash_number], forward, right, start);
|
||||
|
||||
rocketSpeed = 500 + (100 * skill->value);
|
||||
|
||||
if (blindfire)
|
||||
{
|
||||
VectorCopy (self->monsterinfo.blind_fire_target, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy (self->enemy->s.origin, target);
|
||||
}
|
||||
|
||||
if (blindfire)
|
||||
{
|
||||
VectorCopy(target, vec);
|
||||
VectorSubtract(vec, start, dir);
|
||||
}
|
||||
else if(random() < 0.66 || (start[2] < self->enemy->absmin[2]))
|
||||
{
|
||||
// Don't shoot at the feed if enemy is above.
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
VectorSubtract(vec, start, dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shoot at the feed.
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] = self->enemy->absmin[2];
|
||||
VectorSubtract(vec, start, dir);
|
||||
}
|
||||
|
||||
// Lead target: 20, 35, 50, 65 chance of leading.
|
||||
if ((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15)))))
|
||||
{
|
||||
float dist;
|
||||
float time;
|
||||
|
||||
dist = VectorLength(dir);
|
||||
time = dist/rocketSpeed;
|
||||
VectorMA(vec, time, self->enemy->velocity, vec);
|
||||
VectorSubtract(vec, start, dir);
|
||||
}
|
||||
|
||||
VectorCopy(self->enemy->s.origin, vec);
|
||||
vec[2] += self->enemy->viewheight;
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
|
||||
monster_fire_rocket(self, start, dir, 50, 550, flash_number);
|
||||
// Blindfire doesn't check target (done in checkattack). Paranoia:
|
||||
// Make sure we're not shooting a target right next to us.
|
||||
trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
|
||||
|
||||
if (blindfire)
|
||||
{
|
||||
// Blindfire has different fail criteria for the trace
|
||||
if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
|
||||
{
|
||||
monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try shifting the target to the left a little (to help counter large offset)
|
||||
VectorCopy(target, vec);
|
||||
VectorMA(vec, -20, right, vec);
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
|
||||
trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
|
||||
|
||||
if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
|
||||
{
|
||||
monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number);
|
||||
}
|
||||
else
|
||||
{
|
||||
// OK, that failed. Try to the right.
|
||||
VectorCopy(target, vec);
|
||||
VectorMA(vec, 20, right, vec);
|
||||
VectorSubtract(vec, start, dir);
|
||||
VectorNormalize(dir);
|
||||
|
||||
trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
|
||||
|
||||
if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
|
||||
{
|
||||
monster_fire_rocket (self, start, dir, 50, rocketSpeed, flash_number);
|
||||
}
|
||||
else if ((g_showlogic) && (g_showlogic->value))
|
||||
{
|
||||
gi.dprintf ("tank avoiding blindfire shot\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
|
||||
|
||||
if (trace.ent == self->enemy || trace.ent == world)
|
||||
{
|
||||
if (trace.fraction > 0.5 || (trace.ent && trace.ent->client))
|
||||
{
|
||||
monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -505,7 +616,7 @@ TankMachineGun(edict_t *self)
|
|||
vec3_t forward, right;
|
||||
int flash_number;
|
||||
|
||||
if (!self)
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -564,9 +675,12 @@ mframe_t tank_frames_attack_blast[] = {
|
|||
{ai_charge, 0, NULL},
|
||||
{ai_charge, 0, TankBlaster} /* 16 */
|
||||
};
|
||||
mmove_t tank_move_attack_blast =
|
||||
{FRAME_attak101, FRAME_attak116, tank_frames_attack_blast,
|
||||
tank_reattack_blaster};
|
||||
mmove_t tank_move_attack_blast = {
|
||||
FRAME_attak101,
|
||||
FRAME_attak116,
|
||||
tank_frames_attack_blast,
|
||||
tank_reattack_blaster
|
||||
};
|
||||
|
||||
mframe_t tank_frames_reattack_blast[] = {
|
||||
{ai_charge, 0, NULL},
|
||||
|
@ -820,6 +934,13 @@ tank_refire_rocket(edict_t *self)
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
|
||||
{
|
||||
self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
|
||||
self->monsterinfo.currentmove = &tank_move_attack_post_rocket;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only on hard or nightmare */
|
||||
if (skill->value >= 2)
|
||||
{
|
||||
|
@ -856,8 +977,9 @@ tank_attack(edict_t *self)
|
|||
vec3_t vec;
|
||||
float range;
|
||||
float r;
|
||||
float chance;
|
||||
|
||||
if (!self)
|
||||
if (!self || !self->enemy || !self->enemy->inuse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -869,6 +991,45 @@ tank_attack(edict_t *self)
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->monsterinfo.attack_state == AS_BLIND)
|
||||
{
|
||||
if (self->monsterinfo.blind_fire_delay < 1.0)
|
||||
{
|
||||
chance = 1.0;
|
||||
}
|
||||
else if (self->monsterinfo.blind_fire_delay < 7.5)
|
||||
{
|
||||
chance = 0.4;
|
||||
}
|
||||
else
|
||||
{
|
||||
chance = 0.1;
|
||||
}
|
||||
|
||||
r = random();
|
||||
|
||||
self->monsterinfo.blind_fire_delay += 3.2 + 2.0 + random() * 3.0;
|
||||
|
||||
// Don't shoot at the origin.
|
||||
if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't shoot if the dice say not to.
|
||||
if (r > chance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// turn on manual steering to signal both manual steering and blindfire
|
||||
self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
|
||||
self->monsterinfo.currentmove = &tank_move_attack_fire_rocket;
|
||||
self->monsterinfo.attack_finished = level.time + 3.0 + 2*random();
|
||||
self->pain_debounce_time = level.time + 5.0; // no pain for a while
|
||||
return;
|
||||
}
|
||||
|
||||
VectorSubtract(self->enemy->s.origin, self->s.origin, vec);
|
||||
range = VectorLength(vec);
|
||||
|
||||
|
@ -986,8 +1147,7 @@ tank_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* un
|
|||
/* check for gib */
|
||||
if (self->health <= self->gib_health)
|
||||
{
|
||||
gi.sound(self, CHAN_VOICE, gi.soundindex(
|
||||
"misc/udeath.wav"), 1, ATTN_NORM, 0);
|
||||
gi.sound(self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
|
||||
|
||||
for (n = 0; n < 1 /*4*/; n++)
|
||||
{
|
||||
|
@ -1018,6 +1178,20 @@ tank_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* un
|
|||
self->monsterinfo.currentmove = &tank_move_death;
|
||||
}
|
||||
|
||||
qboolean tank_blocked(edict_t *self, float dist)
|
||||
{
|
||||
if (blocked_checkshot(self, 0.25 + (0.05 * skill->value) ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(blocked_checkplat(self, dist))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
|
||||
|
@ -1086,6 +1260,7 @@ SP_monster_tank(edict_t *self)
|
|||
self->monsterinfo.melee = NULL;
|
||||
self->monsterinfo.sight = tank_sight;
|
||||
self->monsterinfo.idle = tank_idle;
|
||||
self->monsterinfo.blocked = tank_blocked;
|
||||
|
||||
gi.linkentity(self);
|
||||
|
||||
|
@ -1094,6 +1269,9 @@ SP_monster_tank(edict_t *self)
|
|||
|
||||
walkmonster_start(self);
|
||||
|
||||
self->monsterinfo.aiflags |= AI_IGNORE_SHOTS;
|
||||
self->monsterinfo.blindfire = true;
|
||||
|
||||
if (strcmp(self->classname, "monster_tank_commander") == 0)
|
||||
{
|
||||
self->s.skinnum = 2;
|
||||
|
|
|
@ -329,6 +329,7 @@ extern void tank_windup ( edict_t * self ) ;
|
|||
extern void tank_thud ( edict_t * self ) ;
|
||||
extern void tank_footstep ( edict_t * self ) ;
|
||||
extern void tank_sight ( edict_t * self , edict_t * other ) ;
|
||||
extern qboolean tank_blocked( edict_t *self, float dist );
|
||||
extern void SP_monster_supertank ( edict_t * self ) ;
|
||||
extern qboolean supertank_blocked ( edict_t * self , float dist ) ;
|
||||
extern void supertank_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
|
@ -442,6 +443,7 @@ extern void parasite_sight ( edict_t * self , edict_t * other ) ;
|
|||
extern void parasite_reel_in ( edict_t * self ) ;
|
||||
extern void parasite_launch ( edict_t * self ) ;
|
||||
extern void SP_monster_mutant ( edict_t * self ) ;
|
||||
extern qboolean mutant_blocked ( edict_t * self , float dist ) ;
|
||||
extern void mutant_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void mutant_dead ( edict_t * self ) ;
|
||||
extern void mutant_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
|
||||
|
@ -586,6 +588,7 @@ extern void gunner_search ( edict_t * self ) ;
|
|||
extern void gunner_sight ( edict_t * self , edict_t * other ) ;
|
||||
extern void gunner_idlesound ( edict_t * self ) ;
|
||||
extern void SP_monster_gladiator ( edict_t * self ) ;
|
||||
qboolean gladiator_blocked ( edict_t *self , float dist ) ;
|
||||
extern void gladiator_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void gladiator_dead ( edict_t * self ) ;
|
||||
extern void gladiator_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
|
||||
|
@ -628,6 +631,7 @@ extern void flyer_pop_blades ( edict_t * self ) ;
|
|||
extern void flyer_idle ( edict_t * self ) ;
|
||||
extern void flyer_sight ( edict_t * self , edict_t * other ) ;
|
||||
extern void SP_monster_floater ( edict_t * self ) ;
|
||||
extern qboolean floater_blocked ( edict_t * self , float dist ) ;
|
||||
extern void floater_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void floater_dead ( edict_t * self ) ;
|
||||
extern void floater_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
|
||||
|
@ -792,6 +796,8 @@ extern void boss2_firebullet_right ( edict_t * self ) ;
|
|||
extern void Boss2Rocket ( edict_t * self ) ;
|
||||
extern void boss2_search ( edict_t * self ) ;
|
||||
extern void SP_monster_berserk ( edict_t * self ) ;
|
||||
extern void berserk_sidestep ( edict_t * self ) ;
|
||||
extern qboolean berserk_blocked ( edict_t * self , float dist ) ;
|
||||
extern void berserk_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
|
||||
extern void berserk_dead ( edict_t * self ) ;
|
||||
extern void berserk_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;
|
||||
|
|
|
@ -329,6 +329,7 @@
|
|||
{"tank_thud", (byte *)tank_thud},
|
||||
{"tank_footstep", (byte *)tank_footstep},
|
||||
{"tank_sight", (byte *)tank_sight},
|
||||
{"tank_blocked", (byte *)tank_blocked},
|
||||
{"SP_monster_supertank", (byte *)SP_monster_supertank},
|
||||
{"supertank_blocked", (byte *)supertank_blocked},
|
||||
{"supertank_die", (byte *)supertank_die},
|
||||
|
@ -442,6 +443,7 @@
|
|||
{"parasite_reel_in", (byte *)parasite_reel_in},
|
||||
{"parasite_launch", (byte *)parasite_launch},
|
||||
{"SP_monster_mutant", (byte *)SP_monster_mutant},
|
||||
{"mutant_blocked", (byte *)mutant_blocked},
|
||||
{"mutant_die", (byte *)mutant_die},
|
||||
{"mutant_dead", (byte *)mutant_dead},
|
||||
{"mutant_pain", (byte *)mutant_pain},
|
||||
|
@ -586,6 +588,7 @@
|
|||
{"gunner_sight", (byte *)gunner_sight},
|
||||
{"gunner_idlesound", (byte *)gunner_idlesound},
|
||||
{"SP_monster_gladiator", (byte *)SP_monster_gladiator},
|
||||
{"gladiator_blocked", (byte *)gladiator_blocked},
|
||||
{"gladiator_die", (byte *)gladiator_die},
|
||||
{"gladiator_dead", (byte *)gladiator_dead},
|
||||
{"gladiator_pain", (byte *)gladiator_pain},
|
||||
|
@ -628,6 +631,7 @@
|
|||
{"flyer_idle", (byte *)flyer_idle},
|
||||
{"flyer_sight", (byte *)flyer_sight},
|
||||
{"SP_monster_floater", (byte *)SP_monster_floater},
|
||||
{"floater_blocked", (byte *)floater_blocked},
|
||||
{"floater_die", (byte *)floater_die},
|
||||
{"floater_dead", (byte *)floater_dead},
|
||||
{"floater_pain", (byte *)floater_pain},
|
||||
|
@ -792,6 +796,8 @@
|
|||
{"Boss2Rocket", (byte *)Boss2Rocket},
|
||||
{"boss2_search", (byte *)boss2_search},
|
||||
{"SP_monster_berserk", (byte *)SP_monster_berserk},
|
||||
{"berserk_sidestep", (byte *)berserk_sidestep},
|
||||
{"berserk_blocked", (byte *)berserk_blocked},
|
||||
{"berserk_die", (byte *)berserk_die},
|
||||
{"berserk_dead", (byte *)berserk_dead},
|
||||
{"berserk_pain", (byte *)berserk_pain},
|
||||
|
|
|
@ -133,6 +133,8 @@ extern mmove_t parasite_move_stand ;
|
|||
extern mmove_t parasite_move_end_fidget ;
|
||||
extern mmove_t parasite_move_fidget ;
|
||||
extern mmove_t parasite_move_start_fidget ;
|
||||
extern mmove_t mutant_move_jump_down ;
|
||||
extern mmove_t mutant_move_jump_up ;
|
||||
extern mmove_t mutant_move_death2 ;
|
||||
extern mmove_t mutant_move_death1 ;
|
||||
extern mmove_t mutant_move_pain3 ;
|
||||
|
@ -252,6 +254,7 @@ extern mmove_t floater_move_pain1 ;
|
|||
extern mmove_t floater_move_death ;
|
||||
extern mmove_t floater_move_attack3 ;
|
||||
extern mmove_t floater_move_attack2 ;
|
||||
extern mmove_t floater_move_attack1a ;
|
||||
extern mmove_t floater_move_attack1 ;
|
||||
extern mmove_t floater_move_activate ;
|
||||
extern mmove_t floater_move_stand2 ;
|
||||
|
@ -346,6 +349,8 @@ extern mmove_t boss2_move_run ;
|
|||
extern mmove_t boss2_move_walk ;
|
||||
extern mmove_t boss2_move_fidget ;
|
||||
extern mmove_t boss2_move_stand ;
|
||||
extern mmove_t berserk_move_jump2 ;
|
||||
extern mmove_t berserk_move_jump ;
|
||||
extern mmove_t berserk_move_death2 ;
|
||||
extern mmove_t berserk_move_death1 ;
|
||||
extern mmove_t berserk_move_pain2 ;
|
||||
|
|
|
@ -133,6 +133,8 @@
|
|||
{"parasite_move_end_fidget", ¶site_move_end_fidget},
|
||||
{"parasite_move_fidget", ¶site_move_fidget},
|
||||
{"parasite_move_start_fidget", ¶site_move_start_fidget},
|
||||
{"mutant_move_jump_down", &mutant_move_jump_down},
|
||||
{"mutant_move_jump_up", &mutant_move_jump_up},
|
||||
{"mutant_move_death2", &mutant_move_death2},
|
||||
{"mutant_move_death1", &mutant_move_death1},
|
||||
{"mutant_move_pain3", &mutant_move_pain3},
|
||||
|
@ -252,6 +254,7 @@
|
|||
{"floater_move_death", &floater_move_death},
|
||||
{"floater_move_attack3", &floater_move_attack3},
|
||||
{"floater_move_attack2", &floater_move_attack2},
|
||||
{"floater_move_attack1a", &floater_move_attack1a},
|
||||
{"floater_move_attack1", &floater_move_attack1},
|
||||
{"floater_move_activate", &floater_move_activate},
|
||||
{"floater_move_stand2", &floater_move_stand2},
|
||||
|
@ -346,6 +349,8 @@
|
|||
{"boss2_move_walk", &boss2_move_walk},
|
||||
{"boss2_move_fidget", &boss2_move_fidget},
|
||||
{"boss2_move_stand", &boss2_move_stand},
|
||||
{"berserk_move_jump2", &berserk_move_jump2},
|
||||
{"berserk_move_jump", &berserk_move_jump},
|
||||
{"berserk_move_death2", &berserk_move_death2},
|
||||
{"berserk_move_death1", &berserk_move_death1},
|
||||
{"berserk_move_pain2", &berserk_move_pain2},
|
||||
|
|
Loading…
Reference in a new issue