Xonotic
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)
 
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_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)
 
void race_InitSpectator ()
 
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 (trigger_race_checkpoint)
 
 spawnfunc (target_checkpoint)
 
 spawnfunc (target_startTimer)
 
 spawnfunc (target_stopTimer)
 
 spawnfunc (info_player_race)
 
 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_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 664 of file race.qc.

References autocvar_g_allow_checkpoints, classname, Damage(), defrag_ents, defragcpexists, DMG_NOWEP, fclose(), FILE_WRITE, fopen(), g_race_qualifying, GetMapname(), IL_EACH, IS_PLAYER, IS_VEHICLE, message, normalize(), NULL, Portal_ClearAll(), race_checkpoint, race_highest_checkpoint, race_ImposePenaltyTime(), race_NextCheckpoint(), race_penalty, race_penalty_reason, race_SendNextCheckpoint(), race_SendTime(), race_timed_checkpoint, spawnflags, strcat(), SUB_UseTargets(), time, and trace_plane_normal.

Referenced by checkpoint_touch(), and checkpoint_use().

665 {
666  if(IS_VEHICLE(player) && player.owner)
667  player = player.owner;
668 
669  if(player.personal && autocvar_g_allow_checkpoints)
670  return; // practice mode!
671 
672  if(player.classname == "porto")
673  {
674  // do not allow portalling through checkpoints
675  trace_plane_normal = normalize(-1 * player.velocity);
676  W_Porto_Fail(player, 0);
677  return;
678  }
679 
680  string oldmsg; // used twice
681 
682  /*
683  * Trigger targets
684  */
685  if (!((this.spawnflags & 2) && (IS_PLAYER(player))))
686  {
687  oldmsg = this.message;
688  this.message = "";
689  SUB_UseTargets(this, player, player);
690  this.message = oldmsg;
691  }
692 
693  if (!IS_PLAYER(player))
694  return;
695 
696  /*
697  * Remove unauthorized equipment
698  */
699  Portal_ClearAll(player);
700 
701  player.porto_forbidden = 2; // decreased by 1 each StartFrame
702 
703  if(defrag_ents)
704  {
705  if(this.race_checkpoint == -2)
706  {
707  this.race_checkpoint = player.race_checkpoint;
708  }
709 
710  int cp_amount = 0, largest_cp_id = 0;
711  IL_EACH(g_race_targets, it.classname == "target_checkpoint",
712  {
713  cp_amount += 1;
714  if(it.race_checkpoint > largest_cp_id) // update the finish id if someone hit a new checkpoint
715  {
716  if(!largest_cp_id)
717  {
718  IL_EACH(g_race_targets, it.classname == "target_checkpoint",
719  {
720  if(it.race_checkpoint == -2) // set defragcpexists to -1 so that the cp id file will be rewritten when someone finishes
721  defragcpexists = -1;
722  });
723  }
724 
725  largest_cp_id = it.race_checkpoint;
726  IL_EACH(g_race_targets, it.classname == "target_stopTimer",
727  {
728  it.race_checkpoint = largest_cp_id + 1; // finish line
729  });
730  race_highest_checkpoint = largest_cp_id + 1;
731  race_timed_checkpoint = largest_cp_id + 1;
732  }
733  });
734 
735  if(!cp_amount)
736  {
737  IL_EACH(g_race_targets, it.classname == "target_stopTimer",
738  {
739  it.race_checkpoint = 1;
740  });
743  }
744  }
745 
746  if((player.race_checkpoint == -1 && this.race_checkpoint == 0) || (player.race_checkpoint == this.race_checkpoint))
747  {
748  if(this.race_penalty)
749  {
750  if(player.race_lastpenalty != this)
751  {
752  player.race_lastpenalty = this;
754  }
755  }
756 
757  if(player.race_penalty)
758  return;
759 
760  /*
761  * Trigger targets
762  */
763  if(this.spawnflags & 2)
764  {
765  oldmsg = this.message;
766  this.message = "";
767  SUB_UseTargets(this, player, player); // TODO: should we be using other for the trigger here?
768  this.message = oldmsg;
769  }
770 
771  if(player.race_respawn_checkpoint != this.race_checkpoint || !player.race_started)
772  player.race_respawn_spotref = this; // this is not a spot but a CP, but spawnpoint selection will deal with that
773  player.race_respawn_checkpoint = this.race_checkpoint;
774  player.race_checkpoint = race_NextCheckpoint(this.race_checkpoint);
775  player.race_started = 1;
776 
777  race_SendTime(player, this.race_checkpoint, player.race_movetime, boolean(player.race_laptime));
778 
779  if(!this.race_checkpoint) // start line
780  {
781  player.race_laptime = time;
782  player.race_movetime = player.race_movetime_frac = player.race_movetime_count = 0;
783  player.race_penalty_accumulator = 0;
784  player.race_lastpenalty = NULL;
785  }
786 
788  race_SendNextCheckpoint(player, 0);
789 
790  if(defrag_ents && defragcpexists < 0 && this.classname == "target_stopTimer")
791  {
792  float fh;
793  defragcpexists = fh = fopen(strcat("maps/", GetMapname(), ".defragcp"), FILE_WRITE);
794  if(fh >= 0)
795  {
796  IL_EACH(g_race_targets, it.classname == "target_checkpoint",
797  {
798  fputs(fh, strcat(it.targetname, " ", ftos(it.race_checkpoint), "\n"));
799  });
800  }
801  fclose(fh);
802  }
803  }
804  else if(player.race_checkpoint == race_NextCheckpoint(this.race_checkpoint))
805  {
806  // ignored
807  }
808  else
809  {
810  if(this.spawnflags & 4)
811  Damage (player, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, player.origin, '0 0 0');
812  }
813 }
#define IL_EACH(this, cond, body)
void race_SendNextCheckpoint(entity e, float spec)
Definition: race.qc:216
float race_timed_checkpoint
Definition: race.qc:177
string GetMapname()
Definition: intermission.qc:18
float race_highest_checkpoint
Definition: race.qc:176
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition: triggers.qc:366
string classname
Definition: csprogsdefs.qc:107
float race_NextCheckpoint(float f)
Definition: race.qc:182
bool g_race_qualifying
Definition: race.qh:12
float spawnflags
Definition: progsdefs.qc:191
#define DMG_NOWEP
Definition: damage.qh:126
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition: race.qc:1225
void race_SendTime(entity e, float cp, float t, float tvalid)
Definition: race.qc:476
float race_checkpoint
Definition: race.qc:163
IntrusiveList g_race_targets
Definition: race.qc:68
void Portal_ClearAll(entity own)
Definition: portals.qc:587
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
bool autocvar_g_allow_checkpoints
Definition: race.qh:3
string message
Definition: powerups.qc:19
#define NULL
Definition: post.qh:17
float defragcpexists
Definition: race.qc:180
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
#define IS_VEHICLE(v)
Definition: utils.qh:22
const float FILE_WRITE
Definition: csprogsdefs.qc:233
vector trace_plane_normal
Definition: csprogsdefs.qc:38
string race_penalty_reason
Definition: race.qc:162
float time
Definition: csprogsdefs.qc:16
#define IS_PLAYER(v)
Definition: utils.qh:9
float defrag_ents
Definition: race.qc:179
float race_penalty
Definition: race.qc:160
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkpoint_touch()

void checkpoint_touch ( entity  this,
entity  toucher 
)

Definition at line 815 of file race.qc.

References checkpoint_passed(), and EXACTTRIGGER_TOUCH.

Referenced by spawnfunc(), and target_checkpoint_setup().

816 {
817  EXACTTRIGGER_TOUCH(this, toucher);
818  checkpoint_passed(this, toucher);
819 }
#define EXACTTRIGGER_TOUCH(e, t)
Definition: common.qh:116
void checkpoint_passed(entity this, entity player)
Definition: race.qc:664
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkpoint_use()

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

Definition at line 821 of file race.qc.

References checkpoint_passed().

Referenced by spawnfunc(), and target_checkpoint_setup().

822 {
823  if(trigger.classname == "info_player_deathmatch") // a spawn, a spawn
824  return;
825 
826  checkpoint_passed(this, actor);
827 }
void checkpoint_passed(entity this, entity player)
Definition: race.qc:664
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ defrag_waypointsprites()

void defrag_waypointsprites ( entity  targeted,
entity  checkpoint 
)

Definition at line 843 of file race.qc.

References entity(), race_waypointsprite_visible_for_player(), sprite, and target.

