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