1 .float race_checkpoint; // player: next checkpoint that has to be reached
6 float race_checkpoint_records[256];
7 string race_checkpoint_recordholders[256];
9 float race_highest_checkpoint;
11 float race_NextCheckpoint(float f)
13 if(f >= race_highest_checkpoint)
19 float race_PreviousCheckpoint(float f)
24 return race_highest_checkpoint;
29 void race_SendNextCheckpoint(entity e)
35 if(clienttype(e) != CLIENTTYPE_REAL)
41 cp = e.race_checkpoint;
42 recordtime = race_checkpoint_records[cp];
43 recordholder = race_checkpoint_recordholders[cp];
45 recordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/", ftos(cp), "/time")));
46 recordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/", ftos(cp), "/netname"));
48 if(recordholder == e.netname)
52 WriteByte(MSG_ONE, SVC_TEMPENTITY);
53 WriteByte(MSG_ONE, TE_CSQC_RACE);
54 WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT);
55 WriteByte(MSG_ONE, cp); // checkpoint the player will be at next
56 WriteShort(MSG_ONE, recordtime);
57 WriteString(MSG_ONE, recordholder);
60 void race_SendTime(entity e, float cp, float t, float tvalid)
62 t = floor(0.5 + 10 * t); // make integer
65 if(cp == 0) // finish line
68 s = PlayerScore_Add(e, SP_RACE_FASTEST, 0);
70 PlayerScore_Add(e, SP_RACE_FASTEST, t - s);
71 PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1);
79 recordtime = race_checkpoint_records[cp];
80 recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it!
81 if(recordholder == e.netname)
84 if(t < recordtime || recordtime == 0)
86 race_checkpoint_records[cp] = t;
87 if(race_checkpoint_recordholders[cp])
88 strunzone(race_checkpoint_recordholders[cp]);
89 race_checkpoint_recordholders[cp] = strzone(e.netname);
94 grecordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/time")));
95 grecordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"));
96 if(grecordholder == e.netname)
100 bprint(e.netname, "^7 set the all-time fastest lap record with ", mmsss(t), "\n");
101 db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
102 db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
104 else if(t < grecordtime)
106 if(grecordholder == "")
107 bprint(e.netname, "^7 broke his all-time fastest lap record with ", mmsss(t), "\n");
109 bprint(e.netname, "^7 broke ", grecordholder, "^7's all-time fastest lap record with ", mmsss(t), "\n");
110 db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
111 db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
115 if(grecordholder == "")
116 bprint(e.netname, "^7's new fastest lap could not break his all-time fastest lap record of ", mmsss(grecordtime), "\n");
118 bprint(e.netname, "^7's new fastest lap could not break ", grecordholder, "^7's all-time fastest lap record of ", mmsss(grecordtime), "\n");
123 FOR_EACH_REALPLAYER(p)
124 if(p.race_checkpoint == cp)
125 race_SendNextCheckpoint(p);
136 if(clienttype(e) != CLIENTTYPE_REAL)
140 WriteByte(MSG_ONE, SVC_TEMPENTITY);
141 WriteByte(MSG_ONE, TE_CSQC_RACE);
142 WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT);
143 WriteByte(MSG_ONE, cp); // checkpoint the player now is at
144 WriteShort(MSG_ONE, t); // time to that intermediate
145 WriteShort(MSG_ONE, recordtime); // previously best time
146 WriteString(MSG_ONE, recordholder); // record holder
149 void race_ClearTime(entity e)
151 e.race_checkpoint = -1;
154 if(clienttype(e) != CLIENTTYPE_REAL)
158 WriteByte(MSG_ONE, SVC_TEMPENTITY);
159 WriteByte(MSG_ONE, TE_CSQC_RACE);
160 WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_CLEAR); // next
163 void checkpoint_touch()
165 if(other.classname != "player")
168 if(other.race_checkpoint == -1 || other.race_checkpoint == self.cnt)
170 other.race_checkpoint = race_NextCheckpoint(self.cnt);
172 race_SendTime(other, self.cnt, time - other.race_laptime, !!other.race_laptime);
174 if(!self.cnt) // finish line
175 other.race_laptime = time;
177 race_SendNextCheckpoint(other);
179 else if(other.race_checkpoint == race_NextCheckpoint(self.cnt))
185 if(self.spawnflags & 4)
186 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
190 void checkpoint_use()
196 float race_waypointsprite_for_player(entity e)
198 if(e.race_checkpoint == -1)
199 return self.modelindex;
200 else if(e.race_checkpoint == self.owner.cnt)
201 return self.modelindex;
206 void spawnfunc_trigger_race_checkpoint()
215 self.use = checkpoint_use;
216 if not(self.spawnflags & 1)
217 self.touch = checkpoint_touch;
219 o = (self.absmin + self.absmax) * 0.5;
220 tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o_z - self.absmin_z), MOVE_NORMAL, self);
221 self.nearestwaypoint = waypoint_spawn(trace_endpos, trace_endpos, WAYPOINTFLAG_GENERATED);
222 self.nearestwaypointtimeout = time + 1000000000;
225 self.message = "went backwards";
227 if(self.cnt > race_highest_checkpoint)
228 race_highest_checkpoint = self.cnt;
232 precache_model("models/sprites/race-checkpoint.sp2");
233 WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite);
237 precache_model("models/sprites/race-finish.sp2");
238 WaypointSprite_SpawnFixed("race-finish", o, self, sprite);
240 self.sprite.waypointsprite_for_player = race_waypointsprite_for_player;
243 void race_PreparePlayer()
247 race_ClearTime(self);
250 void spawnfunc_info_player_race (void)
258 spawnfunc_info_player_deathmatch();