844 {
845  // bones_was_here: spawn a waypoint for every entity with a bmodel
846  // that directly or indirectly targets this checkpoint
847  // (anything a player could touch or shoot to activate this cp)
848 
849  entity s = WP_RaceCheckpoint;
850  if (checkpoint.classname == "target_startTimer")
851  s = WP_RaceStart;
852  else if (checkpoint.classname == "target_stopTimer")
853  s = WP_RaceFinish;
854 
855  for (entity t = findchain(target, targeted.targetname); t; t = t.chain)
856  {
857  if (t.modelindex)
858  {
859  WaypointSprite_SpawnFixed(s, (t.absmin + t.absmax) * 0.5, t, sprite, RADARICON_NONE);
860  t.sprite.realowner = checkpoint;
861  t.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
862  }
863 
864  if (t.targetname)
865  defrag_waypointsprites(t, checkpoint);
866  }
867 }
entity() spawn
void defrag_waypointsprites(entity targeted, entity checkpoint)
Definition: race.qc:843
entity sprite
Definition: race.qc:166
bool race_waypointsprite_visible_for_player(entity this, entity player, entity view)
Definition: race.qc:829
string target
Definition: progsdefs.qc:193
+ Here is the call graph for this function:

◆ penalty_touch()

void penalty_touch ( entity  this,
entity  toucher 
)

Definition at line 1257 of file race.qc.

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

Referenced by spawnfunc().

1258 {
1259  EXACTTRIGGER_TOUCH(this, toucher);
1260  if(toucher.race_lastpenalty != this)
1261  {
1262  toucher.race_lastpenalty = this;
1264  }
1265 }
#define EXACTTRIGGER_TOUCH(e, t)
Definition: common.qh:116
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition: race.qc:1225
string race_penalty_reason
Definition: race.qc:162
float race_penalty
Definition: race.qc:160
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ penalty_use()

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

Definition at line 1267 of file race.qc.

References race_ImposePenaltyTime(), race_penalty, and race_penalty_reason.

Referenced by spawnfunc().

1268 {
1270 }
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition: race.qc:1225
string race_penalty_reason
Definition: race.qc:162
float race_penalty
Definition: race.qc:160
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_AbandonRaceCheck()

void race_AbandonRaceCheck ( entity  p)

Definition at line 1163 of file race.qc.

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

Referenced by MUTATOR_HOOKFUNCTION(), and race_StartCompleting().

1164 {
1165  if(race_completing && !CS(p).race_completed)
1166  {
1167  CS(p).race_completed = 1;
1169  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_ABANDONED, p.netname);
1170  ClientData_Touch(p);
1171  }
1172 }
ClientState CS(Client this)
Definition: state.qh:47
#define MAKE_INDEPENDENT_PLAYER(e)
Definition: client.qh:315
float race_completing
Definition: race.qh:27
#define NULL
Definition: post.qh:17
float race_completed
Definition: race.qh:25
void ClientData_Touch(entity e)
Definition: client.qc:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_checkAndWriteName()

void race_checkAndWriteName ( entity  player)

Definition at line 143 of file race.qc.

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

Referenced by MUTATOR_HOOKFUNCTION().

