Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
race.qc File Reference
Include dependency graph for race.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void checkpoint_passed (entity this, entity player)
void checkpoint_touch (entity this, entity toucher)
void checkpoint_use (entity this, entity actor, entity trigger)
void defrag_waypointsprites (entity targeted, entity checkpoint, int recursionlevel)
void penalty_touch (entity this, entity toucher)
void penalty_use (entity this, entity actor, entity trigger)
void race_AbandonRaceCheck (entity p)
void race_checkAndWriteName (entity player)
float race_CheckpointNetworkID (float f)
void race_ClearPlayerRecords (entity player)
void race_ClearRecords ()
void race_ClearTime (entity e)
void race_deleteTime (string map, float pos)
float race_GetFractionalLapCount (entity e)
void race_ImposePenaltyTime (entity pl, float penalty, string reason)
float race_NextCheckpoint (float f)
void race_PreparePlayer (entity this)
float race_PreviousCheckpoint (float f)
string race_readName (string map, float pos)
float race_readPos (string map, float t)
float race_readTime (string map, float pos)
string race_readUID (string map, float pos)
void race_RetractPlayer (entity this)
void race_send_rankings_cnt (float msg)
void race_send_recordtime (float msg)
void race_send_speedaward (float msg)
void race_send_speedaward_alltimebest (float msg)
void race_SendAll (entity player, bool only_rankings)
void race_SendNextCheckpoint (entity e, float spec)
void race_SendRanking (float pos, float prevpos, float del, float msg)
void race_SendStatus (float id, entity e)
void race_SendTime (entity e, float cp, float t, float tvalid)
void race_setTime (string map, float t, string myuid, string mynetname, entity e, bool showmessage)
void race_SpeedAwardFrame (entity player)
void race_StartCompleting ()
bool race_waypointsprite_visible_for_player (entity this, entity player, entity view)
void race_writeTime (string map, float t, string myuid)
 spawnfunc (info_player_race)
 spawnfunc (target_checkpoint)
 spawnfunc (target_startTimer)
 spawnfunc (target_stopTimer)
 spawnfunc (trigger_race_checkpoint)
 spawnfunc (trigger_race_penalty)
void target_checkpoint_setup (entity this)
vector trigger_race_checkpoint_spawn_evalfunc (entity this, entity player, entity spot, vector current)
void trigger_race_checkpoint_verify (entity this)
string uid2name (string myuid)
void write_recordmarker (entity pl, float tstart, float dt)

Variables

float defrag_ents
float defragcpexists
IntrusiveList g_race_targets
IntrusiveList g_racecheckpoints
const float MAX_CHECKPOINTS = 255
float race_checkpoint
float race_checkpoint_lastlaps [MAX_CHECKPOINTS]
entity race_checkpoint_lastplayers [MAX_CHECKPOINTS]
float race_checkpoint_lasttimes [MAX_CHECKPOINTS]
float race_checkpoint_record [MAX_CHECKPOINTS]
string race_checkpoint_recordholders [MAX_CHECKPOINTS]
float race_checkpoint_records [MAX_CHECKPOINTS]
float race_checkpoint_recordspeed [MAX_CHECKPOINTS]
float race_checkpoint_recordspeeds [MAX_CHECKPOINTS]
float race_highest_checkpoint
entity race_lastpenalty
float race_penalty
float race_penalty_accumulator
string race_penalty_reason
float race_timed_checkpoint
entity sprite
string stored_netname

Function Documentation

◆ checkpoint_passed()

void checkpoint_passed ( entity this,
entity player )

Definition at line 695 of file race.qc.

696{
697 if(IS_VEHICLE(player) && player.owner)
698 player = player.owner;
699
700 if(player.personal && autocvar_g_allow_checkpoints)
701 return; // practice mode!
702
703 if(player.classname == "porto")
704 {
705 // do not allow portalling through checkpoints
706 trace_plane_normal = normalize(-1 * player.velocity);
707 W_Porto_Fail(player, 0);
708 return;
709 }
710
711 string oldmsg; // used twice
712
713 /*
714 * Trigger targets
715 */
716 if (!((this.spawnflags & 2) && (IS_PLAYER(player))))
717 {
718 oldmsg = this.message;
719 this.message = "";
720 SUB_UseTargets(this, player, player);
721 this.message = oldmsg;
722 }
723
724 if (!IS_PLAYER(player))
725 return;
726
727 /*
728 * Remove unauthorized equipment
729 */
730 Portal_ClearAll(player);
731
732 player.porto_forbidden = 2; // decreased by 1 each StartFrame
733
734 if(defrag_ents)
735 {
736 if(this.race_checkpoint == -2)
737 {
738 // duplicate targetname target_checkpoints get the same cp nr
739 IL_EACH(g_race_targets, it.classname == "target_checkpoint" && it.targetname == this.targetname, {
740 if(it.race_checkpoint >= 0)
741 this.race_checkpoint = it.race_checkpoint;
742 });
743 if(this.race_checkpoint == -2)
744 this.race_checkpoint = player.race_checkpoint;
745 }
746
747 int cp_amount = 0, largest_cp_id = 0;
748 IL_EACH(g_race_targets, it.classname == "target_checkpoint",
749 {
750 cp_amount += 1;
751 if(it.race_checkpoint > largest_cp_id) // update the finish id if someone hit a new checkpoint
752 {
753 if(!largest_cp_id)
754 {
755 IL_EACH(g_race_targets, it.classname == "target_checkpoint",
756 {
757 if(it.race_checkpoint == -2) // set defragcpexists to -1 so that the cp id file will be rewritten when someone finishes
758 defragcpexists = -1;
759 });
760 }
761
762 largest_cp_id = it.race_checkpoint;
763 IL_EACH(g_race_targets, it.classname == "target_stopTimer",
764 {
765 it.race_checkpoint = largest_cp_id + 1; // finish line
766 });
767 race_highest_checkpoint = largest_cp_id + 1;
768 race_timed_checkpoint = largest_cp_id + 1;
769 }
770 });
771
772 if(!cp_amount)
773 {
774 IL_EACH(g_race_targets, it.classname == "target_stopTimer",
775 {
776 it.race_checkpoint = 1;
777 });
780 }
781 }
782
783 if((player.race_checkpoint == -1 && this.race_checkpoint == 0) || (player.race_checkpoint == this.race_checkpoint))
784 {
785 if(this.race_penalty)
786 {
787 if(player.race_lastpenalty != this)
788 {
789 player.race_lastpenalty = this;
791 }
792 }
793
794 if(player.race_penalty)
795 return;
796
797 /*
798 * Trigger targets
799 */
800 if(this.spawnflags & 2)
801 {
802 oldmsg = this.message;
803 this.message = "";
804 SUB_UseTargets(this, player, player); // TODO: should we be using other for the trigger here?
805 this.message = oldmsg;
806 }
807
808 if(player.race_respawn_checkpoint != this.race_checkpoint || !player.race_started)
809 player.race_respawn_spotref = this; // this is not a spot but a CP, but spawnpoint selection will deal with that
810 player.race_respawn_checkpoint = this.race_checkpoint;
811 player.race_checkpoint = race_NextCheckpoint(this.race_checkpoint);
812 player.race_started = 1;
813
814 race_SendTime(player, this.race_checkpoint, player.race_movetime, boolean(player.race_laptime));
815
816 if(!this.race_checkpoint) // start line
817 {
818 player.race_laptime = time;
819 player.race_movetime = player.race_movetime_frac = player.race_movetime_count = 0;
820 player.race_penalty_accumulator = 0;
821 player.race_lastpenalty = NULL;
822 }
823
825 race_SendNextCheckpoint(player, 0);
826
827 if(defrag_ents && defragcpexists < 0 && this.classname == "target_stopTimer")
828 {
829 float fh;
830 defragcpexists = fh = fopen(strcat("maps/", GetMapname(), ".defragcp"), FILE_WRITE);
831 if(fh >= 0)
832 {
833 IL_EACH(g_race_targets, it.classname == "target_checkpoint",
834 {
835 fputs(fh, strcat(it.targetname, " ", ftos(it.race_checkpoint), "\n"));
836 });
837 }
838 fclose(fh);
839 }
840 }
841 else if(player.race_checkpoint == race_NextCheckpoint(this.race_checkpoint))
842 {
843 // ignored
844 }
845 else
846 {
847 if(this.spawnflags & 4)
848 Damage (player, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, player.origin, '0 0 0');
849 }
850}
string message
Definition powerups.qc:19
int spawnflags
Definition ammo.qh:15
float race_penalty
Definition player.qh:59
#define IS_PLAYER(s)
Definition player.qh:243
string classname
const float FILE_WRITE
float time
vector trace_plane_normal
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:503
#define DMG_NOWEP
Definition damage.qh:104
string GetMapname()
#define IL_EACH(this, cond, body)
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition triggers.qc:344
void fclose(float fhandle)
float fopen(string filename, float mode)
vector normalize(vector v)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Portal_ClearAll(entity own)
Definition portals.qc:588
void W_Porto_Fail(entity this, float failhard)
Definition porto.qc:108
#define NULL
Definition post.qh:14
float race_checkpoint
Definition racetimer.qh:8
float race_highest_checkpoint
Definition race.qc:169
string race_penalty_reason
Definition race.qc:153
void race_SendNextCheckpoint(entity e, float spec)
Definition race.qc:209
float race_timed_checkpoint
Definition race.qc:170
float defragcpexists
Definition race.qc:173
void race_SendTime(entity e, float cp, float t, float tvalid)
Definition race.qc:486
float defrag_ents
Definition race.qc:172
float race_NextCheckpoint(float f)
Definition race.qc:175
IntrusiveList g_race_targets
Definition race.qc:66
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition race.qc:1301
bool autocvar_g_allow_checkpoints
Definition race.qh:3
int g_race_qualifying
Definition race.qh:13
#define IS_VEHICLE(v)
Definition utils.qh:22

