plutonium/storage/t4/raw/scripts/sp/zm_spawn_fix.gsc
2023-12-10 07:55:13 -05:00

522 lines
11 KiB
Plaintext

#include maps\_utility;
#include common_scripts\utility;
main()
{
if ( GetDvarInt( "scr_disableHotJoinFixes" ) )
return;
level.endGameInCommonZombiemode = [];
level.endGameInCommonZombiemode["nazi_zombie_sumpf"] = true;
if ( isDedicated() )
{
// we are always in coop mode for dedis
is_coop = getFunction( "maps/_utility", "is_coop" );
if ( isDefined( is_coop ) )
replaceFunc( is_coop, ::alwaysTrue );
// make lowest player num the host
get_host = getFunction( "maps/_utility", "get_host" );
if ( isDefined( get_host ) )
replaceFunc( get_host, ::getHostDedi );
// no force Ending
forceEnd = getFunction( "maps/_cooplogic", "forceend" );
if ( isDefined( forceEnd ) )
replaceFunc( forceEnd, ::noop );
// fix this gsc thread leak in the vanilla game
ammo_dialog_timer = getFunction( "maps/_zombiemode", "ammo_dialog_timer" );
if ( isDefined( ammo_dialog_timer ) )
replaceFunc( ammo_dialog_timer, ::ammo_dialog_timer_func );
// add a timeout for all_players_connected
all_players_connected = getFunction( "maps/_load", "all_players_connected" );
if ( isDefined( all_players_connected ) )
replaceFunc( all_players_connected, ::all_players_connected_func );
// fix monkeybomb ent leak
check_point_in_active_zone = getFunction( "maps/_zombiemode_utility", "check_point_in_active_zone" );
if ( isDefined( check_point_in_active_zone ) )
replaceFunc( check_point_in_active_zone, ::check_point_in_active_zone_func );
// fix riser ent leak
do_zombie_rise = getFunction( "maps/_zombiemode_spawner", "do_zombie_rise" );
if ( isDefined( do_zombie_rise ) )
replaceFunc( do_zombie_rise, ::do_zombie_rise_func );
// scripters could 'waittillframeend' in their 'main' to replace these replacefuncs with their own if needed
}
}
init()
{
if ( GetDvarInt( "scr_disableHotJoinFixes" ) )
return;
// do prints, handle hotjoining and leavers
level thread onPlayerConnect();
// lets be the last to setup func ptrs
for ( i = 0; i < 10; i++ )
waittillframeend;
if ( !isDefined( level.script ) )
level.script = Tolower( GetDvar( "mapname" ) );
// setup hot joining
level.oldSpawnClient = level.spawnClient;
level.spawnClient = ::spawnClientOverride;
if ( !isDefined( level.hotJoinPlayer ) )
level.hotJoinPlayer = ::hotJoin;
// setup how endgame
if ( !isDefined( level.endGame ) )
{
if ( level.script == "nazi_zombie_prototype" )
level.endGame = ::endGamePrototype;
else if ( level.script == "nazi_zombie_asylum" )
level.endGame = ::endGameAsylum;
else if ( isDefined( level.endGameInCommonZombiemode[level.script] ) )
level.endGame = ::endGameCommonZombiemodeScript;
else if ( isZombieMode() )
level.endGame = ::endGameNotify;
else
level.endGame = ::endGameSP;
}
if ( !isDefined( level.isPlayerDead ) )
level.isPlayerDead = ::checkIsPlayerDead;
// make dead players into spectators
if ( isZombieMode() )
{
level.oldOverridePlayerKilled = level.overridePlayerKilled;
level.overridePlayerKilled = ::playerKilledOverride;
// setup this callback
zmb_spawnSpectator = GetFunction( "maps/_callbackglobal", "spawnspectator" );
if ( isDefined( zmb_spawnSpectator ) && level.spawnSpectator == zmb_spawnSpectator )
{
if ( level.script == "nazi_zombie_prototype" )
{
zmb_spawnSpectator = GetFunction( "maps/_zombiemode_prototype", "spawnspectator" );
if ( isDefined( zmb_spawnSpectator ) )
level.spawnSpectator = zmb_spawnSpectator;
}
else if ( level.script == "nazi_zombie_asylum" )
{
zmb_spawnSpectator = GetFunction( "maps/_zombiemode_asylum", "spawnspectator" );
if ( isDefined( zmb_spawnSpectator ) )
level.spawnSpectator = zmb_spawnSpectator;
}
else
{
zmb_spawnSpectator = GetFunction( "maps/_zombiemode", "spawnspectator" );
if ( isDefined( zmb_spawnSpectator ) )
level.spawnSpectator = zmb_spawnSpectator;
}
}
}
}
getHostDedi()
{
return get_players()[0];
}
alwaysTrue()
{
return true;
}
noop()
{
}
all_players_connected_func()
{
timeout_started = false;
timeout_point = 0;
while ( 1 )
{
num_con = getnumconnectedplayers();
num_exp = getnumexpectedplayers();
if ( num_con == num_exp && ( num_exp != 0 ) )
break;
if ( num_con > 0 )
{
if ( !timeout_started )
{
timeout_started = true;
timeout_point = getDvarFloat( "sv_connecttimeout" ) * 1000 + getTime();
}
if ( getTime() > timeout_point )
break;
}
else
timeout_started = false;
wait( 0.05 );
}
flag_set( "all_players_connected" );
// CODER_MOD: GMJ (08/28/08): Setting dvar for use by code
SetDvar( "all_players_are_connected", "1" );
}
fixRiserEntLeak()
{
self waittill( "death" );
if ( isDefined( self.anchor ) )
self.anchor delete ();
}
do_zombie_rise_func()
{
self thread fixRiserEntLeak();
func = getFunction( "maps/_zombiemode_spawner", "do_zombie_rise" );
if ( !isDefined( func ) )
return;
disableDetourOnce( func );
self [[func]]();
}
check_point_in_active_zone_func( origin )
{
player_zones = GetEntArray( "player_zone", "script_noteworthy" );
if ( !isDefined( level.zones ) || !isDefined( player_zones ) )
{
return true;
}
scr_org = spawn( "script_origin", origin + ( 0, 0, 40 ) );
one_valid_zone = false;
for ( i = 0; i < player_zones.size; i++ )
{
if ( scr_org isTouching( player_zones[i] ) )
{
if ( isDefined( level.zones[player_zones[i].targetname] ) &&
isDefined( level.zones[player_zones[i].targetname].is_enabled ) )
{
one_valid_zone = true;
}
}
}
scr_org delete ();
return one_valid_zone;
}
ammo_dialog_timer_func()
{
level notify( "ammo_out" );
func = getFunction( "maps/_zombiemode", "ammo_dialog_timer" );
if ( !isDefined( func ) )
return;
disableDetourOnce( func );
self [[func]]();
}
isZombieMode()
{
return ( isDefined( level.is_zombie_level ) && level.is_zombie_level );
}
endGamePrototype()
{
func = getFunction( "maps/_zombiemode_prototype", "end_game" );
if ( isDefined( func ) )
level thread [[func]]();
}
endGameAsylum()
{
func = getFunction( "maps/_zombiemode_asylum", "end_game" );
if ( isDefined( func ) )
level thread [[func]]();
}
endGameCommonZombiemodeScript()
{
func = getFunction( "maps/_zombiemode", "end_game" );
if ( isDefined( func ) )
level thread [[func]]();
}
endGameNotify()
{
level notify( "end_game" );
}
endGameSP()
{
if ( get_players().size <= 0 )
cmdexec( "map_restart" );
else
missionfailed();
}
checkIsPlayerDead( player )
{
in_laststand_func = GetFunction( "maps/_laststand", "player_is_in_laststand" );
return ( player.sessionstate == "spectator" || ( isDefined( in_laststand_func ) && player [[in_laststand_func]]() ) || ( isDefined( player.is_zombie ) && player.is_zombie ) );
}
playerKilledOverride()
{
self [[level.player_becomes_zombie]]();
checkForAllDead( self );
self [[level.oldOverridePlayerKilled]]();
}
spawnClientOverride()
{
if ( flag( "all_players_spawned" ) )
self thread [[level.hotJoinPlayer]]();
else
self thread [[level.oldSpawnClient]]();
}
getHotJoinPlayer()
{
players = get_players();
for ( i = 0; i < players.size; i++ )
{
player = players[i];
if ( !isDefined( player ) || !isDefined( player.sessionstate ) )
continue;
if ( player == self )
continue;
if ( player.sessionstate == "spectator" )
continue;
if ( isDefined( player.is_zombie ) && player.is_zombie )
continue;
return player;
}
return undefined;
}
getHotJoinAi( team )
{
ais = GetAiArray( team );
ai = undefined;
if ( ais.size )
ai = ais[randomint( ais.size )];
return ai;
}
getHotJoinInitSpawn()
{
structs = getstructarray( "initial_spawn_points", "targetname" );
players = get_players();
i = 0;
for ( i = 0; i < players.size; i++ )
{
if ( !isDefined( players[i] ) )
continue;
if ( self == players[i] )
break;
}
spawn_obj = structs[i];
if ( !isDefined( spawn_obj ) )
spawn_obj = structs[0];
return spawn_obj;
}
hotJoin()
{
self endon( "disconnect" );
self endon( "end_respawn" );
// quik hax: prevent spectators_respawn from spawning us
self.sessionstate = "playing";
waittillframeend;
self.sessionstate = "spectator";
player = self getHotJoinPlayer();
ally = self getHotJoinAi( "allies" );
enemy = self getHotJoinAi( "axis" );
spawn_pt = self getHotJoinInitSpawn();
spawn_obj = spawnStruct();
if ( isDefined( spawn_pt ) )
{
spawn_obj = spawn_pt;
}
else if ( isDefined( player ) )
{
spawn_obj.origin = player getOrigin();
spawn_obj.angles = player.angles;
}
else if ( isDefined( ally ) )
{
spawn_obj.origin = ally getOrigin();
spawn_obj.angles = ally.angles;
}
else if ( isDefined( enemy ) )
{
spawn_obj.origin = enemy getOrigin();
spawn_obj.angles = enemy.angles;
}
else
{
spawn_obj.origin = ( 0, 0, 0 );
spawn_obj.angles = ( 0, 0, 0 );
}
// check if custom logic for hotjoining
if ( isDefined( level.customHotJoinPlayer ) )
{
temp_obj = self [[level.customHotJoinPlayer]]( spawn_obj );
// check if theres a spawn obj
if ( isDefined( temp_obj ) )
{
// check if we should cancel spawning this player (maybe its already done)
if ( isDefined( temp_obj.cancel ) && temp_obj.cancel )
return;
// set our spawn location
spawn_obj = temp_obj;
}
}
// set spawn params
self setorigin( spawn_obj.origin );
self setplayerangles( spawn_obj.angles );
self.spectator_respawn = spawn_obj;
self.respawn_point = spawn_obj;
// do the spawn
println( "*************************Client hotjoin***" );
self unlink();
if ( isdefined( self.spectate_cam ) )
self.spectate_cam delete ();
if ( ( !isZombieMode() && !level.otherPlayersSpectate && ( !isDefined( spawn_obj.force_spectator ) || !spawn_obj.force_spectator ) ) ||
( isDefined( spawn_obj.force_spawn ) && spawn_obj.force_spawn ) )
self thread [[level.spawnPlayer]]();
else
{
self thread [[level.spawnSpectator]]();
checkForAllDead( self );
}
}
onDisconnect()
{
lpselfnum = self getentitynumber();
lpguid = self getguid();
name = self.playername;
self waittill( "disconnect" );
logprint( "Q;" + lpguid + ";" + lpselfnum + ";" + name + "\n" );
// check if we need to end the game cause last person left alive left the game
checkForAllDead( self );
}
onConnect()
{
self endon( "disconnect" );
logprint( "J;" + self getguid() + ";" + self getentitynumber() + ";" + self.playername + "\n" );
}
onPlayerConnect()
{
for ( ;; )
{
level waittill( "connected", player );
iprintln( player.playername + " connected." );
player thread onDisconnect();
player thread onConnect();
}
}
checkForAllDead( excluded_player )
{
players = get_players();
count = 0;
for ( i = 0; i < players.size; i++ )
{
player = players[ i ];
if ( !isDefined( player ) || !isDefined( player.sessionstate ) )
continue;
if ( isDefined( excluded_player ) && excluded_player == player )
continue;
if ( [[level.isPlayerDead]]( player ) )
continue;
count++;
}
if ( count == 0 )
{
PrintConsole( "Ending game as no players are left alive..." );
level thread [[level.endGame]]();
}
}