144 {
145  if(CS_CVAR(player).cvar_cl_allow_uidtracking == 1 && CS_CVAR(player).cvar_cl_allow_uid2name == 1)
146  {
147  if (!player.stored_netname)
148  player.stored_netname = strzone(uid2name(player.crypto_idfp));
149  if(player.stored_netname != player.netname)
150  {
151  db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
152  strcpy(player.stored_netname, player.netname);
153  }
154  }
155 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
string uid2name(string myuid)
Definition: race.qc:36
float ServerProgsDB
Definition: world.qh:131
#define CS_CVAR(this)
Definition: state.qh:51
#define strcpy(this, s)
Definition: string.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_CheckpointNetworkID()

float race_CheckpointNetworkID ( float  f)

Definition at line 204 of file race.qc.

References race_timed_checkpoint.

Referenced by race_SendNextCheckpoint(), and race_SendTime().

205 {
207  {
208  if(f == 0)
209  return 254; // start
210  else if(f == race_timed_checkpoint)
211  return 255; // finish
212  }
213  return f;
214 }
float race_timed_checkpoint
Definition: race.qc:177
+ Here is the caller graph for this function:

◆ race_ClearRecords()

void race_ClearRecords ( )

Definition at line 1210 of file race.qc.

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

Referenced by MUTATOR_HOOKFUNCTION().

1211 {
1212  for(int j = 0; j < MAX_CHECKPOINTS; ++j)
1213  {
1214  race_checkpoint_records[j] = 0;
1216  }
1217 
1218  FOREACH_CLIENT(true, {
1219  float p = it.race_place;
1220  race_PreparePlayer(it);
1221  it.race_place = p;
1222  });
1223 }
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
string race_checkpoint_recordholders[MAX_CHECKPOINTS]
Definition: race.qc:169
void race_PreparePlayer(entity this)
Definition: race.qc:1180
float race_checkpoint_records[MAX_CHECKPOINTS]
Definition: race.qc:168
#define strfree(this)
Definition: string.qh:56
const float MAX_CHECKPOINTS
Definition: race.qc:158
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_ClearTime()

void race_ClearTime ( entity  e)

Definition at line 646 of file race.qc.

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

Referenced by race_PreparePlayer(), and race_RetractPlayer().

647 {
648  e.race_checkpoint = 0;
649  e.race_laptime = 0;
650  e.race_movetime = e.race_movetime_frac = e.race_movetime_count = 0;
651  e.race_penalty_accumulator = 0;
652  e.race_lastpenalty = NULL;
653 
654  if(!IS_REAL_CLIENT(e))
655  return;
656 
657  msg_entity = e;
658  WRITESPECTATABLE_MSG_ONE(msg_entity, {
659  WriteHeader(MSG_ONE, TE_CSQC_RACE);
661  });
662 }
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
entity msg_entity
Definition: progsdefs.qc:63
#define NULL
Definition: post.qh:17
const int RACE_NET_CHECKPOINT_CLEAR
Definition: net_linked.qh:11
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_deleteTime()

void race_deleteTime ( string  map,
float  pos 
)

Definition at line 452 of file race.qc.

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

Referenced by GameCommand_delrec().

453 {
454  for(int i = pos; i <= RANKINGS_CNT; ++i)
455  {
456  string therank = ftos(i);
457  if (i == RANKINGS_CNT)
458  {
459  db_remove(ServerProgsDB, strcat(map, record_type, "time", therank));
460  db_remove(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank));
461  }
462  else
463  {
464  db_put(ServerProgsDB, strcat(map, record_type, "time", therank), ftos(race_readTime(GetMapname(), i+1)));
465  db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", therank), race_readUID(GetMapname(), i+1));
466  }
467  }
468 
469  race_SendRanking(pos, 0, 1, MSG_ALL);
470  if(pos == 1)
472 
473  strcpy(rankings_reply, getrankings());
474 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
string getrankings()
Definition: getreplies.qc:46
string GetMapname()
Definition: intermission.qc:18
float ServerProgsDB
Definition: world.qh:131
string race_readUID(string map, float pos)
Definition: race.qc:83
#define strcpy(this, s)
Definition: string.qh:49
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void race_send_recordtime(float msg)
Definition: race.qc:251
float race_readTime(string map, float pos)
Definition: race.qc:78
#define db_remove(db, key)
Definition: map.qh:98
void race_SendRanking(float pos, float prevpos, float del, float msg)
Definition: race.qc:285
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_GetFractionalLapCount()

float race_GetFractionalLapCount ( entity  e)

Definition at line 1289 of file race.qc.

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

1290 {
1291  // interesting metrics (idea by KrimZon) to maybe sort players in the
1292  // scoreboard, immediately updates when overtaking
1293  //
1294  // requires the track to be built so you never get farther away from the
1295  // next checkpoint, though, and current Xonotic race maps are not built that
1296  // way
1297  //
1298  // also, this code is slow and would need optimization (i.e. "next CP"
1299  // links on CP entities)
1300 
1301  float l;
1302  l = GameRules_scoring_add(e, RACE_LAPS, 0);
1303  if(CS(e).race_completed)
1304  return l; // not fractional
1305 
1306  vector o0, o1;
1307  float bestfraction, fraction;
1308  entity lastcp;
1309  float nextcpindex, lastcpindex;
1310 
1311  nextcpindex = max(e.race_checkpoint, 0);
1312  lastcpindex = e.race_respawn_checkpoint;
1313  lastcp = e.race_respawn_spotref;
1314 
1315  if(nextcpindex == lastcpindex)
1316  return l; // finish
1317 
1318  bestfraction = 1;
1319  IL_EACH(g_racecheckpoints, true,
1320  {
1321  if(it.race_checkpoint != lastcpindex)
1322  continue;
1323  if(lastcp)
1324  if(it != lastcp)
1325  continue;
1326  o0 = (it.absmin + it.absmax) * 0.5;
1327  IL_EACH(g_racecheckpoints, true,
1328  {
1329  if(it.race_checkpoint != nextcpindex)
1330  continue;
1331  o1 = (it.absmin + it.absmax) * 0.5;
1332  if(o0 == o1)
1333  continue;
1334  fraction = bound(0.0001, vlen(e.origin - o1) / vlen(o0 - o1), 1);
1335  if(fraction < bestfraction)
1336  bestfraction = fraction;
1337  });
1338  });
1339 
1340  // we are at CP "nextcpindex - bestfraction"
1341  // race_timed_checkpoint == 4: then nextcp==4 means 0.9999x, nextcp==0 means 0.0000x
1342  // race_timed_checkpoint == 0: then nextcp==0 means 0.9999x
1343  float c, nc;
1344  nc = race_highest_checkpoint + 1;
1345  c = ((nextcpindex - race_timed_checkpoint + nc + nc - 1) % nc) + 1 - bestfraction;
1346 
1347  return l + c / nc;
1348 }
#define IL_EACH(this, cond, body)
float race_timed_checkpoint
Definition: race.qc:177
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
#define GameRules_scoring_add(client, fld, value)
Definition: sv_rules.qh:78
float race_highest_checkpoint
Definition: race.qc:176
IntrusiveList g_racecheckpoints
Definition: race.qc:69
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float race_completed
Definition: race.qh:25
+ Here is the call graph for this function:

◆ race_ImposePenaltyTime()

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

Definition at line 1225 of file race.qc.

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

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

1226 {
1227  if(g_race_qualifying)
1228  {
1229  pl.race_penalty_accumulator += penalty;
1230  if(IS_REAL_CLIENT(pl))
1231  {
1232  msg_entity = pl;
1233  WRITESPECTATABLE_MSG_ONE(msg_entity, {
1234  WriteHeader(MSG_ONE, TE_CSQC_RACE);
1236  WriteShort(MSG_ONE, TIME_ENCODE(penalty));
1237  WriteString(MSG_ONE, reason);
1238  });
1239  }
1240  }
1241  else
1242  {
1243  pl.race_penalty = time + penalty;
1244  if(IS_REAL_CLIENT(pl))
1245  {
1246  msg_entity = pl;
1247  WRITESPECTATABLE_MSG_ONE(msg_entity, {
1248  WriteHeader(MSG_ONE, TE_CSQC_RACE);
1250  WriteShort(MSG_ONE, TIME_ENCODE(penalty));
1251  WriteString(MSG_ONE, reason);
1252  });
1253  }
1254  }
1255 }
bool g_race_qualifying
Definition: race.qh:12
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
#define TIME_ENCODE(t)
Definition: util.qh:61
entity msg_entity
Definition: progsdefs.qc:63
const int RACE_NET_PENALTY_QUALIFYING
Definition: net_linked.qh:17
const int RACE_NET_PENALTY_RACE
Definition: net_linked.qh:16
float time
Definition: csprogsdefs.qc:16
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_InitSpectator()

void race_InitSpectator ( )

Definition at line 71 of file race.qc.

References g_race_qualifying, msg_entity, and race_SendNextCheckpoint().

Referenced by SetSpectatee_status().

72 {
74  if(msg_entity.enemy.race_laptime)
76 }
void race_SendNextCheckpoint(entity e, float spec)
Definition: race.qc:216
bool g_race_qualifying
Definition: race.qh:12
entity msg_entity
Definition: progsdefs.qc:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_NextCheckpoint()

float race_NextCheckpoint ( float  f)

Definition at line 182 of file race.qc.

References race_highest_checkpoint.

Referenced by checkpoint_passed(), and trigger_race_checkpoint_verify().

183 {
184  if(f >= race_highest_checkpoint)
185  return 0;
186  else
187  return f + 1;
188 }
float race_highest_checkpoint
Definition: race.qc:176
+ Here is the caller graph for this function:

◆ race_PreparePlayer()

void race_PreparePlayer ( entity  this)

Definition at line 1180 of file race.qc.

References NULL, race_ClearTime(), race_place, race_respawn_checkpoint, race_respawn_spotref, and race_started.

Referenced by MUTATOR_HOOKFUNCTION(), and race_ClearRecords().

1181 {
1182  race_ClearTime(this);
1183  this.race_place = 0;
1184  this.race_started = 0;
1185  this.race_respawn_checkpoint = 0;
1186  this.race_respawn_spotref = NULL;
1187 }
float race_place
Definition: race.qh:23
entity race_respawn_spotref
Definition: race.qh:34
#define NULL
Definition: post.qh:17
float race_started
Definition: race.qh:24
float race_respawn_checkpoint
Definition: race.qh:33
void race_ClearTime(entity e)
Definition: race.qc:646
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_PreviousCheckpoint()

float race_PreviousCheckpoint ( float  f)

Definition at line 190 of file race.qc.

References race_highest_checkpoint.

191 {
192  if(f == -1)
193  return 0;
194  else if(f == 0)
196  else
197  return f - 1;
198 }
float race_highest_checkpoint
Definition: race.qc:176

◆ race_readName()

string race_readName ( string  map,
float  pos 
)

Definition at line 138 of file race.qc.

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

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

139 {
140  return uid2name(db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos))));
141 }
string uid2name(string myuid)
Definition: race.qc:36
float ServerProgsDB
Definition: world.qh:131
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_readPos()

float race_readPos ( string  map,
float  t 
)

Definition at line 88 of file race.qc.

References race_readTime().

Referenced by race_setTime(), and race_writeTime().

89 {
90  for(int i = 1; i <= RANKINGS_CNT; ++i)
91  {
92  int mytime = race_readTime(map, i);
93  if(!mytime || mytime > t)
94  return i;
95  }
96 
97  return 0; // pos is zero if unranked
98 }
float race_readTime(string map, float pos)
Definition: race.qc:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_readTime()

float race_readTime ( string  map,
float  pos 
)

Definition at line 78 of file race.qc.

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

Referenced by getladder(), getlsmaps(), getrankings(), MUTATOR_HOOKFUNCTION(), race_deleteTime(), race_readPos(), race_send_recordtime(), race_SendRanking(), race_setTime(), and race_writeTime().

79 {
80  return stof(db_get(ServerProgsDB, strcat(map, record_type, "time", ftos(pos))));
81 }
float ServerProgsDB
Definition: world.qh:131
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_readUID()

string race_readUID ( string  map,
float  pos 
)

Definition at line 83 of file race.qc.

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

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

84 {
85  return db_get(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(pos)));
86 }
float ServerProgsDB
Definition: world.qh:131
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_RetractPlayer()

void race_RetractPlayer ( entity  this)

Definition at line 1189 of file race.qc.

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

Referenced by MUTATOR_HOOKFUNCTION().

1190 {
1191  if(!g_race && !g_cts)
1192  return;
1194  race_ClearTime(this);
1196 }
float race_timed_checkpoint
Definition: race.qc:177
float race_checkpoint
Definition: race.qc:163
#define g_cts
Definition: cts.qh:36
#define g_race
Definition: race.qh:46
float race_respawn_checkpoint
Definition: race.qh:33
void race_ClearTime(entity e)
Definition: race.qc:646
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_send_rankings_cnt()

void race_send_rankings_cnt ( float  msg)

Definition at line 277 of file race.qc.

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

Referenced by race_SendAll().

278 {
279  WriteHeader(msg, TE_CSQC_RACE);
281  int m = min(RANKINGS_CNT, autocvar_g_cts_send_rankings_cnt);
282  WriteByte(msg, m);
283 }
int autocvar_g_cts_send_rankings_cnt
Definition: race.qh:10
const int RACE_NET_RANKINGS_CNT
Definition: net_linked.qh:25
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_send_recordtime()

void race_send_recordtime ( float  msg)

Definition at line 251 of file race.qc.

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

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

