]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator/gamemode_race.qc
Merge branch 'master' into terencehill/translate_colors_2
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator / gamemode_race.qc
index cc250dfc73e75f870ee649071ac9e2d6c3655b41..7b769e29ff152f193fd1573c09697da7dede3dd6 100644 (file)
@@ -1,3 +1,5 @@
+#include "gamemode_race.qh"
+
 #ifndef GAMEMODE_RACE_H
 #define GAMEMODE_RACE_H
 
@@ -6,12 +8,12 @@ void race_Initialize();
 
 REGISTER_MUTATOR(rc, false)
 {
-       rc_SetLimits();
-
        MUTATOR_ONADD
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
+
+               rc_SetLimits();
                race_Initialize();
        }
 
@@ -31,18 +33,11 @@ REGISTER_MUTATOR(rc, false)
        return 0;
 }
 
-float race_teams;
-
-// scores
-const float ST_RACE_LAPS = 1;
-const float SP_RACE_LAPS = 4;
-const float SP_RACE_TIME = 5;
-const float SP_RACE_FASTEST = 6;
 #endif
 
 #ifdef IMPLEMENTATION
 
-#include "../../race.qh"
+#include <server/race.qh>
 
 #define autocvar_g_race_laps_limit cvar("g_race_laps_limit")
 float autocvar_g_race_qualifying_timelimit;
@@ -51,30 +46,30 @@ int autocvar_g_race_teams;
 
 // legacy bot roles
 .float race_checkpoint;
