53 s =
"^1Unregistered Player";
65 " ",
ftos(tstart),
" ",
ftos(dt),
"\n"));
90 for(
int i = 1; i <= RANKINGS_CNT; ++i)
93 if(!mytime || mytime > t)
105 float i, prevpos = 0;
106 for(i = 1; i <= RANKINGS_CNT; ++i)
114 for (i = prevpos; i > newpos; --i)
123 for (i = RANKINGS_CNT; i > newpos; --i)
145 if(
CS_CVAR(player).cvar_cl_allow_uidtracking == 1 &&
CS_CVAR(player).cvar_cl_allow_uid2name == 1)
147 if (!player.stored_netname)
149 if(player.stored_netname != player.netname)
152 strcpy(player.stored_netname, player.netname);
221 int cp = e.race_checkpoint;
223 float myrecordtime = e.race_checkpoint_record[cp];
225 if(recordholder == e.netname)
234 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
244 WriteInt24_t(
MSG_ONE, recordtime);
246 WriteInt24_t(
MSG_ONE, myrecordtime);
254 WriteHeader(msg, TE_CSQC_RACE);
262 WriteHeader(msg, TE_CSQC_RACE);
271 WriteHeader(msg, TE_CSQC_RACE);
279 WriteHeader(msg, TE_CSQC_RACE);
287 WriteHeader(msg, TE_CSQC_RACE);
342 for (
int i = 1; i <= m; ++i)
358 WriteHeader(msg, TE_CSQC_RACE);
370 int player_prevpos = 0;
371 for(
int i = 1; i <= RANKINGS_CNT; ++i)
378 string oldrec_holder;
379 if (player_prevpos && (player_prevpos < newpos || !newpos))
384 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec);
393 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec);
403 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t);
407 if(
uid2name(myuid) ==
"^1Unregistered Player")
410 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_NEW_MISSING_NAME, mynetname, t);
420 if (newpos == 1 && showmessage)
429 if(newpos == player_prevpos)
432 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec);
439 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t);
446 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec);
454 for(
int i = pos; i <= RANKINGS_CNT; ++i)
456 string therank =
ftos(i);
457 if (i == RANKINGS_CNT)
481 t += e.race_penalty_accumulator;
507 if(autocvar_fraglimit)
508 if(l >= autocvar_fraglimit)
513 CS(e).race_completed = 1;
515 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_FINISHED, e.netname);
529 float myrecordtime = e.race_checkpoint_record[cp];
531 if(recordholder == e.netname)
541 if(t < myrecordtime || myrecordtime == 0)
542 e.race_checkpoint_record[cp] = t;
544 if(t < recordtime || recordtime == 0)
568 if(it == e || (
IS_SPEC(it) && it.enemy == e))
571 WriteHeader(MSG_ONE, TE_CSQC_RACE);
572 WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_QUALIFYING);
573 WriteByte(MSG_ONE, race_CheckpointNetworkID(cp));
574 WriteInt24_t(MSG_ONE, t);
575 WriteInt24_t(MSG_ONE, recordtime);
576 WriteInt24_t(MSG_ONE, ((tvalid) ? it.race_checkpoint_record[cp] : 0));
577 WriteString(MSG_ONE, recordholder);
585 float mylaps, lother, othtime;
594 mylaps = lother = othtime = 0;
600 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
626 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
648 e.race_checkpoint = 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;
659 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
667 player = player.owner;
672 if(player.classname ==
"porto")
676 W_Porto_Fail(player, 0);
701 player.porto_forbidden = 2;
710 int cp_amount = 0, largest_cp_id = 0;
711 IL_EACH(g_race_targets, it.classname ==
"target_checkpoint",
714 if(it.race_checkpoint > largest_cp_id)
718 IL_EACH(g_race_targets, it.classname ==
"target_checkpoint",
720 if(it.race_checkpoint == -2)
725 largest_cp_id = it.race_checkpoint;
726 IL_EACH(g_race_targets, it.classname ==
"target_stopTimer",
728 it.race_checkpoint = largest_cp_id + 1;
730 race_highest_checkpoint = largest_cp_id + 1;
731 race_timed_checkpoint = largest_cp_id + 1;
737 IL_EACH(g_race_targets, it.classname ==
"target_stopTimer",
739 it.race_checkpoint = 1;
746 if((player.race_checkpoint == -1 &&
this.race_checkpoint == 0) || (player.race_checkpoint ==
this.race_checkpoint))
750 if(player.race_lastpenalty !=
this)
752 player.race_lastpenalty =
this;
757 if(player.race_penalty)
771 if(player.race_respawn_checkpoint !=
this.race_checkpoint || !player.race_started)
772 player.race_respawn_spotref =
this;
775 player.race_started = 1;
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;
796 IL_EACH(g_race_targets, it.classname ==
"target_checkpoint",
798 fputs(fh, strcat(it.targetname,
" ", ftos(it.race_checkpoint),
"\n"));
811 Damage (player,
this,
this, 10000, DEATH_HURTTRIGGER.m_id,
DMG_NOWEP, player.origin,
'0 0 0');
823 if(trigger.classname ==
"info_player_deathmatch")
835 if(view.race_checkpoint == -1 || own.race_checkpoint == -2)
837 else if(view.race_checkpoint == own.race_checkpoint)
849 entity s = WP_RaceCheckpoint;
850 if (checkpoint.classname ==
"target_startTimer")
852 else if (checkpoint.classname ==
"target_stopTimer")
855 for (
entity t = findchain(
target, targeted.targetname); t; t = t.chain)
859 WaypointSprite_SpawnFixed(s, (t.absmin + t.absmax) * 0.5, t,
sprite, RADARICON_NONE);
860 t.sprite.realowner = checkpoint;
871 static bool have_verified;
872 if (have_verified)
return;
873 have_verified =
true;
877 int pl_race_checkpoint = 0;
878 int pl_race_place = 0;
888 error(
strcat(
"Checkpoint ",
ftos(i),
" misses a spawnpoint with race_place==",
ftos(pl_race_place),
" (used for respawning in race) - bailing out"));
896 error(
strcat(
"Checkpoint ",
ftos(i),
" misses a spawnpoint with race_place==",
ftos(pl_race_place),
" (used for qualifying) - bailing out"));
904 error(
strcat(
"Checkpoint ",
ftos(i),
" misses a spawnpoint with race_place==",
ftos(pl_race_place),
" (used for initially spawning in race) - bailing out"));
915 error(
strcat(
"Checkpoint 0 misses a spawnpoint with race_place==",
ftos(pl_race_place),
" (used for qualifying) - bailing out"));
929 while ((l =
fgets(fh))) {
936 if (
argv(0) == cp.targetname) {
949 IL_EACH(g_race_targets, it.classname ==
"target_checkpoint" || it.classname ==
"target_startTimer" || it.classname ==
"target_stopTimer",
951 defrag_waypointsprites(it, it);
953 if(it.classname ==
"target_checkpoint") {
954 if(it.race_checkpoint == -2)
959 float largest_cp_id = 0;
961 if (cp.race_checkpoint > largest_cp_id) {
962 largest_cp_id = cp.race_checkpoint;
966 cp.race_checkpoint = largest_cp_id + 1;
972 cp.race_checkpoint = 255;
978 IL_EACH(g_racecheckpoints, it.sprite,
980 if (it.race_checkpoint == 0) {
981 WaypointSprite_UpdateSprites(it.sprite, WP_RaceStart, WP_Null, WP_Null);
983 WaypointSprite_UpdateSprites(it.sprite, WP_RaceFinish, WP_Null, WP_Null);
992 if (targ.classname ==
"target_checkpoint" || targ.classname ==
"target_startTimer" || targ.classname ==
"target_stopTimer") {
1030 if(
this == player.race_respawn_spotref || spot == player.race_respawn_spotref)
1034 int pl = player.race_place;
1037 if(pl == 0 && !player.race_started)
1039 if(spot.race_place != pl)
1058 tracebox(o, PL_MIN_CONST, PL_MAX_CONST, o -
'0 0 1' * (o.z -
this.absmin.z),
MOVE_NORMAL,
this);
1063 this.
message =
"went backwards";
1064 if (this.message2 ==
"")
1065 this.message2 =
"was pushed backwards by";
1083 WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o,
this,
sprite, RADARICON_NONE);
1085 WaypointSprite_SpawnFixed(WP_RaceStartFinish, o,
this,
sprite, RADARICON_NONE);
1091 if (!g_racecheckpoints)
1092 g_racecheckpoints =
IL_NEW();
1093 IL_PUSH(g_racecheckpoints,
this);
1096 if (!g_race_targets)
1097 g_race_targets =
IL_NEW();
1123 tracebox(org, PL_MIN_CONST, PL_MAX_CONST, org -
'0 0 1' * (org.z -
this.absmin.z),
MOVE_NORMAL,
this);
1129 this.
message =
"went backwards";
1130 if (this.message2 ==
"")
1131 this.message2 =
"was pushed backwards by";
1135 if(this.
classname ==
"target_startTimer")
1142 if (!g_race_targets)
1143 g_race_targets =
IL_NEW();
1144 IL_PUSH(g_race_targets,
this);
1147 if (!g_racecheckpoints)
1148 g_racecheckpoints =
IL_NEW();
1167 CS(p).race_completed = 1;
1169 Send_Notification(NOTIF_ALL,
NULL, MSG_INFO, INFO_RACE_ABANDONED, p.netname);
1202 spawnfunc_info_player_deathmatch(
this);
1219 float p = it.race_place;
1229 pl.race_penalty_accumulator += penalty;
1234 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
1243 pl.race_penalty =
time + penalty;
1248 WriteHeader(
MSG_ONE, TE_CSQC_RACE);
1260 if(toucher.race_lastpenalty !=
this)
1262 toucher.race_lastpenalty =
this;
1307 float bestfraction, fraction;
1309 float nextcpindex, lastcpindex;
1311 nextcpindex =
max(e.race_checkpoint, 0);
1312 lastcpindex = e.race_respawn_checkpoint;
1313 lastcp = e.race_respawn_spotref;
1315 if(nextcpindex == lastcpindex)
1319 IL_EACH(g_racecheckpoints,
true,
1321 if(it.race_checkpoint != lastcpindex)
1326 o0 = (it.absmin + it.absmax) * 0.5;
1327 IL_EACH(g_racecheckpoints,
true,
1329 if(it.race_checkpoint != nextcpindex)
1331 o1 = (it.absmin + it.absmax) * 0.5;
1334 fraction =
bound(0.0001,
vlen(e.origin - o1) /
vlen(o0 - o1), 1);
1335 if(fraction < bestfraction)
1336 bestfraction = fraction;
void race_SendAll(entity player, bool only_rankings)
float race_PreviousCheckpoint(float f)
float nearestwaypointtimeout
#define IL_EACH(this, cond, body)
void race_StartCompleting()
ERASEABLE void db_put(int db, string key, string value)
void race_SendNextCheckpoint(entity e, float spec)
vector trigger_race_checkpoint_spawn_evalfunc(entity this, entity player, entity spot, vector current)
float race_checkpoint_record[MAX_CHECKPOINTS]
#define EXACTTRIGGER_INIT
entity race_checkpoint_lastplayers[MAX_CHECKPOINTS]
void race_deleteTime(string map, float pos)
void race_writeTime(string map, float t, string myuid)
float race_timed_checkpoint
int autocvar_g_cts_send_rankings_cnt
float race_readPos(string map, float t)
string uid2name(string myuid)
#define EXACTTRIGGER_TOUCH(e, t)
spawn_evalfunc_t spawn_evalfunc
const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING
float speedaward_lastupdate
ClientState CS(Client this)
#define FOREACH_CLIENT(cond, body)
string speedaward_alltimebest_uid
string speedaward_alltimebest_holder
#define GameRules_scoring_add(client, fld, value)
string race_readUID(string map, float pos)
void race_checkAndWriteName(entity player)
const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING
float race_highest_checkpoint
void SUB_UseTargets(entity this, entity actor, entity trigger)
void defrag_waypointsprites(entity targeted, entity checkpoint)
void penalty_use(entity this, entity actor, entity trigger)
void checkpoint_use(entity this, entity actor, entity trigger)
limitations: NULL cannot be present elements can only be present once a maximum of IL_MAX lists can e...
float race_CheckpointNetworkID(float f)
const int RACE_NET_SPEED_AWARD
#define MAKE_INDEPENDENT_PLAYER(e)
float race_NextCheckpoint(float f)
#define TIME_ENCODED_TOSTRING(n)
void race_send_speedaward_alltimebest(float msg)
void write_recordmarker(entity pl, float tstart, float dt)
const int RACE_NET_SERVER_RECORD
const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
void race_send_speedaward(float msg)
#define IS_REAL_CLIENT(v)
entity race_respawn_spotref
void race_SendStatus(float id, entity e)
void race_SendTime(entity e, float cp, float t, float tvalid)
const int RACE_NET_CHECKPOINT_HIT_RACE
string race_checkpoint_recordholders[MAX_CHECKPOINTS]
void penalty_touch(entity this, entity toucher)
const int RACE_NET_RANKINGS_CNT
void target_checkpoint_setup(entity this)
IntrusiveList g_race_targets
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
spawnfunc(trigger_race_checkpoint)
const int RACE_NET_SERVER_RANKINGS
void Portal_ClearAll(entity own)
float speedaward_alltimebest
void waypoint_spawnforitem_force(entity e, vector org)
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 checkpoint_passed(entity this, entity player)
IntrusiveList g_racecheckpoints
#define GameRules_scoring_add_team(client, fld, value)
bool autocvar_g_allow_checkpoints
void race_send_recordtime(float msg)
float race_readTime(string map, float pos)
void race_SpeedAwardFrame(entity player)
bool race_waypointsprite_visible_for_player(entity this, entity player, entity view)
void race_PreparePlayer(entity this)
void checkpoint_touch(entity this, entity toucher)
void trigger_race_checkpoint_verify(entity this)
const int RACE_NET_PENALTY_QUALIFYING
float race_checkpoint_records[MAX_CHECKPOINTS]
const int RACE_NET_SPEED_AWARD_BEST
const int RACE_NET_SERVER_STATUS
void GameLogEcho(string s)
ERASEABLE string db_get(int db, string key)
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float race_checkpoint_lasttimes[MAX_CHECKPOINTS]
entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck)
void InitializeEntity(entity e, void(entity this) func, int order)
string race_readName(string map, float pos)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
void ClientData_Touch(entity e)
float race_respawn_checkpoint
void race_InitSpectator()
const int RACE_NET_PENALTY_RACE
float race_highest_place_spawn
#define MUTATOR_CALLHOOK(id,...)
void race_ClearTime(entity e)
float race_penalty_accumulator
void race_RetractPlayer(entity this)
float speedaward_lastsent
vector trace_plane_normal
bool intermission_running
float race_checkpoint_lastlaps[MAX_CHECKPOINTS]
const float MAX_CHECKPOINTS
float race_GetFractionalLapCount(entity e)
string race_penalty_reason
#define db_remove(db, key)
void race_SendRanking(float pos, float prevpos, float del, float msg)
void race_setTime(string map, float t, string myuid, string mynetname, entity e, bool showmessage)
void race_send_rankings_cnt(float msg)
const int RACE_NET_CHECKPOINT_CLEAR
const int SPAWN_PRIO_RACE_PREVIOUS_SPAWN
float race_lowest_place_spawn
void race_AbandonRaceCheck(entity p)