]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/cl_player.c
- Added new backpack/tfitem property -- item_backpack gives metal ammo when var...
[divverent/nexuiz.git] / 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/gib3.md3", self.origin, self.velocity,0);\r
186                 TossGib (world, "models/gibs/gib4.md3", self.origin, self.velocity,0);\r
187 \r
188                 // these destory on impact\r
189                 TossGib (world, "models/gibs/gib5.md3", self.origin, '-500 0 450',1);\r
190                 TossGib (world, "models/gibs/gib6.md3", self.origin, '0 500 450',1);\r
191                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 -500 450',1);\r
192                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '500 0 450',1);\r
193                 TossGib (world, "models/gibs/chunk.mdl", self.origin, self.velocity,1);\r
194                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 0 450',1);\r
195 \r
196                 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);\r
197         }\r
198 }\r
199 \r
200 void PlayerKilled (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
201 {\r
202         if(self.class == CLASS_SPY)\r
203                 SpyDecloak();\r
204 \r
205         // fixes death while reloading glitch\r
206         inflictor.reload_time = 0;\r
207         // fixes flash effects staying after death bug\r
208         self.FlashTime = 0;\r
209         stuffcmd(inflictor, "v_cshift 0 0 0 0\n");\r
210         \r
211         // throw a weapon\r
212         SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.wpn5.weapon);//self.weapon);\r
213         // print an obituary message\r
214         Obituary (attacker, self, deathtype);\r
215         // Drop flag or any carried item\r
216         TeamFortress_RemoveTimers ();\r
217         // Make sure corpse cant take tfgoal items\r
218         self.is_dead = 1;\r
219         // make the corpse upright (not tilted)\r
220         self.angles_x = 0;\r
221         self.angles_z = 0;\r
222         // don't spin\r
223         self.avelocity = '0 0 0';\r
224         // no weapon when dead\r
225         self.weaponmodel = "";\r
226         w_clear();\r
227         // view from the floor\r
228         self.view_ofs = '0 0 -8';\r
229         // toss the corpse\r
230         self.movetype = MOVETYPE_TOSS;\r
231         // shootable corpse\r
232         self.solid = SOLID_CORPSE;\r
233         // don't stick to the floor\r
234         self.flags = self.flags - (self.flags & FL_ONGROUND);\r
235         // dying animation\r
236         self.deadflag = DEAD_DYING;\r
237         // when to allow respawn\r
238         self.death_time = time + 0.5;\r
239         // when to switch to the dead_frame\r
240         self.dead_time = time + 2;\r
241         if(!unnatural_death)\r
242         {\r
243                 if (random() < 0.5)\r
244                 {\r
245                         self.die_frame = $die1;\r
246                         self.dead_frame = $dead1;\r
247                 }\r
248                 else\r
249                 {\r
250                         self.die_frame = $die2;\r
251                         self.dead_frame = $dead2;\r
252                 }\r
253         }\r
254         else\r
255         {\r
256                 self.die_frame = $dead2;\r
257                 self.dead_frame = $dead2;\r
258                 if(self.health > -1)\r
259                         self.health = -1;\r
260         }\r
261         // start the animation\r
262         player_anim();\r
263         // set damage function to corpse damage\r
264         self.event_damage = PlayerCorpseDamage;\r
265         // call the corpse damage function just in case it wants to gib\r
266         self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);\r
267         // set up to fade out later\r
268         SUB_SetFade (self, time + 12 + random () * 4, 1);\r
269 }\r
270 \r
271 float PlayerShouldDie (entity inflictor, entity attacker, float damage, float deathtype)\r
272 {\r
273         // returns true if player should die from this source of damage.\r
274         // If so, don't block this damage in any way\r
275 \r
276         if(damage > 2000)\r
277                 return TRUE;\r
278 \r
279         if(    deathtype == DEATH_FALL\r
280                 || deathtype == DEATH_TELEFRAG\r
281                 || deathtype == DEATH_DROWN\r
282                 || deathtype == DEATH_HURTTRIGGER\r
283                 || deathtype == DEATH_LAVA\r
284                 || deathtype == DEATH_SLIME\r
285                 || deathtype == DEATH_KILL\r
286                 || deathtype == DEATH_CLASSCHANGE\r
287 //              || deathtype == DEATH_BURNING\r
288                 || deathtype == DEATH_LASERGATE\r
289                 )\r
290                 return TRUE;\r
291 \r
292         return FALSE;\r
293 }\r
294 \r
295 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
296 {\r
297         local float take, save, damagearmor;\r
298 \r
299          te_blood (hitloc, force, damage);\r
300         if (self.pain_finished < time)          //Don't switch pain sequences like crazy\r
301         {\r
302                 if (random() > 0.5)\r
303                         self.pain_frame = $pain1;\r
304                 else\r
305                         self.pain_frame = $pain2;\r
306                 self.pain_finished = time + 0.5;        //Supajoe\r
307         }\r
308 \r
309         if(self.class == CLASS_MEDIC)\r
310         {\r
311                 if(deathtype == DEATH_BURNING)\r
312                         damage = 0;     // being on fire or near burning targets does nothing to medics\r
313                 // the flame thrower, flame rockets, and hotbombs also do minimal damage\r
314                 else if(deathtype == WEP_FLAMER ||\r
315                                 deathtype == WEP_ROCKET_INCENDIARY ||\r
316                                 deathtype == WEP_HOTBOMBS)\r
317                         damage = damage * cvar("g_balance_class_medic_flame_takedamage");\r
318         }\r
319 \r
320         // how much damage to deal to armor\r
321         damagearmor = bound(0, damage * 0.2 * (self.armorvalue / 50) * cvar("g_balance_armor_takedamage"), self.armorvalue);\r
322         // how much damage armor blocks\r
323         save = bound(0, damage * (self.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
324         // how much damage to deal to player\r
325         take = bound(0, damage - save, damage);\r
326 \r
327         // if being telefragged or killed by a death trigger etc, don't block that\r
328         if(PlayerShouldDie(inflictor, attacker, damage, deathtype))\r
329         {\r
330                 if(take < damage)\r
331                         take = damage; // deal full damage\r
332         }\r
333         else\r
334         {\r
335                 // keep the damage the armor allowed through, and further reduce it if the player is using the shield\r
336                 if(self.class == CLASS_SCOUT)\r
337                         take = SpecialShieldProtect(take);\r
338         }\r
339 \r
340         if (save > 10)\r
341                 sound (self, CHAN_IMPACT, "misc/armorimpact.wav", 1, ATTN_NORM);\r
342         if (take > 10)\r
343                 sound (self, CHAN_IMPACT, "misc/bodyimpact1.wav", 1, ATTN_NORM);\r
344         if (take > 30)\r
345                 sound (self, CHAN_IMPACT, "misc/bodyimpact2.wav", 1, ATTN_NORM);\r
346 \r
347         if (take > 50)\r
348                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
349         if (take > 100)\r
350                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
351 \r
352         if (!(self.flags & FL_GODMODE))\r
353         {\r
354                 self.armorvalue = self.armorvalue - damagearmor;\r
355                 self.health = self.health - take;\r
356         }\r
357 \r
358         DelayHealthRegen(self);\r
359         DelayArmorRegen(self);\r
360 \r
361 \r
362         self.dmg_save = self.dmg_save + max(save - 10, 0);\r
363         self.dmg_take = self.dmg_take + max(take - 10, 0);\r
364         self.dmg_inflictor = inflictor;\r
365         if (self.health <= 2)\r
366         {\r
367                 PlayerKilled(FALSE, inflictor, attacker, damage, deathtype, hitloc, force);\r
368         }\r
369 }\r
370 \r