References autocvar_g_allow_checkpoints, defrag_ents, entity(), g_race_targets, IL_EACH, IS_PLAYER, IS_VEHICLE, message, normalize(), Portal_ClearAll(), race_checkpoint, race_highest_checkpoint, race_timed_checkpoint, spawnflags, SUB_UseTargets(), trace_plane_normal, and W_Porto_Fail().

Referenced by checkpoint_touch(), and checkpoint_use().

◆ checkpoint_touch()

void checkpoint_touch ( entity this,
entity toucher )

Definition at line 852 of file race.qc.

853{
856}
#define EXACTTRIGGER_TOUCH(e, t)
Definition common.qh:115
entity entity toucher
Definition self.qh:72
void checkpoint_passed(entity this, entity player)
Definition race.qc:695

References checkpoint_passed(), entity(), EXACTTRIGGER_TOUCH, and toucher.

Referenced by spawnfunc(), and target_checkpoint_setup().

◆ checkpoint_use()

void checkpoint_use ( entity this,
entity actor,
entity trigger )

Definition at line 858 of file race.qc.

859{
860 if(trigger.classname == "info_player_deathmatch") // a spawn, a spawn
861 return;
862
863 checkpoint_passed(this, actor);
864}

References checkpoint_passed(), and entity().

Referenced by spawnfunc(), and target_checkpoint_setup().

◆ defrag_waypointsprites()

void defrag_waypointsprites ( entity targeted,
entity checkpoint,
int recursionlevel )

Definition at line 880 of file race.qc.

881{
882 // bones_was_here: spawn a waypoint for every entity with a bmodel
883 // that directly or indirectly targets this checkpoint
884 // (anything a player could touch or shoot to activate this cp)
885
886 // spam a few warnings so that larger link chain loops can be found
887 if (recursionlevel > 400)
888 {
889 LOG_WARNF("df cp wp loop: ^4\"target\" ^3\"%s\"^7, ^4\"targetname\" ^3\"%s\"^7",
890 targeted.classname,
891 targeted.targetname);
892 }
893 // avoid a stack overflow
894 if (recursionlevel > 420)
895 {
896 LOG_WARNF("Aborted creating defrag checkpoint waypointsprites for ^2%s^7 due to a loop",
897 checkpoint.classname);
898 return;
899 }
900
901 entity s = WP_RaceCheckpoint;
902 if (checkpoint.classname == "target_startTimer")
903 s = WP_RaceStart;
904 else if (checkpoint.classname == "target_stopTimer")
905 s = WP_RaceFinish;
906
907 for (entity t = findchain(target, targeted.targetname); t; t = t.chain)
908 {
909 if (t.modelindex)
910 {
911 WaypointSprite_SpawnFixed(s, (t.absmin + t.absmax) * 0.5, t, sprite, RADARICON_NONE);
912 t.sprite.realowner = checkpoint;
913 t.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
914 }
915
916 if (t.targetname && t != checkpoint)
917 defrag_waypointsprites(t, checkpoint, ++recursionlevel);
918 }
919}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define LOG_WARNF(...)
Definition log.qh:62
bool race_waypointsprite_visible_for_player(entity this, entity player, entity view)
Definition race.qc:866
void defrag_waypointsprites(entity targeted, entity checkpoint, int recursionlevel)
Definition race.qc:880
entity sprite
Definition sv_assault.qc:11
string target
Definition triggers.qh:55
entity WaypointSprite_SpawnFixed(entity spr, vector ofs, entity own,.entity ownfield, entity icon)

References defrag_waypointsprites(), entity(), LOG_WARNF, race_waypointsprite_visible_for_player(), sprite, target, and WaypointSprite_SpawnFixed().

Referenced by defrag_waypointsprites().

◆ penalty_touch()

void penalty_touch ( entity this,
entity toucher )

Definition at line 1333 of file race.qc.

1334{
1336 if(toucher.race_lastpenalty != this)
1337 {
1338 toucher.race_lastpenalty = this;
1340 }
1341}

References entity(), EXACTTRIGGER_TOUCH, race_ImposePenaltyTime(), race_penalty, race_penalty_reason, and toucher.

Referenced by spawnfunc().

◆ penalty_use()

void penalty_use ( entity this,
entity actor,
entity trigger )

Definition at line 1343 of file race.qc.

1344{
1346}

References entity(), race_ImposePenaltyTime(), race_penalty, and race_penalty_reason.

Referenced by spawnfunc().

◆ race_AbandonRaceCheck()

void race_AbandonRaceCheck ( entity p)

Definition at line 1229 of file race.qc.

1230{
1232 {
1233 CS(p).race_completed = 1;
1235 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_ABANDONED, p.netname);
1236 ClientData_Touch(p, true);
1237 }
1238}
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
void ClientData_Touch(entity e, bool to_spectators_too)
Definition client.qc:185
#define MAKE_INDEPENDENT_PLAYER(e)
Definition client.qh:313
float race_completed
Definition race.qh:26
float race_completing
Definition race.qh:28
ClientState CS(Client this)
Definition state.qh:47

References ClientData_Touch(), CS(), entity(), MAKE_INDEPENDENT_PLAYER, NULL, race_completed, race_completing, and Send_Notification().

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and race_StartCompleting().

◆ race_checkAndWriteName()

void race_checkAndWriteName ( entity player)

Definition at line 134 of file race.qc.

135{
136 if(CS_CVAR(player).cvar_cl_allow_uidtracking == 1 && CS_CVAR(player).cvar_cl_allow_uid2name == 1)
137 {
138 if (!player.stored_netname)
139 player.stored_netname = strzone(uid2name(player.crypto_idfp));
140 if(player.stored_netname != player.netname)
141 {
142 db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
143 strcpy(player.stored_netname, player.netname);
144 }
145 }
146}
ERASEABLE void db_put(int db, string key, string value)
Definition map.qh:101
string strzone(string s)
string uid2name(string myuid)
Definition race.qc:36
#define CS_CVAR(this)
Definition state.qh:51
#define strcpy(this, s)
Definition string.qh:52
float ServerProgsDB
Definition world.qh:128

References CS_CVAR, db_put(), entity(), ServerProgsDB, strcat(), strcpy, strzone(), and uid2name().

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ race_CheckpointNetworkID()

float race_CheckpointNetworkID ( float f)

Definition at line 197 of file race.qc.

198{
200 {
201 if(f == 0)
202 return 254; // start
203 else if(f == race_timed_checkpoint)
204 return 255; // finish
205 }
206 return f;
207}

References race_timed_checkpoint.

Referenced by race_SendNextCheckpoint(), and race_SendTime().

◆ race_ClearPlayerRecords()

void race_ClearPlayerRecords ( entity player)

Definition at line 1276 of file race.qc.

1277{
1278 for(int i = 0; i < MAX_CHECKPOINTS; ++i)
1279 {
1280 player.race_checkpoint_record[i] = 0;
1281 player.race_checkpoint_recordspeed[i] = 0;
1282 }
1283}
const float MAX_CHECKPOINTS
Definition race.qc:149

References entity(), and MAX_CHECKPOINTS.

Referenced by ClientCommand_clear_bestcptimes().

◆ race_ClearRecords()

void race_ClearRecords ( )

Definition at line 1285 of file race.qc.

1286{
1287 for(int j = 0; j < MAX_CHECKPOINTS; ++j)
1288 {
1292 }
1293
1294 FOREACH_CLIENT(true, {
1295 float p = it.race_place;
1297 it.race_place = p;
1298 });
1299}
float race_checkpoint_recordspeeds[MAX_CHECKPOINTS]
Definition race.qc:160
void race_PreparePlayer(entity this)
Definition race.qc:1246
float race_checkpoint_records[MAX_CHECKPOINTS]
Definition race.qc:159
string race_checkpoint_recordholders[MAX_CHECKPOINTS]
Definition race.qc:161
#define strfree(this)
Definition string.qh:59
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50

