]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_client.c
made cl_client.c compile again - you can not assign a string to a float field without...
[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         self.velocity = '0 0 0';
103         self.avelocity = '0 0 0';
104
105         self.viewzoom = 0.6;
106
107         setmodel (self, self.playermodel);
108         self.skin = stof(self.playerskin);
109         setsize (self, PL_MIN, PL_MAX);
110         setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
111         // don't reset back to last position, even if new position is stuck in solid
112         self.oldorigin = self.origin;
113
114 //      self.items = IT_LASER | IT_UZI| IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER;
115 //      self.weapon = IT_UZI;
116
117         if (game & GAME_INSTAGIB)
118         {
119                 self.items = IT_NEX;
120                 self.switchweapon = WEP_NEX;
121                 self.ammo_shells = 0;
122                 self.ammo_nails = 0;
123                 self.ammo_rockets = 0;
124                 self.ammo_cells = 999;
125         }
126         else if (game & GAME_ROCKET_ARENA)
127         {
128                 self.items = IT_ROCKET_LAUNCHER;
129                 self.switchweapon = WEP_ROCKET_LAUNCHER;
130                 self.ammo_shells = 0;
131                 self.ammo_nails = 0;
132                 self.ammo_rockets = 999;
133                 self.ammo_cells = 0;
134         }
135         else
136         {
137                 self.items = IT_LASER | IT_SHOTGUN;
138                 self.switchweapon = WEP_SHOTGUN;
139                 self.ammo_shells = 25;
140                 self.ammo_nails = 0;
141                 self.ammo_rockets = 0;
142                 self.ammo_cells = 0;
143         }
144
145         if (game & GAME_FULLBRIGHT_PLAYERS)
146                 self.effects = EF_FULLBRIGHT;
147
148         self.event_damage = PlayerDamage;
149
150         self.statdraintime = time + 5;
151         self.button0 = self.button1 = self.button2 = self.button3 = 0;
152
153         /*
154         W_UpdateWeapon();
155         W_UpdateAmmo();
156         */
157         CL_SpawnWeaponentity();
158
159         //stuffcmd(self, "chase_active 0");
160 }
161
162 /*
163 =============
164 SetNewParms
165 =============
166 */
167 void SetNewParms (void)
168 {
169
170 }
171
172 /*
173 =============
174 SetChangeParms
175 =============
176 */
177 void SetChangeParms (void)
178 {
179
180 }
181
182 /*
183 =============
184 ClientKill
185
186 Called when a client types 'kill' in the console
187 =============
188 */
189 void ClientKill (void)
190 {
191         Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
192 }
193
194 /*
195 =============
196 ClientConnect
197
198 Called when a client connects to the server
199 =============
200 */
201 void ClientConnect (void)
202 {
203         //ClientInRankings();
204         bprint (self.netname);
205         bprint (" connected\n");
206 }
207
208 /*
209 =============
210 ClientDisconnect
211
212 Called when a client disconnects from the server
213 =============
214 */
215 void ClientDisconnect (void)
216 {
217         //ClientDisconnected();
218         bprint (self.netname);
219         bprint (" disconnected\n");
220 }
221
222 /*
223 =============
224 PlayerJump
225
226 When you press the jump key
227 =============
228 */
229 void PlayerJump (void)
230 {
231         if (self.waterlevel >= 2)
232         {
233                 if (self.watertype == CONTENT_WATER)
234                         self.velocity_z = 200;
235                 else if (self.watertype == CONTENT_SLIME)
236                         self.velocity_z = 80;
237                 else
238                         self.velocity_z = 50;
239
240                 return;
241         }
242
243
244         if (!(self.flags & FL_ONGROUND))
245                 return;
246
247         if (!(self.flags & FL_JUMPRELEASED))
248                 return;
249
250         if (self.items & IT_SPEED)
251                 self.velocity_z = self.velocity_z + POWERUP_SPEED_JUMPVELOCITY;
252         else
253                 self.velocity_z = self.velocity_z + JUMP_VELOCITY;
254
255         self.flags = self.flags - FL_ONGROUND;
256         self.flags = self.flags - FL_JUMPRELEASED;
257 }
258
259 void() WaterMove =
260 {
261         if (self.movetype == MOVETYPE_NOCLIP)
262                 return;
263         if (self.health < 0)
264                 return;
265
266         if (self.waterlevel != 3)
267         {
268                 self.air_finished = time + 12;
269                 self.dmg = 2;
270         }
271         else if (self.air_finished < time)
272         {       // drown!
273                 if (self.pain_finished < time)
274                 {
275                         Damage (self, world, world, 5, DEATH_DROWN, '0 0 0', '0 0 0');
276                         self.pain_finished = time + 0.5;
277                 }
278         }
279
280         if (!self.waterlevel)
281         {
282                 if (self.flags & FL_INWATER)
283                 {
284                         // play leave water sound
285                         sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
286                         self.flags = self.flags - FL_INWATER;
287                 }
288                 return;
289         }
290
291         if (self.watertype == CONTENT_LAVA)
292         {       // do damage
293                 if (self.dmgtime < time)
294                 {
295                         self.dmgtime = time + 0.2;
296                         Damage (self, world, world, 5, DEATH_LAVA, '0 0 0', '0 0 0');
297                 }
298         }
299         else if (self.watertype == CONTENT_SLIME)
300         {       // do damage
301                 if (self.dmgtime < time)
302                 {
303                         self.dmgtime = time + 1;
304                         Damage (self, world, world, 5, DEATH_SLIME, '0 0 0', '0 0 0');
305                 }
306         }
307
308         if ( !(self.flags & FL_INWATER) )
309         {
310
311                 //if (self.watertype == CONTENT_LAVA)
312                 //      sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
313                 //if (self.watertype == CONTENT_WATER)
314                 //      sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
315                 //if (self.watertype == CONTENT_SLIME)
316                 //      sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
317
318                 self.flags = self.flags + FL_INWATER;
319                 self.dmgtime = 0;
320         }
321 };
322
323 void() CheckWaterJump =
324 {
325         local vector start, end;
326
327 // check for a jump-out-of-water
328         makevectors (self.angles);
329         start = self.origin;
330         start_z = start_z + 8;
331         v_forward_z = 0;
332         normalize(v_forward);
333         end = start + v_forward*24;
334         traceline (start, end, TRUE, self);
335         if (trace_fraction < 1)
336         {       // solid at waist
337                 start_z = start_z + self.maxs_z - 8;
338                 end = start + v_forward*24;
339                 self.movedir = trace_plane_normal * -50;
340                 traceline (start, end, TRUE, self);
341                 if (trace_fraction == 1)
342                 {       // open at eye level
343                         self.flags = self.flags | FL_WATERJUMP;
344                         self.velocity_z = 225;
345                         self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
346                         self.teleport_time = time + 2;  // safety net
347                         return;
348                 }
349         }
350 };
351
352
353 void respawn(void)
354 {
355         CopyBody();
356         PutClientInServer();
357 }
358
359 void player_powerups (void)
360 {
361         if (self.items & IT_STRENGTH)
362         {
363                 if (time > self.strength_finished)
364                 {
365                         self.items = self.items - (self.items & IT_STRENGTH);
366                         sprint(self, "Strength has worn off\n");
367                 }
368         }
369         else
370         {
371                 if (time < self.strength_finished)
372                 {
373                         self.items = self.items | IT_STRENGTH;
374                         sprint(self, "Strength infuses your weapons with devestating power\n");
375                 }
376         }
377         if (self.items & IT_INVINCIBLE)
378         {
379                 if (time > self.invincible_finished)
380                 {
381                         self.items = self.items - (self.items & IT_INVINCIBLE);
382                         sprint(self, "Invincible has worn off\n");
383                 }
384         }
385         else
386         {
387                 if (time < self.invincible_finished)
388                 {
389                         self.items = self.items | IT_INVINCIBLE;
390                         sprint(self, "Invincible shielding surrounds you\n");
391                 }
392         }
393         if (self.items & IT_SPEED)
394         {
395                 if (time > self.speed_finished)
396                 {
397                         self.items = self.items - (self.items & IT_SPEED);
398                         sprint(self, "Speed has worn off\n");
399                 }
400         }
401         else
402         {
403                 if (time < self.speed_finished)
404                 {
405                         self.items = self.items | IT_SPEED;
406                         sprint(self, "Speed makes you run faster than ever before\n");
407                 }
408         }
409         if (self.items & IT_SLOWMO)
410         {
411                 if (time > self.slowmo_finished)
412                 {
413                         self.items = self.items - (self.items & IT_SLOWMO);
414                         sprint(self, "Slow Motion has worn off\n");
415                 }
416         }
417         else
418         {
419                 if (time < self.slowmo_finished)
420                 {
421                         self.items = self.items | IT_SLOWMO;
422                         sprint(self, "Slow Motion slows time around you\n");
423                 }
424         }
425         /*
426         self.items = self.items - (self.items & (IT_STRENGTH + IT_INVINCIBLE + IT_SLOWMO + IT_SPEED));
427         if (time < self.strength_finished)
428                 self.items = self.items | IT_STRENGTH;
429         if (time < self.invincible_finished)
430                 self.items = self.items | IT_INVINCIBLE;
431         if (time < self.slowmo_finished)
432                 self.items = self.items | IT_SLOWMO;
433         if (time < self.speed_finished)
434                 self.items = self.items | IT_SPEED;
435         */
436 }
437
438 void player_regen (void)
439 {
440         // GAME_REGENERATION does fast health regeneration up to 200. Note that your armour doesn't rot anymore either.
441         if (game & GAME_REGENERATION)
442         {
443                 self.health = self.health + (200 - self.health) * 0.2 * frametime;
444                 self.armorvalue = bound(0, self.armorvalue, 1000);
445         }
446         else
447         {
448                 self.health = bound(0, self.health + (100 - self.health) * 0.05 * frametime, 1000);
449                 if (self.armorvalue > 100)
450                         self.armorvalue = bound(100, self.armorvalue + (100 - self.armorvalue) * 0.1 * frametime, 1000);
451         }
452 }
453
454 /*
455 =============
456 PlayerPreThink
457
458 Called every frame for each client before the physics are run
459 =============
460 */
461 .float attack_finished;
462 void PlayerPreThink (void)
463 {
464         local vector m1, m2;
465
466         //if (BotPreFrame())
467         //      return;
468
469         if (self.deadflag != DEAD_NO)
470         {
471                 player_anim();
472                 weapon_freeze();
473                 if (self.deadflag == DEAD_DYING)
474                 {
475                         if (time > self.dead_time)
476                                 self.deadflag = DEAD_DEAD;
477                 }
478                 else if (self.deadflag == DEAD_DEAD)
479                 {
480                         if (!self.button0 && !self.button2 && !self.button3)
481                                 self.deadflag = DEAD_RESPAWNABLE;
482                 }
483                 else if (self.deadflag == DEAD_RESPAWNABLE)
484                 {
485                         if (self.button0 || self.button2 || self.button3  || self.button4)
486                                 respawn();
487                 }
488                 return;
489         }
490
491         if (self.playermodel != self.model)
492         {
493                 m1 = self.mins;
494                 m2 = self.maxs;
495                 setmodel (self, self.playermodel);
496                 setsize (self, m1, m2);
497                 self.skin = stof(self.playerskin);
498         }
499
500         W_WeaponFrame();
501
502         if (self.button4)
503         {
504                 if (self.viewzoom > 0.4)
505                         self.viewzoom = max (0.4, self.viewzoom - frametime * 2);
506         }
507         else if (self.viewzoom < 1.0)
508                 self.viewzoom = min (1.0, self.viewzoom + frametime);
509
510
511         if (self.button2)
512                 PlayerJump ();
513         else
514                 self.flags = self.flags | FL_JUMPRELEASED;
515
516
517         player_powerups();
518         player_regen();
519         player_anim();
520
521         self.angles_y=self.v_angle_y + 90;   // temp
522
523         WaterMove ();
524         if (self.waterlevel == 2)
525                 CheckWaterJump ();
526
527         //if (TetrisPreFrame()) return;
528 }
529
530 /*
531 =============
532 PlayerPostThink
533
534 Called every frame for each client after the physics are run
535 =============
536 */
537 void PlayerPostThink (void)
538 {
539         float soundrandom;
540         //if (BotPostFrame())
541         //      return;
542         if (self.health > 0)
543         if (self.impulse)
544                 ImpulseCommands ();
545
546         // VorteX: landing on floor, landing damage etc.
547         // LordHavoc: removed 'big fall' death code that VorteX added
548         if (self.flags & FL_ONGROUND)
549         {
550                 if (self.jump_flag < -100 && !self.watertype == CONTENT_WATER) // HitGround
551                 {
552                         soundrandom = random() * 4;
553                         if (soundrandom < 1)
554                                 sound (self, CHAN_BODY, "misc/hitground1.wav", 1, ATTN_NORM);
555                         else if (soundrandom < 2)
556                                 sound (self, CHAN_BODY, "misc/hitground2.wav", 1, ATTN_NORM);
557                         else if (soundrandom < 3)
558                                 sound (self, CHAN_BODY, "misc/hitground3.wav", 1, ATTN_NORM);
559                         else if (soundrandom < 4)
560                                 sound (self, CHAN_BODY, "misc/hitground4.wav", 1, ATTN_NORM);
561                         if (self.jump_flag < -650) // landing damage
562                         {
563                                 local float dm;
564                                 dm = bound(0, 0.1*(fabs(self.jump_flag) - 600), 5);
565                                 Damage (self, world, world, dm, DEATH_FALL, '0 0 0', '0 0 0');
566                         }
567                         self.jump_flag = 0;
568                 }
569         }
570         else
571                 self.jump_flag = self.velocity_z;
572
573         //if (TetrisPostFrame()) return;
574 }