]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/race.qc
new cvar g_race_teams
[divverent/nexuiz.git] / data / qcsrc / server / race.qc
1 .float race_checkpoint; // player: next checkpoint that has to be reached
2 .float race_laptime;
3
4 .entity sprite;
5
6 float race_checkpoint_records[256];
7 string race_checkpoint_recordholders[256];
8
9 float race_highest_checkpoint;
10
11 void race_SendNextCheckpoint(entity e)
12 {
13         float recordtime;
14         string recordholder;
15         float cp;
16
17         if(clienttype(e) != CLIENTTYPE_REAL)
18                 return;
19
20         if(!e.race_laptime)
21                 return;
22
23         cp = e.race_checkpoint;
24         recordtime = race_checkpoint_records[cp];
25         recordholder = race_checkpoint_recordholders[cp];
26         /*
27         recordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/", ftos(cp), "/time")));
28         recordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/", ftos(cp), "/netname"));
29         */
30         if(recordholder == e.netname)
31                 recordholder = "";
32
33         msg_entity = e;
34         WriteByte(MSG_ONE, SVC_TEMPENTITY);
35         WriteByte(MSG_ONE, TE_CSQC_RACE);
36         WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT);
37         WriteByte(MSG_ONE, cp); // checkpoint the player will be at next
38         WriteShort(MSG_ONE, recordtime);
39         WriteString(MSG_ONE, recordholder);
40 }
41
42 void race_SendTime(entity e, float cp, float t, float tvalid)
43 {
44         t = floor(0.5 + 10 * t); // make integer
45
46         if(tvalid)
47         if(cp == 0) // finish line
48         {
49                 float s;
50                 s = PlayerScore_Add(e, SP_RACE_FASTEST, 0);
51                 if(!s || t < s)
52                         PlayerScore_Add(e, SP_RACE_FASTEST, t - s);
53                 PlayerTeamScore_Add(e, SP_RACE_LAPS, ST_RACE_LAPS, 1);
54         }
55
56         float recordtime;
57         string recordholder;
58
59         if(tvalid)
60         {
61                 recordtime = race_checkpoint_records[cp];
62                 recordholder = strcat1(race_checkpoint_recordholders[cp]); // make a tempstring copy, as we'll possibly strunzone it!
63                 if(recordholder == e.netname)
64                         recordholder = "";
65
66                 if(t < recordtime || recordtime == 0)
67                 {
68                         race_checkpoint_records[cp] = t;
69                         if(race_checkpoint_recordholders[cp])
70                                 strunzone(race_checkpoint_recordholders[cp]);
71                         race_checkpoint_recordholders[cp] = strzone(e.netname);
72                         if(cp == 0)
73                         {
74                                 float grecordtime;
75                                 string grecordholder;
76                                 grecordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/time")));
77                                 grecordholder = db_get(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"));
78                                 if(grecordholder == e.netname)
79                                         grecordholder = "";
80                                 if(grecordtime == 0)
81                                 {
82                                         bprint(e.netname, "^7 set the all-time fastest lap record with ", mmsss(t), "\n");
83                                         db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
84                                         db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
85                                 }
86                                 else if(t < grecordtime)
87                                 {
88                                         if(grecordholder == "")
89                                                 bprint(e.netname, "^7 broke his all-time fastest lap record with ", mmsss(t), "\n");
90                                         else
91                                                 bprint(e.netname, "^7 broke ", grecordholder, "^7's all-time fastest lap record with ", mmsss(t), "\n");
92                                         db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
93                                         db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
94                                 }
95                                 else
96                                 {
97                                         if(grecordholder == "")
98                                                 bprint(e.netname, "^7's new fastest lap could not break his all-time fastest lap record of ", mmsss(grecordtime), "\n");
99                                         else
100                                                 bprint(e.netname, "^7's new fastest lap could not break ", grecordholder, "^7's all-time fastest lap record of ", mmsss(grecordtime), "\n");
101                                 }
102                         }
103
104                         entity p;
105                         FOR_EACH_REALPLAYER(p)
106                                 if(p.race_checkpoint == cp)
107                                         race_SendNextCheckpoint(p);
108                 }
109         }
110         else
111         {
112                 // dummies
113                 t = 0;
114                 recordtime = 0;
115                 recordholder = "";
116         }
117
118         if(clienttype(e) != CLIENTTYPE_REAL)
119                 return;
120
121         msg_entity = e;
122         WriteByte(MSG_ONE, SVC_TEMPENTITY);
123         WriteByte(MSG_ONE, TE_CSQC_RACE);
124         WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT);
125         WriteByte(MSG_ONE, cp); // checkpoint the player now is at
126         WriteShort(MSG_ONE, t); // time to that intermediate
127         WriteShort(MSG_ONE, recordtime); // previously best time
128         WriteString(MSG_ONE, recordholder); // record holder
129 }
130
131 void race_ClearTime(entity e)
132 {
133         e.race_checkpoint = -1;
134         e.race_laptime = 0;
135
136         if(clienttype(e) != CLIENTTYPE_REAL)
137                 return;
138
139         msg_entity = e;
140         WriteByte(MSG_ONE, SVC_TEMPENTITY);
141         WriteByte(MSG_ONE, TE_CSQC_RACE);
142         WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_CLEAR); // next
143 }
144
145 void checkpoint_touch()
146 {
147         if(other.classname != "player")
148                 return;
149
150         if(other.race_checkpoint == -1 || other.race_checkpoint == self.cnt)
151         {
152                 if(self.cnt == race_highest_checkpoint)
153                         other.race_checkpoint = 0;
154                 else
155                         other.race_checkpoint = self.cnt + 1;
156
157                 race_SendTime(other, self.cnt, time - other.race_laptime, !!other.race_laptime);
158
159                 if(!self.cnt) // finish line
160                         other.race_laptime = time;
161
162                 race_SendNextCheckpoint(other);
163         }
164         else if(other.race_checkpoint == self.cnt + 1)
165         {
166                 // ignored
167         }
168         else if(other.race_checkpoint == 0 && self.cnt == race_highest_checkpoint)
169         {
170                 // ignored
171         }
172         else
173         {
174                 if(self.spawnflags & 4)
175                         Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
176         }
177 }
178
179 void checkpoint_use()
180 {
181         other = activator;
182         checkpoint_touch();
183 }
184
185 float race_waypointsprite_for_player(entity e)
186 {
187         if(e.race_checkpoint == -1)
188                 return self.modelindex;
189         else if(e.race_checkpoint == self.owner.cnt)
190                 return self.modelindex;
191         else
192                 return FALSE;
193 }
194
195 void spawnfunc_trigger_race_checkpoint()
196 {
197         vector o;
198         if(!g_race)
199                 return;
200         InitTrigger();
201         if(self.targetname)
202                 self.use = checkpoint_use;
203         else
204                 self.touch = checkpoint_touch;
205
206         o = (self.absmin + self.absmax) * 0.5;
207         tracebox(o, PL_MIN, PL_MAX, o - '0 0 1' * (o_z - self.absmin_z), MOVE_NORMAL, self);
208         self.nearestwaypoint = waypoint_spawn(trace_endpos, trace_endpos, WAYPOINTFLAG_GENERATED);
209         self.nearestwaypointtimeout = time + 1000000000;
210
211         if(!self.message)
212                 self.message = "went backwards";
213
214         if(self.cnt > race_highest_checkpoint)
215                 race_highest_checkpoint = self.cnt;
216
217         if(self.cnt)
218         {
219                 precache_model("models/sprites/race-checkpoint.sp2");
220                 WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite);
221         }
222         else
223         {
224                 precache_model("models/sprites/race-finish.sp2");
225                 WaypointSprite_SpawnFixed("race-finish", o, self, sprite);
226         }
227         self.sprite.waypointsprite_for_player = race_waypointsprite_for_player;
228 }
229
230 void race_PreparePlayer()
231 {
232         if(!g_race)
233                 return;
234         race_ClearTime(self);
235 }