]> icculus.org git repositories - divverent/nexuiz.git/blob - attic/TeamNexuiz/game/gamec/cl_player.c
now menu qc respects g_campaign_name
[divverent/nexuiz.git] / attic / TeamNexuiz / game / gamec / cl_player.c
1 $frame die1 die2 draw duck duckwalk duckjump duckidle idle\r
2 $frame jump pain1 pain2 shoot taunt run runbackwards\r
3 $frame strafeleft straferight dead1 dead2 forwardright\r
4 $frame forwardleft backright backleft\r
5 \r
6 // changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request\r
7 // merged player_run and player_stand to player_anim\r
8 // added death animations to player_anim\r
9 // can now spawn thrown weapons from anywhere, not just from players\r
10 // thrown weapons now fade out after 20 seconds\r
11 // created PlayerGib function\r
12 // PlayerDie no longer uses hitloc or damage\r
13 // PlayerDie now supports dying animations as well as gibbing\r
14 // cleaned up PlayerDie a lot\r
15 // added CopyBody\r
16 \r
17 void player_cooloff();\r
18 void BodyFakePhysics()\r
19 {\r
20         self.think = BodyFakePhysics;\r
21         self.nextthink = time;\r
22 \r
23         SV_PlayerPhysics();\r
24 \r
25         player_cooloff();\r
26 }\r
27 \r
28 void CopyBody2(float keepvelocity, float testbody)\r
29 {\r
30         local entity oldself;\r
31         if (self.effects & EF_NODRAW)\r
32                 return;\r
33         oldself = self;\r
34         self = spawn();\r
35         self.angles = oldself.angles;\r
36         self.avelocity = oldself.avelocity;\r
37         self.classname = "body";\r
38         self.mass = oldself.mass;\r
39         self.damageforcescale = oldself.damageforcescale;\r
40         self.effects = oldself.effects;\r
41         self.event_damage = oldself.event_damage;\r
42         self.frame = oldself.frame;\r
43         self.health = oldself.health;\r
44         self.model = oldself.model;\r
45         self.modelindex = oldself.modelindex;\r
46         self.movetype = oldself.movetype;\r
47         self.nextthink = oldself.nextthink;\r
48         self.skin = oldself.skin;\r
49         self.solid = oldself.solid;\r
50         self.takedamage = oldself.takedamage;\r
51         self.think = oldself.think;\r
52         if (keepvelocity == 1)\r
53                 self.velocity = oldself.velocity;\r
54         self.fade_time = oldself.fade_time;\r
55         self.fade_rate = oldself.fade_rate;\r
56         //self.weapon = oldself.weapon;\r
57         setorigin(self, oldself.origin);\r
58         setsize(self, oldself.mins, oldself.maxs);//'-16 -16 -24',  '16 16 5');\r
59         self.oldorigin = oldself.origin;\r
60         // move any fire burning me to the corpse\r
61         if(oldself.onfire != world)\r
62         {\r
63                 self.onfire = oldself.onfire;           // corpse is now on fire\r
64                 self.onfire.enemy = self;               // burn corpse instead of me when I respawn\r
65                 oldself.onfire = world;                 // I'm not on fire anymore\r
66                 setattachment(self.onfire, self, "");\r
67         }\r
68 \r
69         if(testbody)\r
70         {\r
71                 self.armorvalue = oldself.armorvalue;\r
72                 self.think = BodyFakePhysics;\r
73                 self.nextthink = time;\r
74         }\r
75         \r
76         self = oldself;\r
77 }\r
78 \r
79 void CopyBody(float keepvelocity)\r
80 {\r
81         CopyBody2(keepvelocity, FALSE);\r
82 }\r
83 \r
84 void player_anim (void)\r
85 {\r
86         if (self.deadflag != DEAD_NO)\r
87         {\r
88                 if (time > self.dead_time)\r
89                 {\r
90                         if (self.maxs_z > 5)\r
91                                 setsize(self, '-16 -16 -24', '16 16 5');\r
92                         self.frame = self.dead_frame;\r
93                 }\r
94                 else\r
95                         self.frame = self.die_frame;\r
96                 return;\r
97         }\r
98 \r
99         if (self.is_feigning == 1)\r
100         {\r
101                 self.frame = self.die_frame;\r
102                 return;\r
103         }\r
104 \r
105         if (self.crouch)\r
106         {\r
107                 if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20)\r
108                         self.frame = $duckwalk;\r
109                 else\r
110                         self.frame = $duckidle;\r
111         }\r
112         else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)\r
113         {\r
114                 if (self.movement_x > 0 && self.movement_y == 0)\r
115                 {\r
116                         self.frame = $run;\r
117                 }\r
118                 else if (self.movement_x < 0 && self.movement_y == 0)\r
119                         self.frame = $runbackwards;\r
120                 else if (self.movement_x == 0 && self.movement_y > 0)\r
121                         self.frame = $straferight;\r
122                 else if (self.movement_x == 0 && self.movement_y < 0)\r
123                         self.frame = $strafeleft;\r
124                 else if (self.movement_x > 0 && self.movement_y > 0)\r
125                         self.frame = $forwardright;\r
126                 else if (self.movement_x > 0 && self.movement_y < 0)\r
127                         self.frame = $forwardleft;\r
128                 else if (self.movement_x < 0 && self.movement_y > 0)\r
129                         self.frame = $backright;\r
130                 else if (self.movement_x < 0 && self.movement_y < 0)\r
131                         self.frame = $backleft;\r
132                 else\r
133                         self.frame = $run;\r
134         }\r
135         else if (self.pain_finished > time)\r
136                 self.frame = self.pain_frame;\r
137         else if (self.attack_finished > time)\r
138                 self.frame = $shoot;\r
139         else\r
140                 self.frame = $idle;\r
141 \r
142         if (!(self.flags & FL_ONGROUND))\r
143         {\r
144                 if (self.crouch)\r
145                         self.frame = $duckwalk;\r
146                 else\r
147                         self.frame = $jump;\r
148         }\r
149 }\r
150 //End change by Supajoe on 11:44 PM EST 11/16/03 (Subject: Player animations)\r
151 \r
152 \r
153 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
154 {\r
155         local float take, save;\r
156         te_blood (hitloc, force, damage);\r
157         // damage resistance (ignore most of the damage from a bullet or similar)\r
158         damage = max(damage - 5, 1);\r
159         save = bound(0, damage * 0.6, self.armorvalue);\r
160         take = bound(0, damage - save, damage);\r
161         self.armorvalue = self.armorvalue - save;\r
162         self.health = self.health - take;\r
163         self.dmg_save = self.dmg_save + save;\r
164         self.dmg_take = self.dmg_take + take;\r
165         self.dmg_inflictor = inflictor;\r
166         if (self.health <= -50)\r
167         {\r
168                 // don't use any animations as a gib\r
169                 self.frame = 0;\r
170                 self.dead_frame = 0;\r
171                 self.die_frame = 0;\r
172                 // view just above the floor\r
173                 self.view_ofs = '0 0 4';\r
174 \r
175                 // make a juicy mess\r
176                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 800, 1000);\r
177                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 400, 1000);\r
178 \r
179                 // make a meaty mess\r
180                 TossGib (self, "models/gibs/eye.md3", self.origin, self.velocity,0);\r
181                 TossGib (world, "models/gibs/bloodyskull.md3", self.origin, '0 0 600',0);\r
182 \r
183                 TossGib (world, "models/gibs/gib1.md3", self.origin, self.velocity,0);\r
184                 //TossGib (world, "models/gibs/gib2.md3", self.origin, self.velocity,0);\r
185                 TossGib (world, "models/gibs/gib1.mdl", self.origin, self.velocity,0);\r
186                 //TossGib (world, "models/gibs/gib3.md3", self.origin, self.velocity,0);\r
187                 TossGib (world, "models/gibs/gib2.mdl", self.origin, self.velocity,0);\r
188                 //TossGib (world, "models/gibs/gib4.md3", self.origin, self.velocity,0);\r
189                 TossGib (world, "models/gibs/gib3.mdl", self.origin, self.velocity,0);\r
190 \r
191                 // these destory on impact\r
192                 TossGib (world, "models/gibs/gib5.md3", self.origin, '-500 0 450',1);\r
193                 //TossGib (world, "models/gibs/gib6.md3", self.origin, '0 500 450',1);\r
194                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 -500 450',1);\r
195                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '500 0 450',1);\r
196                 TossGib (world, "models/gibs/chunk.mdl", self.origin, self.velocity,1);\r
197                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 0 450',1);\r
198 \r
199                 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);\r
200 \r
201         }\r
202 }\r
203 \r
204 void PlayerKilled (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
205 {\r
206         if(self.class == CLASS_SPY)\r
207                 SpyDecloak();\r
208 \r
209         // fixes death while reloading glitch\r
210         inflictor.reload_time = 0;\r
211         // fixes flash effects staying after death bug\r
212         self.FlashTime = 0;\r
213         stuffcmd(inflictor, "v_cshift 0 0 0 0\n");\r
214         \r
215         // throw a weapon\r
216         SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.wpn5.weapon);//self.weapon);\r
217         // print an obituary message\r
218         Obituary (attacker, self, deathtype);\r
219         // Drop flag or any carried item\r
220         TeamFortress_RemoveTimers ();\r
221         // Make sure corpse cant take tfgoal items\r
222         self.is_dead = 1;\r
223         // make the corpse upright (not tilted)\r
224         self.angles_x = 0;\r
225         self.angles_z = 0;\r
226         // don't spin\r
227         self.avelocity = '0 0 0';\r
228         // no weapon when dead\r
229         self.weaponmodel = "";\r
230         w_clear();\r
231         // view from the floor\r
232         self.view_ofs = '0 0 -8';\r
233         // toss the corpse\r
234         self.movetype = MOVETYPE_TOSS;\r
235         // shootable corpse\r
236         self.solid = SOLID_CORPSE;\r
237         // don't stick to the floor\r
238         self.flags = self.flags - (self.flags & FL_ONGROUND);\r
239         // dying animation\r
240         self.deadflag = DEAD_DYING;\r
241         // when to allow respawn\r
242         self.death_time = time + 0.5;\r
243         // when to switch to the dead_frame\r
244         self.dead_time = time + 2;\r
245         if(!unnatural_death)\r
246         {\r
247                 if (random() < 0.5)\r
248                 {\r
249                         self.die_frame = $die1;\r
250                         self.dead_frame = $dead1;\r
251                 }\r
252                 else\r
253                 {\r
254                         self.die_frame = $die2;\r
255                         self.dead_frame = $dead2;\r
256                 }\r
257         }\r
258         else\r
259         {\r
260                 self.die_frame = $dead2;\r
261                 self.dead_frame = $dead2;\r
262                 if(self.health > -1)\r
263                         self.health = -1;\r
264         }\r
265         // start the animation\r
266         player_anim();\r
267         // set damage function to corpse damage\r
268         self.event_damage = PlayerCorpseDamage;\r
269         // call the corpse damage function just in case it wants to gib\r
270         self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);\r
271         // set up to fade out later\r
272         SUB_SetFade (self, time + 12 + random () * 4, 1);\r
273 }\r
274 \r
275 float PlayerShouldDie (entity inflictor, entity attacker, float damage, float deathtype)\r
276 {\r
277         // returns true if player should die from this source of damage.\r
278         // If so, don't block this damage in any way\r
279 \r
280         if(damage > 2000)\r
281                 return TRUE;\r
282 \r
283         if(    deathtype == DEATH_FALL\r
284                 || deathtype == DEATH_TELEFRAG\r
285                 || deathtype == DEATH_DROWN\r
286                 || deathtype == DEATH_HURTTRIGGER\r
287                 || deathtype == DEATH_LAVA\r
288                 || deathtype == DEATH_SLIME\r
289                 || deathtype == DEATH_KILL\r
290                 || deathtype == DEATH_CLASSCHANGE\r
291 //              || deathtype == DEATH_BURNING\r
292                 || deathtype == DEATH_LASERGATE\r
293                 )\r
294                 return TRUE;\r
295 \r
296         return FALSE;\r
297 }\r
298 \r
299 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
300 {\r
301         local float take, save, damagearmor;\r
302 \r
303          te_blood (hitloc, force, damage);\r
304         if (self.pain_finished < time)          //Don't switch pain sequences like crazy\r
305         {\r
306                 if (random() > 0.5)\r
307                         self.pain_frame = $pain1;\r
308                 else\r
309                         self.pain_frame = $pain2;\r
310                 self.pain_finished = time + 0.5;        //Supajoe\r
311         }\r
312 \r
313         if(self.class == CLASS_MEDIC)\r
314         {\r
315                 if(deathtype == DEATH_BURNING)\r
316                         damage = 0;     // being on fire or near burning targets does nothing to medics\r
317                 // the flame thrower, flame rockets, and hotbombs also do minimal damage\r
318                 else if(deathtype == WEP_FLAMER ||\r
319                                 deathtype == WEP_ROCKET_INCENDIARY ||\r
320                                 deathtype == WEP_HOTBOMBS)\r
321                         damage = damage * cvar("g_balance_class_medic_flame_takedamage");\r
322         }\r
323 \r
324         // how much damage to deal to armor\r
325         damagearmor = bound(0, damage * 0.2 * (self.armorvalue / 50) * cvar("g_balance_armor_takedamage"), self.armorvalue);\r
326         // how much damage armor blocks\r
327         save = bound(0, damage * (self.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
328         // how much damage to deal to player\r
329         take = bound(0, damage - save, damage);\r
330 \r
331         // if being telefragged or killed by a death trigger etc, don't block that\r
332         if(PlayerShouldDie(inflictor, attacker, damage, deathtype))\r
333         {\r
334                 if(take < damage)\r
335                         take = damage; // deal full damage\r
336         }\r
337         else\r
338         {\r
339                 // keep the damage the armor allowed through, and further reduce it if the player is using the shield\r
340                 if(self.class == CLASS_SCOUT)\r
341                         take = SpecialShieldProtect(take);\r
342         }\r
343 \r
344         if (save > 10)\r
345                 sound (self, CHAN_IMPACT, "misc/armorimpact.wav", 1, ATTN_NORM);\r
346         if (take > 10)\r
347                 sound (self, CHAN_IMPACT, "misc/bodyimpact1.wav", 1, ATTN_NORM);\r
348         if (take > 30)\r
349                 sound (self, CHAN_IMPACT, "misc/bodyimpact2.wav", 1, ATTN_NORM);\r
350 \r
351         if (take > 50)\r
352                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
353         if (take > 100)\r
354                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
355 \r
356         if (!(self.flags & FL_GODMODE))\r
357         {\r
358                 self.armorvalue = self.armorvalue - damagearmor;\r
359                 self.health = self.health - take;\r
360         }\r
361 \r
362         DelayHealthRegen(self);\r
363         DelayArmorRegen(self);\r
364 \r
365 \r
366         self.dmg_save = self.dmg_save + max(save - 10, 0);\r
367         self.dmg_take = self.dmg_take + max(take - 10, 0);\r
368         self.dmg_inflictor = inflictor;\r
369         if (self.health <= 2)\r
370         {\r
371                 PlayerKilled(FALSE, inflictor, attacker, damage, deathtype, hitloc, force);\r
372 \r
373                 // make the corpse upright (not tilted)\r
374                 self.angles_x = 0;\r
375                 self.angles_z = 0;\r
376                 // don't spin\r
377                 self.avelocity = '0 0 0';\r
378                 // no weapon when dead\r
379                 self.weaponmodel = "";\r
380                 w_clear();\r
381                 // view from the floor\r
382                 self.view_ofs = '0 0 -8';\r
383                 // toss the corpse\r
384                 self.movetype = MOVETYPE_TOSS;\r
385                 // shootable corpse\r
386                 self.solid = SOLID_CORPSE;\r
387                 // don't stick to the floor\r
388                 self.flags = self.flags - (self.flags & FL_ONGROUND);\r
389                 // dying animation\r
390                 self.deadflag = DEAD_DYING;\r
391                 // when to allow respawn\r
392                 self.death_time = time + 0.5;\r
393                 // when to switch to the dead_frame\r
394                 self.dead_time = time + 2;\r
395                 if (random() < 0.5)\r
396                 {\r
397                         self.die_frame = $die1;\r
398                         self.dead_frame = $dead1;\r
399                 }\r
400                 else\r
401                 {\r
402                         self.die_frame = $die2;\r
403                         self.dead_frame = $dead2;\r
404                 }\r
405                 // start the animation\r
406                 player_anim();\r
407                 // set damage function to corpse damage\r
408                 self.event_damage = PlayerCorpseDamage;\r
409                 // call the corpse damage function just in case it wants to gib\r
410                 self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);\r
411                 // set up to fade out later\r
412                 SUB_SetFade (self, time + 12 + random () * 4, 1);\r
413 \r
414         }\r
415 }\r
416 \r