mirror of
https://github.com/nzp-team/quakec.git
synced 2024-11-10 14:42:05 +00:00
SERVER: Fix several instances of Zombies not reaching and hopping over barricades
This commit is contained in:
parent
ec76c768cd
commit
0874299caf
2 changed files with 73 additions and 36 deletions
|
@ -58,12 +58,23 @@ void() path_corner =
|
|||
setsize(self, '0 0 0 ', '0 0 0');
|
||||
};
|
||||
|
||||
|
||||
void removeZombie();
|
||||
void() Respawn =
|
||||
{
|
||||
// cypress (20 dec 2023) -- whoever wrote this originally wasn't considering
|
||||
// many factors.. if a zombie respawns there's a chance it'll be in a
|
||||
// completely different playspace, where the initial window isn't visible
|
||||
// at all, and removeZombie() does not clear that field (rightfully so).
|
||||
// so i've replaced this with the same function i use to respawn zombies
|
||||
// inside of the playable area, which calls self.th_die() and fibs to the
|
||||
// zombie counter a little better, fixes that issue.
|
||||
|
||||
// Kill it.
|
||||
self.th_die();
|
||||
|
||||
// This is a pseudo-hack that just tells the rounds core that we should
|
||||
// spawn another.
|
||||
Current_Zombies--;
|
||||
removeZombie();
|
||||
Remaining_Zombies++;
|
||||
};
|
||||
|
||||
entity(entity blarg) find_new_enemy =
|
||||
|
@ -319,7 +330,15 @@ void(float dist) Window_Walk =
|
|||
|
||||
if(self.goalentity.classname == "window")
|
||||
{
|
||||
if(!self.goalentity.box1owner)
|
||||
// cypress (17 dec 2023) -- fixed a nasty race condition here.
|
||||
// essentially, if a new zombie spawns in fast enough after
|
||||
// a zombie is currently/just finished hopping a spot, they will
|
||||
// end up always taking box1owner (the hoppable zombie)'s place,
|
||||
// regardless of whether or not there was someone else waiting.
|
||||
// apparently this is an issue i've created rather recently,
|
||||
// which does not make sense to me considering this is a pretty
|
||||
// glaring oversight that's been here since 2014. not my whoops?
|
||||
if(!self.goalentity.box1owner && !self.goalentity.box2owner && !self.goalentity.box3owner)
|
||||
{
|
||||
//self.used = WBOX1;
|
||||
self.goalentity.box1owner = self;
|
||||
|
@ -369,7 +388,7 @@ void(float dist) Window_Walk =
|
|||
}
|
||||
else if(self.hop_step == 2)//we're at idle box, waiting for a window attack box to be free...
|
||||
{
|
||||
if(!self.goalentity.box1owner)
|
||||
if(self.goalentity.box1owner == world)
|
||||
{
|
||||
//self.used = WBOX1;
|
||||
self.goalentity.box1owner = self;
|
||||
|
@ -378,7 +397,7 @@ void(float dist) Window_Walk =
|
|||
self.reload_delay = time + 30;
|
||||
self.th_walk();
|
||||
}
|
||||
else if(!self.goalentity.box2owner)
|
||||
else if(self.goalentity.box2owner == world)
|
||||
{
|
||||
//self.used = WBOX2;
|
||||
self.goalentity.box2owner = self;
|
||||
|
@ -387,7 +406,7 @@ void(float dist) Window_Walk =
|
|||
self.reload_delay = time + 30;
|
||||
self.th_walk();
|
||||
}
|
||||
else if(!self.goalentity.box3owner)
|
||||
else if(self.goalentity.box3owner == world)
|
||||
{
|
||||
//self.used = WBOX3;
|
||||
self.goalentity.box3owner = self;
|
||||
|
@ -399,6 +418,27 @@ void(float dist) Window_Walk =
|
|||
}
|
||||
else if(self.hop_step == 3)//walking to window attack box
|
||||
{
|
||||
// sometimes, we've assigned a zombie a waiting-position
|
||||
// while another zombie is actively hopping. this can cause
|
||||
// a bit of gameplay slowdown since the zombie has to walk
|
||||
// to that waiting position, then to the hop spot (approx 1sec),
|
||||
// so let's do continuous checks here to see if box1 is free,
|
||||
// and claim it if so, in order to smooth the path and claim
|
||||
// that time. only do this if there isn't anyone else in the queue,
|
||||
// though.
|
||||
if (!self.goalentity.box1owner) {
|
||||
// Claim it as ours mid-walk, if there isn't someone else waiting.
|
||||
if ((self.goalentity.box2owner == self && !self.goalentity.box3owner) ||
|
||||
(self.goalentity.box3owner == self && !self.goalentity.box2owner)) {
|
||||
self.goalentity.box1owner = self;
|
||||
self.goalorigin = self.goalentity.box1;
|
||||
|
||||
// Free up the spot we were walking to before.
|
||||
if (self.goalentity.box2owner == self) self.goalentity.box2owner = world;
|
||||
if (self.goalentity.box3owner == self) self.goalentity.box3owner = world;
|
||||
}
|
||||
}
|
||||
|
||||
if(nearby(self.goalorigin))
|
||||
{
|
||||
self.hop_step = 4;
|
||||
|
@ -430,7 +470,7 @@ void(float dist) Window_Walk =
|
|||
self.chase_time = time + 0.75;
|
||||
return;
|
||||
} else if (self.goalentity.owner) {
|
||||
self.chase_time = time + 0.15;
|
||||
self.chase_time = time + 0.05;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -444,17 +484,6 @@ void(float dist) Window_Walk =
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// kind of a shoddy fix, but essentially what we do to fix
|
||||
// issues with zomb ents colliding with each other during hopping
|
||||
// is make sure we wait a bit longer before freeing the window for
|
||||
// another usage.
|
||||
//
|
||||
void() free_window =
|
||||
{
|
||||
self.usedent = world;
|
||||
}
|
||||
|
||||
void(float dist) Window_Hop =
|
||||
{
|
||||
if(self.hop_step == 0) {
|
||||
|
@ -505,24 +534,15 @@ void(float dist) Window_Hop =
|
|||
self.tries++;
|
||||
self.chase_time = time + 0.2;
|
||||
if(self.tries > 10) {
|
||||
// wait enough time before freeing window, to give time for zomb to move.
|
||||
if (!self.goalentity.owner) {
|
||||
self.goalentity.think = free_window;
|
||||
self.goalentity.nextthink = time + 0.5;
|
||||
}
|
||||
//self.goalentity.usedent = world;//free up the window if we've been waiting to hop
|
||||
if (!self.goalentity.owner)
|
||||
self.goalentity.usedent = world;//free up the window if we've been waiting to hop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(self.hop_step == 6) {
|
||||
self.outside = FALSE;
|
||||
//self.goalentity.usedent = world;//free up the window, we're done hopping it
|
||||
//self.used = 0;
|
||||
if (!self.goalentity.owner) {
|
||||
self.goalentity.think = free_window;
|
||||
self.goalentity.nextthink = time + 0.5;
|
||||
}
|
||||
self.goalentity.usedent = world;//free up the window, we're done hopping it
|
||||
self.goalentity = world;
|
||||
self.enemy = find_new_enemy(self);
|
||||
//self.th_die();
|
||||
|
|
|
@ -486,7 +486,11 @@ void() Zombie_Think = //called every frame for zombies
|
|||
if (self.is_attacking && vlen(self.enemy.origin - self.origin) > 64) {
|
||||
// Cancel the animation, start walking again to catch up.
|
||||
self.is_attacking = false;
|
||||
zombie_decide();
|
||||
|
||||
// zombie_decide() here used to call an idle loop if they were
|
||||
// outside, lesson learned.
|
||||
if (!self.outside)
|
||||
self.th_walk();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1085,6 +1089,12 @@ void() removeZombie =
|
|||
setorigin(self,'0 0 0');
|
||||
setorigin (self.goaldummy, '0 0 0');
|
||||
|
||||
// cypress (20 dec 2023) -- added a nextthink() call here
|
||||
// so the next server frame we'll have always run SUB_Null().
|
||||
// there was some weird behavior here where a zombie's th_idle()
|
||||
// call would carry forward interrupting the procedure for walking
|
||||
// to a barricade.
|
||||
self.nextthink = time + 0.05;
|
||||
self.think = SUB_Null;
|
||||
self.classname = "freeZombieEntity";
|
||||
self.goalentity = world;
|
||||
|
@ -1104,7 +1114,7 @@ void() removeZombie =
|
|||
self.owner = world;
|
||||
|
||||
self.spawnflags = 0;
|
||||
|
||||
self.is_attacking = false;
|
||||
|
||||
self.yaw_speed = 0;
|
||||
|
||||
|
@ -1731,6 +1741,13 @@ void(entity where) spawn_a_zombieB =
|
|||
szombie.movetype = MOVETYPE_WALK;
|
||||
setmodel(szombie, "models/ai/zb%.mdl");
|
||||
szombie.hop_step = 0;
|
||||
|
||||
// cypress (20 dec 2023) -- see comment from removeZombie(),
|
||||
// this is just a sanity check just in case someone decides
|
||||
// to play around with a freeZombieEntity and breaks that check..
|
||||
szombie.nextthink = time + 0.05;
|
||||
szombie.think = SUB_Null;
|
||||
|
||||
szombie.gravity = 1.0;
|
||||
|
||||
szombie.mins = '-8 -8 -32';//-16 16 -32
|
||||
|
|
Loading…
Reference in a new issue