252 {
253  // send the server best time
254  WriteHeader(msg, TE_CSQC_RACE);
256  WriteInt24_t(msg, race_readTime(GetMapname(), 1));
257 }
string GetMapname()
Definition: intermission.qc:18
const int RACE_NET_SERVER_RECORD
Definition: net_linked.qh:18
float race_readTime(string map, float pos)
Definition: race.qc:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_send_speedaward()

void race_send_speedaward ( float  msg)

Definition at line 259 of file race.qc.

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

Referenced by race_SendAll(), and race_SpeedAwardFrame().

260 {
261  // send the best speed of the round
262  WriteHeader(msg, TE_CSQC_RACE);
264  WriteInt24_t(msg, floor(speedaward_speed+0.5));
266 }
const int RACE_NET_SPEED_AWARD
Definition: net_linked.qh:19
float speedaward_speed
Definition: race.qh:57
string speedaward_holder
Definition: race.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_send_speedaward_alltimebest()

void race_send_speedaward_alltimebest ( float  msg)

Definition at line 268 of file race.qc.

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

Referenced by race_SendAll(), and race_SpeedAwardFrame().

269 {
270  // send the best speed
271  WriteHeader(msg, TE_CSQC_RACE);
273  WriteInt24_t(msg, floor(speedaward_alltimebest+0.5));
275 }
string speedaward_alltimebest_holder
Definition: race.qh:62
float speedaward_alltimebest
Definition: race.qh:61
const int RACE_NET_SPEED_AWARD_BEST
Definition: net_linked.qh:20
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SendAll()

void race_SendAll ( entity  player,
bool  only_rankings 
)

Definition at line 324 of file race.qc.

References autocvar_g_cts_send_rankings_cnt, db_get(), GetMapname(), IS_REAL_CLIENT, min(), msg_entity, MSG_ONE, race_send_rankings_cnt(), race_send_recordtime(), race_send_speedaward(), race_send_speedaward_alltimebest(), race_SendRanking(), record_type, ServerProgsDB, speedaward_alltimebest, speedaward_alltimebest_holder, stof(), strcat(), and uid2name().

Referenced by MUTATOR_HOOKFUNCTION().

325 {
326  if(!IS_REAL_CLIENT(player))
327  return;
328 
329  msg_entity = player;
330  if (!only_rankings)
331  {
334 
338  }
339 
340  int m = min(RANKINGS_CNT, autocvar_g_cts_send_rankings_cnt);
342  for (int i = 1; i <= m; ++i)
343  race_SendRanking(i, 0, 0, MSG_ONE);
344 }
int autocvar_g_cts_send_rankings_cnt
Definition: race.qh:10
string uid2name(string myuid)
Definition: race.qc:36
string GetMapname()
Definition: intermission.qc:18
float ServerProgsDB
Definition: world.qh:131
string speedaward_alltimebest_holder
Definition: race.qh:62
void race_send_speedaward_alltimebest(float msg)
Definition: race.qc:268
void race_send_speedaward(float msg)
Definition: race.qc:259
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
entity msg_entity
Definition: progsdefs.qc:63
float speedaward_alltimebest
Definition: race.qh:61
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void race_send_recordtime(float msg)
Definition: race.qc:251
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
void race_SendRanking(float pos, float prevpos, float del, float msg)
Definition: race.qc:285
void race_send_rankings_cnt(float msg)
Definition: race.qc:277
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SendNextCheckpoint()

void race_SendNextCheckpoint ( entity  e,
float  spec 
)

Definition at line 216 of file race.qc.

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

Referenced by checkpoint_passed(), and race_InitSpectator().

217 {
218  if(!e.race_laptime)
219  return;
220 
221  int cp = e.race_checkpoint;
222  float recordtime = race_checkpoint_records[cp];
223  float myrecordtime = e.race_checkpoint_record[cp];
224  string recordholder = race_checkpoint_recordholders[cp];
225  if(recordholder == e.netname)
226  recordholder = "";
227 
228  if(!IS_REAL_CLIENT(e))
229  return;
230 
231  if(!spec)
232  msg_entity = e;
233  WRITESPECTATABLE_MSG_ONE(msg_entity, {
234  WriteHeader(MSG_ONE, TE_CSQC_RACE);
235  if(spec)
236  {
238  //WriteCoord(MSG_ONE, e.race_laptime - e.race_penalty_accumulator);
239  WriteCoord(MSG_ONE, time - e.race_movetime - e.race_penalty_accumulator);
240  }
241  else
243  WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player will be at next
244  WriteInt24_t(MSG_ONE, recordtime);
245  if(!spec)
246  WriteInt24_t(MSG_ONE, myrecordtime);
247  WriteString(MSG_ONE, recordholder);
248  });
249 }
const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING
Definition: net_linked.qh:12
const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING
Definition: net_linked.qh:15
float race_CheckpointNetworkID(float f)
Definition: race.qc:204
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
string race_checkpoint_recordholders[MAX_CHECKPOINTS]
Definition: race.qc:169
entity msg_entity
Definition: progsdefs.qc:63
float race_checkpoint_records[MAX_CHECKPOINTS]
Definition: race.qc:168
float time
Definition: csprogsdefs.qc:16
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SendRanking()

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

Definition at line 285 of file race.qc.

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

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

286 {
287  WriteHeader(msg, TE_CSQC_RACE);
289  WriteShort(msg, pos);
290  WriteShort(msg, prevpos);
291  WriteShort(msg, del);
292  WriteString(msg, race_readName(GetMapname(), pos));
293  WriteInt24_t(msg, race_readTime(GetMapname(), pos));
294 }
string GetMapname()
Definition: intermission.qc:18
const int RACE_NET_SERVER_RANKINGS
Definition: net_linked.qh:21
float race_readTime(string map, float pos)
Definition: race.qc:78
string race_readName(string map, float pos)
Definition: race.qc:138
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SendStatus()

void race_SendStatus ( float  id,
entity  e 
)

Definition at line 346 of file race.qc.

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

Referenced by race_setTime().

347 {
348  if(!IS_REAL_CLIENT(e))
349  return;
350 
351  float msg;
352  if (id == 0)
353  msg = MSG_ONE;
354  else
355  msg = MSG_ALL;
356  msg_entity = e;
357  WRITESPECTATABLE_MSG_ONE(msg_entity, {
358  WriteHeader(msg, TE_CSQC_RACE);
360  WriteShort(msg, id);
361  WriteString(msg, e.netname);
362  });
363 }
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
entity msg_entity
Definition: progsdefs.qc:63
const int RACE_NET_SERVER_STATUS
Definition: net_linked.qh:22
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SendTime()

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

Definition at line 476 of file race.qc.

References ClientData_Touch(), CS(), entity(), etof(), FOREACH_CLIENT, g_race_qualifying, GameRules_scoring_add, GameRules_scoring_add_team, GetMapname(), 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_CheckpointNetworkID(), race_completed, race_completing, RACE_NET_CHECKPOINT_HIT_RACE, RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT, race_setTime(), race_StartCompleting(), race_timed_checkpoint, strcpy, time, TIME_ENCODE, and WriteByte().

Referenced by checkpoint_passed().

