+#include "gamemode_race.qh"
+
#ifndef GAMEMODE_RACE_H
#define GAMEMODE_RACE_H
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();
}
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;
// 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);
}
}
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;
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)
{
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();
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();
}
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;
}
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;