From 1f3f0face668264911fba1e51dfcb1c5a79101be Mon Sep 17 00:00:00 2001 From: ineedbots Date: Wed, 1 Sep 2021 13:57:01 -0600 Subject: [PATCH] team balance and kick spectators https://github.com/efinst0rm/PlutoBO2-Autobalance/blob/master/maps/mp/teams/_teams.gsc --- .gitignore | 1 + raw/maps/mp/teams/_teams-src.gsc | 577 ++++++++++++++++++++++ raw/maps/mp/teams/_teams.gsc | Bin 0 -> 8076 bytes raw/scripts/mp/spectatorKick-compiled.gsc | Bin 0 -> 620 bytes raw/scripts/mp/spectatorKick.gsc | 35 ++ 5 files changed, 613 insertions(+) create mode 100644 raw/maps/mp/teams/_teams-src.gsc create mode 100644 raw/maps/mp/teams/_teams.gsc create mode 100644 raw/scripts/mp/spectatorKick-compiled.gsc create mode 100644 raw/scripts/mp/spectatorKick.gsc diff --git a/.gitignore b/.gitignore index 3dc63c6..f37fdbd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ !/raw/maps/mp/bots/ !/raw/bw-assets !/raw/bots.txt +!/raw/maps/mp/teams/ !/README.md diff --git a/raw/maps/mp/teams/_teams-src.gsc b/raw/maps/mp/teams/_teams-src.gsc new file mode 100644 index 0000000..11a24a8 --- /dev/null +++ b/raw/maps/mp/teams/_teams-src.gsc @@ -0,0 +1,577 @@ +#include maps/mp/gametypes/_spectating; +#include maps/mp/gametypes/_globallogic_ui; +#include maps/mp/gametypes/_persistence; +#include maps/mp/_utility; + +init() +{ + precacheshader( "mpflag_spectator" ); + game["strings"]["autobalance"] = &"MP_AUTOBALANCE_NOW"; + precachestring( &"MP_AUTOBALANCE_NOW" ); + + if ( GetDvar( "scr_teambalance" ) == "" ) + { + setdvar( "scr_teambalance", "0" ); + } + + level.teambalance = GetDvarInt( "scr_teambalance" ); + level.teambalancetimer = 0; + + if ( GetDvar( "scr_timeplayedcap" ) == "" ) + { + setdvar( "scr_timeplayedcap", "1800" ); + } + + level.timeplayedcap = int( GetDvarInt( "scr_timeplayedcap" ) ); + level.freeplayers = []; + + if ( level.teambased ) + { + level.alliesplayers = []; + level.axisplayers = []; + level thread onplayerconnect(); + level thread updateTeamBalance(); + wait( 0.15 ); + level thread updateplayertimes(); + } + else + { + level thread onfreeplayerconnect(); + wait( 0.15 ); + level thread updateplayertimes(); + } +} + + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onjoinedteam(); + player thread onjoinedspectators(); + player thread trackplayedtime(); + } +} + + +onfreeplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread trackfreeplayedtime(); + } +} + + +onjoinedteam() +{ + self endon( "disconnect" ); + + for ( ;; ) + { + self waittill( "joined_team" ); + self logstring( "joined team: " + self.pers["team"] ); + self updateteamtime(); + } +} + + +onjoinedspectators() +{ + self endon( "disconnect" ); + + for ( ;; ) + { + self waittill( "joined_spectators" ); + self.pers["teamTime"] = undefined; + } +} + +trackplayedtime() +{ + self endon( "disconnect" ); + + foreach ( team in level.teams ) + { + self.timePlayed[team] = 0; + } + + self.timePlayed["free"] = 0; + self.timePlayed["other"] = 0; + self.timePlayed["alive"] = 0; + + + if ( !isdefined( self.timePlayed["total"] ) || !( ( level.gameType == "twar" ) && ( 0 < game["roundsplayed"] ) && ( 0 < self.timeplayed["total"] ) ) ) + self.timePlayed["total"] = 0; + + while ( level.inprematchperiod ) + { + wait( 0.05 ); + } + + for ( ;; ) + { + if ( game["state"] == "playing" ) + { + if ( isdefined( level.teams[self.sessionteam] ) ) + { + self.timeplayed[self.sessionteam]++; + self.timeplayed["total"]++; + + if ( isalive( self ) ) + { + self.timeplayed["alive"]++; + } + } + else if ( self.sessionteam == "spectator" ) + { + self.timeplayed["other"]++; + } + } + + wait ( 1.0 ); + } + +} + +updateplayertimes() +{ + nexttoupdate = 0; + + for ( ;; ) + { + nexttoupdate++; + + if ( nexttoupdate >= level.players.size ) + { + nexttoupdate = 0; + } + + if ( isdefined( level.players[nexttoupdate] ) ) + { + level.players[nexttoupdate] updateplayedtime(); + level.players[nexttoupdate] maps\mp\gametypes\_persistence::checkcontractexpirations(); + } + + wait( 1 ); + } +} + +updateplayedtime() +{ + pixbeginevent( "updatePlayedTime" ); + + foreach ( team in level.teams ) + { + if ( self.timeplayed[team] ) + { + 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 maps\mp\gametypes\_persistence::incrementcontracttimes( timealive ); + self addplayerstat( "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; +} + +updateteamtime() +{ + if ( game["state"] != "playing" ) + { + return; + } + + self.pers["teamTime"] = GetTime(); +} + +updateteambalancedvar() +{ + 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 ); + } +} + +updateTeamBalance() +{ + level.teamLimit = level.maxclients / 2; + + level thread updateTeamBalanceDvar(); + + wait .15; + + if ( level.teamBalance && isRoundBased() && level.numlives ) + { + if ( isDefined( game["BalanceTeamsNextRound"] ) ) + iPrintLnbold( &"MP_AUTOBALANCE_NEXT_ROUND" ); + + level waittill( "game_ended" ); + wait 1; + + if ( isDefined( game["BalanceTeamsNextRound"] ) ) + { + level balanceTeams(); + game["BalanceTeamsNextRound"] = undefined; + } + else if ( !getTeamBalance() ) + { + game["BalanceTeamsNextRound"] = true; + } + } + else + { + level endon ( "game_ended" ); + + for ( ;; ) + { + if ( level.teamBalance ) + { + if ( !getTeamBalance() ) + { + iPrintLnBold( &"MP_AUTOBALANCE_SECONDS", 15 ); + wait 15.0; + + if ( !getTeamBalance() ) + level balanceTeams(); + } + + wait 59.0; + } + + wait 1.0; + } + } + +} + +getTeamBalance() +{ + 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; +} + +balanceTeams() +{ + 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 changeTeam( "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 changeTeam( "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 changeTeam( "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 changeTeam( "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]; + } + } +} + +changeTeam( team ) +{ + teams[0] = "allies"; + teams[1] = "axis"; + assignment = team; + + if ( assignment != self.pers["team"] ) + { + if ( self.sessionstate == "playing" || self.sessionstate == "dead" ) + { + self.switching_teams = true; + self.joining_team = assignment; + self.leaving_team = self.pers["team"]; + self suicide(); + } + } + + self.pers["team"] = assignment; + self.team = assignment; + self.pers["class"] = undefined; + self.class = undefined; + self.pers["weapon"] = undefined; + self.pers["savedmodel"] = undefined; + + self maps\mp\gametypes\_globallogic_ui::updateObjectiveText(); + self maps\mp\gametypes\_spectating::setspectatepermissions(); + + if ( level.teamBased ) + self.sessionteam = assignment; + else + { + self.sessionteam = "none"; + self.ffateam = assignment; + } + + if ( !isAlive( self ) ) + self.statusicon = "hud_status_dead"; + + + self notify( "joined_team" ); + level notify( "joined_team" ); + self setclientscriptmainmenu( game["menu_class"] ); + self openmenu( game["menu_class"] ); + self notify( "end_respawn" ); +} + +countplayers() +{ + 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; +} + +trackfreeplayedtime() +{ + self endon( "disconnect" ); + + foreach ( team in level.teams ) + { + self.timeplayed[team] = 0; + } + + self.timeplayed["other"] = 0; + self.timeplayed["total"] = 0; + self.timeplayed["alive"] = 0; + + while ( 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 ); + } +} + +set_player_model( team, weapon ) +{ + weaponclass = getweaponclass( weapon ); + bodytype = "default"; + + switch ( weaponclass ) + { + case "weapon_sniper": + bodytype = "rifle"; + break; + + case "weapon_cqb": + bodytype = "spread"; + break; + + case "weapon_lmg": + bodytype = "mg"; + break; + + case "weapon_smg": + bodytype = "smg"; + break; + } + + self detachall(); + self setmovespeedscale( 1 ); + self setsprintduration( 4 ); + self setsprintcooldown( 0 ); + + if ( level.multiteam ) + { + bodytype = "default"; + + switch ( team ) + { + case "team7": + case "team8": + team = "allies"; + break; + } + } + + self [[ game[ "set_player_model" ][ team ][ bodytype ] ]](); +} + +getteamflagmodel( teamref ) +{ + return game["flagmodels"][teamref]; +} + +getteamflagcarrymodel( teamref ) +{ + return game["carry_flagmodels"][teamref]; +} + +getteamflagicon( teamref ) +{ + return game["carry_icon"][teamref]; +} diff --git a/raw/maps/mp/teams/_teams.gsc b/raw/maps/mp/teams/_teams.gsc new file mode 100644 index 0000000000000000000000000000000000000000..2642b0a9a5df6eb2785cedb3133100bc4d5e7496 GIT binary patch literal 8076 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 LZiPM$eH8jXu$efn literal 0 HcmV?d00001 diff --git a/raw/scripts/mp/spectatorKick-compiled.gsc b/raw/scripts/mp/spectatorKick-compiled.gsc new file mode 100644 index 0000000000000000000000000000000000000000..435d1ecad1180971a3c3ff909388e116b586ed5f GIT binary patch literal 620 zcmX|;u}d656vn^VJ=82Y8w*{lQxb1MPQ*fy#atwy5+M<{&#|t<-JIuo>`pWafmBze z6VqrXSK5e>a#KpcKOtaYVJ)drM8CP^9Qfw<&Ad1B-tK%`4c-+U41nVg^-tu41zghq zrdsqyX1s;NP$6G%PTMllq25c@RkQ;YD~)+2xA((@IsM@CSsa8q zYP4J7p-fVIX{S-xlF$vQ)vkm>KavxTFiqRxK`giP@+N7=l&?!IW6iSh=iM!tV9G&& zhNH0JkD&6xG;MZf$R;)K1ZWQ2+Z)9RB=CwQ&h~pB{N&0U;~kTOQTr697T-25Z;bNh5g++g<=Q7k5eY}KgaepF%SACuP zQihMc>g%S@ii=s?u$t-f+VoHs%T=5_R&n$QjE@w)nwR=OWureYC)uv)w23$D+_L`C zcX}T77-KiNFZ`gt?s;LI(dQ$8ja%9W>OZA;#~sN(A%>VWOns+LA;c^4oSY&rNRK=w Y=gBTCu|jTASKQkoGv3i6kEjmy1O= level.inactivitySpectator ) + kick( player getEntityNumber() ); + } + } + } +}