#include "race.qh"
-#include <server/defs.qh>
-#include <server/miscfunctions.qh>
-#include "client.qh"
-#include "portals.qh"
-#include "scores.qh"
-#include "spawnpoints.qh"
-#include "bot/api.qh"
-#include "command/getreplies.qh"
-#include "../common/deathtypes/all.qh"
-#include "../common/notifications/all.qh"
-#include "../common/mapinfo.qh"
+#include <common/deathtypes/all.qh>
+#include <common/gamemodes/_mod.qh>
#include <common/gamemodes/rules.qh>
+#include <common/mapobjects/subs.qh>
+#include <common/mapobjects/triggers.qh>
+#include <common/mutators/mutator/waypoints/waypointsprites.qh>
#include <common/net_linked.qh>
+#include <common/notifications/all.qh>
#include <common/state.qh>
-#include "../common/mapobjects/subs.qh"
-#include <common/mapobjects/triggers.qh>
-#include "../lib/warpzone/util_server.qh"
-#include "../lib/warpzone/common.qh"
-#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
+#include <common/stats.qh>
+#include <common/vehicles/sv_vehicles.qh>
+#include <common/weapons/_all.qh>
+#include <common/weapons/weapon/porto.qh>
+#include <lib/warpzone/common.qh>
+#include <lib/warpzone/util_server.qh>
+#include <server/bot/api.qh>
+#include <server/cheats.qh>
+#include <server/client.qh>
+#include <server/command/getreplies.qh>
+#include <server/damage.qh>
+#include <server/gamelog.qh>
+#include <server/intermission.qh>
+#include <server/main.qh>
+#include <server/mutators/_mod.qh>
+#include <server/portals.qh>
+#include <server/scores.qh>
+#include <server/spawnpoints.qh>
+#include <server/weapons/common.qh>
+#include <server/world.qh>
+
+string uid2name(string myuid)
+{
+ string s = db_get(ServerProgsDB, strcat("/uid2name/", myuid));
+
+ // FIXME remove this later after 0.6 release
+ // convert old style broken records to correct style
+ if(s == "")
+ {
+ s = db_get(ServerProgsDB, strcat("uid2name", myuid));
+ if(s != "")
+ {
+ db_put(ServerProgsDB, strcat("/uid2name/", myuid), s);
+ db_remove(ServerProgsDB, strcat("uid2name", myuid));
+ }
+ }
+
+ if(s == "")
+ s = "^1Unregistered Player";
+ return s;
+}
+
+void write_recordmarker(entity pl, float tstart, float dt)
+{
+ GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
+
+ // also write a marker into demo files for demotc-race-record-extractor to find
+ stuffcmd(pl,
+ strcat(
+ strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
+ " ", ftos(tstart), " ", ftos(dt), "\n"));
+}
IntrusiveList g_race_targets;
-STATIC_INIT(g_race_targets) { g_race_targets = IL_NEW(); }
+IntrusiveList g_racecheckpoints;
+STATIC_INIT(g_race)
+{
+ g_race_targets = IL_NEW();
+ g_racecheckpoints = IL_NEW();
+}
void race_InitSpectator()
{
race_SendNextCheckpoint(msg_entity.enemy, 1);
}
-void W_Porto_Fail(entity this, float failhard);
-
float race_readTime(string map, float pos)
{
string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD));
// player has no ranked record yet
for (i = RANKINGS_CNT; i > newpos; --i)
{
- db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
- db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
+ float other_time = race_readTime(map, i - 1);
+ if (other_time) {
+ db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(other_time));
+ db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
+ }
}
}
const float MAX_CHECKPOINTS = 255;
-spawnfunc(target_checkpoint);
-
.float race_penalty;
.float race_penalty_accumulator;
.string race_penalty_reason;
void checkpoint_passed(entity this, entity player)
{
+ if(IS_VEHICLE(player) && player.owner)
+ player = player.owner;
+
if(player.personal && autocvar_g_allow_checkpoints)
return; // practice mode!
// race only (middle of the race)
g_race_qualifying = false;
pl_race_place = 0;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for respawning in race) - bailing out"));
}
// qualifying only
g_race_qualifying = 1;
pl_race_place = race_lowest_place_spawn;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
}
g_race_qualifying = 0;
for (int p = 1; p <= race_highest_place_spawn; ++p) {
pl_race_place = p;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for initially spawning in race) - bailing out"));
}
}
pl_race_checkpoint = race_NextCheckpoint(0);
g_race_qualifying = 1;
pl_race_place = race_lowest_place_spawn;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
}
} else {
InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
}
-spawnfunc(target_checkpoint) // defrag entity
+void target_checkpoint_setup(entity this)
{
if(!g_race && !g_cts) { delete(this); return; }
defrag_ents = 1;
InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
}
-spawnfunc(target_startTimer) { spawnfunc_target_checkpoint(this); }
-spawnfunc(target_stopTimer) { spawnfunc_target_checkpoint(this); }
+spawnfunc(target_checkpoint)
+{
+ // xonotic defrag entity
+ target_checkpoint_setup(this);
+}
+
+// compatibility entity names
+spawnfunc(target_startTimer) { target_checkpoint_setup(this); }
+spawnfunc(target_stopTimer) { target_checkpoint_setup(this); }
void race_AbandonRaceCheck(entity p)
{