477 {
478  float snew, l;
479 
481  t += e.race_penalty_accumulator;
482 
483  t = TIME_ENCODE(t); // make integer
484 
485  if(tvalid)
486  if(cp == race_timed_checkpoint) // finish line
487  if (!CS(e).race_completed)
488  {
489  float s;
491  {
492  s = GameRules_scoring_add(e, RACE_FASTEST, 0);
493  if(!s || t < s)
494  GameRules_scoring_add(e, RACE_FASTEST, t - s);
495  }
496  else
497  {
498  s = GameRules_scoring_add(e, RACE_FASTEST, 0);
499  if(!s || t < s)
500  GameRules_scoring_add(e, RACE_FASTEST, t - s);
501 
502  s = GameRules_scoring_add(e, RACE_TIME, 0);
503  snew = TIME_ENCODE(time - game_starttime);
504  GameRules_scoring_add(e, RACE_TIME, snew - s);
505  l = GameRules_scoring_add_team(e, RACE_LAPS, 1);
506 
507  if(autocvar_fraglimit)
508  if(l >= autocvar_fraglimit)
510 
511  if(race_completing)
512  {
513  CS(e).race_completed = 1;
515  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FINISHED, e.netname);
516  ClientData_Touch(e);
517  }
518  }
519  }
520 
522  {
523  float recordtime;
524  string recordholder;
525 
526  if(tvalid)
527  {
528  recordtime = race_checkpoint_records[cp];
529  float myrecordtime = e.race_checkpoint_record[cp];
530  recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it!
531  if(recordholder == e.netname)
532  recordholder = "";
533 
534  if(t != 0)
535  {
536  if(cp == race_timed_checkpoint)
537  {
538  race_setTime(GetMapname(), t, e.crypto_idfp, e.netname, e, true);
539  MUTATOR_CALLHOOK(Race_FinalCheckpoint, e);
540  }
541  if(t < myrecordtime || myrecordtime == 0)
542  e.race_checkpoint_record[cp] = t; // resending done below
543 
544  if(t < recordtime || recordtime == 0)
545  {
546  race_checkpoint_records[cp] = t;
547  strcpy(race_checkpoint_recordholders[cp], e.netname);
549  FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.race_checkpoint == cp, { race_SendNextCheckpoint(it, 0); });
550  }
551 
552  }
553  }
554  else
555  {
556  // dummies
557  t = 0;
558  recordtime = 0;
559  recordholder = "";
560  }
561 
562  if(IS_REAL_CLIENT(e))
563  {
565  {
567  {
568  if(it == e || (IS_SPEC(it) && it.enemy == e))
569  {
570  msg_entity = it;
571  WriteHeader(MSG_ONE, TE_CSQC_RACE);
572  WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_QUALIFYING);
573  WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
574  WriteInt24_t(MSG_ONE, t); // time to that intermediate
575  WriteInt24_t(MSG_ONE, recordtime); // previously best time
576  WriteInt24_t(MSG_ONE, ((tvalid) ? it.race_checkpoint_record[cp] : 0)); // previously best time
577  WriteString(MSG_ONE, recordholder); // record holder
578  }
579  });
580  }
581  }
582  }
583  else // RACE! Not Qualifying
584  {
585  float mylaps, lother, othtime;
587  if(oth)
588  {
589  mylaps = GameRules_scoring_add(e, RACE_LAPS, 0);
590  lother = race_checkpoint_lastlaps[cp];
591  othtime = race_checkpoint_lasttimes[cp];
592  }
593  else
594  mylaps = lother = othtime = 0;
595 
596  if(IS_REAL_CLIENT(e))
597  {
598  msg_entity = e;
599  WRITESPECTATABLE_MSG_ONE(msg_entity, {
600  WriteHeader(MSG_ONE, TE_CSQC_RACE);
602  WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
603  if(e == oth)
604  {
605  WriteInt24_t(MSG_ONE, 0);
606  WriteByte(MSG_ONE, 0);
607  WriteByte(MSG_ONE, 0);
608  }
609  else
610  {
611  WriteInt24_t(MSG_ONE, TIME_ENCODE(time - race_checkpoint_lasttimes[cp]));
612  WriteByte(MSG_ONE, mylaps - lother);
613  WriteByte(MSG_ONE, etof(oth)); // record holder
614  }
615  });
616  }
617 
620  race_checkpoint_lastlaps[cp] = mylaps;
621 
622  if(IS_REAL_CLIENT(oth))
623  {
624  msg_entity = oth;
625  WRITESPECTATABLE_MSG_ONE(msg_entity, {
626  WriteHeader(MSG_ONE, TE_CSQC_RACE);
628  WriteByte(MSG_ONE, race_CheckpointNetworkID(cp)); // checkpoint the player now is at
629  if(e == oth)
630  {
631  WriteInt24_t(MSG_ONE, 0);
632  WriteByte(MSG_ONE, 0);
633  WriteByte(MSG_ONE, 0);
634  }
635  else
636  {
637  WriteInt24_t(MSG_ONE, TIME_ENCODE(time - othtime));
638  WriteByte(MSG_ONE, lother - mylaps);
639  WriteByte(MSG_ONE, etof(e) - 1); // record holder
640  }
641  });
642  }
643  }
644 }
void race_StartCompleting()
Definition: race.qc:1174
entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]
Definition: race.qc:172
float race_timed_checkpoint
Definition: race.qc:177
string GetMapname()
Definition: intermission.qc:18
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
#define GameRules_scoring_add(client, fld, value)
Definition: sv_rules.qh:78
float race_CheckpointNetworkID(float f)
Definition: race.qc:204
#define MAKE_INDEPENDENT_PLAYER(e)
Definition: client.qh:315
float race_completing
Definition: race.qh:27
bool g_race_qualifying
Definition: race.qh:12
const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT
Definition: net_linked.qh:14
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
#define strcpy(this, s)
Definition: string.qh:49
const int RACE_NET_CHECKPOINT_HIT_RACE
Definition: net_linked.qh:13
string race_checkpoint_recordholders[MAX_CHECKPOINTS]
Definition: race.qc:169
#define TIME_ENCODE(t)
Definition: util.qh:61
#define IS_SPEC(v)
Definition: utils.qh:10
entity msg_entity
Definition: progsdefs.qc:63
#define GameRules_scoring_add_team(client, fld, value)
Definition: sv_rules.qh:80
#define NULL
Definition: post.qh:17
float race_checkpoint_records[MAX_CHECKPOINTS]
Definition: race.qc:168
float race_checkpoint_lasttimes[MAX_CHECKPOINTS]
Definition: race.qc:170
float race_completed
Definition: race.qh:25
void ClientData_Touch(entity e)
Definition: client.qc:171
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
float race_checkpoint_lastlaps[MAX_CHECKPOINTS]
Definition: race.qc:171
float time
Definition: csprogsdefs.qc:16
void race_setTime(string map, float t, string myuid, string mynetname, entity e, bool showmessage)
Definition: race.qc:365
#define IS_PLAYER(v)
Definition: utils.qh:9
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_setTime()

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

Definition at line 365 of file race.qc.

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

Referenced by ctf_CaptureRecord(), and race_SendTime().

366 {
367  // netname only used TEMPORARILY for printing
368  int newpos = race_readPos(map, t);
369 
370  int player_prevpos = 0;
371  for(int i = 1; i <= RANKINGS_CNT; ++i)
372  {
373  if(race_readUID(map, i) == myuid)
374  player_prevpos = i;
375  }
376 
377  float oldrec;
378  string oldrec_holder;
379  if (player_prevpos && (player_prevpos < newpos || !newpos))
380  {
381  oldrec = race_readTime(GetMapname(), player_prevpos);
382  race_SendStatus(0, e); // "fail"
383  if(showmessage)
384  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec);
385  return;
386  }
387  else if (!newpos)
388  {
389  // no ranking, time worse than the worst ranked
390  oldrec = race_readTime(GetMapname(), RANKINGS_CNT);
391  race_SendStatus(0, e); // "fail"
392  if(showmessage)
393  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec);
394  return;
395  }
396 
397  // if we didn't hit a return yet, we have a new record!
398 
399  // if the player does not have a UID we can unfortunately not store the record, as the rankings system relies on UIDs
400  if(myuid == "")
401  {
402  if(showmessage)
403  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t);
404  return;
405  }
406 
407  if(uid2name(myuid) == "^1Unregistered Player")
408  {
409  if(showmessage)
410  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_NAME, mynetname, t);
411  return;
412  }
413 
414  oldrec = race_readTime(GetMapname(), newpos);
415  oldrec_holder = race_readName(GetMapname(), newpos);
416 
417  // store new ranking
418  race_writeTime(GetMapname(), t, myuid);
419 
420  if (newpos == 1 && showmessage)
421  {
424  }
425 
426  race_SendRanking(newpos, player_prevpos, 0, MSG_ALL);
427  strcpy(rankings_reply, getrankings());
428 
429  if(newpos == player_prevpos)
430  {
431  if(showmessage)
432  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec);
433  if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
434  else { race_SendStatus(1, e); } // "new time"
435  }
436  else if(oldrec == 0)
437  {
438  if(showmessage)
439  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t);
440  if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
441  else { race_SendStatus(2, e); } // "new rank"
442  }
443  else
444  {
445  if(showmessage)
446  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec);
447  if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
448  else { race_SendStatus(2, e); } // "new rank"
449  }
450 }
string getrankings()
Definition: getreplies.qc:46
void race_writeTime(string map, float t, string myuid)
Definition: race.qc:100
float race_readPos(string map, float t)
Definition: race.qc:88
string uid2name(string myuid)
Definition: race.qc:36
string GetMapname()
Definition: intermission.qc:18
string race_readUID(string map, float pos)
Definition: race.qc:83
void write_recordmarker(entity pl, float tstart, float dt)
Definition: race.qc:57
#define TIME_DECODE(n)
Definition: util.qh:62
#define strcpy(this, s)
Definition: string.qh:49
void race_SendStatus(float id, entity e)
Definition: race.qc:346
void race_send_recordtime(float msg)
Definition: race.qc:251
float race_readTime(string map, float pos)
Definition: race.qc:78
#define NULL
Definition: post.qh:17
string race_readName(string map, float pos)
Definition: race.qc:138
float time
Definition: csprogsdefs.qc:16
void race_SendRanking(float pos, float prevpos, float del, float msg)
Definition: race.qc:285
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_SpeedAwardFrame()