References FOREACH_CLIENT, MAX_CHECKPOINTS, race_checkpoint_recordholders, race_checkpoint_records, race_checkpoint_recordspeeds, race_PreparePlayer(), and strfree.

Referenced by MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ race_ClearTime()

void race_ClearTime ( entity e)

Definition at line 677 of file race.qc.

678{
679 e.race_checkpoint = 0;
680 e.race_laptime = 0;
681 e.race_movetime = e.race_movetime_frac = e.race_movetime_count = 0;
682 e.race_penalty_accumulator = 0;
683 e.race_lastpenalty = NULL;
684
685 if(!IS_REAL_CLIENT(e))
686 return;
687
688 msg_entity = e;
689 WRITESPECTATABLE_MSG_ONE(msg_entity, {
690 WriteHeader(MSG_ONE, TE_CSQC_RACE);
692 });
693}
#define WriteHeader(to, id)
Definition net.qh:221
float MSG_ONE
Definition menudefs.qc:56
void WriteByte(float data, float dest, float desto)
const int RACE_NET_CHECKPOINT_CLEAR
Definition net_linked.qh:12
entity msg_entity
Definition progsdefs.qc:63
#define IS_REAL_CLIENT(v)
Definition utils.qh:17

References entity(), IS_REAL_CLIENT, msg_entity, MSG_ONE, NULL, RACE_NET_CHECKPOINT_CLEAR, WriteByte(), and WriteHeader.

Referenced by race_PreparePlayer(), and race_RetractPlayer().

◆ race_deleteTime()

void race_deleteTime ( string map,
float pos )

Definition at line 462 of file race.qc.

463{
464 for(int i = pos; i <= RANKINGS_CNT; ++i)
465 {
466 string therank = ftos(i);
467 if (i == RANKINGS_CNT)
468 {
469 db_remove(ServerProgsDB, strcat(map, record_type, "time", therank));
470 db_remove(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank));
471 }
472 else
473 {
474 db_put(ServerProgsDB, strcat(map, record_type, "time", therank), ftos(race_readTime(GetMapname(), i+1)));
475 db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank), race_readUID(GetMapname(), i+1));
476 }
477 }
478
479 race_SendRanking(pos, 0, 1, MSG_ALL);
480 if(pos == 1)
482
484}
string rankings_reply
Definition util.qh:161
const int RANKINGS_CNT
Definition constants.qh:31
string getrankings()
Definition getreplies.qc:46
#define db_remove(db, key)
Definition map.qh:98
string ftos(float f)
float MSG_ALL
Definition menudefs.qc:57
void race_SendRanking(float pos, float prevpos, float del, float msg)
Definition race.qc:294
float race_readTime(string map, float pos)
Definition race.qc:69
void race_send_recordtime(float msg)
Definition race.qc:260
string race_readUID(string map, float pos)
Definition race.qc:74
string record_type
Definition world.qh:55

References db_put(), db_remove, ftos(), GetMapname(), getrankings(), MSG_ALL, race_readTime(), race_readUID(), race_send_recordtime(), race_SendRanking(), RANKINGS_CNT, rankings_reply, record_type, ServerProgsDB, strcat(), and strcpy.

Referenced by GameCommand_delrec().

◆ race_GetFractionalLapCount()

float race_GetFractionalLapCount ( entity e)

Definition at line 1365 of file race.qc.

1366{
1367 // interesting metrics (idea by KrimZon) to maybe sort players in the
1368 // scoreboard, immediately updates when overtaking
1369 //
1370 // requires the track to be built so you never get farther away from the
1371 // next checkpoint, though, and current Xonotic race maps are not built that
1372 // way
1373 //
1374 // also, this code is slow and would need optimization (i.e. "next CP"
1375 // links on CP entities)
1376
1377 float l;
1378 l = GameRules_scoring_add(e, RACE_LAPS, 0);
1379 if(CS(e).race_completed)
1380 return l; // not fractional
1381
1382 vector o0, o1;
1383 float bestfraction, fraction;
1384 entity lastcp;
1385 float nextcpindex, lastcpindex;
1386
1387 nextcpindex = max(e.race_checkpoint, 0);
1388 lastcpindex = e.race_respawn_checkpoint;
1389 lastcp = e.race_respawn_spotref;
1390
1391 if(nextcpindex == lastcpindex)
1392 return l; // finish
1393
1394 bestfraction = 1;
1396 {
1397 if(it.race_checkpoint != lastcpindex)
1398 continue;
1399 if(lastcp)
1400 if(it != lastcp)
1401 continue;
1402 o0 = (it.absmin + it.absmax) * 0.5;
1404 {
1405 if(it.race_checkpoint != nextcpindex)
1406 continue;
1407 o1 = (it.absmin + it.absmax) * 0.5;
1408 if(o0 == o1)
1409 continue;
1410 fraction = bound(0.0001, vlen(e.origin - o1) / vlen(o0 - o1), 1);
1411 if(fraction < bestfraction)
1412 bestfraction = fraction;
1413 });
1414 });
1415
1416 // we are at CP "nextcpindex - bestfraction"
1417 // race_timed_checkpoint == 4: then nextcp==4 means 0.9999x, nextcp==0 means 0.0000x
1418 // race_timed_checkpoint == 0: then nextcp==0 means 0.9999x
1419 float c, nc;
1420 nc = race_highest_checkpoint + 1;
1421 c = ((nextcpindex - race_timed_checkpoint + nc + nc - 1) % nc) + 1 - bestfraction;
1422
1423 return l + c / nc;
1424}
float bound(float min, float value, float max)
float vlen(vector v)
float max(float f,...)
vector
Definition self.qh:92
IntrusiveList g_racecheckpoints
Definition race.qc:67
#define GameRules_scoring_add(client, fld, value)
Definition sv_rules.qh:85

References bound(), CS(), entity(), g_racecheckpoints, GameRules_scoring_add, IL_EACH, max(), race_completed, race_highest_checkpoint, race_timed_checkpoint, vector, and vlen().

◆ race_ImposePenaltyTime()

void race_ImposePenaltyTime ( entity pl,
float penalty,
string reason )

Definition at line 1301 of file race.qc.

1302{
1304 {
1305 pl.race_penalty_accumulator += penalty;
1306 if(IS_REAL_CLIENT(pl))
1307 {
1308 msg_entity = pl;
1309 WRITESPECTATABLE_MSG_ONE(msg_entity, {
1310 WriteHeader(MSG_ONE, TE_CSQC_RACE);
1312 WriteShort(MSG_ONE, TIME_ENCODE(penalty));
1313 WriteString(MSG_ONE, reason);
1314 });
1315 }
1316 }
1317 else
1318 {
1319 pl.race_penalty = time + penalty;
1320 if(IS_REAL_CLIENT(pl))
1321 {
1322 msg_entity = pl;
1323 WRITESPECTATABLE_MSG_ONE(msg_entity, {
1324 WriteHeader(MSG_ONE, TE_CSQC_RACE);
1326 WriteShort(MSG_ONE, TIME_ENCODE(penalty));
1327 WriteString(MSG_ONE, reason);
1328 });
1329 }
1330 }
1331}
#define TIME_ENCODE(t)
Definition util.qh:100
void WriteString(string data, float dest, float desto)
void WriteShort(float data, float dest, float desto)
const int RACE_NET_PENALTY_RACE
Definition net_linked.qh:17
const int RACE_NET_PENALTY_QUALIFYING
Definition net_linked.qh:18

References entity(), g_race_qualifying, IS_REAL_CLIENT, msg_entity, MSG_ONE, RACE_NET_PENALTY_QUALIFYING, RACE_NET_PENALTY_RACE, time, TIME_ENCODE, WriteByte(), WriteHeader, WriteShort(), and WriteString().

Referenced by CheatCommand(), penalty_touch(), and penalty_use().

◆ race_NextCheckpoint()

float race_NextCheckpoint ( float f)

Definition at line 175 of file race.qc.

176{
178 return 0;
179 else
180 return f + 1;
181}

References race_highest_checkpoint.

Referenced by havocbot_role_cts(), havocbot_role_race(), and trigger_race_checkpoint_verify().

◆ race_PreparePlayer()

void race_PreparePlayer ( entity this)

◆ race_PreviousCheckpoint()

float race_PreviousCheckpoint ( float f)

Definition at line 183 of file race.qc.

184{
185 if(f == -1)
186 return 0;
187 else if(f == 0)
189 else
190 return f - 1;
191}

