]> 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..3f6a8a85603f6c95dbb7361472d1e457ee5e3b3f 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_QualifyingThenRace(checkrules_fraglimit);
+                       return true;
+               }
+               else if(g_race_qualifying == 2)
+               {
+                       ret_float = WinningCondition_QualifyingThenRace(checkrules_fraglimit);
+                       return true;
+               }
        }
 
        return false;