void race_SpeedAwardFrame ( entity  player)

Definition at line 296 of file race.qc.

References db_put(), 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().

297 {
298  if (IS_OBSERVER(player))
299  return;
300 
301  if(vdist(player.velocity - player.velocity_z * '0 0 1', >, speedaward_speed))
302  {
303  speedaward_speed = vlen(player.velocity - player.velocity_z * '0 0 1');
304  speedaward_holder = player.netname;
305  speedaward_uid = player.crypto_idfp;
307  }
309  {
313  {
320  }
321  }
322 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
string speedaward_uid
Definition: race.qh:59
string GetMapname()
Definition: intermission.qc:18
float ServerProgsDB
Definition: world.qh:131
float speedaward_lastupdate
Definition: race.qh:15
string speedaward_alltimebest_uid
Definition: race.qh:63
string speedaward_alltimebest_holder
Definition: race.qh:62
#define IS_OBSERVER(v)
Definition: utils.qh:11
void race_send_speedaward_alltimebest(float msg)
Definition: race.qc:268
void race_send_speedaward(float msg)
Definition: race.qc:259
float speedaward_alltimebest
Definition: race.qh:61
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float speedaward_speed
Definition: race.qh:57
float speedaward_lastsent
Definition: race.qh:14
bool intermission_running
Definition: intermission.qh:9
float time
Definition: csprogsdefs.qc:16
string speedaward_holder
Definition: race.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_StartCompleting()

void race_StartCompleting ( )

Definition at line 1174 of file race.qc.

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

Referenced by InitiateSuddenDeath(), and race_SendTime().

1175 {
1176  race_completing = 1;
1177  FOREACH_CLIENT(IS_PLAYER(it) && IS_DEAD(it), { race_AbandonRaceCheck(it); });
1178 }
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
float race_completing
Definition: race.qh:27
#define IS_DEAD(s)
Definition: utils.qh:26
#define IS_PLAYER(v)
Definition: utils.qh:9
void race_AbandonRaceCheck(entity p)
Definition: race.qc:1163
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_waypointsprite_visible_for_player()

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

Definition at line 829 of file race.qc.

References entity(), owner, and realowner.

Referenced by defrag_waypointsprites(), and spawnfunc().

830 {
831  entity own = this.owner;
832  if(this.realowner)
833  own = this.realowner; // target support
834 
835  if(view.race_checkpoint == -1 || own.race_checkpoint == -2)
836  return true;
837  else if(view.race_checkpoint == own.race_checkpoint)
838  return true;
839  else
840  return false;
841 }
entity() spawn
entity owner
Definition: main.qh:73
entity realowner
Definition: common.qh:25
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ race_writeTime()

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

Definition at line 100 of file race.qc.

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

Referenced by race_setTime().

101 {
102  float newpos;
103  newpos = race_readPos(map, t);
104 
105  float i, prevpos = 0;
106  for(i = 1; i <= RANKINGS_CNT; ++i)
107  {
108  if(race_readUID(map, i) == myuid)
109  prevpos = i;
110  }
111  if (prevpos)
112  {
113  // player improved his existing record, only have to iterate on ranks between new and old recs
114  for (i = prevpos; i > newpos; --i)
115  {
116  db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
117  db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
118  }
119  }
120  else
121  {
122  // player has no ranked record yet
123  for (i = RANKINGS_CNT; i > newpos; --i)
124  {
125  float other_time = race_readTime(map, i - 1);
126  if (other_time) {
127  db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(i)), ftos(other_time));
128  db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
129  }
130  }
131  }
132 
133  // store new time itself
134  db_put(ServerProgsDB, strcat(map, record_type, "time", ftos(newpos)), ftos(t));
135  db_put(ServerProgsDB, strcat(map, record_type, "crypto_idfp", ftos(newpos)), myuid);
136 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
float race_readPos(string map, float t)
Definition: race.qc:88
float ServerProgsDB
Definition: world.qh:131
string race_readUID(string map, float pos)
Definition: race.qc:83
string record_type
Definition: world.qh:49
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
float race_readTime(string map, float pos)
Definition: race.qc:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spawnfunc() [1/6]

spawnfunc ( trigger_race_checkpoint  )

Definition at line 1046 of file race.qc.

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

1047 {
1048  vector o;
1049  if(!g_race && !g_cts) { delete(this); return; }
1050 
1052 
1053  this.use = checkpoint_use;
1054  if (!(this.spawnflags & 1))
1055  settouch(this, checkpoint_touch);
1056 
1057  o = (this.absmin + this.absmax) * 0.5;
1058  tracebox(o, PL_MIN_CONST, PL_MAX_CONST, o - '0 0 1' * (o.z - this.absmin.z), MOVE_NORMAL, this);
1060  this.nearestwaypointtimeout = -1;
1061 
1062  if(this.message == "")
1063  this.message = "went backwards";
1064  if (this.message2 == "")
1065  this.message2 = "was pushed backwards by";
1066  if (this.race_penalty_reason == "")
1067  this.race_penalty_reason = "missing a checkpoint";
1068 
1069  this.race_checkpoint = this.cnt;
1070 
1072  {
1074  if(this.spawnflags & 8)
1076  else
1078  }
1079 
1080  if(!this.race_penalty)
1081  {
1082  if(this.race_checkpoint)
1083  WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, this, sprite, RADARICON_NONE);
1084  else
1085  WaypointSprite_SpawnFixed(WP_RaceStartFinish, o, this, sprite, RADARICON_NONE);
1086  }
1087 
1088  this.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
1090 
1091  if (!g_racecheckpoints)
1093  IL_PUSH(g_racecheckpoints, this);
1094 
1095  // trigger_race_checkpoint_verify checks this list too
1096  if (!g_race_targets)
1097  g_race_targets = IL_NEW();
1098 
1099  InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
1100 }
float nearestwaypointtimeout
Definition: api.qh:53
vector trigger_race_checkpoint_spawn_evalfunc(entity this, entity player, entity spot, vector current)
Definition: race.qc:1015
#define EXACTTRIGGER_INIT
Definition: common.qh:117
float race_timed_checkpoint
Definition: race.qc:177
#define IL_NEW()
spawn_evalfunc_t spawn_evalfunc
Definition: spawnpoints.qh:28
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
float race_highest_checkpoint
Definition: race.qc:176
void checkpoint_use(entity this, entity actor, entity trigger)
Definition: race.qc:821
float spawnflags
Definition: progsdefs.qc:191
vector absmax
Definition: csprogsdefs.qc:92
float race_checkpoint
Definition: race.qc:163
float cnt
Definition: powerups.qc:24
#define g_cts
Definition: cts.qh:36
#define g_race
Definition: race.qh:46
IntrusiveList g_race_targets
Definition: race.qc:68
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void waypoint_spawnforitem_force(entity e, vector org)
Definition: waypoints.qc:1978
entity sprite
Definition: race.qc:166
IntrusiveList g_racecheckpoints
Definition: race.qc:69
bool race_waypointsprite_visible_for_player(entity this, entity player, entity view)
Definition: race.qc:829
string message
Definition: powerups.qc:19
void checkpoint_touch(entity this, entity toucher)
Definition: race.qc:815
void trigger_race_checkpoint_verify(entity this)
Definition: race.qc:869
vector trace_endpos
Definition: csprogsdefs.qc:37
vector(float skel, float bonenum) _skel_get_boneabs_hidden
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
#define use
Definition: csprogsdefs.qh:50
vector absmin
Definition: csprogsdefs.qc:92
string race_penalty_reason
Definition: race.qc:162
float race_penalty
Definition: race.qc:160
+ Here is the call graph for this function:

◆ spawnfunc() [2/6]

spawnfunc ( target_checkpoint  )

Definition at line 1153 of file race.qc.

References target_checkpoint_setup().

1154 {
1155  // xonotic defrag entity
1157 }
void target_checkpoint_setup(entity this)
Definition: race.qc:1102
+ Here is the call graph for this function:

◆ spawnfunc() [3/6]

spawnfunc ( target_startTimer  )

