From 66bea25aaa2b388397b3ca8defec80955c323df4 Mon Sep 17 00:00:00 2001 From: efinst0rm Date: Sat, 25 Mar 2023 13:53:20 -0500 Subject: [PATCH 1/2] Add autobalance support. Setting scr_teambalance 1 will now autobalance teams after 60 seconds. --- data/scripts/mp/teams/_teams.gsc | Bin 0 -> 12284 bytes data/scripts/mp/teams/_teams.gsc_raw | 670 +++++++++++++++++++++++++++ 2 files changed, 670 insertions(+) create mode 100644 data/scripts/mp/teams/_teams.gsc create mode 100644 data/scripts/mp/teams/_teams.gsc_raw diff --git a/data/scripts/mp/teams/_teams.gsc b/data/scripts/mp/teams/_teams.gsc new file mode 100644 index 0000000000000000000000000000000000000000..bb53019a4c6f7f0da902752f6d9a0c1b16c48cff GIT binary patch literal 12284 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 literal 0 HcmV?d00001 diff --git a/data/scripts/mp/teams/_teams.gsc_raw b/data/scripts/mp/teams/_teams.gsc_raw new file mode 100644 index 00000000..1260a17b --- /dev/null +++ b/data/scripts/mp/teams/_teams.gsc_raw @@ -0,0 +1,670 @@ +#using scripts\codescripts\struct; + +#using scripts\shared\callbacks_shared; +#using scripts\shared\persistence_shared; +#using scripts\shared\system_shared; +#using scripts\shared\util_shared; + +#insert scripts\shared\shared.gsh; + +#using scripts\mp\gametypes\_globallogic_ui; +#using scripts\mp\gametypes\_spectating; + +#using scripts\mp\_util; + +#precache( "material", "mpflag_spectator" ); +#precache( "string", "MP_AUTOBALANCE_NOW" ); + +#namespace teams; + +REGISTER_SYSTEM( "teams", &__init__, undefined ) + +function __init__() +{ + callback::on_start_gametype( &init ); + + level.getEnemyTeam = &getEnemyTeam; + level.use_team_based_logic_for_locking_on = true; +} + +function init() +{ + game["strings"]["autobalance"] = &"MP_AUTOBALANCE_NOW"; + + if(GetDvarString( "scr_teambalance") == "") + SetDvar("scr_teambalance", "0"); + level.teambalance = GetDvarint( "scr_teambalance"); + level.teambalancetimer = 0; + + if(GetDvarString( "scr_timeplayedcap") == "") + SetDvar("scr_timeplayedcap", "1800"); + level.timeplayedcap = int(GetDvarint( "scr_timeplayedcap")); + + level.freeplayers = []; + + if( level.teamBased ) + { + level.alliesplayers = []; + level.axisplayers = []; + + callback::on_connect( &on_player_connect ); + callback::on_joined_team( &on_joined_team ); + callback::on_joined_spectate( &on_joined_spectators ); + level thread update_team_balance(); + + wait .15; + + level thread update_player_times(); + + } + else + { + callback::on_connect( &on_free_player_connect ); + + wait .15; + + level thread update_player_times(); + + } +} + +function on_player_connect() +{ + self thread track_played_time(); +} + +function on_free_player_connect() +{ + self thread track_free_played_time(); +} + +function on_joined_team() +{ + /#println( "joined team: " + self.pers["team"] );#/ + self update_time(); +} + +function on_joined_spectators() +{ + self.pers["teamTime"] = undefined; +} + +function track_played_time() +{ + self endon( "disconnect" ); + + if ( !isdefined( self.pers["totalTimePlayed"] ) ) + { + self.pers["totalTimePlayed"] = 0; + } + + foreach ( team in level.teams ) + { + self.timePlayed[team] = 0; + } + self.timePlayed["free"] = 0; + self.timePlayed["other"] = 0; + self.timePlayed["alive"] = 0; + + // dont reset time played in War when going into final fight, this is used for calculating match bonus + if ( !isdefined( self.timePlayed["total"] ) || !( (level.gameType == "twar") && (0 < game["roundsplayed"]) && (0 < self.timeplayed["total"]) ) ) + self.timePlayed["total"] = 0; + + while ( level.inPrematchPeriod ) + WAIT_SERVER_FRAME; + + for ( ;; ) + { + if ( game["state"] == "playing" ) + { + if ( isdefined( level.teams[self.sessionteam] ) ) + { + self.timePlayed[self.sessionteam]++; + self.timePlayed["total"]++; + + if ( level.mpCustomMatch ) + { + self.pers["sbtimeplayed"] = self.timeplayed["total"]; + self.sbtimeplayed = self.pers["sbtimeplayed"]; + } + + if ( IsAlive( self ) ) + self.timePlayed["alive"]++; + } + else if ( self.sessionteam == "spectator" ) + { + self.timePlayed["other"]++; + } + } + + wait ( 1.0 ); + } +} + + +function update_player_times() +{ + const minWait = 10.0; + const step = 1.0; + varWait = minWait; + + nextToUpdate = 0; + for ( ;; ) + { + varWait = varWait - step; + nextToUpdate++; + + if ( nextToUpdate >= level.players.size ) + { + nextToUpdate = 0; + + if ( varWait > 0 ) + { + wait ( varWait ); + } + + varWait = minWait; + } + + if ( isdefined( level.players[nextToUpdate] ) ) + { + level.players[nextToUpdate] update_played_time(); + level.players[nextToUpdate] persistence::check_contract_expirations(); + } + + wait ( step ); + } +} + +function update_played_time() +{ + pixbeginevent("updatePlayedTime"); + + if ( level.rankedMatch || level.leagueMatch ) + { + foreach( team in level.teams ) + { + if ( self.timePlayed[team] ) + { + if ( level.teambased ) + { + self AddPlayerStat( "time_played_"+team, int( min( self.timePlayed[team], level.timeplayedcap ) ) ); + } + + self AddPlayerStatWithGameType( "time_played_total", int( min( self.timePlayed[team], level.timeplayedcap ) ) ); + } + } + + if ( self.timePlayed["other"] ) + { + self AddPlayerStat( "time_played_other", int( min( self.timePlayed["other"], level.timeplayedcap ) ) ); + self AddPlayerStatWithGameType( "time_played_total", int( min( self.timePlayed["other"], level.timeplayedcap ) ) ); + } + + if ( self.timePlayed["alive"] ) + { + timeAlive = int( min( self.timePlayed["alive"], level.timeplayedcap ) ); + self persistence::increment_contract_times( timeAlive ); + self AddPlayerStat( "time_played_alive", timeAlive ); + } + } + + if ( level.onlineGame ) + { + timeAlive = int( min( self.timePlayed["alive"], level.timeplayedcap ) ); + self.pers["time_played_alive"] += timeAlive; + } + + pixendevent(); + + if ( game["state"] == "postgame" ) + return; + + foreach( team in level.teams ) + { + self.timePlayed[team] = 0; + } + self.timePlayed["other"] = 0; + self.timePlayed["alive"] = 0; +} + + +function update_time() +{ + if ( game["state"] != "playing" ) + return; + + self.pers["teamTime"] = getTime(); +} + +function update_balance_dvar() +{ + for(;;) + { + teambalance = GetDvarint( "scr_teambalance"); + if(level.teambalance != teambalance) + level.teambalance = GetDvarint( "scr_teambalance"); + + timeplayedcap = GetDvarint( "scr_timeplayedcap"); + if(level.timeplayedcap != timeplayedcap) + level.timeplayedcap = int(GetDvarint( "scr_timeplayedcap")); + + wait 1; + } +} + + +function update_team_balance() +{ + level thread update_balance_dvar(); + + wait .15; + + if ( level.teamBalance && util::isRoundBased() && level.numlives ) + { + if ( isDefined( game["BalanceTeamsNextRound"] ) ) + iPrintLnbold( &"MP_AUTOBALANCE_NEXT_ROUND" ); + + level waittill( "game_ended" ); + wait 1; + + if ( isDefined( game["BalanceTeamsNextRound"] ) ) + { + level balance_teams(); + game["BalanceTeamsNextRound"] = undefined; + } + else if ( !get_team_balance() ) + { + game["BalanceTeamsNextRound"] = true; + } + } + else + { + level endon ( "game_ended" ); + + for ( ;; ) + { + if ( level.teamBalance ) + { + if ( !get_team_balance() ) + { + iPrintLnBold( &"MP_AUTOBALANCE_SECONDS", 15 ); + wait 15.0; + + if ( !get_team_balance() ) + level balance_teams(); + } + + wait 59.0; + } + + wait 1.0; + } + } + +} + + +function get_team_balance() +{ + level.team["allies"] = 0; + level.team["axis"] = 0; + + players = level.players; + + for ( i = 0; i < players.size; i++ ) + { + if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) ) + level.team["allies"]++; + else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) ) + level.team["axis"]++; + } + + if ( ( level.team["allies"] > ( level.team["axis"] + level.teamBalance ) ) || ( level.team["axis"] > ( level.team["allies"] + level.teamBalance ) ) ) + return false; + else + return true; +} + + +function balance_teams() +{ + iPrintLnBold( game["strings"]["autobalance"] ); + //Create/Clear the team arrays + AlliedPlayers = []; + AxisPlayers = []; + + // Populate the team arrays + players = level.players; + + for ( i = 0; i < players.size; i++ ) + { + if ( !isdefined( players[i].pers["teamTime"] ) ) + continue; + + if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) ) + AlliedPlayers[AlliedPlayers.size] = players[i]; + else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) ) + AxisPlayers[AxisPlayers.size] = players[i]; + } + + MostRecent = undefined; + + while ( ( AlliedPlayers.size > ( AxisPlayers.size + 1 ) ) || ( AxisPlayers.size > ( AlliedPlayers.size + 1 ) ) ) + { + if ( AlliedPlayers.size > ( AxisPlayers.size + 1 ) ) + { + // Move the player that's been on the team the shortest ammount of time (highest teamTime value) + // Ignore players capturing or carrying objects + for ( j = 0; j < AlliedPlayers.size; j++ ) + { + + if ( !isdefined( MostRecent ) ) + MostRecent = AlliedPlayers[j]; + else if ( AlliedPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] ) + MostRecent = AlliedPlayers[j]; + } + + if ( isdefined( MostRecent ) ) + MostRecent change( "axis" ); + else + { + // Move the player that's been on the team the shortest ammount of time + for ( j = 0; j < AlliedPlayers.size; j++ ) + { + if ( !isdefined( MostRecent ) ) + MostRecent = AlliedPlayers[j]; + else if ( AlliedPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] ) + MostRecent = AlliedPlayers[j]; + } + + MostRecent change( "axis" ); + } + } + else if ( AxisPlayers.size > ( AlliedPlayers.size + 1 ) ) + { + // Move the player that's been on the team the shortest ammount of time (highest teamTime value) + // Ignore players capturing or carrying objects + for ( j = 0; j < AxisPlayers.size; j++ ) + { + + if ( !isdefined( MostRecent ) ) + MostRecent = AxisPlayers[j]; + else if ( AxisPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] ) + MostRecent = AxisPlayers[j]; + } + + if ( isdefined( MostRecent ) ) + MostRecent change( "allies" ); + else + { + // Move the player that's been on the team the shortest ammount of time + for ( j = 0; j < AxisPlayers.size; j++ ) + { + if ( !isdefined( MostRecent ) ) + MostRecent = AxisPlayers[j]; + else if ( AxisPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] ) + MostRecent = AxisPlayers[j]; + } + + MostRecent change( "allies" ); + } + } + + MostRecent = undefined; + AlliedPlayers = []; + AxisPlayers = []; + + players = level.players; + + for ( i = 0; i < players.size; i++ ) + { + if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) ) + AlliedPlayers[AlliedPlayers.size] = players[i]; + else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) ) + AxisPlayers[AxisPlayers.size] = players[i]; + } + } +} + + +function change( team ) +{ + if (self.sessionstate != "dead") + { + // Set a flag on the player to they aren't robbed points for dying - the callback will remove the flag + self.switching_teams = true; + self.switchedTeamsResetGadgets = true; + self.joining_team = team; + self.leaving_team = self.pers["team"]; + + // Suicide the player so they can't hit escape and fail the team balance + self suicide(); + } + + self.pers["team"] = team; + self.team = team; + self.pers["weapon"] = undefined; + self.pers["spawnweapon"] = undefined; + self.pers["savedmodel"] = undefined; + self.pers["teamTime"] = undefined; + self.sessionteam = self.pers["team"]; + + self globallogic_ui::updateObjectiveText(); + + // update spectator permissions immediately on change of team + self spectating::set_permissions(); + + self SetClientScriptMainMenu( game[ "menu_start_menu" ] ); + self openMenu(game[ "menu_start_menu" ]); + + self notify("end_respawn"); +} + +function count_players() +{ + players = level.players; + + playerCounts = []; + foreach( team in level.teams ) + { + playerCounts[team] = 0; + } + + foreach( player in level.players ) + { + if( player == self ) + continue; + + team = player.pers["team"]; + if( isdefined(team) && isdefined( level.teams[team] ) ) + playerCounts[team]++; + } + return playerCounts; +} + + +function track_free_played_time() +{ + self endon( "disconnect" ); + + foreach( team in level.teams ) + { + self.timePlayed[team] = 0; + } + + self.timePlayed["other"] = 0; + self.timePlayed["total"] = 0; + self.timePlayed["alive"] = 0; + + for ( ;; ) + { + if ( game["state"] == "playing" ) + { + team = self.pers["team"]; + if ( isdefined( team ) && isdefined( level.teams[team] ) && self.sessionteam != "spectator" ) + { + self.timePlayed[team]++; + self.timePlayed["total"]++; + if ( IsAlive( self ) ) + self.timePlayed["alive"]++; + } + else + { + self.timePlayed["other"]++; + } + } + + wait ( 1.0 ); + } +} + +function set_player_model( team, weapon ) +{ + self DetachAll(); + self SetMoveSpeedScale( 1 ); + self SetSprintDuration( 4 ); + self SetSprintCooldown( 0 ); +} + +function get_flag_model( teamRef ) +{ + assert(isdefined(game["flagmodels"])); + assert(isdefined(game["flagmodels"][teamRef])); + return ( game["flagmodels"][teamRef] ); +} + +function get_flag_carry_model( teamRef ) +{ + assert(isdefined(game["carry_flagmodels"])); + assert(isdefined(game["carry_flagmodels"][teamRef])); + return ( game["carry_flagmodels"][teamRef] ); +} + +function getTeamIndex( team ) +{ + if( !isdefined( team ) ) + { + return TEAM_FREE; + } + + if( team == "free" ) + { + return TEAM_FREE; + } + + if( team == "allies" ) + { + return TEAM_ALLIES; + } + + if( team == "axis" ) + { + return TEAM_AXIS; + } + + return TEAM_FREE; +} + +function getEnemyTeam( player_team ) +{ + foreach( team in level.teams ) + { + if ( team == player_team ) + continue; + + if ( team == "spectator" ) + continue; + + return team; + } + + return util::getOtherTeam( player_team ); +} + +function GetEnemyPlayers() +{ + enemies = []; + + foreach( player in level.players ) + { + if( player.team == "spectator" ) + { + continue; + } + + if( ( level.teamBased && player.team != self.team ) || ( !level.teamBased && player != self ) ) + { + ARRAY_ADD( enemies, player ); + } + } + + return enemies; +} + +function GetFriendlyPlayers() +{ + friendlies = []; + + foreach( player in level.players ) + { + if( ( player.team == self.team ) && ( player != self ) ) + { + ARRAY_ADD( friendlies, player ); + } + } + + return friendlies; +} + +function WaitUntilTeamChange( player, callback, arg, end_condition1, end_condition2, end_condition3 ) +{ + if( isdefined( end_condition1 ) ) + self endon( end_condition1 ); + if( isdefined( end_condition2 ) ) + self endon( end_condition2 ); + if( isdefined( end_condition3 ) ) + self endon( end_condition3 ); + + event = player util::waittill_any( "joined_team", "disconnect", "joined_spectators" ); + + if( isdefined( callback ) ) + { + self [[ callback ]]( arg, event ); + } +} + + +function WaitUntilTeamChangeSingleTon( player, singletonString, callback, arg, end_condition1, end_condition2, end_condition3 ) +{ + self notify( singletonString ); + self endon( singletonString ); + if( isdefined( end_condition1 ) ) + self endon( end_condition1 ); + if( isdefined( end_condition2 ) ) + self endon( end_condition2 ); + if( isdefined( end_condition3 ) ) + self endon( end_condition3 ); + + event = player util::waittill_any( "joined_team", "disconnect", "joined_spectators" ); + + if( isdefined( callback ) ) + { + self thread [[ callback ]]( arg, event ); + } +} + + +function HideToSameTeam() +{ + if( level.teambased ) + { + self SetVisibleToAllExceptTeam( self.team ); + } + else + { + self SetVisibleToAll(); + self SetInvisibleToPlayer( self.owner ); + } +} + From 3695b95c3b57fde4395f8a3b86f923f91c6e8d9c Mon Sep 17 00:00:00 2001 From: efinst0rm Date: Sat, 25 Mar 2023 14:06:11 -0500 Subject: [PATCH 2/2] Replace _clientids.gsc with _serversettings.gsc Server crashes after a few hours due to script vm. Overwriting _serversettings.gsc seems to better option when setting level.allow_teamchange 1. --- data/scripts/mp/gametypes/_clientids.gsc | Bin 732 -> 0 bytes data/scripts/mp/gametypes/_clientids.gsc_raw | 33 --- data/scripts/mp/gametypes/_serversettings.gsc | Bin 0 -> 4446 bytes .../mp/gametypes/_serversettings.gsc_raw | 196 ++++++++++++++++++ 4 files changed, 196 insertions(+), 33 deletions(-) delete mode 100644 data/scripts/mp/gametypes/_clientids.gsc delete mode 100644 data/scripts/mp/gametypes/_clientids.gsc_raw create mode 100644 data/scripts/mp/gametypes/_serversettings.gsc create mode 100644 data/scripts/mp/gametypes/_serversettings.gsc_raw diff --git a/data/scripts/mp/gametypes/_clientids.gsc b/data/scripts/mp/gametypes/_clientids.gsc deleted file mode 100644 index 0c2f5f36133e507e03aa29362543da6030205ac9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 732 zcmZp04|e9|Vvx~S+g@^kfq~%&69dB?7!72z0C5ON42m@v85q_8<(U{*7}$X{2rvVA z#mPmP1trD$$@wX%Fm`cCQE74sT&g%Du_!e~KRGccCn+&GyEq;qfG%HLSzMBu3zJOF z$xO{F$xJC`FoY}2EznO-%uOw+EJ!WZkB6(!OD|4lXa>3`8HhcA*fJ=+7D#~suL7UK zRr9Ylzs%|L7r;8oC9s#n#mN!NQkFW->Y04QYNYIsw36_7DYKh`?s>G8+AH3SrZ zTrdFHuW47L#$b|SrCuDPcP91OHIRg{qE#5k3{`_!S|ED0rm~j55+6gJx??(sZ)nD7 zK1176L4qMt8^ph16jTPH<*gT+gJ^3b0for2n>$_r%}ShlQ1{*>-5y|cGORm$FBlZp zpl||<0p<6HF$Yxu#Xw;I6LY!Mk+1?N2J$yd45kMttoQ+_4-}?d*30%W0#g$Ql75i9 z4v+wap~l1Aw-^~1nJj>Om{}lsA0Pn=LzsL7kPq@Z$S$CIrFB650-zm0ih%`4fWi;N Ho&Y2OWr5T7 diff --git a/data/scripts/mp/gametypes/_clientids.gsc_raw b/data/scripts/mp/gametypes/_clientids.gsc_raw deleted file mode 100644 index 1e8ac023..00000000 --- a/data/scripts/mp/gametypes/_clientids.gsc_raw +++ /dev/null @@ -1,33 +0,0 @@ -#using scripts\codescripts\struct; - -#using scripts\shared\callbacks_shared; -#using scripts\shared\system_shared; - -#insert scripts\shared\shared.gsh; - -#namespace clientids; - -REGISTER_SYSTEM( "clientids", &__init__, undefined ) - -function __init__() -{ - callback::on_start_gametype( &init ); - callback::on_connect( &on_player_connect ); -} - -function init() -{ - level.clientid = 0; - wait 0.5; - level.allow_teamchange = "1"; -} - -function on_player_connect() -{ - self.clientid = matchRecordNewPlayer( self ); - if ( !isdefined( self.clientid ) || self.clientid == -1 ) - { - self.clientid = level.clientid; - level.clientid++; - } -} \ No newline at end of file diff --git a/data/scripts/mp/gametypes/_serversettings.gsc b/data/scripts/mp/gametypes/_serversettings.gsc new file mode 100644 index 0000000000000000000000000000000000000000..cd63bd0b2ebb53e9107b14ed65d7fff569375288 GIT binary patch literal 4446 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 Nf^(-=o9OLG{~zTmftmmS literal 0 HcmV?d00001 diff --git a/data/scripts/mp/gametypes/_serversettings.gsc_raw b/data/scripts/mp/gametypes/_serversettings.gsc_raw new file mode 100644 index 00000000..02669e86 --- /dev/null +++ b/data/scripts/mp/gametypes/_serversettings.gsc_raw @@ -0,0 +1,196 @@ +#using scripts\codescripts\struct; + +#using scripts\shared\callbacks_shared; +#using scripts\shared\system_shared; + +#insert scripts\shared\shared.gsh; + +#namespace serversettings; + +REGISTER_SYSTEM( "serversettings", &__init__, undefined ) + +function __init__() +{ + callback::on_start_gametype( &init ); +} + +function init() +{ + level.hostname = GetDvarString( "sv_hostname"); + if(level.hostname == "") + level.hostname = "CoDHost"; + SetDvar("sv_hostname", level.hostname); + SetDvar("ui_hostname", level.hostname); + + level.motd = GetDvarString( "scr_motd" ); + if(level.motd == "") + level.motd = ""; + SetDvar("scr_motd", level.motd); + SetDvar("ui_motd", level.motd); + + level.allowvote = GetDvarString( "g_allowvote"); + if(level.allowvote == "") + level.allowvote = "1"; + SetDvar("g_allowvote", level.allowvote); + SetDvar("ui_allowvote", level.allowvote); + + level.allow_teamchange = "1"; + SetDvar("ui_allow_teamchange", level.allow_teamchange); + + + level.friendlyfire = GetGametypeSetting( "friendlyfiretype" ); + + SetDvar("ui_friendlyfire", level.friendlyfire); + + if(GetDvarString( "scr_mapsize") == "") + SetDvar("scr_mapsize", "64"); + else if(GetDvarfloat( "scr_mapsize") >= 64) + SetDvar("scr_mapsize", "64"); + else if(GetDvarfloat( "scr_mapsize") >= 32) + SetDvar("scr_mapsize", "32"); + else if(GetDvarfloat( "scr_mapsize") >= 16) + SetDvar("scr_mapsize", "16"); + else + SetDvar("scr_mapsize", "8"); + level.mapsize = GetDvarfloat( "scr_mapsize"); + + constrain_gametype(GetDvarString( "g_gametype")); + constrain_map_size(level.mapsize); + + for(;;) + { + update(); + wait 5; + } +} + +function update() +{ + sv_hostname = GetDvarString( "sv_hostname"); + if(level.hostname != sv_hostname) + { + level.hostname = sv_hostname; + SetDvar("ui_hostname", level.hostname); + } + + scr_motd = GetDvarString( "scr_motd"); + if(level.motd != scr_motd) + { + level.motd = scr_motd; + SetDvar("ui_motd", level.motd); + } + + g_allowvote = GetDvarString( "g_allowvote"); + if(level.allowvote != g_allowvote) + { + level.allowvote = g_allowvote; + SetDvar("ui_allowvote", level.allowvote); + } + + scr_friendlyfire = GetGametypeSetting( "friendlyfiretype" ); + if(level.friendlyfire != scr_friendlyfire) + { + level.friendlyfire = scr_friendlyfire; + SetDvar("ui_friendlyfire", level.friendlyfire); + } +} + +function constrain_gametype(gametype) +{ + entities = getentarray(); + for(i = 0; i < entities.size; i++) + { + entity = entities[i]; + + if(gametype == "dm") + { + if(isdefined(entity.script_gametype_dm) && entity.script_gametype_dm != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + else if(gametype == "tdm") + { + if(isdefined(entity.script_gametype_tdm) && entity.script_gametype_tdm != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + else if(gametype == "ctf") + { + if(isdefined(entity.script_gametype_ctf) && entity.script_gametype_ctf != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + else if(gametype == "hq") + { + if(isdefined(entity.script_gametype_hq) && entity.script_gametype_hq != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + else if(gametype == "sd") + { + if(isdefined(entity.script_gametype_sd) && entity.script_gametype_sd != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + else if(gametype == "koth") + { + if(isdefined(entity.script_gametype_koth) && entity.script_gametype_koth != "1") + { + //iprintln("DELETED(GameType): ", entity.classname); + entity delete(); + } + } + } +} + +function constrain_map_size(mapsize) +{ + entities = getentarray(); + for(i = 0; i < entities.size; i++) + { + entity = entities[i]; + + if(int(mapsize) == 8) + { + if(isdefined(entity.script_mapsize_08) && entity.script_mapsize_08 != "1") + { + //iprintln("DELETED(MapSize): ", entity.classname); + entity delete(); + } + } + else if(int(mapsize) == 16) + { + if(isdefined(entity.script_mapsize_16) && entity.script_mapsize_16 != "1") + { + //iprintln("DELETED(MapSize): ", entity.classname); + entity delete(); + } + } + else if(int(mapsize) == 32) + { + if(isdefined(entity.script_mapsize_32) && entity.script_mapsize_32 != "1") + { + //iprintln("DELETED(MapSize): ", entity.classname); + entity delete(); + } + } + else if(int(mapsize) == 64) + { + if(isdefined(entity.script_mapsize_64) && entity.script_mapsize_64 != "1") + { + //iprintln("DELETED(MapSize): ", entity.classname); + entity delete(); + } + } + } +} \ No newline at end of file