-void havocbot_role_race()
-{SELFPARAM();
-       if(self.deadflag != DEAD_NO)
+void havocbot_role_race(entity this)
+{
+       if(IS_DEAD(this))
                return;
 
        entity e;
-       if (self.bot_strategytime < time)
+       if (this.bot_strategytime < time)
        {
-               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-               navigation_goalrating_start();
+               this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+               navigation_goalrating_start(this);
 
                for(e = world; (e = find(e, classname, "trigger_race_checkpoint")) != world; )
                {
-                       if(e.cnt == self.race_checkpoint)
+                       if(e.cnt == this.race_checkpoint)
                        {
-                               navigation_routerating(e, 1000000, 5000);
+                               navigation_routerating(this, e, 1000000, 5000);
                        }
-                       else if(self.race_checkpoint == -1)
+                       else if(this.race_checkpoint == -1)
                        {
-                               navigation_routerating(e, 1000000, 5000);
+                               navigation_routerating(this, e, 1000000, 5000);
                        }
                }
 
-               navigation_goalrating_end();
+               navigation_goalrating_end(this);
        }
 }
 
@@ -107,6 +102,44 @@ void race_EventLog(string mode, entity actor) // use an alias for easy changing
                GameLogEcho(strcat(":race:", mode, ":", ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
 }
 
+float WinningCondition_Race(float fraglimit)
+{
+       float wc;
+       float n, c;
+
+       n = 0;
+       c = 0;
+       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
+               ++n;
+               if(it.race_completed)
+                       ++c;
+       ));
+       if(n && (n == c))
+               return WINNING_YES;
+       wc = WinningCondition_Scores(fraglimit, 0);
+
+       // ALWAYS initiate overtime, unless EVERYONE has finished the race!
+       if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+       // do NOT support equality when the laps are all raced!
+               return WINNING_STARTSUDDENDEATHOVERTIME;
+       else
+               return WINNING_NEVER;
+}
+
+float WinningCondition_QualifyingThenRace(float limit)
+{
+       float wc;
+       wc = WinningCondition_Scores(limit, 0);
+
+       // NEVER initiate overtime
+       if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
+       {
+               return WINNING_YES;
+       }
+
+       return wc;
+}
+
 MUTATOR_HOOKFUNCTION(rc, PlayerPhysics)
 {SELFPARAM();
        self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
@@ -188,17 +221,15 @@ MUTATOR_HOOKFUNCTION(rc, reset_map_global)
        race_ClearRecords();
        PlayerScore_Sort(race_place, 0, 1, 0);
 
-       entity e;
-       FOR_EACH_CLIENT(e)
-       {
-               if(e.race_place)
+       FOREACH_CLIENT(true, LAMBDA(
+               if(it.race_place)
                {
-                       s = PlayerScore_Add(e, SP_RACE_FASTEST, 0);
+                       s = PlayerScore_Add(it, SP_RACE_FASTEST, 0);
                        if(!s)
-                               e.race_place = 0;
+                               it.race_place = 0;
                }
-               race_EventLog(ftos(e.race_place), e);
-       }
+               race_EventLog(ftos(it.race_place), it);
+       ));
 
        if(g_race_qualifying == 2)
        {
@@ -213,16 +244,6 @@ MUTATOR_HOOKFUNCTION(rc, reset_map_global)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(rc, PlayerPreThink)
-{SELFPARAM();
-       if(IS_SPEC(self) || IS_OBSERVER(self))
-       if(g_race_qualifying)
-       if(msg_entity.enemy.race_laptime)
-               race_SendNextCheckpoint(msg_entity.enemy, 1);
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(rc, ClientConnect)
 {SELFPARAM();
        race_PreparePlayer();
@@ -284,7 +305,7 @@ MUTATOR_HOOKFUNCTION(rc, PutClientInServer)
        if(IS_PLAYER(self))
        if(!gameover)
        {
-               if(self.killcount == -666 /* initial spawn */ || g_race_qualifying) // spawn
+               if(self.killcount == FRAGS_SPECTATOR /* initial spawn */ || g_race_qualifying) // spawn
                        race_PreparePlayer();
                else // respawn
                        race_RetractPlayer();
@@ -295,9 +316,9 @@ MUTATOR_HOOKFUNCTION(rc, PutClientInServer)
 }
 
 MUTATOR_HOOKFUNCTION(rc, PlayerDies)
-{SELFPARAM();
-       self.respawn_flags |= RESPAWN_FORCE;
-       race_AbandonRaceCheck(self);
+{
+       frag_target.respawn_flags |= RESPAWN_FORCE;
+       race_AbandonRaceCheck(frag_target);
        return false;
 }
 
@@ -399,10 +420,18 @@ MUTATOR_HOOKFUNCTION(rc, FixClientCvars)
 
 MUTATOR_HOOKFUNCTION(rc, CheckRules_World)
 {
-       if(g_race_qualifying == 2 && checkrules_timelimit >= 0)
+       if(checkrules_timelimit >= 0)
        {
-               ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
-               return true;
+               if(!g_race_qualifying)
+               {
+                       ret_float = WinningCondition_Race(checkrules_fraglimit);
+                       return true;
+               }
+               else if(g_race_qualifying == 2)
+               {
+                       ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+                       return true;
+               }
        }
 
        return false;
@@ -439,9 +468,8 @@ void rc_SetLimits()
        qualifying_override = autocvar_g_race_qualifying_timelimit_override;
        fraglimit_override = autocvar_g_race_laps_limit;
        leadlimit_override = 0; // currently not supported by race
-       timelimit_override = -1; // use default if we don't set it below
+       timelimit_override = autocvar_timelimit_override;
 
-       // we need to find out the correct value for g_race_qualifying
        float want_qualifying = ((qualifying_override >= 0) ? qualifying_override : autocvar_g_race_qualifying_timelimit) > 0;
 
        if(autocvar_g_campaign)
@@ -449,20 +477,20 @@ void rc_SetLimits()
                g_race_qualifying = 1;
                independent_players = 1;
        }
-       else if(!autocvar_g_campaign && want_qualifying)
+       else if(want_qualifying)
        {
                g_race_qualifying = 2;
                independent_players = 1;
-               race_fraglimit = (race_fraglimit >= 0) ? fraglimit_override : autocvar_fraglimit;
-               race_leadlimit = (race_leadlimit >= 0) ? leadlimit_override : autocvar_leadlimit;
-               race_timelimit = (race_timelimit >= 0) ? timelimit_override : autocvar_timelimit;
+               race_fraglimit = (fraglimit_override >= 0) ? fraglimit_override : autocvar_fraglimit;
+               race_leadlimit = (leadlimit_override >= 0) ? leadlimit_override : autocvar_leadlimit;
+               race_timelimit = (timelimit_override >= 0) ? timelimit_override : autocvar_timelimit;
+               qualifying_override = (qualifying_override >= 0) ? qualifying_override : autocvar_g_race_qualifying_timelimit;
                fraglimit_override = 0;
                leadlimit_override = 0;
-               timelimit_override = autocvar_g_race_qualifying_timelimit;
+               timelimit_override = qualifying_override;
        }
        else
                g_race_qualifying = 0;
-
        SetLimits(fraglimit_override, leadlimit_override, timelimit_override, qualifying_override);
 }