From 70d4d6a3913d157c99481ae8fbffc849b7af5f46 Mon Sep 17 00:00:00 2001 From: div0 Date: Mon, 11 Aug 2008 08:16:29 +0000 Subject: [PATCH] race: let everyone complete his lap when the race is over; players who have completed their race get the intermission scoreboard but still can walk (as nonsolid players) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4101 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/cl_client.qc | 5 ++--- data/qcsrc/server/clientcommands.qc | 2 +- data/qcsrc/server/defs.qh | 2 ++ data/qcsrc/server/g_damage.qc | 2 +- data/qcsrc/server/g_world.qc | 27 ++++++++++++++++++++++++++- data/qcsrc/server/havocbot.qc | 4 ++-- data/qcsrc/server/race.qc | 22 ++++++++++++++++++++-- data/qcsrc/server/race.qh | 2 ++ data/qcsrc/server/scores.qc | 8 +++++--- data/qcsrc/server/scores.qh | 5 +++-- 10 files changed, 64 insertions(+), 15 deletions(-) diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index e192b907f..808dfb62a 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -613,10 +613,9 @@ void PutClientInServer (void) self.classname = "player"; self.iscreature = TRUE; self.movetype = MOVETYPE_WALK; + self.solid = SOLID_SLIDEBOX; if(independent_players) - self.solid = SOLID_TRIGGER; - else - self.solid = SOLID_SLIDEBOX; + MAKE_INDEPENDENT_PLAYER(self); self.flags = FL_CLIENT; self.takedamage = DAMAGE_AIM; if(g_minstagib) diff --git a/data/qcsrc/server/clientcommands.qc b/data/qcsrc/server/clientcommands.qc index 95bdf78b5..3efb351b2 100644 --- a/data/qcsrc/server/clientcommands.qc +++ b/data/qcsrc/server/clientcommands.qc @@ -385,7 +385,7 @@ void ReadyRestart() bprint("^1Server is restarting...\n"); // no arena, assault support yet... - if(g_arena | g_assault | gameover | intermission_running) + if(g_arena | g_assault | gameover | intermission_running | race_completing) localcmd("restart\n"); if(readyNagActive) { //if every player is ready, remove the ready-nagger again diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index 9746623d7..d4d00c022 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -484,3 +484,5 @@ void VoiceMessage(string type); .float version_mismatch; float independent_players; +#define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER) +#define MAKE_INDEPENDENT_PLAYER(e) ((e).solid = SOLID_TRIGGER) diff --git a/data/qcsrc/server/g_damage.qc b/data/qcsrc/server/g_damage.qc index 6227dd8b9..d9e3e1298 100644 --- a/data/qcsrc/server/g_damage.qc +++ b/data/qcsrc/server/g_damage.qc @@ -515,7 +515,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float if(deathtype != DEATH_TELEFRAG) if(attacker.classname == "player") { - if(independent_players && targ != attacker && targ.classname == "player") + if(targ.classname == "player" && targ != attacker && IS_INDEPENDENT_PLAYER(attacker) && IS_INDEPENDENT_PLAYER(targ)) { damage = 0; force = '0 0 0'; diff --git a/data/qcsrc/server/g_world.qc b/data/qcsrc/server/g_world.qc index d610302ac..edf506d71 100644 --- a/data/qcsrc/server/g_world.qc +++ b/data/qcsrc/server/g_world.qc @@ -1497,6 +1497,24 @@ float WinningCondition_Scores(float limit) return GetWinningCode(limit && WinningConditionHelper_topscore && (WinningConditionHelper_topscore >= limit), WinningConditionHelper_equality); } +float WinningCondition_Race(float fraglimit) +{ + float wc; + entity p; + wc = WinningCondition_Scores(fraglimit); + + // ALWAYS initiate overtime, unless EVERYONE has finished the race! + if(wc == WINNING_YES || wc == WINNING_STARTOVERTIME) + // do NOT support equality when the laps are all raced! + { + FOR_EACH_PLAYER(p) + if not(p.race_completed) + return WINNING_STARTOVERTIME; + return WINNING_YES; + } + return wc; +} + float WinningCondition_RanOutOfSpawns() { entity head; @@ -1609,7 +1627,10 @@ void CheckRules_World() { checkrules_overtimewarning = TRUE; //announceall("announcer/robotic/1minuteremains.wav"); - bcenterprint("^3Now playing ^1OVERTIME^3!\n\n^3Keep fragging until we have a ^1winner^3!"); + if(!g_race_qualifying) + bcenterprint("^3Everyone, finish your lap! The race is over!"); + else + bcenterprint("^3Now playing ^1OVERTIME^3!\n\n^3Keep fragging until we have a ^1winner^3!"); } } else @@ -1635,6 +1656,10 @@ void CheckRules_World() { bprint("Hey! Someone ran out of spawns!\n"); } + else if(g_race && !g_race_qualifying) + { + status = WinningCondition_Race(fraglimit); + } else if(g_assault) { status = WinningCondition_Assault(); // TODO remove this? diff --git a/data/qcsrc/server/havocbot.qc b/data/qcsrc/server/havocbot.qc index 7e588c2d9..e1963a054 100644 --- a/data/qcsrc/server/havocbot.qc +++ b/data/qcsrc/server/havocbot.qc @@ -258,7 +258,7 @@ void havocbot_chooseenemy() local entity head, best; local float rating, bestrating; local vector eye, v; - if (cvar("bot_nofire") || independent_players) + if (cvar("bot_nofire") || IS_INDEPENDENT_PLAYER(self)) { self.enemy = world; return; @@ -457,7 +457,7 @@ void havocbot_ai() if (self.bot_aimtarg) { weapon_action(self.weapon, WR_AIM); - if (cvar("bot_nofire") || independent_players) + if (cvar("bot_nofire") || IS_INDEPENDENT_PLAYER(self)) { self.BUTTON_ATCK = FALSE; self.BUTTON_ATCK2 = FALSE; diff --git a/data/qcsrc/server/race.qc b/data/qcsrc/server/race.qc index b408aa185..66bb8f232 100644 --- a/data/qcsrc/server/race.qc +++ b/data/qcsrc/server/race.qc @@ -65,11 +65,12 @@ void race_SendNextCheckpoint(entity e) void race_SendTime(entity e, float cp, float t, float tvalid) { + float snew, l; t = floor(0.5 + 10 * t); // make integer - float snew; if(tvalid) if(cp == 0) // finish line + if not(e.race_completed) { float s; if(g_race_qualifying) @@ -83,7 +84,24 @@ void race_SendTime(entity e, float cp, float t, float tvalid) s = PlayerScore_Add(e, SP_RACE_TIME, 0); snew = floor(0.5 + 10 * (time - restart_countdown)); PlayerScore_Add(e, SP_RACE_TIME, snew - s); - PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1); + l = PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1); + + if(cvar("fraglimit")) + if(l > cvar("fraglimit")) + race_completing = 1; + + if(race_completing) + { + e.race_completed = 1; + MAKE_INDEPENDENT_PLAYER(e); + bprint(e.netname, "^7 has finished the race.\n"); + if(clienttype(e) == CLIENTTYPE_REAL) + { + msg_entity = e; + WriteByte(MSG_ONE, SVC_INTERMISSION); + // he can still move, but will see the scoreboard now + } + } } } diff --git a/data/qcsrc/server/race.qh b/data/qcsrc/server/race.qh index 38b4349d2..56bdbe91e 100644 --- a/data/qcsrc/server/race.qh +++ b/data/qcsrc/server/race.qh @@ -9,3 +9,5 @@ float race_NextCheckpoint(float f); float race_highest_place_spawn; float race_fraglimit; .float race_place; +.float race_completed; +float race_completing; diff --git a/data/qcsrc/server/scores.qc b/data/qcsrc/server/scores.qc index 86253c55e..c2767c674 100644 --- a/data/qcsrc/server/scores.qc +++ b/data/qcsrc/server/scores.qc @@ -270,11 +270,13 @@ float PlayerScore_Add(entity player, float scorefield, float score) return (s.(scores[scorefield]) += score); } -void PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score) +float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score) { - PlayerScore_Add(player, pscorefield, score); + float r; + r = PlayerScore_Add(player, pscorefield, score); if(teamscores_entities_count) // only for teamplay - TeamScore_Add(player, tscorefield, score); + r = TeamScore_Add(player, tscorefield, score); + return r; } float PlayerScore_Compare(entity t1, entity t2) diff --git a/data/qcsrc/server/scores.qh b/data/qcsrc/server/scores.qh index e42c3beb9..89bad5dc0 100644 --- a/data/qcsrc/server/scores.qh +++ b/data/qcsrc/server/scores.qh @@ -41,9 +41,10 @@ float TeamScore_Add(entity player, float scorefield, float score); float TeamScore_AddToTeam(float t, float scorefield, float score); /** - * Adds a score to both the player and the team. + * Adds a score to both the player and the team. Returns the team score if + * possible, otherwise the player score. */ -void PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score); +float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score); /** * Adds to the generic score fields for both the player and the team. -- 2.39.2