[ZM][RELEASE] Moon Spawn Cancel fix
-
Special thanks to TTS4life's video and 5and5's comment
I replaced the RotateTo to ForceTeleport as 5and5 suggested in the video's comments, I also called the
zombie_faller_death_wait() Method again in the method to ensure we always check for deaths correctly.
Also created a custom watcher that makes sure to enable the spawn again, as I was unable to make the spawns work correctly by replacing the moveTo with a ForceTeleport.
How I tested it:
I went in a solo game and spammed the raygun and wavegun at the ceiling spawn, I never managed to cancel the spawn. Removed the patch to be sure, and I was indeed able to cancel the spawn without the patch.
#include maps\_utility; #include common_scripts\utility; #include maps\_zombiemode_utility; main() { if ( GetDvar( #"zombiemode" ) == "1" ) { level thread onPlayerConnect(); replacefunc(maps\_zombiemode_ai_faller::do_zombie_fall, ::custom_do_zombie_fall); } } custom_do_zombie_fall() { self endon("death"); self thread maps\_zombiemode_ai_faller::setup_deathfunc(); // don't drop powerups until we are on the ground self.no_powerups = true; self.in_the_ceiling = true; self.anchor = spawn("script_origin", self.origin); self.anchor.angles = self.angles; self linkto(self.anchor); if ( !IsDefined( self.zone_name ) ) { self.zone_name = self get_current_zone(); } spots = maps\_zombiemode_ai_faller::get_available_fall_locations(); if( spots.size < 1 ) { self unlink(); self.anchor delete(); //IPrintLnBold("deleting zombie faller - no available fall locations"); //can't delete if we're in the middle of spawning, so wait a frame self Hide();//hide so we're not visible for one frame while waiting to delete self delayThread( 0.1, maps\_zombiemode_ai_faller::zombie_faller_delete ); return; } else if ( GetDvarInt(#"zombie_fall_test") ) { // use the spot closest to the first player always player = GetPlayers()[0]; spot = undefined; bestDist = 0.0; for ( i = 0; i < spots.size; i++ ) { checkDist = DistanceSquared(spots[i].origin, player.origin); if ( !IsDefined(spot) || checkDist < bestDist ) { spot = spots[i]; bestDist = checkDist; } } } else { spot = random(spots); } self.zombie_faller_location = spot; //NOTE: multiple zombie fallers could be waiting in the same spot now, need to have spawners detect this // and not use the spot again until the previous zombie has died or dropped down self.zombie_faller_location.is_enabled = false; self thread maps\_zombiemode_ai_faller::zombie_faller_death_wait(); self.zombie_faller_location maps\_zombiemode_ai_faller::parse_script_parameters(); // Start a monitor that will ensure the spot gets re-enabled if this zombie dies early or gets stuck. // This is defensive: it will re-enable on death or after a timeout. self thread zombie_faller_spot_monitor(self, spot); if( !isDefined( spot.angles ) ) { spot.angles = (0, 0, 0); } //Patch begin anim_org = spot.origin; anim_ang = spot.angles; self Hide(); self.anchor moveto(anim_org, .05); self.anchor waittill("movedone"); // face goal target_org = maps\_zombiemode_spawner::get_desired_origin(); if (IsDefined(target_org)) { anim_ang = VectorToAngles(target_org - self.origin); current_pos = self.anchor.origin; // Instantly rotate the anchor instead of waiting for RotateTo self.anchor ForceTeleport(current_pos, (0, anim_ang[1], 0), false, false); } self unlink(); self.anchor delete(); self thread maps\_zombiemode_ai_faller::hide_pop(); // hack to hide the pop when the zombie gets to the start position before the anim starts level thread maps\_zombiemode_ai_faller::zombie_fall_death(self, spot); spot thread maps\_zombiemode_ai_faller::zombie_fall_fx(self); self thread maps\_zombiemode_ai_faller::zombie_faller_death_wait(); //need to thread off the rest because we're apparently still in the middle of our init! self thread maps\_zombiemode_ai_faller::zombie_faller_do_fall(); } zombie_faller_spot_monitor(zombie, spot) { // sanity if ( !IsDefined(spot) ) return; // If the zombie dies cleanly, we re-enable the spot immediately. zombie waittill("death"); // At this point the zombie is dead (or the entity has been freed). if ( IsDefined(spot) ) { spot.is_enabled = true; } // Safety: also ensure we don't leave the spot disabled in pathological cases. wait(0.25); if ( IsDefined(spot) ) spot.is_enabled = true; } onPlayerConnect() { for(;;) { level waittill ("connecting", player); player thread onPlayerSpawned(); } } onPlayerSpawned() { for(;;) { self waittill("spawned_player"); self SetClientDvars( "player_backSpeedScale", "1", "player_strafeSpeedScale", "1"); self iPrintLn("Spawn cancel fix by AlexInZombies"); } }
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login