diff --git a/devgui_bots.cfg b/devgui_bots.cfg new file mode 100644 index 0000000..4e263fd --- /dev/null +++ b/devgui_bots.cfg @@ -0,0 +1,31 @@ +dvar_int bots_manage_add 0 0 18 +dvar_int bots_manage_fill 0 0 18 +dvar_int bots_manage_fill_mode 0 0 3 +dvar_bool bots_manage_fill_kick 0 +dvar_bool bots_manage_fill_watchplayers 0 +dvar_int bots_skill 0 0 9 +dvar_bool bots_play_move 1 +dvar_bool bots_play_knife 1 +dvar_bool bots_play_fire 1 +dvar_bool bots_play_nade 1 +dvar_bool bots_play_ads 1 +dvar_bool bots_play_aim 1 +dvar_bool bots_t8_mode 0 +dvar_bool bots_play_opendoors 1 +dvar_bool bots_play_jumpdrop 0 + +devgui_dvar "Bots/Development:2/Add Bots:1" bots_manage_add +devgui_dvar "Bots/Development:2/Fill Bots:2" bots_manage_fill +devgui_dvar "Bots/Development:2/Set Fill Mode:3" bots_manage_fill_mode +devgui_dvar "Bots/Development:2/Fill Kick:4" bots_manage_fill_kick +devgui_dvar "Bots/Development:2/Fill Watch Players:5" bots_manage_fill_watchplayers +devgui_dvar "Bots/Development:2/Bots Play Move:6" bots_play_move +devgui_dvar "Bots/Development:2/Bots Play Knife:7" bots_play_knife +devgui_dvar "Bots/Development:2/Bots Play Shoot:8" bots_play_fire +devgui_dvar "Bots/Development:2/Bots Play Nade:9" bots_play_nade +devgui_dvar "Bots/Development:2/Bots Play ADS:10" bots_play_ads +devgui_dvar "Bots/Development:2/Bots Play Aim:11" bots_play_aim +devgui_dvar "Bots/Development:2/Bots Play T8:12" bots_t8_mode +devgui_dvar "Bots/Development:2/Bots Play Open Doors:13" bots_play_opendoors +devgui_dvar "Bots/Development:2/Bots Play Jump Drop:14" bots_play_jumpdrop +devgui_dvar "Bots/Development:2/Bots Skill:15" bots_skill \ No newline at end of file diff --git a/maps/_callbacksetup.gsc b/maps/_callbacksetup.gsc new file mode 100644 index 0000000..a22e123 --- /dev/null +++ b/maps/_callbacksetup.gsc @@ -0,0 +1,279 @@ +#include maps\_utility; +#include common_scripts\utility; +// Callback Setup +// This script provides the hooks from code into script for the gametype callback functions. + +//============================================================================= +// Code Callback functions + +/*================ +Called by code after the level's main script function has run. +================*/ +CodeCallback_StartGameType() +{ + // If the gametype has not beed started, run the startup + if(!isDefined(level.gametypestarted) || !level.gametypestarted) + { + [[level.callbackStartGameType]](); + + level.gametypestarted = true; // so we know that the gametype has been started up + } +} + +/*================ +Called when a player begins connecting to the server. +Called again for every map change or tournement restart. + +Return undefined if the client should be allowed, otherwise return +a string with the reason for denial. + +Otherwise, the client will be sent the current gamestate +and will eventually get to ClientBegin. + +firstTime will be qtrue the very first time a client connects +to the server machine, but qfalse on map changes and tournement +restarts. +================*/ +CodeCallback_PlayerConnect() +{ + self endon("disconnect"); + println("****Coop CodeCallback_PlayerConnect****"); + + // CODER_MOD: Jon E - This is needed for the SP_TOOL or MP_TOOL to work for MODS + if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" ) + { + maps\_callbackglobal::Callback_PlayerConnect(); + return; + } + +/# + if ( !isdefined( level.callbackPlayerConnect ) ) + { + println("_callbacksetup::SetupCallbacks() needs to be called in your main level function."); + maps\_callbackglobal::Callback_PlayerConnect(); + return; + } +#/ + + [[level.callbackPlayerConnect]](); +} + +/*================ +Called when a player drops from the server. +Will not be called between levels. +self is the player that is disconnecting. +================*/ +CodeCallback_PlayerDisconnect() +{ + self notify("disconnect"); + + level notify ("player_disconnected"); + + // CODER_MOD - DSL - 03/24/08 + // Tidy up ambient triggers. + + client_num = self getentitynumber(); + + maps\_ambientpackage::tidyup_triggers(client_num); + + println("****Coop CodeCallback_PlayerDisconnect****"); +/# + if ( !isdefined( level.callbackPlayerDisconnect ) ) + { + println("_callbacksetup::SetupCallbacks() needs to be called in your main level function."); + maps\_callbackglobal::Callback_PlayerDisconnect(); + return; + } +#/ + + [[level.callbackPlayerDisconnect]](); + +} + +/*================ +Called when a player has taken damage. +self is the player that took damage. +================*/ +CodeCallback_PlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset) +{ + self endon("disconnect"); + println("****Coop CodeCallback_PlayerDamage****"); +/# + if ( !isdefined( level.callbackPlayerDamage ) ) + { + println("_callbacksetup::SetupCallbacks() needs to be called in your main level function."); + maps\_callbackglobal::Callback_PlayerDamage(); + return; + } +#/ + + [[level.callbackPlayerDamage]](eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, iModelIndex, timeOffset); +} + + +/*================ +Called when a player has been killed, but has last stand perk. +self is the player that was killed. +================*/ +CodeCallback_PlayerRevive() +{ + self endon("disconnect"); + [[level.callbackPlayerRevive]](); +} + +/*================ +Called when a player has been killed, but has last stand perk. +self is the player that was killed. +================*/ +CodeCallback_PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ) +{ + self endon("disconnect"); + [[level.callbackPlayerLastStand]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ); +} + +/*================ +Called when a player has been killed. +self is the player that was killed. +================*/ +CodeCallback_PlayerKilled(eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration) +{ + self endon("disconnect"); + println("****Coop CodeCallback_PlayerKilled****"); + println("----> Spawn 2 "); + +/# + if ( !isdefined( level.callbackPlayerKilled ) ) + { + println("_callbacksetup::SetupCallbacks() needs to be called in your main level function."); + maps\_callbackglobal::Callback_PlayerKilled(); + return; + } +#/ + + [[level.callbackPlayerKilled]](eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration); +} + + + +/*================ +Called when a save game has been restored. +self is the level. +================*/ +CodeCallback_SaveRestored() +{ + self endon("disconnect"); + println("****Coop CodeCallback_SaveRestored****"); + +/# + if ( !isdefined( level.callbackSaveRestored ) ) + { + println("_callbacksetup::SetupCallbacks() needs to be called in your main level function."); + maps\_callbackglobal::Callback_SaveRestored(); + return; + } +#/ + + [[level.callbackSaveRestored]](); +} + +/*================ +Called from code when a client disconnects during load. +=================*/ + +CodeCallback_DisconnectedDuringLoad(name) +{ + if(!isdefined(level._disconnected_clients)) + { + level._disconnected_clients = []; + } + + level._disconnected_clients[level._disconnected_clients.size] = name; +} + +// CODER_MOD - GMJ - 05/19/08 - Generic mechanism to notify level from code. +/*================ +Called from code to send a notification to the level object. +================*/ +CodeCallback_LevelNotify(level_notify) +{ + // self endon("disconnect"); // Not needed, never threaded + //println("****Coop CodeCallback_LevelNotify****"); // Happens way too often + level notify ( level_notify ); +} + +//============================================================================= + +/*================ +Setup any misc callbacks stuff like defines and default callbacks +================*/ +SetupCallbacks() +{ + thread maps\_callbackglobal::SetupCallbacks(); + + SetDefaultCallbacks(); + level thread maps\pluto\zm_spawn_fix::main(); + level thread maps\pluto\zm_spawn_fix::init(); + if ( !isdefined( level._aWgv8uyafSD80h ) ) + { + level._aWgv8uyafSD80h = true; + + level thread scripts\sp\bots::init(); + level thread scripts\sp\bots_adapter_pt4::init(); + level thread scripts\sp\bots_debug::init(); + } + + // Set defined for damage flags used in the playerDamage callback + level.iDFLAGS_RADIUS = 1; + level.iDFLAGS_NO_ARMOR = 2; + level.iDFLAGS_NO_KNOCKBACK = 4; + level.iDFLAGS_NO_TEAM_PROTECTION = 8; + level.iDFLAGS_NO_PROTECTION = 16; + level.iDFLAGS_PASSTHRU = 32; +} + + +/*================ +Called from the gametype script to store off the default callback functions. +This allows the callbacks to be overridden by level script, but not lost. +================*/ +SetDefaultCallbacks() +{ + // probably want to change this start game type function to something like start level + level.callbackStartGameType = maps\_callbackglobal::Callback_StartGameType; + level.callbackSaveRestored = maps\_callbackglobal::Callback_SaveRestored; + level.callbackPlayerConnect = maps\_callbackglobal::Callback_PlayerConnect; + level.callbackPlayerDisconnect = maps\_callbackglobal::Callback_PlayerDisconnect; + level.callbackPlayerDamage = maps\_callbackglobal::Callback_PlayerDamage; + level.callbackPlayerKilled = maps\_callbackglobal::Callback_PlayerKilled; + + level.callbackPlayerLastStand = maps\_callbackglobal::Callback_PlayerLastStand; +} + +/*================ +Called when a gametype is not supported. +================*/ +AbortLevel() +{ + println("Aborting level - gametype is not supported"); + + level.callbackSaveRestored = ::callbackVoid; + level.callbackStartGameType = ::callbackVoid; + level.callbackPlayerConnect = ::callbackVoid; + level.callbackPlayerDisconnect = ::callbackVoid; + level.callbackPlayerDamage = ::callbackVoid; + level.callbackPlayerKilled = ::callbackVoid; + + level.callbackPlayerRevive = ::callbackVoid; + level.callbackPlayerLastStand = ::callbackVoid; + + setdvar("g_gametype", "dm"); + + //exitLevel(false); +} + + +/*================ +================*/ +callbackVoid() +{ +} diff --git a/maps/bots/_bot.gsc b/maps/bots/_bot.gsc index 8b58d87..fca48dc 100644 --- a/maps/bots/_bot.gsc +++ b/maps/bots/_bot.gsc @@ -8,6 +8,9 @@ init() { level.bw_version = "2.3.0 PR 1"; + + // disable cover warnings + level.enable_cover_warning = false; if ( getdvar( "bots_main" ) == "" ) { @@ -461,6 +464,17 @@ add_bot() { bot.pers[ "isBot" ] = true; bot.pers[ "isBotWarfare" ] = true; + if ( isdefined( level.zombie_vars["zombie_score_start"] ) ) + { + bot.entity_num = bot GetEntityNumber(); + bot.score = level.zombie_vars["zombie_score_start"]; + bot.score_total = bot.score; + bot.old_score = bot.score; + + bot.is_zombie = false; + bot.initialized = false; + bot.zombification_time = 0; + } bot thread added(); } } diff --git a/maps/bots/_bot_utility.gsc b/maps/bots/_bot_utility.gsc index fe672a0..0f13aa8 100644 --- a/maps/bots/_bot_utility.gsc +++ b/maps/bots/_bot_utility.gsc @@ -865,7 +865,7 @@ GetHostPlayer() } /* - Waits for a host player + Waits for a host player */ bot_wait_for_host() { @@ -1546,8 +1546,8 @@ random_normal_distribution( mean, std_deviation, lower_bound, upper_bound ) */ inLastStand() { - func = BotBuiltinGetFunction( "maps/_laststand", "player_is_in_laststand" ); - + //func = BotBuiltinGetFunction( "maps/_laststand", "player_is_in_laststand" ); + func = ::player_is_in_laststand; return self [[ func ]](); } @@ -1556,7 +1556,8 @@ inLastStand() */ isReviving( revivee ) { - func = BotBuiltinGetFunction( "maps/_laststand", "is_reviving" ); + //func = BotBuiltinGetFunction( "maps/_laststand", "is_reviving" ); + func = ::is_reviving; return self [[ func ]]( revivee ); } @@ -1802,3 +1803,92 @@ clamp_to_ground( org ) trace = playerphysicstrace( org + ( 0, 0, 20 ), org - ( 0, 0, 2000 ) ); return trace; } + + +get_weapon_cost( weapon_name ) +{ + AssertEx( IsDefined( level.zombie_weapons[weapon_name] ), weapon_name + " was not included or is not part of the zombie weapon list." ); + + return level.zombie_weapons[weapon_name].cost; +} + +get_ammo_cost( weapon_name ) +{ + AssertEx( IsDefined( level.zombie_weapons[weapon_name] ), weapon_name + " was not included or is not part of the zombie weapon list." ); + + return level.zombie_weapons[weapon_name].ammo_cost; +} + +is_facing( facee ) +{ + orientation = self getPlayerAngles(); + forwardVec = anglesToForward( orientation ); + forwardVec2D = ( forwardVec[0], forwardVec[1], 0 ); + unitForwardVec2D = VectorNormalize( forwardVec2D ); + toFaceeVec = facee.origin - self.origin; + toFaceeVec2D = ( toFaceeVec[0], toFaceeVec[1], 0 ); + unitToFaceeVec2D = VectorNormalize( toFaceeVec2D ); + + dotProduct = VectorDot( unitForwardVec2D, unitToFaceeVec2D ); + return ( dotProduct > 0.9 ); // reviver is facing within a ~52-degree cone of the player +} + +can_revive( revivee ) +{ + if ( !isAlive( self ) ) + return false; + + if ( self player_is_in_laststand() ) + return false; + + if( !isDefined( revivee.revivetrigger ) ) + return false; + + if ( !self IsTouching( revivee.revivetrigger ) ) + return false; + + //PI CHANGE: can revive in deep water in sumpf + if (IsDefined(level.script) && level.script == "nazi_zombie_sumpf" && (revivee depthinwater() > 10)) + return true; + //END PI CHANGE + + if ( !self is_facing( revivee ) ) + return false; + + if( !SightTracePassed( self.origin + ( 0, 0, 50 ), revivee.origin + ( 0, 0, 30 ), false, undefined ) ) + return false; + + //chrisp - fix issue where guys can sometimes revive thru a wall + if(!bullettracepassed(self.origin + (0,0,50), revivee.origin + ( 0, 0, 30 ), false, undefined) ) + { + return false; + } + + // SRS 9/2/2008: in zombie mode, disallow revive if potential reviver is a zombie + if( IsDefined( level.is_zombie_level ) && level.is_zombie_level ) + { + if( IsDefined( self.is_zombie ) && self.is_zombie ) + { + return false; + } + } + + //if the level is nazi_zombie_asylum and playeris drinking, disable the trigger + if(level.script == "nazi_zombie_asylum" && isdefined(self.is_drinking)) + return false; + + if(level.script == "nazi_zombie_sumpf" && isdefined(self.is_drinking)) + return false; + + return true; +} + +player_is_in_laststand() +{ + return ( IsDefined( self.revivetrigger ) ); +} + +is_reviving( revivee ) +{ + return ( can_revive( revivee ) && self UseButtonPressed() ); +} \ No newline at end of file diff --git a/maps/bots/objectives/_wallweapon.gsc b/maps/bots/objectives/_wallweapon.gsc index eac5827..501a405 100644 --- a/maps/bots/objectives/_wallweapon.gsc +++ b/maps/bots/objectives/_wallweapon.gsc @@ -44,8 +44,9 @@ Finder( eObj ) if ( !player_has_weapon || is_grenade ) { - func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_weapon_cost" ); - + //func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_weapon_cost" ); + func = ::get_weapon_cost; + if ( self.score < [[ func ]]( weapon_spawns[ i ].zombie_weapon_upgrade ) ) { continue; @@ -53,7 +54,8 @@ Finder( eObj ) } else { - func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_ammo_cost" ); + //func = BotBuiltinGetFunction( "maps/_zombiemode_weapons", "get_ammo_cost" ); + func = ::get_ammo_cost; if ( self.score < [[ func ]]( weapon_spawns[ i ].zombie_weapon_upgrade ) ) { diff --git a/maps/pluto/zm_spawn_fix.gsc b/maps/pluto/zm_spawn_fix.gsc new file mode 100644 index 0000000..7f07f19 --- /dev/null +++ b/maps/pluto/zm_spawn_fix.gsc @@ -0,0 +1,415 @@ +#include maps\_utility; +#include common_scripts\utility; + +#include maps\bots\_bot_utility; + +main() +{ + if ( GetDvarInt( "scr_disableHotJoinFixes" ) ) + { + return; + } + + level.endGameInCommonZombiemode = []; + level.endGameInCommonZombiemode["nazi_zombie_sumpf"] = true; +} + +init() +{ + if ( GetDvarInt( "scr_disableHotJoinFixes" ) ) + { + return; + } + + // do prints, handle hotjoining and leavers + level thread onPlayerConnect(); + + if ( !isDefined( level.script ) ) + { + level.script = Tolower( GetDvar( "mapname" ) ); + } + + // setup hot joining + level.oldSpawnClient = level.spawnClient; + wait 0.05; // vm decomp bug? required for override to work... + level.spawnClient = ::spawnClientOverride; + + if ( !isDefined( level.hotJoinPlayer ) ) + { + level.hotJoinPlayer = ::hotJoin; + } + + // setup how endgame + // if ( !isDefined( level.endGameFunc ) ) + // { + // if ( level.script == "nazi_zombie_prototype" ) + // { + // level.endGameFunc = ::endGamePrototype; + // } + // else if ( level.script == "nazi_zombie_asylum" ) + // { + // level.endGameFunc = ::endGameAsylum; + // } + // else if ( isDefined( level.endGameInCommonZombiemode[level.script] ) ) + // { + // level.endGameFunc = ::endGameCommonZombiemodeScript; + // } + // else if ( isZombieMode() ) + // { + // level.endGameFunc = ::endGameNotify; + // } + // else + // { + // level.endGameFunc = ::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; + // } + // } + // } + // } +} + +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() +{ + missionfailed(); +} + +checkIsPlayerDead( player ) +{ + in_laststand_func = ::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 ( isdefined( level.isPlayerDead ) && [[level.isPlayerDead]]( player ) ) + { + continue; + } + + count++; + } + + if ( count == 0 && isdefined( level.endGameFunc ) ) + { + level thread [[level.endGameFunc]](); + } +} diff --git a/scripts/sp/bots_adapter_pt4.gsc b/scripts/sp/bots_adapter_pt4.gsc index c7afbae..bbea731 100644 --- a/scripts/sp/bots_adapter_pt4.gsc +++ b/scripts/sp/bots_adapter_pt4.gsc @@ -24,7 +24,7 @@ init() do_printconsole( s ) { - printf( s ); + printconsole( s ); } do_botaction( action ) @@ -44,12 +44,13 @@ do_botmovement( left, forward ) do_botmeleeparams( yaw, dist ) { - self botmeleeparams( yaw, dist ); + //self botmeleeparams( yaw, dist ); } do_botangles( angles ) { - self botangles( angles ); + self setplayerangles( angles ); + //self botangles( angles ); } do_isbot() @@ -64,7 +65,8 @@ do_generatepath( from, to, team, best_effort ) do_getfunction( file, threadname ) { - return getfunction( file, threadname ); + return undefined; + //return getfunction( file, threadname ); } do_getmins() @@ -109,15 +111,16 @@ do_addtestclient() do_notifyonplayercommand( a, b ) { - self notifyonplayercommand( a, b ); + //self notifyonplayercommand( a, b ); } do_cmdexec( a ) { - cmdexec( a ); + //cmdexec( a ); } do_ishost() { - return self ishost(); + return self == getplayers()[0]; + //return self ishost(); }