References race_highest_checkpoint.

◆ race_readName()

string race_readName ( string map,
float pos )

Definition at line 129 of file race.qc.

130{
131 return uid2name(db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos))));
132}
ERASEABLE string db_get(int db, string key)
Definition map.qh:91

References db_get(), ftos(), record_type, ServerProgsDB, strcat(), and uid2name().

Referenced by getrankings(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), race_SendRanking(), and race_setTime().

◆ race_readPos()

float race_readPos ( string map,
float t )

Definition at line 79 of file race.qc.

80{
81 for(int i = 1; i <= RANKINGS_CNT; ++i)
82 {
83 int mytime = race_readTime(map, i);
84 if(!mytime || mytime > t)
85 return i;
86 }
87
88 return 0; // pos is zero if unranked
89}

References race_readTime(), and RANKINGS_CNT.

Referenced by race_setTime(), and race_writeTime().

◆ race_readTime()

float race_readTime ( string map,
float pos )

◆ race_readUID()

string race_readUID ( string map,
float pos )

Definition at line 74 of file race.qc.

75{
76 return db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos)));
77}

References db_get(), ftos(), record_type, ServerProgsDB, and strcat().

Referenced by getladder(), race_deleteTime(), race_setTime(), and race_writeTime().

◆ race_RetractPlayer()

void race_RetractPlayer ( entity this)

Definition at line 1255 of file race.qc.

1256{
1257 if(!g_race && !g_cts)
1258 return;
1260 race_ClearTime(this);
1262}
#define g_race
Definition race.qh:48
#define g_cts
Definition cts.qh:36

References entity(), g_cts, g_race, race_checkpoint, race_ClearTime(), race_respawn_checkpoint, and race_timed_checkpoint.

Referenced by MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ race_send_rankings_cnt()

void race_send_rankings_cnt ( float msg)

Definition at line 286 of file race.qc.

287{
288 WriteHeader(msg, TE_CSQC_RACE);
291 WriteByte(msg, m);
292}
float min(float f,...)
const int RACE_NET_RANKINGS_CNT
Definition net_linked.qh:26
int autocvar_g_cts_send_rankings_cnt
Definition race.qh:10

References autocvar_g_cts_send_rankings_cnt, min(), RACE_NET_RANKINGS_CNT, RANKINGS_CNT, WriteByte(), and WriteHeader.

Referenced by race_SendAll().

◆ race_send_recordtime()

void race_send_recordtime ( float msg)

Definition at line 260 of file race.qc.

261{
262 // send the server best time
263 WriteHeader(msg, TE_CSQC_RACE);
265 WriteInt24_t(msg, race_readTime(GetMapname(), 1));
266}
const int RACE_NET_SERVER_RECORD
Definition net_linked.qh:19

References GetMapname(), RACE_NET_SERVER_RECORD, race_readTime(), WriteByte(), and WriteHeader.

Referenced by race_deleteTime(), race_SendAll(), and race_setTime().

◆ race_send_speedaward()

void race_send_speedaward ( float msg)

Definition at line 268 of file race.qc.

269{
270 // send the best speed of the round
271 WriteHeader(msg, TE_CSQC_RACE);
273 WriteInt24_t(msg, floor(speedaward_speed+0.5));
275}
float floor(float f)
const int RACE_NET_SPEED_AWARD
Definition net_linked.qh:20
float speedaward_speed
Definition race.qh:59
string speedaward_holder
Definition race.qh:60

References floor(), RACE_NET_SPEED_AWARD, speedaward_holder, speedaward_speed, WriteByte(), WriteHeader, and WriteString().

Referenced by race_SendAll(), and race_SpeedAwardFrame().

◆ race_send_speedaward_alltimebest()

void race_send_speedaward_alltimebest ( float msg)

Definition at line 277 of file race.qc.

278{
279 // send the best speed
280 WriteHeader(msg, TE_CSQC_RACE);
282 WriteInt24_t(msg, floor(speedaward_alltimebest+0.5));
284}
const int RACE_NET_SPEED_AWARD_BEST
Definition net_linked.qh:21
float speedaward_alltimebest
Definition race.qh:63
string speedaward_alltimebest_holder
Definition race.qh:64

References floor(), RACE_NET_SPEED_AWARD_BEST, speedaward_alltimebest, speedaward_alltimebest_holder, WriteByte(), WriteHeader, and WriteString().

Referenced by race_SendAll(), and race_SpeedAwardFrame().

◆ race_SendAll()

◆ race_SendNextCheckpoint()

void race_SendNextCheckpoint ( entity e,
float spec )

Definition at line 209 of file race.qc.

210{
211 if(!e.race_laptime)
212 return;
213
214 int cp = e.race_checkpoint;
215 float recordtime;
216 float recordspeed;
217 float myrecordtime = e.race_checkpoint_record[cp];
218 float myrecordspeed = e.race_checkpoint_recordspeed[cp];
219 string recordholder;
221 recordtime = myrecordtime;
222 recordspeed = myrecordspeed;
223 recordholder = "";
224 } else {
225 recordtime = race_checkpoint_records[cp];
226 recordspeed = race_checkpoint_recordspeeds[cp];
227 recordholder = race_checkpoint_recordholders[cp];
228
229 if(recordholder == e.netname)
230 recordholder = "";
231 }
232
233 if(!IS_REAL_CLIENT(e))
234 return;
235
236 if(!spec)
237 msg_entity = e;
238 WRITESPECTATABLE_MSG_ONE(msg_entity, {
239 WriteHeader(MSG_ONE, TE_CSQC_RACE);
240 if(spec)
241 {
243 //WriteCoord(MSG_ONE, e.race_laptime - e.race_penalty_accumulator);
244 WriteCoord(MSG_ONE, time - e.race_movetime - e.race_penalty_accumulator);
245 }
246 else
248 WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player will be at next
249 WriteInt24_t(MSG_ONE, recordtime);
250 if(!spec)
251 WriteInt24_t(MSG_ONE, myrecordtime);
252 WriteString(MSG_ONE, recordholder);
253 // All speeds networked as floats to have decimal precision
254 WriteFloat(MSG_ONE, recordspeed);
255 if(!spec)
256 WriteFloat(MSG_ONE, myrecordspeed);
257 });
258}
void WriteCoord(float data, float dest, float desto)
const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING
Definition net_linked.qh:13
const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING
Definition net_linked.qh:16
float race_CheckpointNetworkID(float f)
Definition race.qc:197
bool autocvar_g_race_cptimes_onlyself
Definition race.qh:11

References autocvar_g_race_cptimes_onlyself, entity(), IS_REAL_CLIENT, msg_entity, MSG_ONE, race_checkpoint_recordholders, race_checkpoint_records, race_checkpoint_recordspeeds, race_CheckpointNetworkID(), RACE_NET_CHECKPOINT_NEXT_QUALIFYING, RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING, time, WriteByte(), WriteCoord(), WriteHeader, and WriteString().

Referenced by SetSpectatee_status().

◆ race_SendRanking()

void race_SendRanking ( float pos,
float prevpos,
float del,
float msg )

Definition at line 294 of file race.qc.

295{
296 WriteHeader(msg, TE_CSQC_RACE);
298 WriteShort(msg, pos);
299 WriteShort(msg, prevpos);
300 WriteShort(msg, del);
302 WriteInt24_t(msg, race_readTime(GetMapname(), pos));
303}
const int RACE_NET_SERVER_RANKINGS
Definition net_linked.qh:22
string race_readName(string map, float pos)
Definition race.qc:129

References GetMapname(), RACE_NET_SERVER_RANKINGS, race_readName(), race_readTime(), WriteByte(), WriteHeader, WriteShort(), and WriteString().

Referenced by race_deleteTime(), race_SendAll(), and race_setTime().

◆ race_SendStatus()

void race_SendStatus ( float id,
entity e )

Definition at line 355 of file race.qc.

356{
357 if(!IS_REAL_CLIENT(e))
358 return;
359
360 float msg;
361 if (id == 0)
362 msg = MSG_ONE;
363 else
364 msg = MSG_ALL;
365 msg_entity = e;
366 WRITESPECTATABLE_MSG_ONE(msg_entity, {
367 WriteHeader(msg, TE_CSQC_RACE);
369 WriteShort(msg, id);
370 WriteString(msg, e.netname);
371 });
372}
const int RACE_NET_SERVER_STATUS
Definition net_linked.qh:23

References entity(), IS_REAL_CLIENT, MSG_ALL, msg_entity, MSG_ONE, RACE_NET_SERVER_STATUS, WriteByte(), WriteHeader, WriteShort(), and WriteString().

Referenced by race_setTime().

◆ race_SendTime()

void race_SendTime ( entity e,
float cp,
float t,
float tvalid )

Definition at line 486 of file race.qc.