Definition at line 1160 of file race.qc.

References target_checkpoint_setup().

1160 { target_checkpoint_setup(this); }
void target_checkpoint_setup(entity this)
Definition: race.qc:1102
+ Here is the call graph for this function:

◆ spawnfunc() [4/6]

spawnfunc ( target_stopTimer  )

Definition at line 1161 of file race.qc.

References target_checkpoint_setup().

1161 { target_checkpoint_setup(this); }
void target_checkpoint_setup(entity this)
Definition: race.qc:1102
+ Here is the call graph for this function:

◆ spawnfunc() [5/6]

spawnfunc ( info_player_race  )

Definition at line 1198 of file race.qc.

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

1199 {
1200  if(!g_race && !g_cts) { delete(this); return; }
1201  ++race_spawns;
1202  spawnfunc_info_player_deathmatch(this);
1203 
1208 }
float race_place
Definition: race.qh:23
float race_spawns
Definition: race.qh:17
#define g_cts
Definition: cts.qh:36
#define g_race
Definition: race.qh:46
float race_highest_place_spawn
Definition: race.qh:18
float race_lowest_place_spawn
Definition: race.qh:19

◆ spawnfunc() [6/6]

spawnfunc ( trigger_race_penalty  )

Definition at line 1272 of file race.qc.

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

1273 {
1274  // TODO: find out why this wasnt done:
1275  //if(!g_cts && !g_race) { remove(this); return; }
1276 
1278 
1279  this.use = penalty_use;
1280  if (!(this.spawnflags & 1))
1281  settouch(this, penalty_touch);
1282 
1283  if (this.race_penalty_reason == "")
1284  this.race_penalty_reason = "missing a checkpoint";
1285  if (!this.race_penalty)
1286  this.race_penalty = 5;
1287 }
#define EXACTTRIGGER_INIT
Definition: common.qh:117
void penalty_use(entity this, entity actor, entity trigger)
Definition: race.qc:1267
float spawnflags
Definition: progsdefs.qc:191
void penalty_touch(entity this, entity toucher)
Definition: race.qc:1257
#define use
Definition: csprogsdefs.qh:50
string race_penalty_reason
Definition: race.qc:162
float race_penalty
Definition: race.qc:160
+ Here is the call graph for this function:

◆ target_checkpoint_setup()

void target_checkpoint_setup ( entity  this)

Definition at line 1102 of file race.qc.

References absmax, absmin, checkpoint_touch(), checkpoint_use(), classname, defrag_ents, EXACTTRIGGER_INIT, g_cts, g_race, IL_NEW, IL_PUSH(), InitializeEntity(), message, MOVE_NORMAL, nearestwaypointtimeout, origin, race_checkpoint, race_penalty_reason, race_timed_checkpoint, spawnflags, targetname, trace_endpos, trigger_race_checkpoint_verify(), use, vector(), and waypoint_spawnforitem_force().

Referenced by spawnfunc().

1103 {
1104  if(!g_race && !g_cts) { delete(this); return; }
1105  defrag_ents = 1;
1106 
1107  // if this is targeted, then it probably isn't a trigger
1108  bool is_trigger = this.targetname == "";
1109 
1110  if(is_trigger)
1112 
1113  this.use = checkpoint_use;
1114  if (is_trigger && !(this.spawnflags & 1))
1115  settouch(this, checkpoint_touch);
1116 
1117  vector org = this.origin;
1118 
1119  // bots should only pathfind to this if it is a valid touchable trigger
1120  if(is_trigger)
1121  {
1122  org = (this.absmin + this.absmax) * 0.5;
1123  tracebox(org, PL_MIN_CONST, PL_MAX_CONST, org - '0 0 1' * (org.z - this.absmin.z), MOVE_NORMAL, this);
1125  this.nearestwaypointtimeout = -1;
1126  }
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  if(this.classname == "target_startTimer")
1136  this.race_checkpoint = 0;
1137  else
1138  this.race_checkpoint = -2;
1139 
1141 
1142  if (!g_race_targets)
1143  g_race_targets = IL_NEW();
1144  IL_PUSH(g_race_targets, this);
1145 
1146  // trigger_race_checkpoint_verify checks this list too
1147  if (!g_racecheckpoints)
1149 
1150  InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
1151 }
float nearestwaypointtimeout
Definition: api.qh:53
#define EXACTTRIGGER_INIT
Definition: common.qh:117
float race_timed_checkpoint
Definition: race.qc:177
#define IL_NEW()
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
void checkpoint_use(entity this, entity actor, entity trigger)
Definition: race.qc:821
origin
Definition: ent_cs.qc:114
string classname
Definition: csprogsdefs.qc:107
float spawnflags
Definition: progsdefs.qc:191
vector absmax
Definition: csprogsdefs.qc:92
float race_checkpoint
Definition: race.qc:163
#define g_cts
Definition: cts.qh:36
#define g_race
Definition: race.qh:46
IntrusiveList g_race_targets
Definition: race.qc:68
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void waypoint_spawnforitem_force(entity e, vector org)
Definition: waypoints.qc:1978
IntrusiveList g_racecheckpoints
Definition: race.qc:69
string message
Definition: powerups.qc:19
void checkpoint_touch(entity this, entity toucher)
Definition: race.qc:815
void trigger_race_checkpoint_verify(entity this)
Definition: race.qc:869
vector trace_endpos
Definition: csprogsdefs.qc:37
vector(float skel, float bonenum) _skel_get_boneabs_hidden
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
string targetname
Definition: progsdefs.qc:194
#define use
Definition: csprogsdefs.qh:50
vector absmin
Definition: csprogsdefs.qc:92
string race_penalty_reason
Definition: race.qc:162
float defrag_ents
Definition: race.qc:179
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ trigger_race_checkpoint_spawn_evalfunc()

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

Definition at line 1015 of file race.qc.

References g_race_qualifying, race_checkpoint, race_highest_place_spawn, race_lowest_place_spawn, and SPAWN_PRIO_RACE_PREVIOUS_SPAWN.

Referenced by spawnfunc().

1016 {
1017  if(g_race_qualifying)
1018  {
1019  // spawn at first
1020  if(this.race_checkpoint != 0)
1021  return '-1 0 0';
1022  if(spot.race_place != race_lowest_place_spawn)
1023  return '-1 0 0';
1024  }
1025  else
1026  {
1027  if(this.race_checkpoint != player.race_respawn_checkpoint)
1028  return '-1 0 0';
1029  // try reusing the previous spawn
1030  if(this == player.race_respawn_spotref || spot == player.race_respawn_spotref)
1031  current.x += SPAWN_PRIO_RACE_PREVIOUS_SPAWN;
1032  if(this.race_checkpoint == 0)
1033  {
1034  int pl = player.race_place;
1035  if(pl > race_highest_place_spawn)
1036  pl = 0;
1037  if(pl == 0 && !player.race_started)
1038  pl = race_highest_place_spawn; // use last place if he has not even touched finish yet
1039  if(spot.race_place != pl)
1040  return '-1 0 0';
1041  }
1042  }
1043  return current;
1044 }
bool g_race_qualifying
Definition: race.qh:12
float race_checkpoint
Definition: race.qc:163
float race_highest_place_spawn
Definition: race.qh:18
const int SPAWN_PRIO_RACE_PREVIOUS_SPAWN
Definition: spawnpoints.qh:12
float race_lowest_place_spawn
Definition: race.qh:19
+ Here is the caller graph for this function:

◆ trigger_race_checkpoint_verify()

void trigger_race_checkpoint_verify ( entity  this)

Definition at line 869 of file race.qc.

References argv(), classname, defrag_ents, defragcpexists, entity(), error(), fclose(), fgets(), FILE_READ, find(), fopen(), ftos(), g_race, g_race_qualifying, 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(), targetname, and tokenize_console.

Referenced by spawnfunc(), and target_checkpoint_setup().

