From d5c7dad7b2743c88160c353fa876c087255c8b97 Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Mon, 11 Jul 2011 18:35:10 +0300 Subject: [PATCH] Use Xonotic's system for selecting teams and spectating --- data/defaultVT.cfg | 4 +- data/qcsrc/server/cl_client.qc | 83 +++++++++++++++++++++++------ data/qcsrc/server/clientcommands.qc | 24 +++------ data/qcsrc/server/race.qc | 6 +++ 4 files changed, 83 insertions(+), 34 deletions(-) diff --git a/data/defaultVT.cfg b/data/defaultVT.cfg index 419ddd8d..60e08cfa 100644 --- a/data/defaultVT.cfg +++ b/data/defaultVT.cfg @@ -487,6 +487,7 @@ set g_rc_respawn_delay 0 set g_cts_respawn_waves 0 set g_cts_respawn_delay 0 set g_cts_selfdamage 1 "0 = disable all selfdamage and falldamage in cts" +set g_cts_finish_kill_delay 10 "prevent cheating by running back to the start line, and starting out with more speed than otherwise possible" set g_rpg_respawn_waves 0 set g_rpg_respawn_delay 0 @@ -1262,7 +1263,8 @@ sv_gameplayfix_q2airaccelerate 1 sv_gameplayfix_stepmultipletimes 1 // delay for "kill" to prevent abuse -set g_balance_kill_delay 5 +set g_balance_kill_delay 2 +set g_balance_kill_antispam 5 // this feature is currently buggy in the engine (it appears to PREVENT any dropping in lots of maps, leading to weirdly aligned entities, and in some cases even CAUSES them to drop through solid, like in facing worlds nex) sv_gameplayfix_droptofloorstartsolid 0 diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index 702125d7..91d566f1 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -1119,6 +1119,7 @@ Called when a client types 'kill' in the console ============= */ +.float clientkill_nexttime; void ClientKill_Now_TeamChange() { if(self.killindicator_teamchange == -1) @@ -1126,24 +1127,32 @@ void ClientKill_Now_TeamChange() self.team = -1; JoinBestTeam( self, FALSE, FALSE ); } + else if(self.killindicator_teamchange == -2) + { + if(g_ca) + self.caplayer = 0; + if(blockSpectators) + sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); + PutObserverInServer(); + } else SV_ChangeTeam(self.killindicator_teamchange - 1); } void ClientKill_Now() -{ +{ + if(self.killindicator && !wasfreed(self.killindicator)) + remove(self.killindicator); + + self.killindicator = world; + if(self.killindicator_teamchange) ClientKill_Now_TeamChange(); // in any case: Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0'); - if(self.killindicator) - { - dprint("Cleaned up after a leaked kill indicator.\n"); - remove(self.killindicator); - self.killindicator = world; - } + // now I am sure the player IS dead } void KillIndicator_Think() { @@ -1160,6 +1169,11 @@ void KillIndicator_Think() ClientKill_Now(); // no oldself needed return; } + else if(g_cts && self.health == 1) // health == 1 means that it's silent + { + self.nextthink = time + 1; + self.cnt -= 1; + } else { if(self.cnt <= 10) @@ -1172,6 +1186,8 @@ void KillIndicator_Think() { if(self.owner.killindicator_teamchange == -1) centerprint(self.owner, strcat("Changing team in ", ftos(self.cnt), " seconds")); + else if(self.owner.killindicator_teamchange == -2) + centerprint(self.owner, strcat("Spectating in ", ftos(self.cnt), " seconds")); else centerprint(self.owner, strcat("Changing to ", ColoredTeamName(self.owner.killindicator_teamchange), " in ", ftos(self.cnt), " seconds")); } @@ -1183,19 +1199,34 @@ void KillIndicator_Think() } } -void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto +void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec { float killtime; entity e; killtime = cvar("g_balance_kill_delay"); - if(g_race_qualifying) + if(g_race_qualifying || g_cts) killtime = 0; + if(g_cts && self.killindicator && self.killindicator.health == 1) // self.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill + { + remove(self.killindicator); + self.killindicator = world; + + ClientKill_Now(); // allow instant kill in this case + return; + } + self.killindicator_teamchange = targetteam; - if(!self.killindicator) + if(!self.killindicator) { + if(self.modelindex && self.deadflag == DEAD_NO) + { + killtime = max(killtime, self.clientkill_nexttime - time); + self.clientkill_nexttime = time + killtime + cvar("g_balance_kill_antispam"); + } + if(killtime <= 0 || !self.modelindex || self.deadflag != DEAD_NO) { ClientKill_Now(); @@ -1211,7 +1242,7 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto self.killindicator.nextthink = time + (self.lip) * 0.05; self.killindicator.cnt = ceil(killtime); self.killindicator.count = bound(0, ceil(killtime), 10); - sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n")); + //sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n")); for(e = world; (e = find(e, classname, "body")) != world; ) { @@ -1231,22 +1262,42 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto } if(self.killindicator) { - if(targetteam) - self.killindicator.colormod = TeamColor(targetteam); - else + if(targetteam == 0) // just die self.killindicator.colormod = '0 0 0'; + else if(targetteam == -1) // auto + self.killindicator.colormod = '0 1 0'; + else if(targetteam == -2) // spectate + self.killindicator.colormod = '0.5 0.5 0.5'; + else + self.killindicator.colormod = TeamColor(targetteam); } } void ClientKill (void) { - ClientKill_TeamChange(0); + if((g_arena || g_ca) && ((champion && champion.classname == "player" && player_count > 1) || player_count == 1)) // don't allow a kill in this case either + { + // do nothing + } + else + ClientKill_TeamChange(0); +} + +void CTS_ClientKill (entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed +{ + e.killindicator = spawn(); + e.killindicator.owner = e; + e.killindicator.think = KillIndicator_Think; + e.killindicator.nextthink = time + (e.lip) * 0.05; + e.killindicator.cnt = ceil(cvar("g_cts_finish_kill_delay")); + e.killindicator.health = 1; // this is used to indicate that it should be silent + e.lip = 0; } void DoTeamChange(float destteam) { float t, c0; - if(!teams_matter) + if(!teamplay) { if(destteam >= 0) SetPlayerColors(self, destteam); diff --git a/data/qcsrc/server/clientcommands.qc b/data/qcsrc/server/clientcommands.qc index 369005ad..3d52a019 100644 --- a/data/qcsrc/server/clientcommands.qc +++ b/data/qcsrc/server/clientcommands.qc @@ -166,9 +166,8 @@ void SV_ParseClientCommand(string s) { } if(self.version != cvar("gameversion")) { - self.classname = "observer"; self.version_mismatch = 1; - PutClientInServer(); + ClientKill_TeamChange(-2); // observe } else if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force")) { //JoinBestTeam(self, FALSE, TRUE); } else if(teams_matter && !cvar("sv_spectate")) { @@ -221,16 +220,7 @@ void SV_ParseClientCommand(string s) { } } if(self.classname == "player" && cvar("sv_spectate") == 1) { - if(self.flagcarried) - DropFlag(self.flagcarried, world, world); - kh_Key_DropAll(self, TRUE); - WaypointSprite_PlayerDead(); - self.classname = "observer"; - if(g_ca) - self.caplayer = 0; - if(blockSpectators) - sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); - PutClientInServer(); + ClientKill_TeamChange(-2); // observe } } else if(cmd == "join") { if not(self.flags & FL_CLIENT) @@ -264,15 +254,15 @@ void SV_ParseClientCommand(string s) { } else if(lockteams) { sprint( self, "^7The game has already begun, you must wait until the next map to be able to join a team.\n"); } else if( argv(1) == "red" ) { - DoTeamChange(COLOR_TEAM1); + ClientKill_TeamChange(COLOR_TEAM1); } else if( argv(1) == "blue" ) { - DoTeamChange(COLOR_TEAM2); + ClientKill_TeamChange(COLOR_TEAM2); } else if( argv(1) == "yellow" ) { - DoTeamChange(COLOR_TEAM3); + ClientKill_TeamChange(COLOR_TEAM3); } else if( argv(1) == "pink" ) { - DoTeamChange(COLOR_TEAM4); + ClientKill_TeamChange(COLOR_TEAM4); } else if( argv(1) == "auto" ) { - DoTeamChange(-1); + ClientKill_TeamChange(-1); } else { sprint( self, strcat( "selectteam none/red/blue/yellow/pink/auto - \"", argv(1), "\" not recognised\n" ) ); } diff --git a/data/qcsrc/server/race.qc b/data/qcsrc/server/race.qc index e48d8659..0f84c665 100644 --- a/data/qcsrc/server/race.qc +++ b/data/qcsrc/server/race.qc @@ -485,7 +485,13 @@ void race_SendTime(entity e, float cp, float t, float tvalid) if(t != 0) { if(cp == race_timed_checkpoint) + { race_SetTime(e, t, recordtime); + if(g_cts && cvar("g_cts_finish_kill_delay")) + { + CTS_ClientKill(e); + } + } if(t < recordtime || recordtime == 0) { -- 2.39.2