487{
489 t += e.race_penalty_accumulator;
490
491 t = TIME_ENCODE(t); // make integer
492
493 if(tvalid)
494 if(cp == race_timed_checkpoint) // finish line
495 if (!CS(e).race_completed)
496 {
497 int s = GameRules_scoring_add(e, RACE_FASTEST, 0);
498 if(!s || t < s)
499 GameRules_scoring_add(e, RACE_FASTEST, t - s);
501 {
502 s = GameRules_scoring_add(e, RACE_TIME, 0);
503 int snew = TIME_ENCODE(time - game_starttime);
504 GameRules_scoring_add(e, RACE_TIME, snew - s);
505 int l = GameRules_scoring_add_team(e, RACE_LAPS, 1);
506
508 if(l >= autocvar_fraglimit)
510
512 {
513 CS(e).race_completed = 1;
515 if(e.bot_attack)
517 e.bot_attack = false;
518 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FINISHED, e.netname);
519 ClientData_Touch(e, true);
520 }
521 }
522 }
523
525 {
526 float recordtime;
527 float recordtimespeed;
528 string recordholder;
529
530 if(tvalid)
531 {
533 {
534 // return their own checkpoint time
535 recordtime = e.race_checkpoint_record[cp];
536 recordtimespeed = e.race_checkpoint_recordspeed[cp];
537 recordholder = "";
538 }
539 else
540 {
541 recordtime = race_checkpoint_records[cp];
542 recordtimespeed = race_checkpoint_recordspeeds[cp];
543 // make a tempstring copy, as we'll possibly strunzone it
544 recordholder = strcat(race_checkpoint_recordholders[cp]);
545
546 if(recordholder == e.netname)
547 recordholder = "";
548 }
549
550 if(t != 0)
551 {
552 if(cp == race_timed_checkpoint)
553 {
554 race_setTime(GetMapname(), t, e.crypto_idfp, e.netname, e, true);
555 MUTATOR_CALLHOOK(Race_FinalCheckpoint, e);
556 }
557
558 if(t < recordtime || recordtime == 0)
559 {
561 race_checkpoint_recordspeeds[cp] = vlen(vec2(e.velocity));
564 FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.race_checkpoint == cp, { race_SendNextCheckpoint(it, 0); });
565 }
566
567 }
568 }
569 else
570 {
571 // dummies
572 t = 0;
573 recordtime = 0;
574 recordtimespeed = 0;
575 recordholder = "";
576 }
577
578 if(IS_REAL_CLIENT(e))
579 {
581 {
583 {
584 if(it == e || (IS_SPEC(it) && it.enemy == e))
585 {
586 msg_entity = it;
587 WriteHeader(MSG_ONE, TE_CSQC_RACE);
589 WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
590 WriteInt24_t(MSG_ONE, t); // time to that checkpoint
591 WriteInt24_t(MSG_ONE, recordtime); // previously best time
592 WriteInt24_t(MSG_ONE, ((tvalid) ? it.race_checkpoint_record[cp] : 0)); // previously best time
593 WriteString(MSG_ONE, recordholder); // record holder
594 // All speeds networked as floats to have decimal precision
595 WriteFloat(MSG_ONE, vlen(vec2(e.velocity))); // speed of cp hit
596 WriteFloat(MSG_ONE, recordtimespeed); // speed of previous best cp hit
597 WriteFloat(MSG_ONE, ((tvalid) ? it.race_checkpoint_recordspeed[cp] : 0)); // speed of my previous best cp hit
598 }
599 });
600 }
601 }
602 // check if new pb should be set for a checkpoint
603 if(tvalid)
604 {
605 float myrecordtime = e.race_checkpoint_record[cp];
606 if(t != 0)
607 if(t < myrecordtime || myrecordtime == 0)
608 {
609 e.race_checkpoint_record[cp] = t;
610 e.race_checkpoint_recordspeed[cp] = vlen(vec2(e.velocity));
611 }
612 }
613 }
614 else // RACE! Not Qualifying
615 {
616 float mylaps, lother, othtime;
618 if(oth)
619 {
620 mylaps = GameRules_scoring_add(e, RACE_LAPS, 0);
621 lother = race_checkpoint_lastlaps[cp];
622 othtime = race_checkpoint_lasttimes[cp];
623 }
624 else
625 mylaps = lother = othtime = 0;
626
627 if(IS_REAL_CLIENT(e))
628 {
629 msg_entity = e;
630 WRITESPECTATABLE_MSG_ONE(msg_entity, {
631 WriteHeader(MSG_ONE, TE_CSQC_RACE);
633 WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
634 if(e == oth)
635 {
636 WriteInt24_t(MSG_ONE, 0);
637 WriteByte(MSG_ONE, 0);
638 WriteByte(MSG_ONE, 0);
639 }
640 else
641 {
643 WriteByte(MSG_ONE, mylaps - lother);
644 WriteByte(MSG_ONE, etof(oth)); // record holder
645 }
646 });
647 }
648
651 race_checkpoint_lastlaps[cp] = mylaps;
652
653 if(IS_REAL_CLIENT(oth))
654 {
655 msg_entity = oth;
656 WRITESPECTATABLE_MSG_ONE(msg_entity, {
657 WriteHeader(MSG_ONE, TE_CSQC_RACE);
659 WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
660 if(e == oth)
661 {
662 WriteInt24_t(MSG_ONE, 0);
663 WriteByte(MSG_ONE, 0);
664 WriteByte(MSG_ONE, 0);
665 }
666 else
667 {
668 WriteInt24_t(MSG_ONE, TIME_ENCODE(time - othtime));
669 WriteByte(MSG_ONE, lother - mylaps);
670 WriteByte(MSG_ONE, etof(e) - 1); // record holder
671 }
672 });
673 }
674 }
675}
IntrusiveList g_bot_targets
Definition api.qh:149
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define autocvar_fraglimit
Definition stats.qh:90
float game_starttime
Definition stats.qh:82
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
#define etof(e)
Definition misc.qh:25
const int RACE_NET_CHECKPOINT_HIT_QUALIFYING
Definition net_linked.qh:11
const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT
Definition net_linked.qh:15
const int RACE_NET_CHECKPOINT_HIT_RACE
Definition net_linked.qh:14
float race_checkpoint_lastlaps[MAX_CHECKPOINTS]
Definition race.qc:163
void race_StartCompleting()
Definition race.qc:1240
entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]
Definition race.qc:164
void race_setTime(string map, float t, string myuid, string mynetname, entity e, bool showmessage)
Definition race.qc:374
float race_checkpoint_lasttimes[MAX_CHECKPOINTS]
Definition race.qc:162
#define GameRules_scoring_add_team(client, fld, value)
Definition sv_rules.qh:89
#define IS_SPEC(v)
Definition utils.qh:10
#define vec2(...)
Definition vector.qh:90

References autocvar_fraglimit, autocvar_g_race_cptimes_onlyself, ClientData_Touch(), CS(), entity(), etof, FOREACH_CLIENT, g_bot_targets, g_race_qualifying, game_starttime, GameRules_scoring_add, GameRules_scoring_add_team, GetMapname(), IL_REMOVE(), IS_PLAYER, IS_REAL_CLIENT, IS_SPEC, MAKE_INDEPENDENT_PLAYER, msg_entity, MSG_ONE, MUTATOR_CALLHOOK, NULL, race_checkpoint_lastlaps, race_checkpoint_lastplayers, race_checkpoint_lasttimes, race_checkpoint_recordholders, race_checkpoint_records, race_checkpoint_recordspeeds, race_CheckpointNetworkID(), race_completed, race_completing, RACE_NET_CHECKPOINT_HIT_QUALIFYING, RACE_NET_CHECKPOINT_HIT_RACE, RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT, race_setTime(), race_StartCompleting(), race_timed_checkpoint, Send_Notification(), strcat(), strcpy, time, TIME_ENCODE, vec2, vlen(), WriteByte(), WriteHeader, and WriteString().

◆ race_setTime()

void race_setTime ( string map,
float t,
string myuid,
string mynetname,
entity e,
bool showmessage )

Definition at line 374 of file race.qc.

