]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_client.c
nextthink = -1 is bad, set it to 0
[divverent/nexuiz.git] / qcsrc / gamec / cl_client.c
1
2 void info_player_start (void)
3 {
4         self.classname = "info_player_deathmatch";
5 }
6
7 void info_player_deathmatch (void)
8 {
9 }
10
11 /*
12 =============
13 SelectSpawnPoint
14
15 Finds a point to respawn
16 =============
17 */
18 entity SelectSpawnPoint (void)
19 {
20         local entity spot, thing;
21         local float pcount;
22
23         spot = find (world, classname, "testplayerstart");
24         if (spot)
25                 return spot;
26
27         spot = lastspawn;
28         while (1)
29         {
30                 spot = find(spot, classname, "info_player_deathmatch");
31                 if (spot != world)
32                 {
33                         if (spot == lastspawn)
34                                 return lastspawn;
35                         pcount = 0;
36                         thing = findradius(spot.origin, 70);
37                         while(thing)
38                         {
39                                 if (thing.classname == "player")
40                                         pcount = pcount + 1;
41                                 thing = thing.chain;
42                         }
43                         if (pcount == 0)
44                         {
45                                 lastspawn = spot;
46                                 return spot;
47                         }
48                 }
49         }
50
51         spot = find (world, classname, "info_player_start");
52         if (!spot)
53                 error ("PutClientInServer: no info_player_start on level");
54         
55         return spot;
56 }
57
58
59 /*
60 =============
61 PutClientInServer
62
63 Called when a client spawns in the server
64 =============
65 */
66 void PutClientInServer (void)
67 {
68         entity  spot;
69         float mdlrandom;
70
71         spot = SelectSpawnPoint ();
72
73         self.classname = "player";
74         self.movetype = MOVETYPE_WALK;
75         self.solid = SOLID_SLIDEBOX;
76         self.flags = FL_CLIENT;
77         self.takedamage = DAMAGE_YES;
78         self.effects = 0;
79         self.health = 150;
80         self.damageforcescale = 2;
81         self.death_time = 0;
82         self.dead_time = 0;
83         self.dead_frame = 0;
84         self.die_frame = 0;
85         self.alpha = 0;
86         self.scale = 0;
87         self.fade_time = 0;
88         self.pain_frame = 0;
89         self.pain_finished = 0;
90         self.strength_finished = 0;
91         self.invincible_finished = 0;
92         self.speed_finished = 0;
93         self.slowmo_finished = 0;
94         // players have no think function
95         self.think = nullfunction;
96         self.nextthink = 0;
97
98         self.deadflag = DEAD_NO;
99
100         self.view_ofs = PL_VIEW_OFS;
101         self.angles = spot.angles;
102
103         self.viewzoom = 0.6;
104
105         setmodel (self, self.playermodel);
106         setsize (self, PL_MIN, PL_MAX);
107         setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
108         // don't reset back to last position, even if new position is stuck in solid
109         self.oldorigin = self.origin;
110
111 //      self.items = IT_LASER | IT_UZI| IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER;
112 //      self.weapon = IT_UZI;
113
114         if (game & GAME_INSTAGIB)
115         {
116                 self.items = IT_NEX;
117                 self.switchweapon = WEP_NEX;
118                 self.ammo_shells = 0;
119                 self.ammo_nails = 0;
120                 self.ammo_rockets = 0;
121                 self.ammo_cells = 999;
122         }
123         else if (game & GAME_ROCKET_ARENA)
124         {
125                 self.items = IT_ROCKET_LAUNCHER;
126                 self.switchweapon = WEP_ROCKET_LAUNCHER;
127                 self.ammo_shells = 0;
128                 self.ammo_nails = 0;
129                 self.ammo_rockets = 999;
130                 self.ammo_cells = 0;
131         }
132         else
133         {
134                 self.items = IT_LASER | IT_SHOTGUN;
135                 self.switchweapon = WEP_SHOTGUN;
136                 self.ammo_shells = 25;
137                 self.ammo_nails = 0;
138                 self.ammo_rockets = 0;
139                 self.ammo_cells = 0;
140         }
141
142         if (game & GAME_FULLBRIGHT_PLAYERS)
143                 self.effects = EF_FULLBRIGHT;
144
145         self.event_damage = PlayerDamage;
146
147         self.statdraintime = time + 5;
148         self.button0 = self.button1 = self.button2 = self.button3 = 0;
149
150         /*
151         W_UpdateWeapon();
152         W_UpdateAmmo();
153         */
154         CL_SpawnWeaponentity();
155
156         //stuffcmd(self, "chase_active 0");
157 }
158
159 /*
160 =============
161 SetNewParms
162 =============
163 */
164 void SetNewParms (void)
165 {
166
167 }
168
169 /*
170 =============
171 SetChangeParms
172 =============
173 */
174 void SetChangeParms (void)
175 {
176
177 }
178
179 /*
180 =============
181 ClientKill
182
183 Called when a client types 'kill' in the console
184 =============
185 */
186 void ClientKill (void)
187 {
188
189 }
190
191 /*
192 =============
193 ClientConnect
194
195 Called when a client connects to the server
196 =============
197 */
198 void ClientConnect (void)
199 {
200         ClientInRankings();
201         bprint (self.netname);
202         bprint (" connected\n");
203 }
204
205 /*
206 =============
207 ClientDisconnect
208
209 Called when a client disconnects from the server
210 =============
211 */
212 void ClientDisconnect (void)
213 {
214         ClientDisconnected();
215         bprint (self.netname);
216         bprint (" disconnected\n");
217 }
218
219 /*
220 =============
221 PlayerJump
222
223 When you press the jump key
224 =============
225 */
226 void PlayerJump (void)
227 {
228         if (!(self.flags & FL_ONGROUND))
229                 return;
230         if (!(self.flags & FL_JUMPRELEASED))
231                 return;
232
233         if (self.items & IT_SPEED)
234                 self.velocity_z = self.velocity_z + POWERUP_SPEED_JUMPVELOCITY;
235         else
236                 self.velocity_z = self.velocity_z + JUMP_VELOCITY;
237
238         self.flags = self.flags - FL_ONGROUND;
239         self.flags = self.flags - FL_JUMPRELEASED;
240 }
241
242 void respawn(void)
243 {
244         CopyBody();
245         PutClientInServer();
246 }
247
248 void player_powerups (void)
249 {
250         if (self.items & IT_STRENGTH)
251         {
252                 if (time > self.strength_finished)
253                 {
254                         self.items = self.items - (self.items & IT_STRENGTH);
255                         sprint(self, "Strength has worn off\n");
256                 }
257         }
258         else
259         {
260                 if (time < self.strength_finished)
261                 {
262                         self.items = self.items | IT_STRENGTH;
263                         sprint(self, "Strength infuses your weapons with devestating power\n");
264                 }
265         }
266         if (self.items & IT_INVINCIBLE)
267         {
268                 if (time > self.invincible_finished)
269                 {
270                         self.items = self.items - (self.items & IT_INVINCIBLE);
271                         sprint(self, "Invincible has worn off\n");
272                 }
273         }
274         else
275         {
276                 if (time < self.invincible_finished)
277                 {
278                         self.items = self.items | IT_INVINCIBLE;
279                         sprint(self, "Invincible shielding surrounds you\n");
280                 }
281         }
282         if (self.items & IT_SPEED)
283         {
284                 if (time > self.speed_finished)
285                 {
286                         self.items = self.items - (self.items & IT_SPEED);
287                         sprint(self, "Speed has worn off\n");
288                 }
289         }
290         else
291         {
292                 if (time < self.speed_finished)
293                 {
294                         self.items = self.items | IT_SPEED;
295                         sprint(self, "Speed makes you run faster than ever before\n");
296                 }
297         }
298         if (self.items & IT_SLOWMO)
299         {
300                 if (time > self.slowmo_finished)
301                 {
302                         self.items = self.items - (self.items & IT_SLOWMO);
303                         sprint(self, "Slow Motion has worn off\n");
304                 }
305         }
306         else
307         {
308                 if (time < self.slowmo_finished)
309                 {
310                         self.items = self.items | IT_SLOWMO;
311                         sprint(self, "Slow Motion slows time around you\n");
312                 }
313         }
314         /*
315         self.items = self.items - (self.items & (IT_STRENGTH + IT_INVINCIBLE + IT_SLOWMO + IT_SPEED));
316         if (time < self.strength_finished)
317                 self.items = self.items | IT_STRENGTH;
318         if (time < self.invincible_finished)
319                 self.items = self.items | IT_INVINCIBLE;
320         if (time < self.slowmo_finished)
321                 self.items = self.items | IT_SLOWMO;
322         if (time < self.speed_finished)
323                 self.items = self.items | IT_SPEED;
324         */
325 }
326
327 void player_regen (void)
328 {
329         // GAME_REGENERATION does fast health regeneration up to 200. Note that your armour doesn't rot anymore either.
330         if (game & GAME_REGENERATION)
331         {
332                 self.health = self.health + (200 - self.health) * 0.2 * frametime;
333                 self.armorvalue = bound(0, self.armorvalue, 1000);
334         }
335         else
336         {
337                 self.health = bound(0, self.health + (100 - self.health) * 0.05 * frametime, 1000);
338                 if (self.armorvalue > 100)
339                         self.armorvalue = bound(100, self.armorvalue + (100 - self.armorvalue) * 0.05 * frametime, 1000);
340         }
341 }
342
343 /*
344 =============
345 PlayerPreThink
346
347 Called every frame for each client before the physics are run
348 =============
349 */
350 .float attack_finished;
351 void PlayerPreThink (void)
352 {
353         if (BotPreFrame())
354                 return;
355         if (!self.hasaliases)
356             DoAliases();
357
358         if (self.deadflag != DEAD_NO)
359         {
360                 player_anim();
361                 weapon_freeze();
362                 if (self.deadflag == DEAD_DYING)
363                 {
364                         if (time > self.dead_time)
365                                 self.deadflag = DEAD_DEAD;
366                 }
367                 else if (self.deadflag == DEAD_DEAD)
368                 {
369                         if (!self.button0 && !self.button2 && !self.button3)
370                                 self.deadflag = DEAD_RESPAWNABLE;
371                 }
372                 else if (self.deadflag == DEAD_RESPAWNABLE)
373                 {
374                         if (self.button0 || self.button2 || self.button3  || self.button4)
375                                 respawn();
376                 }
377                 return;
378         }
379
380         W_WeaponFrame();
381
382         if (self.button4)
383         {
384                 if (self.viewzoom > 0.4)
385                         self.viewzoom = max (0.4, self.viewzoom - frametime * 2);
386         }
387         else if (self.viewzoom < 1.0)
388                 self.viewzoom = min (1.0, self.viewzoom + frametime);
389
390
391         if (self.button2)
392                 PlayerJump ();
393         else
394                 self.flags = self.flags | FL_JUMPRELEASED;
395
396
397         player_powerups();
398         player_regen();
399         player_anim();
400
401         self.angles_y=self.v_angle_y + 90;   // temp
402
403         if (TetrisPreFrame()) return;
404 }
405
406 /*
407 =============
408 PlayerPostThink
409
410 Called every frame for each client after the physics are run
411 =============
412 */
413 void PlayerPostThink (void)
414 {
415         float soundrandom;
416         if (BotPostFrame())
417                 return;
418         if (self.health > 0)
419         if (self.impulse)
420                 ImpulseCommands ();
421
422         // VorteX: landing on floor, landing damage etc.
423         if (self.flags & FL_ONGROUND)
424         {
425                 if (fabs(self.jump_flag) > 100)
426                 {
427                         if (self.jump_flag < -100 && !self.watertype == CONTENT_WATER) // HitGround
428                         {
429                                 soundrandom = random() * 3;
430                                 if (soundrandom < 1)
431                                         sound (self, CHAN_BODY, "misc/hitground1.wav", 1, ATTN_NORM);
432                                 if (soundrandom < 2)
433                                         sound (self, CHAN_BODY, "misc/hitground2.wav", 1, ATTN_NORM);
434                                 if (soundrandom < 3)
435                                         sound (self, CHAN_BODY, "misc/hitground3.wav", 1, ATTN_NORM);
436                                 if (soundrandom < 4)
437                                         sound (self, CHAN_BODY, "misc/hitground4.wav", 1, ATTN_NORM);
438                                 if (self.jump_flag < -650) // landing damage
439                                 {
440                                         local float dm;
441                                         dm = bound(0, 0.1*(fabs(self.jump_flag) - 600), 20);
442                                         Damage (self, world, world, dm, DEATH_FALL, '0 0 0', '0 0 0');
443                                 }
444                                 self.jump_flag = 0;
445                         }
446                 }
447         }
448         else
449         {
450                 if (self.jump_flag != -10000) // not in falling death
451                 {
452                         self.jump_flag = self.velocity_z;
453                         // check for falling into the void
454                         if (self.jump_flag < -700)
455                         {
456                                 tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 -1'*2048, MOVE_NORMAL, self);
457                                 if (trace_fraction == 1)
458                                 {// VorteX: add player falling sound here
459                                         self.jump_flag = -10000;
460                                         self.lip = time + 1;
461                                 }
462                         }
463                 }
464                 else
465                 {
466                         if (time < self.lip)
467                         {// prevent all inventory drop
468                                 self.weapon = 0;
469                                 Damage (self, world, world, 40000, DEATH_BIGFALL, '0 0 0', '0 0 0');
470                         }
471                 }
472         }
473
474         if (TetrisPostFrame()) return;
475 }