]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/class.c
- Added spy feign function (TeamNexuiz_Feign) & impulse constant
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / class.c
1 \r
2 void PlayerKilled (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);\r
3 \r
4 \r
5 \r
6 /*\r
7 =============\r
8 NameOfClass\r
9 \r
10 Translates class number to a string for printing\r
11 =============\r
12 */\r
13 string NameOfClass(float cl)\r
14 {\r
15         if(cl == CLASS_SCOUT)\r
16                 return "Scout";\r
17         if(cl == CLASS_SPY)\r
18                 return "Spy";\r
19         if(cl == CLASS_SOLDIER)\r
20                 return "Soldier";\r
21         if(cl == CLASS_PYRO)\r
22                 return "Pryo";\r
23         if(cl == CLASS_MEDIC)\r
24                 return "Medic";\r
25         if(cl == CLASS_ENGINEER)\r
26                 return "Engineer";\r
27         return "Invalid Class";\r
28 }\r
29 \r
30 /*\r
31 =============\r
32 GetPlayerClass\r
33 \r
34 Returns the player's class by checking his model name\r
35 =============\r
36 */\r
37 float GetPlayerClass()\r
38 {\r
39         //string s;\r
40         //s = substring(self.playermodel,13,3);\r
41 \r
42         //bprint("Class Prefix: ");\r
43         //bprint(s);\r
44         //bprint("\n");\r
45 \r
46         // only the prefix matters;\r
47         // thus, you could have multiple medic models, such as a male and female.\r
48         if(substring(self.playermodel,13,5)\r
49                 == "scout")\r
50                 return CLASS_SCOUT;\r
51         if(substring(self.playermodel,13,3)\r
52                 == "spy")\r
53                 return CLASS_SPY;\r
54         if(substring(self.playermodel,13,7)\r
55                 == "soldier")\r
56                 return CLASS_SOLDIER;\r
57         if(substring(self.playermodel,13,4)\r
58                 == "pyro")\r
59                 return CLASS_PYRO;\r
60         if(substring(self.playermodel,13,5)\r
61                 == "medic")\r
62                 return CLASS_MEDIC;\r
63         if(substring(self.playermodel,13,8)\r
64                 == "engineer")\r
65                 return CLASS_ENGINEER;\r
66 \r
67         return -1;\r
68 }\r
69 \r
70 /*\r
71 =============\r
72 ChangeClass\r
73 \r
74 Changes the player's class\r
75 =============\r
76 */\r
77 \r
78 void ChangeClass(float announce_change, float instant_change)\r
79 {\r
80         float portion, aportion;\r
81         if(announce_change)\r
82                 bprint(self.netname, " becomes a ", NameOfClass(self.class), "\n");\r
83 \r
84         portion = 1.0;\r
85 \r
86         if(instant_change)\r
87         {\r
88                 // health\r
89                 if(self.health < self.max_health)\r
90                         aportion = self.health / self.max_health;\r
91                 else\r
92                         aportion = 1.0;\r
93 \r
94                 if(aportion < portion)\r
95                         portion = aportion;\r
96 \r
97                 // armor\r
98                 if(self.armorvalue < self.max_armor)\r
99                         aportion = self.armorvalue / self.max_armor;\r
100                 else\r
101                         aportion = 1.0;\r
102 \r
103                 if(aportion < portion)\r
104                         portion = aportion;\r
105         }\r
106 \r
107         if(self.class == CLASS_SCOUT)\r
108                 BecomeScout(portion);\r
109 \r
110         if(self.class == CLASS_SPY)\r
111                 BecomeSpy(portion);\r
112 \r
113         if(self.class == CLASS_SOLDIER)\r
114                 BecomeSoldier(portion);\r
115 \r
116         if(self.class == CLASS_PYRO)\r
117                 BecomePyro(portion);\r
118 \r
119         if(self.class == CLASS_MEDIC)\r
120                 BecomeMedic(portion);\r
121 \r
122         if(self.class == CLASS_ENGINEER)\r
123                 BecomeEngineer(portion);\r
124 \r
125         // set starting health\r
126         if(!instant_change)//portion == 1.0)\r
127                 self.health = ceil(self.max_health * 1.2);\r
128         else\r
129                 self.health = self.max_health;\r
130         // set starting armor\r
131         if(!instant_change)//portion == 1.0)\r
132                 self.armorvalue = ceil(self.max_armor * 1.2);\r
133         else\r
134                 self.armorvalue = self.max_armor;\r
135 \r
136         // test code\r
137         //if(instant_change)\r
138         //      self.health = 2 + self.health * 0.8;\r
139 };\r
140 \r
141 float SetPlayerMass(entity pl)\r
142 {\r
143         float m, extra_mass;\r
144         if(self.class == CLASS_SCOUT)\r
145         {\r
146                 m = cvar("g_balance_class_scout_mass");\r
147         }\r
148         else if(self.class == CLASS_SPY)\r
149         {\r
150                 m = cvar("g_balance_class_spy_mass");\r
151         }\r
152         else if(self.class == CLASS_SOLDIER)\r
153         {\r
154                 m = cvar("g_balance_class_soldier_mass");\r
155         }\r
156         else if(self.class == CLASS_PYRO)\r
157         {\r
158                 m = cvar("g_balance_class_pyro_mass");\r
159         }\r
160         else if(self.class == CLASS_MEDIC)\r
161         {\r
162                 m = cvar("g_balance_class_medic_mass");\r
163         }\r
164         else if(self.class == CLASS_ENGINEER)\r
165         {\r
166                 m = cvar("g_balance_class_engineer_mass");\r
167         }\r
168         else\r
169                 m = cvar("sv_maxspeed");\r
170 \r
171         // fixme: if I'm carrying a flag or extra weapon, add that mass\r
172         extra_mass = 0;\r
173 \r
174         if(self.wpn5.mass)\r
175                 extra_mass = extra_mass + self.wpn5.mass;\r
176 \r
177 \r
178         self.mass = m + extra_mass;\r
179 \r
180         return m; // return what my natural mass is\r
181 };\r
182 \r
183 void SetPlayerSpeed(entity pl)\r
184 {\r
185         local float s, m, plmass;\r
186         string temp;\r
187         if(self.class == CLASS_SCOUT)\r
188         {\r
189                 s = cvar("g_balance_class_scout_speed");\r
190                 //m = cvar("g_balance_class_scout_mass");\r
191         }\r
192         else if(self.class == CLASS_SPY)\r
193         {\r
194                 s = cvar("g_balance_class_spy_speed");\r
195                 //m = cvar("g_balance_class_spy_mass");\r
196         }\r
197         else if(self.class == CLASS_SOLDIER)\r
198         {\r
199                 s = cvar("g_balance_class_soldier_speed");\r
200                 //m = cvar("g_balance_class_soldier_mass");\r
201         }\r
202         else if(self.class == CLASS_PYRO)\r
203         {\r
204                 s = cvar("g_balance_class_pyro_speed");\r
205                 //m = cvar("g_balance_class_pyro_mass");\r
206         }\r
207         else if(self.class == CLASS_MEDIC)\r
208         {\r
209                 s = cvar("g_balance_class_medic_speed");\r
210                 //m = cvar("g_balance_class_medic_mass");\r
211         }\r
212         else if(self.class == CLASS_ENGINEER)\r
213         {\r
214                 s = cvar("g_balance_class_engineer_speed");\r
215                 //m = cvar("g_balance_class_engineer_mass");\r
216         }\r
217 \r
218 \r
219         // fixme: if I'm in a manned turret, set my speed to 0\r
220         // fixme: if I'm piloting a vehicle, what to do?\r
221 \r
222 \r
223         // if my mass is different because of what I'm carrying,\r
224         // slow me down\r
225 \r
226         m = SetPlayerMass(pl);\r
227 \r
228         if(pl.mass == 0)\r
229                 plmass = 1;\r
230         else\r
231                 plmass = pl.mass;\r
232         s = ceil( s * (m / plmass ) );\r
233 \r
234         if(s != pl.speed)\r
235         {\r
236                 //bprint("debug: adjusting speed\n");\r
237                 temp = ftos(s);\r
238                 \r
239                 //stuffcmd( pl, strcat("cl_movement_maxspeed ", temp , "\n"));\r
240                 //stuffcmd( pl, strcat("cl_movement_maxairspeed ", temp , "\n"));\r
241 \r
242                 //stuffcmd( pl, strcat("cl_forwardspeed ", temp , "\n"));\r
243                 //stuffcmd( pl, strcat("cl_backspeed ", temp , "\n"));\r
244                 //stuffcmd( pl, strcat("cl_sidespeed ", temp , "\n"));\r
245                 //stuffcmd( pl, strcat("cl_upspeed ", temp , "\n"));\r
246         }\r
247 \r
248         pl.speed = s;\r
249 }\r
250 \r
251 \r
252 \r
253 /*\r
254 =============\r
255 ResetPlayerModel\r
256 \r
257 Resets the player's model to what it should be when returning from invisibility,\r
258  or trying to change class but not being allowed.\r
259 =============\r
260 */\r
261 \r
262 void ResetPlayerModel(entity pl)\r
263 {\r
264         local vector m1, m2;\r
265         m1 = pl.mins;\r
266         m2 = pl.maxs;\r
267         //precache_model (self.playermodel); needed?\r
268         setmodel (pl, pl.playermodel);\r
269         setsize (pl, m1, m2);\r
270 }\r
271 \r
272 /*\r
273 =============\r
274 CheckForClassChange\r
275 \r
276 Returns the player's class by checking his model.\r
277 Called from PlayerPreThink whenever the player changes his model, before change is made.\r
278 =============\r
279 */\r
280 \r
281 void() respawn;\r
282 float CheckForClassChange()\r
283 {\r
284         float cl;\r
285         float tfcl;\r
286 \r
287         // FIXME: need an option to not allow class changes at all once the player has changed once\r
288 \r
289         //bprint("check if allow change\n");\r
290 \r
291         // don't monitor the player's model when he's dead.\r
292         // this means he can change class when dead and respawn as the new class.\r
293         //if(self.health <= 0) // fixme: or if player is an observer\r
294         //      return 0;\r
295 \r
296 //      bprint("healthy\n");\r
297 \r
298         if(self.playermodel == self.mdl)\r
299                 return 0; // haven't changed models since last legitimate change\r
300 \r
301         //bprint("model has changed\n");\r
302 \r
303         cl = GetPlayerClass();\r
304         if(self.class == cl) // changed models, but it didn't affect my class\r
305         {\r
306                 if(self.change_mdl_on_respawn) // if was going to change class, but I just switched models of the same class I'm in now, undo the future class change\r
307                         self.change_mdl_on_respawn = "";\r
308                 return 0;\r
309         }\r
310 \r
311         //bprint("class changed\n");\r
312 \r
313 \r
314         // it's changed; now figure out what to do about it\r
315 \r
316         // don't allow player class\r
317         if(cvar("g_classchange_not_allowed"))\r
318         {\r
319                 self.playermodel = self.mdl;    // return to old model\r
320                 ResetPlayerModel(self);\r
321 \r
322                 /*local vector m1, m2;\r
323                 self.playermodel = self.model;  // return to old model\r
324                 m1 = self.mins;\r
325                 m2 = self.maxs;\r
326                 //precache_model (self.playermodel); needed?\r
327                 setmodel (self, self.playermodel);\r
328                 setsize (self, m1, m2);*/\r
329                 return 0;\r
330         }\r
331 \r
332         if (cl == CLASS_SCOUT)\r
333         {\r
334                 tfcl = TF_CLASS_SCOUT;\r
335         }\r
336         else if (cl == CLASS_SOLDIER)\r
337         {\r
338                 tfcl = TF_CLASS_SOLDIER;\r
339         }\r
340         else if (cl == CLASS_MEDIC)\r
341         {\r
342                 tfcl = TF_CLASS_MEDIC;\r
343         }\r
344         else if (cl == CLASS_PYRO)\r
345         {\r
346                 tfcl = TF_CLASS_PYRO;\r
347         }\r
348         else if (cl == CLASS_ENGINEER)\r
349         {\r
350                 tfcl = TF_CLASS_ENGINEER;\r
351         }\r
352         else if (cl == CLASS_SPY)\r
353         {\r
354                 tfcl = TF_CLASS_SPY;\r
355         }\r
356 \r
357         if (self.lives == 0)\r
358         {\r
359                 self.playermodel = self.mdl;    // return to old model\r
360                 ResetPlayerModel(self);\r
361                 sprint(self, "You have no lives left.\n");\r
362                 return 0;\r
363         }\r
364         if (!IsLegalClass(tfcl))                // Checks if class is legal for the map\r
365         {\r
366                 self.playermodel = self.mdl;    // return to old model\r
367                 ResetPlayerModel(self);\r
368                 sprint(self, "You cannot play that playerclass on this map. \n");\r
369                 TeamFortress_DisplayLegalClasses();\r
370                 return 0;\r
371         }\r
372         self.respawn_as_new_class = tfcl;       // makes sure conversion from TF .playerclass goes through\r
373 \r
374         // allow change, but don't take effect until death\r
375         if(cvar("g_classchange_delay_until_death"))\r
376         {\r
377                 self.change_mdl_on_respawn = self.playermodel;\r
378                 self.change_mdl_on_respawn = strzone(self.change_mdl_on_respawn);\r
379                 self.playermodel = self.model;\r
380                 if (self.team_no > 0)\r
381                 {\r
382                         sprint (self, "After dying, you will return as a ");\r
383                         TeamFortress_PrintClassName (self, cl, (self.tfstate & 8));\r
384                 }\r
385 //                      sprint(self, "You will change class after you die\n");\r
386                 return 0;\r
387         }\r
388 \r
389         // allow change, possibly with stipulations (like force respawn)\r
390 \r
391         //bprint("allowing change\n");\r
392 \r
393         if(self.class == CLASS_SPY)\r
394                 SpyDecloak();\r
395 \r
396         self.class = cl;\r
397         //self.mdl = strzone(self.playermodel);\r
398 \r
399 \r
400         // allow change, but instant kill & respawn\r
401         if(cvar("g_classchange_force_respawn"))\r
402         {\r
403                 PlayerKilled(TRUE, world, world, 1, DEATH_CLASSCHANGE, '0 0 0', '0 0 0');\r
404                 respawn();\r
405                 return 1;\r
406         }\r
407 \r
408         // allow class change without a hitch\r
409         ChangeClass(TRUE, TRUE);\r
410         return 0;\r
411 }\r
412 \r
413 void ClassSpecial()\r
414 {\r
415         if(self.class == CLASS_SCOUT)\r
416                 ScoutSpecial();\r
417         if(self.class == CLASS_SPY)\r
418                 SpySpecial();\r
419         if(self.class == CLASS_SOLDIER)\r
420                 SoldierSpecial();\r
421         if(self.class == CLASS_PYRO)\r
422                 PyroSpecial();\r
423         if(self.class == CLASS_MEDIC)\r
424                 MedicSpecial();\r
425         if(self.class == CLASS_ENGINEER)\r
426                 EngineerSpecial();\r
427 }\r
428 \r
429 void ClassGrenade(float req)\r
430 {\r
431         if(self.grenade_time > time)\r
432                 return;\r
433 \r
434         if(self.class == CLASS_SCOUT)\r
435                 ScoutGrenade(req);\r
436         if(self.class == CLASS_SPY)\r
437                 SpyGrenade(req);\r
438         if(self.class == CLASS_SOLDIER)\r
439                 SoldierGrenade(req);\r
440         if(self.class == CLASS_PYRO)\r
441                 PyroGrenade(req);\r
442         if(self.class == CLASS_MEDIC)\r
443                 MedicGrenade(req);\r
444         if(self.class == CLASS_ENGINEER)\r
445                 EngineerGrenade(req);\r
446 }\r
447 \r
448 void ClassPreThink()\r
449 {\r
450         if(self.class == CLASS_SCOUT)\r
451                 ScoutPreThink();\r
452         if(self.class == CLASS_SPY)\r
453                 SpyPreThink();\r
454         if(self.class == CLASS_SOLDIER)\r
455                 SoldierPreThink();\r
456         if(self.class == CLASS_PYRO)\r
457                 PyroPreThink();\r
458         if(self.class == CLASS_MEDIC)\r
459                 MedicPreThink();\r
460         if(self.class == CLASS_ENGINEER)\r
461                 EngineerPreThink();\r
462 }\r
463 \r
464 void ClassPostThink()\r
465 {\r
466         if(self.class == CLASS_SCOUT)\r
467                 ScoutPostThink();\r
468         if(self.class == CLASS_SPY)\r
469                 SpyPostThink();\r
470         if(self.class == CLASS_SOLDIER)\r
471                 SoldierPostThink();\r
472         if(self.class == CLASS_PYRO)\r
473                 PyroPostThink();\r
474         if(self.class == CLASS_MEDIC)\r
475                 MedicPostThink();\r
476         if(self.class == CLASS_ENGINEER)\r
477                 EngineerPostThink();\r
478 }\r
479 \r
480 /*\r
481 =========================\r
482  Set MaxAmmo for classes\r
483   Wazat - edit these values to whatever\r
484                            =========================\r
485 */\r
486 void (float classnum) SetMaxAmmoFor =\r
487 {\r
488         self.is_feigning = 0;\r
489         self.leg_damage = 0;            //temp here //so leg damage doesnt stay on player respawn\r
490         // if no class is found, it will just default to these\r
491         self.maxammo_shells = 200;\r
492         self.maxammo_nails = 200;\r
493         self.maxammo_cells = 40;\r
494         self.maxammo_rockets = 40;\r
495         self.no_grenades_1 = 4;\r
496         self.clip_rockets = CLIP_MAX_ROCKETS;\r
497         self.clip_pistol = CLIP_MAX_PISTOL;\r
498         self.tp_grenades_1 = 1;\r
499         self.tp_grenades_2 = 0;\r
500 \r
501         if (classnum == CLASS_SCOUT)            // Scout Supplies\r
502         {\r
503                 self.maxammo_shells = 200;\r
504                 self.maxammo_nails = 200;\r
505                 self.maxammo_cells = 40;\r
506                 self.maxammo_rockets = 40;\r
507                 self.clip_crylink = CLIP_MAX_CRYLINK;\r
508                 self.tp_grenades_1 = 9;\r
509         }\r
510         else if (classnum == CLASS_SPY) {               // Spy supplies\r
511                 self.maxammo_shells = 150;\r
512                 self.maxammo_nails = 200;               // MAC10 uses nails\r
513                 self.maxammo_cells = 70;\r
514                 self.maxammo_rockets = 15;\r
515                 self.ammo_nails = 100;\r
516         }\r
517         else if (classnum == CLASS_SOLDIER) {\r
518                 self.ammo_rockets = 62;                 //translates to 20\r
519                 self.maxammo_rockets = 40;\r
520                 self.tp_grenades_2 = 3;\r
521         }\r
522         else if (classnum == CLASS_PYRO) {\r
523                 self.clip_pipegrenades = 6;\r
524         }\r
525         else if (classnum == CLASS_ENGINEER) {\r
526                 self.maxammo_cells = 200;\r
527                 self.ammo_cells = 100;\r
528         }\r
529 };\r