375{
376 // netname only used TEMPORARILY for printing
377 int newpos = race_readPos(map, t);
378
379 int player_prevpos = 0;
380 for(int i = 1; i <= RANKINGS_CNT; ++i)
381 {
382 if(race_readUID(map, i) == myuid)
383 player_prevpos = i;
384 }
385
386 float oldrec;
387 string oldrec_holder;
388 if (player_prevpos && (player_prevpos < newpos || !newpos))
389 {
390 oldrec = race_readTime(GetMapname(), player_prevpos);
391 race_SendStatus(0, e); // "fail"
392 if(showmessage)
393 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec);
394 return;
395 }
396 else if (!newpos)
397 {
398 // no ranking, time worse than the worst ranked
400 race_SendStatus(0, e); // "fail"
401 if(showmessage)
402 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec);
403 return;
404 }
405
406 // if we didn't hit a return yet, we have a new record!
407
408 // if the player does not have a UID we can unfortunately not store the record, as the rankings system relies on UIDs
409 if(myuid == "")
410 {
411 if(showmessage)
412 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t);
413 return;
414 }
415
416 if(CS_CVAR(e).cvar_cl_allow_uidtracking != 1 || CS_CVAR(e).cvar_cl_allow_uid2name != 1
417 || uid2name(myuid) == "^1Unregistered Player")
418 {
419 if(showmessage)
420 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_NAME, mynetname, t);
421 return;
422 }
423
424 oldrec = race_readTime(GetMapname(), newpos);
425 oldrec_holder = race_readName(GetMapname(), newpos);
426
427 // store new ranking
428 race_writeTime(GetMapname(), t, myuid);
429
430 if (newpos == 1 && showmessage)
431 {
434 }
435
436 race_SendRanking(newpos, player_prevpos, 0, MSG_ALL);
438
439 if(newpos == player_prevpos)
440 {
441 if(showmessage)
442 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec);
443 if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
444 else { race_SendStatus(1, e); } // "new time"
445 }
446 else if(oldrec == 0)
447 {
448 if(showmessage)
449 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t);
450 if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
451 else { race_SendStatus(2, e); } // "new rank"
452 }
453 else
454 {
455 if(showmessage)
456 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec);
457 if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
458 else { race_SendStatus(2, e); } // "new rank"
459 }
460}
#define TIME_DECODE(n)
Definition util.qh:101
void write_recordmarker(entity pl, float tstart, float dt)
Definition race.qc:57
float race_readPos(string map, float t)
Definition race.qc:79
void race_SendStatus(float id, entity e)
Definition race.qc:355
void race_writeTime(string map, float t, string myuid)
Definition race.qc:91

References CS_CVAR, entity(), GetMapname(), getrankings(), MSG_ALL, NULL, race_readName(), race_readPos(), race_readTime(), race_readUID(), race_send_recordtime(), race_SendRanking(), race_SendStatus(), race_writeTime(), RANKINGS_CNT, rankings_reply, Send_Notification(), strcpy, time, TIME_DECODE, uid2name(), and write_recordmarker().

Referenced by ctf_CaptureRecord(), and race_SendTime().

◆ race_SpeedAwardFrame()

void race_SpeedAwardFrame ( entity player)

Definition at line 305 of file race.qc.

306{
307 if (IS_OBSERVER(player))
308 return;
309
310 if(vdist(player.velocity - player.velocity_z * '0 0 1', >, speedaward_speed))
311 {
312 speedaward_speed = vlen(player.velocity - player.velocity_z * '0 0 1');
313 speedaward_holder = player.netname;
314 speedaward_uid = player.crypto_idfp;
316 }
318 {
322 {
329 }
330 }
331}
bool intermission_running
float speedaward_lastupdate
Definition race.qh:16
string speedaward_alltimebest_uid
Definition race.qh:65
string speedaward_uid
Definition race.qh:61
float speedaward_lastsent
Definition race.qh:15
#define IS_OBSERVER(v)
Definition utils.qh:11
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8

References db_put(), entity(), ftos(), GetMapname(), intermission_running, IS_OBSERVER, MSG_ALL, race_send_speedaward(), race_send_speedaward_alltimebest(), record_type, ServerProgsDB, speedaward_alltimebest, speedaward_alltimebest_holder, speedaward_alltimebest_uid, speedaward_holder, speedaward_lastsent, speedaward_lastupdate, speedaward_speed, speedaward_uid, strcat(), time, vdist, and vlen().

Referenced by MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ race_StartCompleting()

void race_StartCompleting ( )

Definition at line 1240 of file race.qc.

1241{
1242 race_completing = 1;
1244}
#define IS_DEAD(s)
Definition player.qh:245
void race_AbandonRaceCheck(entity p)
Definition race.qc:1229

References FOREACH_CLIENT, IS_DEAD, IS_PLAYER, race_AbandonRaceCheck(), and race_completing.

Referenced by InitiateSuddenDeath(), and race_SendTime().

◆ race_waypointsprite_visible_for_player()

bool race_waypointsprite_visible_for_player ( entity this,
entity player,
entity view )

Definition at line 866 of file race.qc.

867{
868 entity own = this.owner;
869 if(this.realowner)
870 own = this.realowner; // target support
871
872 if(view.race_checkpoint == -1 || own.race_checkpoint == -2)
873 return true;
874 else if(view.race_checkpoint == own.race_checkpoint)
875 return true;
876 else
877 return false;
878}
entity owner
Definition main.qh:87
entity realowner

References entity(), owner, and realowner.

Referenced by defrag_waypointsprites(), and spawnfunc().

◆ race_writeTime()

void race_writeTime ( string map,
float t,
string myuid )

Definition at line 91 of file race.qc.

92{
93 float newpos;
94 newpos = race_readPos(map, t);
95
96 float i, prevpos = 0;
97 for(i = 1; i <= RANKINGS_CNT; ++i)
98 {
99 if(race_readUID(map, i) == myuid)
100 prevpos = i;
101 }
102 if (prevpos)
103 {
104 // player improved their existing record, only have to iterate on ranks between new and old recs
105 for (i = prevpos; i > newpos; --i)
106 {
107 db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
108 db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
109 }
110 }
111 else
112 {
113 // player has no ranked record yet
114 for (i = RANKINGS_CNT; i > newpos; --i)
115 {
116 float other_time = race_readTime(map, i - 1);
117 if (other_time) {
118 db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(other_time));
119 db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
120 }
121 }
122 }
123
124 // store new time itself
125 db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(newpos)), ftos(t));
126 db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(newpos)), myuid);
127}

References db_put(), ftos(), race_readPos(), race_readTime(), race_readUID(), RANKINGS_CNT, record_type, ServerProgsDB, and strcat().

Referenced by race_setTime().

◆ spawnfunc() [1/6]

spawnfunc ( info_player_race )

Definition at line 1264 of file race.qc.

1265{
1266 if(!g_race && !g_cts) { delete(this); return; }
1267 ++race_spawns;
1268 spawnfunc_info_player_deathmatch(this);
1269
1274}
float race_spawns
Definition race.qh:18
float race_lowest_place_spawn
Definition race.qh:20
float race_highest_place_spawn
Definition race.qh:19

References g_cts, g_race, race_highest_place_spawn, race_lowest_place_spawn, race_place, and race_spawns.

◆ spawnfunc() [2/6]

spawnfunc ( target_checkpoint )

Definition at line 1219 of file race.qc.

1220{
1221 // xonotic defrag entity
1223}
void target_checkpoint_setup(entity this)
Definition race.qc:1168

References target_checkpoint_setup().

◆ spawnfunc() [3/6]

spawnfunc ( target_startTimer )

Definition at line 1226 of file race.qc.

1226{ target_checkpoint_setup(this); }

References target_checkpoint_setup().

◆ spawnfunc() [4/6]

spawnfunc ( target_stopTimer )

Definition at line 1227 of file race.qc.

1227{ target_checkpoint_setup(this); }

References target_checkpoint_setup().

◆ spawnfunc() [5/6]

spawnfunc ( trigger_race_checkpoint )

Definition at line 1112 of file race.qc.

1113{
1114 vector o;
1115 if(!g_race && !g_cts) { delete(this); return; }
1116
1118
1119 this.use = checkpoint_use;
1120 if (!(this.spawnflags & 1))
1122
1123 o = (this.absmin + this.absmax) * 0.5;
1124 tracebox(o, PL_MIN_CONST, PL_MAX_CONST, o - '0 0 1' * (o.z - this.absmin.z), MOVE_NORMAL, this);
1126 this.nearestwaypointtimeout = -1;
1127
1128 if(this.message == "")
1129 this.message = "went backwards";
1130 if (this.message2 == "")
1131 this.message2 = "was pushed backwards by";
1132 if (this.race_penalty_reason == "")
1133 this.race_penalty_reason = "missing a checkpoint";
1134
1135 this.race_checkpoint = this.cnt;
1136
1138 {
1140 if(this.spawnflags & 8)
1142 else
1144 }
1145
1146 if(!this.race_penalty)
1147 {
1148 if(this.race_checkpoint)
1149 WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, this, sprite, RADARICON_NONE);
1150 else
1151 WaypointSprite_SpawnFixed(WP_RaceStartFinish, o, this, sprite, RADARICON_NONE);
1152 }
1153
1154 this.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
1156
1157 if (!g_racecheckpoints)
1160
1161 // trigger_race_checkpoint_verify checks this list too
1162 if (!g_race_targets)
1164
1166}
float nearestwaypointtimeout
Definition api.qh:53
void waypoint_spawnforitem_force(entity e, vector org)
float cnt
Definition powerups.qc:24
const vector PL_MIN_CONST
Definition constants.qh:56
const int INITPRIO_FINDTARGET
Definition constants.qh:96
const vector PL_MAX_CONST
Definition constants.qh:55
const float MOVE_NORMAL
vector trace_endpos
vector absmax
vector absmin
#define use
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_NEW()
#define EXACTTRIGGER_INIT
Definition common.qh:116
#define settouch(e, f)
Definition self.qh:73
vector trigger_race_checkpoint_spawn_evalfunc(entity this, entity player, entity spot, vector current)
Definition race.qc:1081
void checkpoint_use(entity this, entity actor, entity trigger)
Definition race.qc:858
void checkpoint_touch(entity this, entity toucher)
Definition race.qc:852
void trigger_race_checkpoint_verify(entity this)
Definition race.qc:921
spawn_evalfunc_t spawn_evalfunc
string message2
Definition triggers.qh:19
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2209

