]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/cl_client.c
bumps for morphed's teleporter model
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / cl_client.c
1 void info_player_start (void)\r
2 {\r
3         if (self.allowteams != "")\r
4         {\r
5                 if (self.allowteams == "blue")\r
6                         self.team_no = 1;\r
7                 if (self.allowteams == "red")\r
8                         self.team_no = 2;\r
9                 if (!self.goal_state)\r
10                         self.goal_state = 1;\r
11                 if (!self.group_no)\r
12                         self.group_no = 1;\r
13                 i_p_t();\r
14                 return;\r
15         }\r
16         else\r
17         {\r
18                 self.classname = "info_player_deathmatch";\r
19         }\r
20 };\r
21 \r
22 void info_player_deathmatch (void)\r
23 {\r
24 }\r
25 /*\r
26 ===============\r
27  Find Team Spawn Point (NexTF!)\r
28                                  ===============\r
29 */\r
30 entity (float team_num) FindTeamSpawnPoint =\r
31 {\r
32         local entity spot;\r
33         local entity at_spot;\r
34         local float spot_found;\r
35         local float attempts;\r
36 \r
37         if ((team_num == 1))\r
38         {\r
39                 spot = lastspawn_team1;\r
40                 attempts = 0;\r
41                 while (1)\r
42                 {\r
43                         attempts = (attempts + 1);\r
44                         spot = find (spot, team_str_home, "ts1");\r
45                         if ((spot == world))\r
46                         {\r
47                                 spot = find (world, team_str_home, "ts1");\r
48                         }\r
49                         if ((spot == world))\r
50                         {\r
51                                 return (world);\r
52                         }\r
53                         at_spot = findradius (spot.origin, 40);\r
54                         spot_found = 1;\r
55                         while ((at_spot != world))\r
56                         {\r
57                                 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))\r
58                                 {\r
59                                         spot_found = 0;\r
60                                 }\r
61                                 at_spot = at_spot.chain;\r
62                         }\r
63                         if (!Activated (spot, self))\r
64                         {\r
65                                 spot_found = 0;\r
66                         }\r
67                         if ((spot_found || (attempts >= 30)))\r
68                         {\r
69                                 lastspawn_team1 = spot;\r
70                                 return (spot);\r
71                         }\r
72                 }\r
73         }\r
74         else\r
75         {\r
76                 if ((team_num == 2))\r
77                 {\r
78                         spot = lastspawn_team2;\r
79                         attempts = 0;\r
80                         while (1)\r
81                         {\r
82                                 attempts = (attempts + 1);\r
83                                 spot = find (spot, team_str_home, "ts2");\r
84                                 if ((spot == world))\r
85                                 {\r
86                                         spot = find (world, team_str_home, "ts2");\r
87                                 }\r
88                                 if ((spot == world))\r
89                                 {\r
90                                         return (world);\r
91                                 }\r
92                                 at_spot = findradius (spot.origin, 40);\r
93                                 spot_found = 1;\r
94                                 while ((at_spot != world))\r
95                                 {\r
96                                         if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))\r
97                                         {\r
98                                                 spot_found = 0;\r
99                                         }\r
100                                         at_spot = at_spot.chain;\r
101                                 }\r
102                                 if (!Activated (spot, self))\r
103                                 {\r
104                                         spot_found = 0;\r
105                                 }\r
106                                 if ((spot_found || (attempts >= 30)))\r
107                                 {\r
108                                         lastspawn_team2 = spot;\r
109                                         return (spot);\r
110                                 }\r
111                         }\r
112                 }\r
113                 else\r
114                 {\r
115                         if ((team_num == 3))\r
116                         {\r
117                                 spot = lastspawn_team3;\r
118                                 attempts = 0;\r
119                                 while (1)\r
120                                 {\r
121                                         attempts = (attempts + 1);\r
122                                         spot = find (spot, team_str_home, "ts3");\r
123                                         if ((spot == world))\r
124                                         {\r
125                                                 spot = find (world, team_str_home, "ts3");\r
126                                         }\r
127                                         if ((spot == world))\r
128                                         {\r
129                                                 return (world);\r
130                                         }\r
131                                         at_spot = findradius (spot.origin, 40);\r
132                                         spot_found = 1;\r
133                                         while ((at_spot != world))\r
134                                         {\r
135                                                 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))\r
136                                                 {\r
137                                                         spot_found = 0;\r
138                                                 }\r
139                                                 at_spot = at_spot.chain;\r
140                                         }\r
141                                         if (!Activated (spot, self))\r
142                                         {\r
143                                                 spot_found = 0;\r
144                                         }\r
145                                         if ((spot_found || (attempts >= 30)))\r
146                                         {\r
147                                                 lastspawn_team3 = spot;\r
148                                                 return (spot);\r
149                                         }\r
150                                 }\r
151                         }\r
152                         else\r
153                         {\r
154                                 if ((team_num == 4))\r
155                                 {\r
156                                         spot = lastspawn_team4;\r
157                                         attempts = 0;\r
158                                         while (1)\r
159                                         {\r
160                                                 attempts = (attempts + 1);\r
161                                                 spot = find (spot, team_str_home, "ts4");\r
162                                                 if ((spot == world))\r
163                                                 {\r
164                                                         spot = find (world, team_str_home, "ts4");\r
165                                                 }\r
166                                                 if ((spot == world))\r
167                                                 {\r
168                                                         return (world);\r
169                                                 }\r
170                                                 at_spot = findradius (spot.origin, 40);\r
171                                                 spot_found = 1;\r
172                                                 while ((at_spot != world))\r
173                                                 {\r
174                                                         if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))\r
175                                                         {\r
176                                                                 spot_found = 0;\r
177                                                         }\r
178                                                         at_spot = at_spot.chain;\r
179                                                 }\r
180                                                 if (!Activated (spot, self))\r
181                                                 {\r
182                                                         spot_found = 0;\r
183                                                 }\r
184                                                 if ((spot_found || (attempts >= 30)))\r
185                                                 {\r
186                                                         lastspawn_team4 = spot;\r
187                                                         return (spot);\r
188                                                 }\r
189                                         }\r
190                                 }\r
191                         }\r
192                 }\r
193         }\r
194         return (world);\r
195 };\r
196 \r
197 /*\r
198 =============\r
199 SelectSpawnPoint\r
200 \r
201 Finds a point to respawn\r
202 =============\r
203 */\r
204 entity () SelectSpawnPoint =\r
205 {\r
206         local entity spot;\r
207         local entity at_spot;\r
208         local float spot_found;\r
209         local float attempts;\r
210 \r
211         if (self.team_no < 1)\r
212         {\r
213 //              self.origin_z = self.origin_z + 30;\r
214                 stuffcmd(self, "alias menu_showteamselect \"set scmenu_directmenu TeamSelect; togglemenu\"\n");\r
215                 stuffcmd(self, "set scmenu_directmenu TeamSelect; togglemenu\n");\r
216 \r
217 //              spot = find (world, classname, "item_tfgoal");\r
218 //              return (spot);\r
219         }\r
220         self.is_dead = 0;               //TEMP\r
221 \r
222         if ((self.team_no != 0))\r
223         {\r
224                 spot = FindTeamSpawnPoint (self.team_no);\r
225                 if ((spot != world))\r
226                 {\r
227                         return (spot);\r
228                 }\r
229         }\r
230         if (coop)\r
231         {\r
232                 lastspawn = find (lastspawn, classname, "info_player_coop");\r
233                 if ((lastspawn == world))\r
234                 {\r
235                         lastspawn = find (world, classname, "info_player_coop");\r
236                 }\r
237                 if ((lastspawn != world))\r
238                 {\r
239                         return (lastspawn);\r
240                 }\r
241         }\r
242         else\r
243         {\r
244                 if (deathmatch)\r
245                 {\r
246                         spot = find (lastspawn, classname, "info_player_deathmatch");\r
247                         if ((spot == world))\r
248                         {\r
249                                 spot = find (world, classname, "info_player_deathmatch");\r
250                         }\r
251                         attempts = 0;\r
252                         while (((spot != world) && (attempts < 100)))\r
253                         {\r
254                                 attempts = (attempts + 1);\r
255                                 at_spot = findradius (spot.origin, 40);\r
256                                 spot_found = 1;\r
257                                 while (at_spot)\r
258                                 {\r
259                                         if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))\r
260                                         {\r
261                                                 spot_found = 0;\r
262                                         }\r
263                                         at_spot = at_spot.chain;\r
264                                 }\r
265                                 if ((spot_found || (attempts >= 10)))\r
266                                 {\r
267                                         lastspawn = spot;\r
268                                         return (spot);\r
269                                 }\r
270                                 spot = find (spot, classname, "info_player_deathmatch");\r
271                                 if ((spot == world))\r
272                                 {\r
273                                         spot = find (world, classname, "info_player_deathmatch");\r
274                                 }\r
275                         }\r
276                 }\r
277         }\r
278         if (serverflags)\r
279         {\r
280                 spot = find (world, classname, "info_player_start2");\r
281                 if (spot)\r
282                 {\r
283                         return (spot);\r
284                 }\r
285         }\r
286         spot = find (world, classname, "info_player_start");\r
287         if (!spot)\r
288         {\r
289                 spot = find (world, is_converted_goal, "yes");\r
290         }\r
291         if (!spot)\r
292         {\r
293                 spot = find (world, classname, "info_tfgoal");\r
294         }\r
295         if (!spot)\r
296         {\r
297                 error ("PutClientInServer: no info_player_start on level\n");\r
298         }\r
299         return (spot);\r
300 };\r
301 \r
302 /*entity SelectSpawnPoint (void)                // Old, non-tf code\r
303 {\r
304         local entity spot, thing;\r
305         local float pcount;\r
306 \r
307         spot = find (world, classname, "testplayerstart");\r
308         if (spot)\r
309                 return spot;\r
310 \r
311         spot = lastspawn;\r
312         while (1)\r
313         {\r
314                 spot = find(spot, classname, "info_player_deathmatch");\r
315                 if (spot != world)\r
316                 {\r
317                         if (spot == lastspawn)\r
318                                 return lastspawn;\r
319                         pcount = 0;\r
320                         thing = findradius(spot.origin, 70);\r
321                         while(thing)\r
322                         {\r
323                                 if (thing.classname == "player")\r
324                                         pcount = pcount + 1;\r
325                                 thing = thing.chain;\r
326                         }\r
327                         if (pcount == 0)\r
328                         {\r
329                                 lastspawn = spot;\r
330                                 return spot;\r
331                         }\r
332                 }\r
333         }\r
334 \r
335         spot = find (world, classname, "info_player_start");\r
336         if (!spot)\r
337                 error ("PutClientInServer: no info_player_start on level");\r
338 \r
339         return spot;\r
340 }*/\r
341 \r
342 /*\r
343 =============\r
344 CheckPlayerModel\r
345 \r
346 Checks if the argument string can be a valid playermodel.\r
347 Returns a valid one in doubt.\r
348 =============\r
349 */\r
350 string CheckPlayerModel(string playermodel) {\r
351         if( substring(playermodel,0,13) != "models/class/") playermodel = "models/class/scout.zym";\r
352 \r
353         /* Possible Fixme: Check if server can open the model?\r
354            This would kill custom models, however. */\r
355 \r
356         return playermodel;\r
357 }\r
358 \r
359 \r
360 /*\r
361 =============\r
362 PutClientInServer\r
363 \r
364 Called when a client spawns in the server\r
365 =============\r
366 */\r
367 void PutClientInServer (void)\r
368 {\r
369         entity  spot;\r
370         float oldcl;\r
371         if (self.team_no < 1)\r
372         {\r
373         self.movetype = 0;\r
374         self.solid = 0;\r
375         self.flags = FL_CLIENT;\r
376         self.takedamage = DAMAGE_AIM;\r
377         self.effects = 0;\r
378         self.health = cvar("g_balance_health_start");\r
379         self.max_health = cvar("g_balance_health_stable");\r
380         self.armorvalue = cvar("g_balance_armor_start");\r
381         self.max_armor = self.armorvalue;\r
382         self.damageforcescale = 2;\r
383         self.death_time = 0;\r
384         self.dead_time = 0;\r
385         self.dead_frame = 0;\r
386         self.die_frame = 0;\r
387         self.alpha = 0;\r
388         self.scale = 0;\r
389         self.fade_time = 0;\r
390         self.pain_frame = 0;\r
391         self.pain_finished = 0;\r
392         self.strength_finished = 0;\r
393         self.invincible_finished = 0;\r
394         //self.speed_finished = 0;\r
395         //self.slowmo_finished = 0;\r
396         // players have no think function\r
397         self.think = SUB_Null;\r
398         self.nextthink = 0;\r
399         self.speed = -1;\r
400         self.jump_pad = 0;\r
401         spot = SelectSpawnPoint();\r
402 //      setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z + 24));\r
403         setorigin (self, spot.origin + '-2 0 4' * (1 - self.mins_z + 24));\r
404         self.angles_y = self.angles_y + 180;\r
405         return;\r
406         }\r
407         // fixme: are these the right teams & colors?\r
408         /*if(self.team == 5)            // Wazat -- I'm using TeamFortress_TeamSet for this now\r
409         {\r
410                 self.team_no = 1;\r
411         }\r
412         if(self.team == 14)\r
413         {\r
414                 self.team_no = 2;\r
415         }\r
416         if(self.team == 4)\r
417         {\r
418                 self.team_no = 3;\r
419         }\r
420         if(self.team == 13)\r
421         {\r
422                 self.team_no = 4;\r
423         }*/\r
424 \r
425         DoTFAliases ();\r
426 \r
427 //      spot = SelectSpawnPoint ();             // moved down\r
428         self.classname = "player";\r
429         self.movetype = MOVETYPE_WALK;\r
430         self.solid = SOLID_SLIDEBOX;\r
431         self.flags = FL_CLIENT;\r
432         self.takedamage = DAMAGE_AIM;\r
433         self.effects = 0;\r
434         self.health = cvar("g_balance_health_start");\r
435         self.max_health = cvar("g_balance_health_stable");\r
436         self.armorvalue = cvar("g_balance_armor_start");\r
437         self.max_armor = self.armorvalue;\r
438         self.damageforcescale = 2;\r
439         self.death_time = 0;\r
440         self.dead_time = 0;\r
441         self.dead_frame = 0;\r
442         self.die_frame = 0;\r
443         self.alpha = 0;\r
444         self.scale = 0;\r
445         self.fade_time = 0;\r
446         self.pain_frame = 0;\r
447         self.pain_finished = 0;\r
448         self.strength_finished = 0;\r
449         self.invincible_finished = 0;\r
450         //self.speed_finished = 0;\r
451         //self.slowmo_finished = 0;\r
452         // players have no think function\r
453         self.think = SUB_Null;\r
454         self.nextthink = 0;\r
455         self.speed = -1;\r
456         self.jump_pad = 0;\r
457         //self.wpn5 = 0; // not carrying an extra weapon\r
458         ResetExtraWeapon(); // not carrying an extra weapon\r
459 \r
460         DelayHealthRegen(self);\r
461         DelayArmorRegen(self);\r
462         DelayHealthRot(self);\r
463         DelayArmorRot(self);\r
464 \r
465 \r
466         self.special_active = 0;\r
467         self.special_time = 0;\r
468 \r
469         self.grenade_time = 0;\r
470 \r
471         if(self.onfire != world)\r
472                 remove(self.onfire);\r
473         self.onfire = world;\r
474         self.flame_heat = 0;\r
475         self.flame_heat_time = 0;\r
476 \r
477         self.poison_damage = 0;\r
478         self.poison_rate = 0;\r
479 \r
480         // if the player is supposed to change model (and hence class) on respawn, do it.\r
481         if(self.change_mdl_on_respawn != "")\r
482         {\r
483                 self.playermodel = self.change_mdl_on_respawn;\r
484                 //strunzone(self.change_mdl_on_respawn); // can't unzone or it'll crash later\r
485         }\r
486         // set the class.  If he changed classes while dead it will take effect now.\r
487         oldcl = self.class;\r
488         self.class = GetPlayerClass();\r
489         ChangeClass((oldcl != self.class), FALSE);\r
490 \r
491 \r
492 \r
493         self.deadflag = DEAD_NO;\r
494 \r
495         spot = SelectSpawnPoint ();             // maybe temp\r
496         self.angles = spot.angles;\r
497         self.fixangle = TRUE; // turn this way immediately\r
498         self.velocity = '0 0 0';\r
499         self.avelocity = '0 0 0';\r
500         self.punchangle = '0 0 0';\r
501         self.punchvector = '0 0 0';\r
502 \r
503         self.viewzoom = 0.6;\r
504 \r
505 \r
506         self.playermodel = CheckPlayerModel(self.playermodel);\r
507 \r
508         precache_model (self.playermodel);\r
509         setmodel (self, self.playermodel);\r
510         self.skin = stof(self.playerskin);\r
511         self.mdl = strzone(self.playermodel);\r
512 \r
513         self.crouch = FALSE;\r
514         self.view_ofs = PL_VIEW_OFS;\r
515         setsize (self, PL_MIN, PL_MAX);\r
516         setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));\r
517         // don't reset back to last position, even if new position is stuck in solid\r
518         self.oldorigin = self.origin;\r
519 \r
520 //      self.items = IT_LASER | IT_UZI| IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER;\r
521 //      self.weapon = IT_UZI;\r
522 \r
523 \r
524         // fixme: move this to Become<Class> code\r
525 /*      self.items = IT_WEP1 | IT_WEP2 | IT_WEP3 | IT_WEP4;\r
526         //self.weapon = 1;\r
527         self.switchweapon = IT_WEP2;\r
528         self.ammo_shells = 50;\r
529         self.ammo_nails = 0;\r
530         self.ammo_rockets = 0;\r
531         self.ammo_cells = 0;*/\r
532 \r
533         if (cvar("g_fullbrightplayers") == 1)\r
534                 self.effects = EF_FULLBRIGHT;\r
535 \r
536         self.event_damage = PlayerDamage;\r
537 \r
538         self.statdraintime = time + 5;\r
539         self.button0 = self.button1 = self.button2 = self.button3 = 0;\r
540 \r
541         /*\r
542         W_UpdateWeapon();\r
543         W_UpdateAmmo();\r
544         */\r
545         CL_SpawnWeaponentity();\r
546         self.weaponentity.alpha = self.exteriorweaponentity.alpha = 0;\r
547         self.weaponentity.colormod = '0 0 0';\r
548         self.weaponentity.scale = 0;\r
549 \r
550         //stuffcmd(self, "chase_active 0");\r
551 }\r
552 \r
553 /*\r
554 =============\r
555 SetNewParms\r
556 =============\r
557 */\r
558 void SetNewParms (void)\r
559 {\r
560 \r
561 }\r
562 \r
563 /*\r
564 =============\r
565 SetChangeParms\r
566 =============\r
567 */\r
568 void SetChangeParms (void)\r
569 {\r
570 \r
571 }\r
572 \r
573 /*\r
574 =============\r
575 ClientKill\r
576 \r
577 Called when a client types 'kill' in the console\r
578 =============\r
579 */\r
580 void ClientKill (void)\r
581 {\r
582         Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');\r
583 }\r
584 \r
585 /*\r
586 =============\r
587 ClientConnect\r
588 \r
589 Called when a client connects to the server\r
590 =============\r
591 */\r
592 void ClientConnect (void)\r
593 {\r
594         //ClientInRankings();\r
595         bprint ("^4",self.netname);\r
596         bprint (" connected\n");\r
597         stuffcmd(self, strcat("exec maps/", mapname, ".cfg\n"));\r
598         // send prediction settings to the client\r
599         stuffcmd(self, strcat("cl_movement_maxspeed ", ftos(cvar("sv_maxspeed")), "\n"));\r
600         stuffcmd(self, strcat("cl_movement_maxairspeed ", ftos(cvar("sv_maxairspeed")), "\n"));\r
601         stuffcmd(self, strcat("cl_movement_accelerate ", ftos(cvar("sv_accelerate")), "\n"));\r
602         stuffcmd(self, strcat("cl_movement_friction ", ftos(cvar("sv_friction")), "\n"));\r
603         stuffcmd(self, strcat("cl_movement_stopspeed ", ftos(cvar("sv_stopspeed")), "\n"));\r
604         stuffcmd(self, strcat("cl_movement_jumpvelocity ", ftos(cvar("g_balance_jumpheight")), "\n"));\r
605         stuffcmd(self, strcat("cl_movement_stepheight ", ftos(cvar("sv_stepheight")), "\n"));\r
606         stuffcmd(self, strcat("cl_movement_edgefriction 0\n"));\r
607                         // TEMP FOR TESTING PURPOSES!\r
608         //teamplay = 21?TeamFortress;\r
609         DecodeLevelParms ();\r
610         //cvar_set ("teamplay", "21?TeamFortress");\r
611         //      teamplay = cvar ("teamplay");\r
612 \r
613 /*      joinorder = joinorder + 1;                      // old temp autoteam, but now we have a menu instead :P\r
614         if (joinorder == 1 || joinorder == 3 || joinorder == 5 || joinorder == 7)\r
615                 TeamFortress_TeamSet (1);\r
616         else {\r
617                 TeamFortress_TeamSet (2);\r
618         }*/\r
619 }\r
620 \r
621 /*\r
622 =============\r
623 ClientDisconnect\r
624 \r
625 Called when a client disconnects from the server\r
626 =============\r
627 */\r
628 void ClientDisconnect (void)\r
629 {\r
630         //ClientDisconnected();\r
631         self.has_disconnected = 1;\r
632         bprint ("^4",self.netname);\r
633         bprint (" disconnected\n");\r
634 }\r
635 \r
636 .entity chatbubbleentity;\r
637 .float buttonchat;\r
638 void() ChatBubbleThink =\r
639 {\r
640         self.nextthink = time;\r
641         if (!self.owner.modelindex || self.owner.chatbubbleentity != self)\r
642         {\r
643                 remove(self);\r
644                 return;\r
645         }\r
646         setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1');\r
647         if (self.owner.buttonchat)\r
648                 self.effects = 0;\r
649         else\r
650                 self.effects = EF_NODRAW;\r
651 };\r
652 \r
653 void() UpdateChatBubble =\r
654 {\r
655         if (!self.modelindex)\r
656                 return;\r
657         // spawn a chatbubble entity if needed\r
658         if (!self.chatbubbleentity)\r
659         {\r
660                 self.chatbubbleentity = spawn();\r
661                 self.chatbubbleentity.owner = self;\r
662                 self.chatbubbleentity.think = ChatBubbleThink;\r
663                 self.chatbubbleentity.nextthink = time;\r
664                 setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr");\r
665                 setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');\r
666                 self.chatbubbleentity.effects = EF_NODRAW;\r
667         }\r
668 }\r
669 \r
670 // LordHavoc: this hack will be removed when proper _pants/_shirt layers are\r
671 // added to the model skins\r
672 void() UpdateColorModHack =\r
673 {\r
674         local float c;\r
675         c = self.clientcolors & 15;\r
676         // LordHavoc: only bothering to support white, green, red, yellow, blue\r
677              if (teamplay == 0) self.colormod = '0 0 0';\r
678         else if (c ==  0) self.colormod = '1.00 1.00 1.00';\r
679         else if (c ==  3) self.colormod = '0.10 1.73 0.10';\r
680         else if (c ==  4) self.colormod = '1.73 0.10 0.10';\r
681         else if (c == 12) self.colormod = '1.22 1.22 0.10';\r
682         else if (c == 13) self.colormod = '0.10 0.10 1.73';\r
683         else self.colormod = '1 1 1';\r
684 };\r
685 \r
686 /*\r
687 =============\r
688 PlayerJump\r
689 \r
690 When you press the jump key\r
691 =============\r
692 */\r
693 void PlayerJump (void)\r
694 {\r
695         if (self.waterlevel >= 2)\r
696         {\r
697                 if (self.watertype == CONTENT_WATER)\r
698                         self.velocity_z = 200;\r
699                 else if (self.watertype == CONTENT_SLIME)\r
700                         self.velocity_z = 80;\r
701                 else\r
702                         self.velocity_z = 50;\r
703 \r
704                 return;\r
705         }\r
706         if(self.jump_pad)\r
707                 return;\r
708 \r
709 //      self.jump_pad = 0;\r
710         CapPlayerVelocity(self, self.speed);\r
711 \r
712 \r
713         if (!(self.flags & FL_ONGROUND))\r
714                 return;\r
715 \r
716         if (!(self.flags & FL_JUMPRELEASED))\r
717                 return;\r
718 \r
719         self.velocity_z = self.velocity_z + cvar("g_balance_jumpheight");\r
720 \r
721         self.flags = self.flags - FL_ONGROUND;\r
722         self.flags = self.flags - FL_JUMPRELEASED;\r
723 }\r
724 \r
725 .float watersound_finished;\r
726 void() WaterMove =\r
727 {\r
728         if (self.movetype == MOVETYPE_NOCLIP)\r
729                 return;\r
730         if (self.health < 0)\r
731                 return;\r
732 \r
733         if (self.waterlevel != 3)\r
734         {\r
735                 self.air_finished = time + 12;\r
736                 self.dmg = 2;\r
737         }\r
738         else if (self.air_finished < time)\r
739         {       // drown!\r
740                 if (self.pain_finished < time)\r
741                 {\r
742                         Damage (self, world, world, 5, DEATH_DROWN, self.origin, '0 0 0');\r
743                         self.pain_finished = time + 0.5;\r
744                 }\r
745         }\r
746 \r
747         if (!self.waterlevel)\r
748         {\r
749                 if (self.flags & FL_INWATER)\r
750                 {\r
751                         // play leave water sound\r
752                         self.flags = self.flags - FL_INWATER;\r
753                 }\r
754                 return;\r
755         }\r
756 \r
757         if (self.watersound_finished < time)\r
758         {\r
759                 self.watersound_finished = time + 0.5;\r
760                 if (self.watertype == CONTENT_LAVA)\r
761                         sound (self, CHAN_BODY, "player/lava.wav", 1, ATTN_NORM);\r
762                 if (self.watertype == CONTENT_SLIME)\r
763                         sound (self, CHAN_BODY, "player/slime.wav", 1, ATTN_NORM);\r
764                 //if (self.watertype == CONTENT_WATER)\r
765                 //      sound (self, CHAN_BODY, "player/water.wav", 1, ATTN_NORM);\r
766         }\r
767 \r
768         if (self.watertype == CONTENT_LAVA)\r
769         {       // do damage\r
770 \r
771                 // lava sets me to the maximum heat level, so I'll catch fire easily\r
772                 self.flame_heat = cvar("g_balance_maxheat");\r
773 \r
774                 if (self.dmgtime < time)\r
775                 {\r
776                         self.dmgtime = time + 0.1;\r
777                         Damage (self, world, world, 3 * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');\r
778                 }\r
779         }\r
780         else if (self.watertype == CONTENT_SLIME)\r
781         {       // do damage\r
782 \r
783                 // cool me off\r
784                 self.flame_heat = 0;\r
785 \r
786                 if (self.dmgtime < time)\r
787                 {\r
788                         self.dmgtime = time + 0.1;\r
789                         Damage (self, world, world, 1 * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');\r
790                 }\r
791         }\r
792         else if (self.watertype == CONTENT_WATER)\r
793         {\r
794                 // cool me off\r
795                 self.flame_heat = 0;\r
796         }\r
797 \r
798         if ( !(self.flags & FL_INWATER) )\r
799         {\r
800 \r
801                 //if (self.watertype == CONTENT_LAVA)\r
802                 //      sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);\r
803                 //if (self.watertype == CONTENT_WATER)\r
804                 //      sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);\r
805                 //if (self.watertype == CONTENT_SLIME)\r
806                 //      sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);\r
807 \r
808                 self.flags = self.flags + FL_INWATER;\r
809                 self.dmgtime = 0;\r
810         }\r
811 };\r
812 \r
813 void() CheckWaterJump =\r
814 {\r
815         local vector start, end;\r
816 \r
817 // check for a jump-out-of-water\r
818         makevectors (self.angles);\r
819         start = self.origin;\r
820         start_z = start_z + 8;\r
821         v_forward_z = 0;\r
822         normalize(v_forward);\r
823         end = start + v_forward*24;\r
824         traceline (start, end, TRUE, self);\r
825         if (trace_fraction < 1)\r
826         {       // solid at waist\r
827                 start_z = start_z + self.maxs_z - 8;\r
828                 end = start + v_forward*24;\r
829                 self.movedir = trace_plane_normal * -50;\r
830                 traceline (start, end, TRUE, self);\r
831                 if (trace_fraction == 1)\r
832                 {       // open at eye level\r
833                         self.flags = self.flags | FL_WATERJUMP;\r
834                         self.velocity_z = 225;\r
835                         self.flags = self.flags - (self.flags & FL_JUMPRELEASED);\r
836                         self.teleport_time = time + 2;  // safety net\r
837                         return;\r
838                 }\r
839         }\r
840 };\r
841 \r
842 \r
843 void respawn(void)\r
844 {\r
845         CopyBody(1);\r
846         PutClientInServer();\r
847 }\r
848 \r
849 void player_powerups (void)\r
850 {\r
851         self.effects = self.effects - (self.effects & (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT));\r
852         if (self.items & IT_STRENGTH)\r
853         {\r
854                 self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);\r
855                 if (time > self.strength_finished)\r
856                 {\r
857                         self.items = self.items - (self.items & IT_STRENGTH);\r
858                         sprint(self, "^3Strength has worn off\n");\r
859                 }\r
860         }\r
861         else\r
862         {\r
863                 if (time < self.strength_finished)\r
864                 {\r
865                         self.items = self.items | IT_STRENGTH;\r
866                         sprint(self, "^3Strength infuses your weapons with devestating power\n");\r
867                 }\r
868         }\r
869         if (self.items & IT_INVINCIBLE)\r
870         {\r
871                 self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);\r
872                 if (time > self.invincible_finished)\r
873                 {\r
874                         self.items = self.items - (self.items & IT_INVINCIBLE);\r
875                         sprint(self, "^3Shield has worn off\n");\r
876                 }\r
877         }\r
878         else\r
879         {\r
880                 if (time < self.invincible_finished)\r
881                 {\r
882                         self.items = self.items | IT_INVINCIBLE;\r
883                         sprint(self, "^3Shield surrounds you\n");\r
884                 }\r
885         }\r
886 }\r
887 \r
888 void player_regen_health (float maxh, float regen_rate_mod)\r
889 {\r
890         if (self.health < maxh && time > self.health_regen_delay)\r
891                 self.health = bound(0, self.health + regen_rate_mod*(maxh- self.health) * cvar("g_balance_health_regen") * frametime, 1000);\r
892 }\r
893 void player_rot_health (float maxh, float rot_rate_mod)\r
894 {\r
895         if (self.health > maxh && time > self.health_rot_delay)\r
896                 self.health = bound(0, self.health + rot_rate_mod*(maxh - self.health) * cvar("g_balance_health_rot") * frametime, 1000);\r
897 }\r
898 void player_regen_armor (float maxa, float regen_rate_mod)\r
899 {\r
900         if (self.armorvalue < maxa && time > self.armor_regen_delay)\r
901                 self.armorvalue = bound(0, self.armorvalue + regen_rate_mod*(maxa - self.armorvalue) * cvar("g_balance_armor_regen") * frametime, 1000);\r
902 }\r
903 void player_rot_armor (float maxa, float regen_rot_mod)\r
904 {\r
905         if (self.armorvalue > maxa && time > self.armor_rot_delay)\r
906                 self.armorvalue = bound(0, self.armorvalue + regen_rot_mod*(maxa - self.armorvalue) * cvar("g_balance_armor_rot") * frametime, 1000);\r
907 }\r
908 \r
909 void player_clearpoison(entity targ)\r
910 {\r
911         targ.poison_damage = targ.poison_rate = 0;\r
912 }\r
913 \r
914 void DelayHealthRegen(entity e) {       e.health_regen_delay = time + cvar("g_balance_regen_wait");}\r
915 void DelayHealthRot(entity e)   {       e.health_rot_delay = time + cvar("g_balance_rot_wait");}\r
916 void DelayArmorRegen(entity e)  {       e.armor_regen_delay = time + cvar("g_balance_regen_wait");}\r
917 void DelayArmorRot(entity e)    {       e.armor_rot_delay = time + cvar("g_balance_rot_wait");}\r
918 \r
919 \r
920 void player_takepoison()\r
921 {\r
922         float oldhealth, take;\r
923         if(self.health <= 5)\r
924         {\r
925                 player_clearpoison(self);\r
926                 return;\r
927         }\r
928         oldhealth = self.health;\r
929 \r
930         take = bound(0, self.poison_rate * frametime, self.health - 5);\r
931         if(take <= 0)\r
932         {\r
933                 player_clearpoison(self);\r
934                 return;\r
935         }\r
936 \r
937         DelayHealthRegen(self);\r
938         self.health = self.health - take;\r
939         self.poison_damage = self.poison_damage - take;\r
940 \r
941         if(self.health <= 5 || self.poison_damage <= 0)\r
942         {\r
943                 player_clearpoison(self);\r
944                 return;\r
945         }\r
946 }\r
947 \r
948 // cool off so you're not so vulnerable to fire\r
949 void player_cooloff ()\r
950 {\r
951         if(self.flame_heat_time > time)//heat up\r
952                 self.flame_heat = bound(0, self.flame_heat + self.flame_heat * cvar("g_balance_heatup_rate")  * frametime, cvar("g_balance_maxheat"));\r
953         else//cool off\r
954                 self.flame_heat = bound(0, self.flame_heat - self.flame_heat * cvar("g_balance_cooloff_rate") * frametime, cvar("g_balance_maxheat"));\r
955 }\r
956 \r
957 void player_regen (void)\r
958 {\r
959         local float maxh;\r
960         local float maxa;\r
961         maxh = self.max_health;//cvar("g_balance_health_stable");\r
962         maxa = self.max_armor;//cvar("g_balance_armor_stable");\r
963 \r
964         if(self.poison_damage)\r
965         {\r
966                 player_takepoison();\r
967                 return;\r
968         }\r
969 \r
970         if(self.class == CLASS_SPY)\r
971         {// don't let spy regenerate if cloaked, but do allow rot if above max\r
972                 if(self.special_active)\r
973                 {\r
974                         //if(self.health > maxh)\r
975                                 player_rot_health(maxh, 1.0);\r
976                         //if(self.armorvalue > maxa)\r
977                                 player_rot_armor(maxa, 1.0);\r
978                 }\r
979                 else\r
980                 {\r
981                         player_regen_health(maxh, 0.1); // spies regenerate slowly, and mostly rely on health packs\r
982                         player_regen_armor(maxa, 1.0);\r
983                         player_rot_health(maxh, 1.0);\r
984                         player_rot_armor(maxa, 1.0);\r
985                 }\r
986         }\r
987         else\r
988         {\r
989                 player_regen_health(maxh, 1.0);\r
990                 player_regen_armor(maxa, 1.0);\r
991                 player_rot_health(maxh, 1.0);\r
992                 player_rot_armor(maxa, 1.0);\r
993         }\r
994 \r
995         player_cooloff();\r
996 }\r
997 \r
998 /*\r
999 =============\r
1000 PlayerPreThink\r
1001 \r
1002 Called every frame for each client before the physics are run\r
1003 =============\r
1004 */\r
1005 .float attack_finished;\r
1006 void PlayerPreThink (void)\r
1007 {\r
1008         local vector m1, m2;\r
1009 \r
1010         CheckRules_Player();\r
1011 \r
1012         if (intermission_running)\r
1013         {\r
1014                 IntermissionThink ();   // otherwise a button could be missed between\r
1015                 return;                                 // the think tics\r
1016         }\r
1017 \r
1018         if (self.deadflag != DEAD_NO)\r
1019         {\r
1020                 player_anim();\r
1021                 weapon_freeze();\r
1022                 if (self.deadflag == DEAD_DYING)\r
1023                 {\r
1024                         if (time > self.dead_time)\r
1025                                 self.deadflag = DEAD_DEAD;\r
1026                 }\r
1027                 else if (self.deadflag == DEAD_DEAD)\r
1028                 {\r
1029                         if (!self.button0 && !self.button2 && !self.button3)\r
1030                                 self.deadflag = DEAD_RESPAWNABLE;\r
1031                 }\r
1032                 else if (self.deadflag == DEAD_RESPAWNABLE)\r
1033                 {\r
1034                         if (self.button0 || self.button2 || self.button3  || self.button4)\r
1035                                 respawn();\r
1036                 }\r
1037                 return;\r
1038         }\r
1039 \r
1040         if (self.button5)\r
1041         {\r
1042                 if (!self.crouch)\r
1043                 {\r
1044                         self.crouch = TRUE;\r
1045                         self.view_ofs = PL_CROUCH_VIEW_OFS;\r
1046                         setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);\r
1047                 }\r
1048         }\r
1049         else\r
1050         {\r
1051                 if (self.crouch)\r
1052                 {\r
1053                         tracebox(self.origin, PL_MIN, PL_MAX, self.origin, FALSE, self);\r
1054                         if (!trace_startsolid)\r
1055                         {\r
1056                                 self.crouch = FALSE;\r
1057                                 self.view_ofs = PL_VIEW_OFS;\r
1058                                 setsize (self, PL_MIN, PL_MAX);\r
1059                         }\r
1060                 }\r
1061         }\r
1062 \r
1063         if (self.playermodel != self.mdl)\r
1064         {\r
1065                 //bprint("playermodel changed\n");\r
1066                 self.playermodel = CheckPlayerModel(self.playermodel);\r
1067                 if(CheckForClassChange()) // check if we'll allow it\r
1068                         return; // if there's a return value, drop what you're doing and let the player respawn\r
1069 \r
1070                 if(self.playermodel != self.mdl) // if change has been allowed\r
1071                 {\r
1072                         m1 = self.mins;\r
1073                         m2 = self.maxs;\r
1074                         precache_model (self.playermodel);\r
1075                         if(self.model != "")\r
1076                         {\r
1077                                 setmodel (self, self.playermodel);\r
1078                                 setsize (self, m1, m2);\r
1079                         }\r
1080                         self.mdl = strzone(self.playermodel);\r
1081                 }\r
1082         }\r
1083 \r
1084         ClassPreThink();\r
1085 \r
1086         if (self.skin != stof(self.playerskin))\r
1087                 self.skin = stof(self.playerskin);\r
1088 \r
1089         if(self.class == CLASS_SCOUT)\r
1090                 GrapplingHookFrame();\r
1091 \r
1092         W_WeaponFrame();\r
1093 \r
1094         if (self.button4 || (self.weapon == WEP_NEX && self.button3))\r
1095         {\r
1096                 if (self.viewzoom > 0.4)\r
1097                         self.viewzoom = max (0.4, self.viewzoom - frametime * 2);\r
1098         }\r
1099         else if (self.viewzoom < 1.0)\r
1100                 self.viewzoom = min (1.0, self.viewzoom + frametime);\r
1101 \r
1102 \r
1103         if (self.button2)\r
1104                 PlayerJump ();\r
1105         else\r
1106                 self.flags = self.flags | FL_JUMPRELEASED;\r
1107 \r
1108 \r
1109         player_powerups();\r
1110         player_regen();\r
1111         player_anim();\r
1112 \r
1113         //self.angles_y=self.v_angle_y + 90;   // temp\r
1114 \r
1115         WaterMove ();\r
1116         if (self.waterlevel == 2)\r
1117                 CheckWaterJump ();\r
1118 \r
1119         //if (TetrisPreFrame()) return;\r
1120 \r
1121         PlayerLasergatePreThink();\r
1122 }\r
1123 \r
1124 /*\r
1125 =============\r
1126 PlayerPostThink\r
1127 \r
1128 Called every frame for each client after the physics are run\r
1129 =============\r
1130 */\r
1131 void PlayerPostThink (void)\r
1132 {\r
1133         float soundrandom;\r
1134         CheckRules_Player();\r
1135         UpdateChatBubble();\r
1136         UpdateColorModHack();\r
1137         if (self.deadflag == DEAD_NO)\r
1138         if (self.impulse)\r
1139                 ImpulseCommands ();\r
1140         if (intermission_running)\r
1141                 return;         // intermission or finale\r
1142 \r
1143         // VorteX: landing on floor, landing damage etc.\r
1144         // LordHavoc: removed 'big fall' death code that VorteX added\r
1145         if (self.flags & FL_ONGROUND || (self.waterlevel >= 2 && self.velocity_z <= 0))\r
1146                         self.jump_pad = 0;\r
1147 \r
1148         if (self.flags & FL_ONGROUND)\r
1149         {\r
1150                 CapPlayerVelocity(self, self.speed);\r
1151 \r
1152                 if (self.jump_flag < -100 && !self.watertype == CONTENT_WATER) // HitGround\r
1153                 {\r
1154                         soundrandom = random() * 4;\r
1155 \r
1156                         self.air_time = time;           //temp BH var\r
1157 \r
1158                         if (soundrandom < 1)\r
1159                                 sound (self, CHAN_BODY, "misc/hitground1.wav", 1, ATTN_NORM);\r
1160                         else if (soundrandom < 2)\r
1161                                 sound (self, CHAN_BODY, "misc/hitground2.wav", 1, ATTN_NORM);\r
1162                         else if (soundrandom < 3)\r
1163                                 sound (self, CHAN_BODY, "misc/hitground3.wav", 1, ATTN_NORM);\r
1164                         else if (soundrandom < 4)\r
1165                                 sound (self, CHAN_BODY, "misc/hitground4.wav", 1, ATTN_NORM);\r
1166                         if (self.jump_flag < -650) // landing damage\r
1167                         {\r
1168                                 local float dm;\r
1169                                 dm = bound(0, 0.1*(fabs(self.jump_flag) - 600), 5);\r
1170                                 Damage (self, world, world, dm, DEATH_FALL, self.origin, '0 0 0');\r
1171                         }\r
1172                         self.jump_flag = 0;\r
1173                 }\r
1174         }\r
1175         else\r
1176                 self.jump_flag = self.velocity_z;\r
1177 \r
1178         ClassPostThink();\r
1179 \r
1180         //if (TetrisPostFrame()) return;\r
1181         PlayerLasergatePostThink();\r
1182 }\r
1183 \r
1184 // Parse team join, class etc.\r
1185 void SV_ParseClientCommand (string s)\r
1186 {\r
1187         local float args;\r
1188         local float h;\r
1189         local string c;\r
1190         local string d;\r
1191         local string f;\r
1192         local string g;\r
1193         local string i;\r
1194         args = tokenize(s);\r
1195         c = argv(0);\r
1196         d = argv(1);\r
1197         f = argv(2);\r
1198         g = argv(3);\r
1199         i = argv(4);\r
1200 \r
1201         if (c == "join")\r
1202     {\r
1203                 return;\r
1204         }\r
1205         if (c == "selectteam")\r
1206     {\r
1207                 if (self.team_no > 0)\r
1208                 {\r
1209                         sprint(self, "You are already on a team!\n");\r
1210                         return;\r
1211                 }\r
1212                 if (d == "auto" || d == "5")\r
1213                 {\r
1214                         TeamFortress_TeamPutPlayerInTeam();\r
1215                         PutClientInServer ();\r
1216                 }\r
1217                 if (d == "red" || d == "2")\r
1218                 {\r
1219                         TeamFortress_TeamSet (2);\r
1220                         PutClientInServer ();\r
1221                 }\r
1222                 if (d == "blue" || d == "1")\r
1223                 {\r
1224                         TeamFortress_TeamSet (1);\r
1225                         PutClientInServer ();\r
1226                 }\r
1227         }\r
1228         else\r
1229         {\r
1230                 clientcommand(self, s);\r
1231         }\r
1232 };