870 {
871  static bool have_verified;
872  if (have_verified) return;
873  have_verified = true;
874 
875  bool qual = g_race_qualifying;
876 
877  int pl_race_checkpoint = 0;
878  int pl_race_place = 0;
879 
880  if (g_race) {
881  for (int i = 0; i <= race_highest_checkpoint; ++i) {
882  pl_race_checkpoint = race_NextCheckpoint(i);
883 
884  // race only (middle of the race)
885  g_race_qualifying = false;
886  pl_race_place = 0;
887  if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
888  error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for respawning in race) - bailing out"));
889  }
890 
891  if (i == 0) {
892  // qualifying only
893  g_race_qualifying = 1;
894  pl_race_place = race_lowest_place_spawn;
895  if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
896  error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
897  }
898 
899  // race only (initial spawn)
900  g_race_qualifying = 0;
901  for (int p = 1; p <= race_highest_place_spawn; ++p) {
902  pl_race_place = p;
903  if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
904  error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for initially spawning in race) - bailing out"));
905  }
906  }
907  }
908  }
909  } else if (!defrag_ents) {
910  // qualifying only
911  pl_race_checkpoint = race_NextCheckpoint(0);
912  g_race_qualifying = 1;
913  pl_race_place = race_lowest_place_spawn;
914  if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
915  error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
916  }
917  } else {
918  pl_race_checkpoint = race_NextCheckpoint(0);
919  g_race_qualifying = 1;
920  pl_race_place = 0; // there's only one spawn on defrag maps
921 
922  // check if a defragcp file already exists, then read it and apply the checkpoint order
923  float fh;
924  float len;
925  string l;
926 
927  defragcpexists = fh = fopen(strcat("maps/", GetMapname(), ".defragcp"), FILE_READ);
928  if (fh >= 0) {
929  while ((l = fgets(fh))) {
930  len = tokenize_console(l);
931  if (len != 2) {
932  defragcpexists = -1; // something's wrong in the defrag cp file, set defragcpexists to -1 so that it will be rewritten when someone finishes
933  continue;
934  }
935  for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) {
936  if (argv(0) == cp.targetname) {
937  cp.race_checkpoint = stof(argv(1));
938  }
939  }
940  }
941  fclose(fh);
942  }
943  }
944 
945  g_race_qualifying = qual;
946 
947  if (race_timed_checkpoint) {
948  if (defrag_ents) {
949  IL_EACH(g_race_targets, it.classname == "target_checkpoint" || it.classname == "target_startTimer" || it.classname == "target_stopTimer",
950  {
951  defrag_waypointsprites(it, it);
952 
953  if(it.classname == "target_checkpoint") {
954  if(it.race_checkpoint == -2)
955  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
956  }
957  });
958  if (defragcpexists != -1) {
959  float largest_cp_id = 0;
960  for (entity cp = NULL; (cp = find(cp, classname, "target_checkpoint"));) {
961  if (cp.race_checkpoint > largest_cp_id) {
962  largest_cp_id = cp.race_checkpoint;
963  }
964  }
965  for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) {
966  cp.race_checkpoint = largest_cp_id + 1; // finish line
967  }
968  race_highest_checkpoint = largest_cp_id + 1;
969  race_timed_checkpoint = largest_cp_id + 1;
970  } else {
971  for (entity cp = NULL; (cp = find(cp, classname, "target_stopTimer"));) {
972  cp.race_checkpoint = 255; // finish line
973  }
975  race_timed_checkpoint = 255;
976  }
977  } else {
978  IL_EACH(g_racecheckpoints, it.sprite,
979  {
980  if (it.race_checkpoint == 0) {
981  WaypointSprite_UpdateSprites(it.sprite, WP_RaceStart, WP_Null, WP_Null);
982  } else if (it.race_checkpoint == race_timed_checkpoint) {
983  WaypointSprite_UpdateSprites(it.sprite, WP_RaceFinish, WP_Null, WP_Null);
984  }
985  });
986  }
987  }
988 
989  if (defrag_ents) { /* The following hack shall be removed when per-player trigger_multiple.wait is implemented for cts */
990  for (entity trigger = NULL; (trigger = find(trigger, classname, "trigger_multiple")); ) {
991  for (entity targ = NULL; (targ = find(targ, targetname, trigger.target)); ) {
992  if (targ.classname == "target_checkpoint" || targ.classname == "target_startTimer" || targ.classname == "target_stopTimer") {
993  trigger.wait = 0;
994  trigger.delay = 0;
995  targ.wait = 0;
996  targ.delay = 0;
997 
998  // These just make the game crash on some maps with oddly shaped triggers.
999  // (on the other hand they used to fix the case when two players ran through a checkpoint at once,
1000  // and often one of them just passed through without being registered. Hope it's fixed in a better way now.
1001  // (happened on item triggers too)
1002  //
1003  //targ.wait = -2;
1004  //targ.delay = 0;
1005 
1006  //setsize(targ, trigger.mins, trigger.maxs);
1007  //setorigin(targ, trigger.origin);
1008  //remove(trigger);
1009  }
1010  }
1011  }
1012  }
1013 }
#define IL_EACH(this, cond, body)
float race_timed_checkpoint
Definition: race.qc:177
string GetMapname()
Definition: intermission.qc:18
entity() spawn
float race_highest_checkpoint
Definition: race.qc:176
const float FILE_READ
Definition: csprogsdefs.qc:231
string classname
Definition: csprogsdefs.qc:107
float race_NextCheckpoint(float f)
Definition: race.qc:182
bool g_race_qualifying
Definition: race.qh:12
#define g_race
Definition: race.qh:46
IntrusiveList g_race_targets
Definition: race.qc:68
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
IntrusiveList g_racecheckpoints
Definition: race.qc:69
#define NULL
Definition: post.qh:17
float defragcpexists
Definition: race.qc:180
#define tokenize_console
Definition: dpextensions.qh:24
entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck)
Definition: spawnpoints.qc:281
float race_highest_place_spawn
Definition: race.qh:18
string targetname
Definition: progsdefs.qc:194
if(IS_DEAD(this))
Definition: impulse.qc:92
float race_lowest_place_spawn
Definition: race.qh:19
float defrag_ents
Definition: race.qc:179
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ uid2name()

string uid2name ( string  myuid)

Definition at line 36 of file race.qc.

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

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

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 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
float ServerProgsDB
Definition: world.qh:131
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
#define db_remove(db, key)
Definition: map.qh:98
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ write_recordmarker()

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

Definition at line 57 of file race.qc.

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

Referenced by ctf_CaptureRecord(), and race_setTime().

58 {
59  GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
60 
61  // also write a marker into demo files for demotc-race-record-extractor to find
62  stuffcmd(pl,
63  strcat(
64  strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
65  " ", ftos(tstart), " ", ftos(dt), "\n"));
66 }
#define TIME_ENCODED_TOSTRING(n)
Definition: util.qh:57
#define TIME_ENCODE(t)
Definition: util.qh:61
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void GameLogEcho(string s)
Definition: gamelog.qc:12
#define stuffcmd(cl,...)
Definition: progsdefs.qh:23
string GetGametype()
Definition: intermission.qc:13
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ defrag_ents

float defrag_ents

◆ defragcpexists

float defragcpexists

Definition at line 180 of file race.qc.

Referenced by checkpoint_passed(), and trigger_race_checkpoint_verify().

◆ g_race_targets

IntrusiveList g_race_targets

Definition at line 68 of file race.qc.

◆ g_racecheckpoints

IntrusiveList g_racecheckpoints

Definition at line 69 of file race.qc.

Referenced by havocbot_role_cts(), and havocbot_role_race().

◆ MAX_CHECKPOINTS

const float MAX_CHECKPOINTS = 255

Definition at line 158 of file race.qc.

Referenced by race_ClearRecords().

◆ race_checkpoint

◆ race_checkpoint_lastlaps

float race_checkpoint_lastlaps[MAX_CHECKPOINTS]

Definition at line 171 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_lastplayers

entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]

Definition at line 172 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_lasttimes

float race_checkpoint_lasttimes[MAX_CHECKPOINTS]

Definition at line 170 of file race.qc.

Referenced by race_SendTime().

◆ race_checkpoint_record

float race_checkpoint_record[MAX_CHECKPOINTS]

Definition at line 174 of file race.qc.

◆ race_checkpoint_recordholders

string race_checkpoint_recordholders[MAX_CHECKPOINTS]

Definition at line 169 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 168 of file race.qc.

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

◆ race_highest_checkpoint

◆ race_lastpenalty

entity race_lastpenalty

Definition at line 164 of file race.qc.

◆ race_penalty

float race_penalty

Definition at line 160 of file race.qc.

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

◆ race_penalty_accumulator

float race_penalty_accumulator

Definition at line 161 of file race.qc.

◆ race_penalty_reason

string race_penalty_reason

◆ race_timed_checkpoint

◆ sprite

entity sprite

Definition at line 166 of file race.qc.

Referenced by defrag_waypointsprites(), and spawnfunc().

◆ stored_netname

string stored_netname

Definition at line 34 of file race.qc.