References absmax, absmin, checkpoint_touch(), checkpoint_use(), cnt, EXACTTRIGGER_INIT, g_cts, g_race, g_race_targets, g_racecheckpoints, IL_NEW, IL_PUSH(), InitializeEntity(), INITPRIO_FINDTARGET, message, message2, MOVE_NORMAL, nearestwaypointtimeout, PL_MAX_CONST, PL_MIN_CONST, race_checkpoint, race_highest_checkpoint, race_penalty, race_penalty_reason, race_timed_checkpoint, race_waypointsprite_visible_for_player(), settouch, spawn_evalfunc, spawnflags, sprite, trace_endpos, trigger_race_checkpoint_spawn_evalfunc(), trigger_race_checkpoint_verify(), use, vector, waypoint_spawnforitem_force(), and WaypointSprite_SpawnFixed().

◆ spawnfunc() [6/6]

spawnfunc ( trigger_race_penalty )

Definition at line 1348 of file race.qc.

1349{
1350 // TODO: find out why this wasnt done:
1351 //if(!g_cts && !g_race) { remove(this); return; }
1352
1354
1355 this.use = penalty_use;
1356 if (!(this.spawnflags & 1))
1357 settouch(this, penalty_touch);
1358
1359 if (this.race_penalty_reason == "")
1360 this.race_penalty_reason = "missing a checkpoint";
1361 if (!this.race_penalty)
1362 this.race_penalty = 5;
1363}
void penalty_use(entity this, entity actor, entity trigger)
Definition race.qc:1343
void penalty_touch(entity this, entity toucher)
Definition race.qc:1333

References EXACTTRIGGER_INIT, penalty_touch(), penalty_use(), race_penalty, race_penalty_reason, settouch, spawnflags, and use.

◆ target_checkpoint_setup()

void target_checkpoint_setup ( entity this)

Definition at line 1168 of file race.qc.

1169{
1170 if(!g_race && !g_cts) { delete(this); return; }
1171 defrag_ents = 1;
1172
1173 // if this is targeted, then it probably isn't a trigger
1174 bool is_trigger = this.targetname == "";
1175
1176 if(is_trigger)
1178
1179 this.use = checkpoint_use;
1180 if (is_trigger && !(this.spawnflags & 1))
1182
1183 vector org = this.origin;
1184
1185 // bots should only pathfind to this if it is a valid touchable trigger
1186 if(is_trigger)
1187 {
1188 org = (this.absmin + this.absmax) * 0.5;
1189 tracebox(org, PL_MIN_CONST, PL_MAX_CONST, org - '0 0 1' * (org.z - this.absmin.z), MOVE_NORMAL, this);
1191 this.nearestwaypointtimeout = -1;
1192 }
1193
1194 if(this.message == "")
1195 this.message = "went backwards";
1196 if (this.message2 == "")
1197 this.message2 = "was pushed backwards by";
1198 if (this.race_penalty_reason == "")
1199 this.race_penalty_reason = "missing a checkpoint";
1200
1201 if(this.classname == "target_startTimer")
1202 this.race_checkpoint = 0;
1203 else
1204 this.race_checkpoint = -2;
1205
1207
1208 if (!g_race_targets)
1210 IL_PUSH(g_race_targets, this);
1211
1212 // trigger_race_checkpoint_verify checks this list too
1213 if (!g_racecheckpoints)
1215
1217}
vector origin
vector org
Definition self.qh:92
string targetname
Definition triggers.qh:56

References absmax, absmin, checkpoint_touch(), checkpoint_use(), classname, defrag_ents, entity(), EXACTTRIGGER_INIT, g_cts, g_race, g_race_targets, g_racecheckpoints, IL_NEW, IL_PUSH(), InitializeEntity(), INITPRIO_FINDTARGET, message, message2, MOVE_NORMAL, nearestwaypointtimeout, org, origin, PL_MAX_CONST, PL_MIN_CONST, race_checkpoint, race_penalty_reason, race_timed_checkpoint, settouch, spawnflags, targetname, trace_endpos, trigger_race_checkpoint_verify(), use, vector, and waypoint_spawnforitem_force().

Referenced by spawnfunc(), spawnfunc(), and spawnfunc().

◆ trigger_race_checkpoint_spawn_evalfunc()

vector trigger_race_checkpoint_spawn_evalfunc ( entity this,
entity player,
entity spot,
vector current )

Definition at line 1081 of file race.qc.

1082{
1084 {
1085 // spawn at first
1086 if(this.race_checkpoint != 0)
1087 return '-1 0 0';
1088 if(spot.race_place != race_lowest_place_spawn)
1089 return '-1 0 0';
1090 }
1091 else
1092 {
1093 if(this.race_checkpoint != player.race_respawn_checkpoint)
1094 return '-1 0 0';
1095 // try reusing the previous spawn
1096 if(this == player.race_respawn_spotref || spot == player.race_respawn_spotref)
1097 current.x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN;
1098 if(this.race_checkpoint == 0)
1099 {
1100 int pl = player.race_place;
1102 pl = 0;
1103 if(pl == 0 && !player.race_started)
1104 pl = race_highest_place_spawn; // use last place if they have not even touched finish yet
1105 if(spot.race_place != pl)
1106 return '-1 0 0';
1107 }
1108 }
1109 return current;
1110}
const int SPAWN_PRIO_RACE_PREVIOUS_SPAWN

References entity(), g_race_qualifying, race_checkpoint, race_highest_place_spawn, race_lowest_place_spawn, SPAWN_PRIO_RACE_PREVIOUS_SPAWN, and vector.

Referenced by spawnfunc().

◆ trigger_race_checkpoint_verify()

void trigger_race_checkpoint_verify ( entity this)

Definition at line 921 of file race.qc.

922{
923 static bool have_verified;
924 if (have_verified) return;
925 have_verified = true;
926
927 int qual = g_race_qualifying;
928
929 int pl_race_checkpoint = 0;
930 int pl_race_place = 0;
931
932 if (g_race) {
933 for (int i = 0; i <= race_highest_checkpoint; ++i) {
934 pl_race_checkpoint = race_NextCheckpoint(i);
935
936 // race only (middle of the race)
938 pl_race_place = 0;
939 if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
940 error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for respawning in race) - bailing out"));
941 }
942
943 if (i == 0) {
944 // qualifying only
946 pl_race_place = race_lowest_place_spawn;
947 if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
948 error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
949 }
950
951 // race only (initial spawn)
953 for (int p = 1; p <= race_highest_place_spawn; ++p) {
954 pl_race_place = p;
955 if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
956 error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for initially spawning in race) - bailing out"));
957 }
958 }
959 }
960 }
961 } else if (!defrag_ents) {
962 // qualifying only
963 pl_race_checkpoint = race_NextCheckpoint(0);
965 pl_race_place = race_lowest_place_spawn;
966 if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
967 error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
968 }
969 } else {
970 pl_race_checkpoint = race_NextCheckpoint(0);
972 pl_race_place = 0; // there's only one spawn on defrag maps
973
974 // check if a defragcp file already exists, then read it and apply the checkpoint order
975 float fh;
976 float len;
977 bool broken_defragcp = false;
978 string l;
979
980 defragcpexists = fh = fopen(strcat("maps/", GetMapname(), ".defragcp"), FILE_READ);
981 if (fh >= 0) {
982 while ((l = fgets(fh))) {
983 len = tokenize_console(l);
984 if (len != 2) {
985 broken_defragcp = true;
986 break;
987 }
988 for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) {
989 if (argv(0) == cp.targetname) {
990 if(cp.race_checkpoint != -2 && cp.race_checkpoint != stof(argv(1))) {
991 broken_defragcp = true; // cp had been previously set with diff order nr defragcp file is broken
992 break;
993 }
994 cp.race_checkpoint = stof(argv(1));
995 }
996 }
997 if(broken_defragcp) break; // no point to keep going we'll rebuild the whole order
998 }
999 fclose(fh);
1000 if(broken_defragcp) {
1001 // something's wrong in the defrag cp file, set defragcpexists to -1 so that it will be rewritten when someone finishes
1002 // also clear any set cp order to make sure map is completable
1003 defragcpexists = -1;
1004 for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) {
1005 cp.race_checkpoint = -2;
1006 }
1007 }
1008 }
1009 }
1010
1011 g_race_qualifying = qual;
1012
1014 if (defrag_ents) {
1015 IL_EACH(g_race_targets, it.classname == "target_checkpoint" || it.classname == "target_startTimer" || it.classname == "target_stopTimer",
1016 {
1017 defrag_waypointsprites(it, it, 0);
1018
1019 if(it.classname == "target_checkpoint") {
1020 if(it.race_checkpoint == -2)
1021 defragcpexists = -1; // something's wrong with the defrag cp file or it has not been written yet, set defragcpexists to -1 so that it will be rewritten when someone finishes
1022 }
1023 });
1024 if (defragcpexists != -1) {
1025 float largest_cp_id = 0;
1026 for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) {
1027 if (cp.race_checkpoint > largest_cp_id) {
1028 largest_cp_id = cp.race_checkpoint;
1029 }
1030 }
1031 for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) {
1032 cp.race_checkpoint = largest_cp_id + 1; // finish line
1033 }
1034 race_highest_checkpoint = largest_cp_id + 1;
1035 race_timed_checkpoint = largest_cp_id + 1;
1036 } else {
1037 for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) {
1038 cp.race_checkpoint = 255; // finish line
1039 }
1042 }
1043 } else {
1044 IL_EACH(g_racecheckpoints, it.sprite,
1045 {
1046 if (it.race_checkpoint == 0) {
1047 WaypointSprite_UpdateSprites(it.sprite, WP_RaceStart, WP_Null, WP_Null);
1048 } else if (it.race_checkpoint == race_timed_checkpoint) {
1049 WaypointSprite_UpdateSprites(it.sprite, WP_RaceFinish, WP_Null, WP_Null);
1050 }
1051 });
1052 }
1053 }
1054
1055 if (defrag_ents) { /* The following hack shall be removed when per-player trigger_multiple.wait is implemented for cts */
1056 for (entity trigger = NULL; (trigger = find(trigger, classname, "trigger_multiple")); ) {
1057 for (entity targ = NULL; (targ = find(targ, targetname, trigger.target)); ) {
1058 if (targ.classname == "target_checkpoint" || targ.classname == "target_startTimer" || targ.classname == "target_stopTimer") {
1059 trigger.wait = 0;
1060 trigger.delay = 0;
1061 targ.wait = 0;
1062 targ.delay = 0;
1063
1064 // These just make the game crash on some maps with oddly shaped triggers.
1065 // (on the other hand they used to fix the case when two players ran through a checkpoint at once,
1066 // and often one of them just passed through without being registered. Hope it's fixed in a better way now.
1067 // (happened on item triggers too)
1068 //
1069 //targ.wait = -2;
1070 //targ.delay = 0;
1071
1072 //setsize(targ, trigger.mins, trigger.maxs);
1073 //setorigin(targ, trigger.origin);
1074 //remove(trigger);
1075 }
1076 }
1077 }
1078 }
1079}
const float FILE_READ
#define tokenize_console
string fgets(float fhandle)
entity find(entity start,.string field, string match)
string argv(float n)
#define error
Definition pre.qh:6
entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck)
if(frag_attacker.flagcarried)
Definition sv_ctf.qc:2325

References argv(), classname, defrag_ents, defragcpexists, entity(), error, fclose(), fgets(), FILE_READ, find(), fopen(), ftos(), g_race, g_race_qualifying, g_race_targets, g_racecheckpoints, GetMapname(), if(), IL_EACH, NULL, race_highest_checkpoint, race_highest_place_spawn, race_lowest_place_spawn, race_NextCheckpoint(), race_timed_checkpoint, Spawn_FilterOutBadSpots(), stof(), strcat(), and tokenize_console.

Referenced by spawnfunc(), and target_checkpoint_setup().

◆ uid2name()

string uid2name ( string myuid)

Definition at line 36 of file race.qc.

37{
38 string s = db_get(ServerProgsDB, strcat("/uid2name/", myuid));
39
40 // FIXME remove this later after 0.6 release
41 // convert old style broken records to correct style
42 if(s == "")
43 {
44 s = db_get(ServerProgsDB, strcat("uid2name", myuid));
45 if(s != "")
46 {
47 db_put(ServerProgsDB, strcat("/uid2name/", myuid), s);
48 db_remove(ServerProgsDB, strcat("uid2name", myuid));
49 }
50 }
51
52 if(s == "")
53 s = "^1Unregistered Player";
54 return s;
55}

References db_get(), db_put(), db_remove, ServerProgsDB, and strcat().

Referenced by getladder(), race_checkAndWriteName(), race_readName(), race_SendAll(), and race_setTime().

◆ write_recordmarker()

void write_recordmarker ( entity pl,
float tstart,
float dt )

Definition at line 57 of file race.qc.

58{
59 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
60 // also write a marker into demo files for demotc-race-record-extractor to find
61 stuffcmd(pl,
62 sprintf("//%s RECORD SET %s %f %f\n", strconv(2, 0, 0, GetGametype()),
63 TIME_ENCODED_TOSTRING(TIME_ENCODE(dt), false), tstart, dt));
64}
#define TIME_ENCODED_TOSTRING(n, compact)
Definition util.qh:96
void GameLogEcho(string s)
Definition gamelog.qc:15
string GetGametype()
#define stuffcmd(cl,...)
Definition progsdefs.qh:23

References entity(), ftos(), GameLogEcho(), GetGametype(), strcat(), stuffcmd, TIME_ENCODE, and TIME_ENCODED_TOSTRING.

Referenced by ctf_CaptureRecord(), and race_setTime().

Variable Documentation

◆ defrag_ents

float defrag_ents

◆ defragcpexists

float defragcpexists

Definition at line 173 of file race.qc.

Referenced by trigger_race_checkpoint_verify().

◆ g_race_targets

IntrusiveList g_race_targets

◆ g_racecheckpoints

◆ MAX_CHECKPOINTS

const float MAX_CHECKPOINTS = 255

Definition at line 149 of file race.qc.

Referenced by race_ClearPlayerRecords(), and race_ClearRecords().

◆ race_checkpoint

float race_checkpoint

Definition at line 154 of file race.qc.

◆ race_checkpoint_lastlaps

float race_checkpoint_lastlaps[MAX_CHECKPOINTS]

Definition at line 163 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_lastplayers

entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]

Definition at line 164 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_lasttimes

float race_checkpoint_lasttimes[MAX_CHECKPOINTS]

Definition at line 162 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_record

float race_checkpoint_record[MAX_CHECKPOINTS]

Definition at line 166 of file race.qc.

◆ race_checkpoint_recordholders

string race_checkpoint_recordholders[MAX_CHECKPOINTS]

Definition at line 161 of file race.qc.

Referenced by race_ClearRecords(), race_SendNextCheckpoint(), and race_SendTime().

◆ race_checkpoint_records

float race_checkpoint_records[MAX_CHECKPOINTS]

Definition at line 159 of file race.qc.

Referenced by race_ClearRecords(), race_SendNextCheckpoint(), and race_SendTime().

◆ race_checkpoint_recordspeed

float race_checkpoint_recordspeed[MAX_CHECKPOINTS]

Definition at line 167 of file race.qc.

◆ race_checkpoint_recordspeeds

float race_checkpoint_recordspeeds[MAX_CHECKPOINTS]

Definition at line 160 of file race.qc.

Referenced by race_ClearRecords(), race_SendNextCheckpoint(), and race_SendTime().

◆ race_highest_checkpoint

◆ race_lastpenalty

entity race_lastpenalty

Definition at line 155 of file race.qc.

◆ race_penalty

float race_penalty

Definition at line 151 of file race.qc.

◆ race_penalty_accumulator

float race_penalty_accumulator

Definition at line 152 of file race.qc.

◆ race_penalty_reason

string race_penalty_reason

Definition at line 153 of file race.qc.

Referenced by penalty_touch(), penalty_use(), spawnfunc(), spawnfunc(), and target_checkpoint_setup().

◆ race_timed_checkpoint

◆ sprite

entity sprite

Definition at line 157 of file race.qc.

◆ stored_netname

string stored_netname

Definition at line 34 of file race.qc.