]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/cl_player.c
Added new GameC with class selection and random class selection working
[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 \r
100         if (self.crouch)\r
101         {\r
102                 if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20)\r
103                         self.frame = $duckwalk;\r
104                 else\r
105                         self.frame = $duckidle;\r
106         }\r
107         else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)\r
108         {\r
109                 if (self.movement_x > 0 && self.movement_y == 0)\r
110                 {\r
111                         self.frame = $run;\r
112                 }\r
113                 else if (self.movement_x < 0 && self.movement_y == 0)\r
114                         self.frame = $runbackwards;\r
115                 else if (self.movement_x == 0 && self.movement_y > 0)\r
116                         self.frame = $straferight;\r
117                 else if (self.movement_x == 0 && self.movement_y < 0)\r
118                         self.frame = $strafeleft;\r
119                 else if (self.movement_x > 0 && self.movement_y > 0)\r
120                         self.frame = $forwardright;\r
121                 else if (self.movement_x > 0 && self.movement_y < 0)\r
122                         self.frame = $forwardleft;\r
123                 else if (self.movement_x < 0 && self.movement_y > 0)\r
124                         self.frame = $backright;\r
125                 else if (self.movement_x < 0 && self.movement_y < 0)\r
126                         self.frame = $backleft;\r
127                 else\r
128                         self.frame = $run;\r
129         }\r
130         else if (self.pain_finished > time)\r
131                 self.frame = self.pain_frame;\r
132         else if (self.attack_finished > time)\r
133                 self.frame = $shoot;\r
134         else\r
135                 self.frame = $idle;\r
136 \r
137         if (!(self.flags & FL_ONGROUND))\r
138                 self.frame = $jump;\r
139 }\r
140 //End change by Supajoe on 11:44 PM EST 11/16/03 (Subject: Player animations)\r
141 \r
142 \r
143 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
144 {\r
145         local float take, save;\r
146         te_blood (hitloc, force, damage);\r
147         // damage resistance (ignore most of the damage from a bullet or similar)\r
148         damage = max(damage - 5, 1);\r
149         save = bound(0, damage * 0.6, self.armorvalue);\r
150         take = bound(0, damage - save, damage);\r
151         self.armorvalue = self.armorvalue - save;\r
152         self.health = self.health - take;\r
153         self.dmg_save = self.dmg_save + save;\r
154         self.dmg_take = self.dmg_take + take;\r
155         self.dmg_inflictor = inflictor;\r
156         if (self.health <= -50)\r
157         {\r
158                 // don't use any animations as a gib\r
159                 self.frame = 0;\r
160                 self.dead_frame = 0;\r
161                 self.die_frame = 0;\r
162                 // view just above the floor\r
163                 self.view_ofs = '0 0 4';\r
164 \r
165                 // make a juicy mess\r
166                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 800, 1000);\r
167                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 400, 1000);\r
168 \r
169                 // make a meaty mess\r
170                 TossGib (self, "models/gibs/eye.md3", self.origin, self.velocity,0);\r
171                 TossGib (world, "models/gibs/bloodyskull.md3", self.origin, '0 0 600',0);\r
172 \r
173                 TossGib (world, "models/gibs/gib1.md3", self.origin, self.velocity,0);\r
174                 TossGib (world, "models/gibs/gib2.md3", self.origin, self.velocity,0);\r
175                 TossGib (world, "models/gibs/gib3.md3", self.origin, self.velocity,0);\r
176                 TossGib (world, "models/gibs/gib4.md3", self.origin, self.velocity,0);\r
177 \r
178                 // these destory on impact\r
179                 TossGib (world, "models/gibs/gib5.md3", self.origin, '-500 0 450',1);\r
180                 TossGib (world, "models/gibs/gib6.md3", self.origin, '0 500 450',1);\r
181                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 -500 450',1);\r
182                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '500 0 450',1);\r
183                 TossGib (world, "models/gibs/chunk.mdl", self.origin, self.velocity,1);\r
184                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 0 450',1);\r
185 \r
186                 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);\r
187         }\r
188 }\r
189 \r
190 void PlayerKilled (float unnatural_death, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
191 {\r
192         if(self.class == CLASS_SPY)\r
193                 SpyDecloak();\r
194 \r
195         // throw a weapon\r
196         SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.wpn5.weapon);//self.weapon);\r
197         // print an obituary message\r
198         Obituary (attacker, self, deathtype);\r
199         // Drop flag or any carried item\r
200         TeamFortress_RemoveTimers ();\r
201         // Make sure corpse cant take tfgoal items\r
202         self.is_dead = 1;\r
203         // make the corpse upright (not tilted)\r
204         self.angles_x = 0;\r
205         self.angles_z = 0;\r
206         // don't spin\r
207         self.avelocity = '0 0 0';\r
208         // no weapon when dead\r
209         self.weaponmodel = "";\r
210         w_clear();\r
211         // view from the floor\r
212         self.view_ofs = '0 0 -8';\r
213         // toss the corpse\r
214         self.movetype = MOVETYPE_TOSS;\r
215         // shootable corpse\r
216         self.solid = SOLID_CORPSE;\r
217         // don't stick to the floor\r
218         self.flags = self.flags - (self.flags & FL_ONGROUND);\r
219         // dying animation\r
220         self.deadflag = DEAD_DYING;\r
221         // when to allow respawn\r
222         self.death_time = time + 0.5;\r
223         // when to switch to the dead_frame\r
224         self.dead_time = time + 2;\r
225         if(!unnatural_death)\r
226         {\r
227                 if (random() < 0.5)\r
228                 {\r
229                         self.die_frame = $die1;\r
230                         self.dead_frame = $dead1;\r
231                 }\r
232                 else\r
233                 {\r
234                         self.die_frame = $die2;\r
235                         self.dead_frame = $dead2;\r
236                 }\r
237         }\r
238         else\r
239         {\r
240                 self.die_frame = $dead2;\r
241                 self.dead_frame = $dead2;\r
242                 if(self.health > -1)\r
243                         self.health = -1;\r
244         }\r
245         // start the animation\r
246         player_anim();\r
247         // set damage function to corpse damage\r
248         self.event_damage = PlayerCorpseDamage;\r
249         // call the corpse damage function just in case it wants to gib\r
250         self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);\r
251         // set up to fade out later\r
252         SUB_SetFade (self, time + 12 + random () * 4, 1);\r
253 }\r
254 \r
255 float PlayerShouldDie (entity inflictor, entity attacker, float damage, float deathtype)\r
256 {\r
257         // returns true if player should die from this source of damage.\r
258         // If so, don't block this damage in any way\r
259 \r
260         if(damage > 2000)\r
261                 return TRUE;\r
262 \r
263         if(    deathtype == DEATH_FALL\r
264                 || deathtype == DEATH_TELEFRAG\r
265                 || deathtype == DEATH_DROWN\r
266                 || deathtype == DEATH_HURTTRIGGER\r
267                 || deathtype == DEATH_LAVA\r
268                 || deathtype == DEATH_SLIME\r
269                 || deathtype == DEATH_KILL\r
270                 || deathtype == DEATH_CLASSCHANGE\r
271 //              || deathtype == DEATH_BURNING\r
272                 || deathtype == DEATH_LASERGATE\r
273                 )\r
274                 return TRUE;\r
275 \r
276         return FALSE;\r
277 }\r
278 \r
279 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
280 {\r
281         local float take, save, damagearmor;\r
282 \r
283          te_blood (hitloc, force, damage);\r
284         if (self.pain_finished < time)          //Don't switch pain sequences like crazy\r
285         {\r
286                 if (random() > 0.5)\r
287                         self.pain_frame = $pain1;\r
288                 else\r
289                         self.pain_frame = $pain2;\r
290                 self.pain_finished = time + 0.5;        //Supajoe\r
291         }\r
292 \r
293         if(self.class == CLASS_MEDIC)\r
294         {\r
295                 if(deathtype == DEATH_BURNING)\r
296                         damage = 0;     // being on fire or near burning targets does nothing to medics\r
297                 // the flame thrower, flame rockets, and hotbombs also do minimal damage\r
298                 else if(deathtype == WEP_FLAMER ||\r
299                                 deathtype == WEP_ROCKET_INCENDIARY ||\r
300                                 deathtype == WEP_HOTBOMBS)\r
301                         damage = damage * cvar("g_balance_class_medic_flame_takedamage");\r
302         }\r
303 \r
304         // how much damage to deal to armor\r
305         damagearmor = bound(0, damage * 0.2 * (self.armorvalue / 50) * cvar("g_balance_armor_takedamage"), self.armorvalue);\r
306         // how much damage armor blocks\r
307         save = bound(0, damage * (self.armorvalue / 100) * cvar("g_balance_armor_effectiveness"), damage);\r
308         // how much damage to deal to player\r
309         take = bound(0, damage - save, damage);\r
310 \r
311         // if being telefragged or killed by a death trigger etc, don't block that\r
312         if(PlayerShouldDie(inflictor, attacker, damage, deathtype))\r
313         {\r
314                 if(take < damage)\r
315                         take = damage; // deal full damage\r
316         }\r
317         else\r
318         {\r
319                 // keep the damage the armor allowed through, and further reduce it if the player is using the shield\r
320                 if(self.class == CLASS_SCOUT)\r
321                         take = SpecialShieldProtect(take);\r
322         }\r
323 \r
324         if (save > 10)\r
325                 sound (self, CHAN_IMPACT, "misc/armorimpact.wav", 1, ATTN_NORM);\r
326         if (take > 10)\r
327                 sound (self, CHAN_IMPACT, "misc/bodyimpact1.wav", 1, ATTN_NORM);\r
328         if (take > 30)\r
329                 sound (self, CHAN_IMPACT, "misc/bodyimpact2.wav", 1, ATTN_NORM);\r
330 \r
331         if (take > 50)\r
332                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
333         if (take > 100)\r
334                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);\r
335 \r
336         if (!(self.flags & FL_GODMODE))\r
337         {\r
338                 self.armorvalue = self.armorvalue - damagearmor;\r
339                 self.health = self.health - take;\r
340         }\r
341 \r
342         DelayHealthRegen(self);\r
343         DelayArmorRegen(self);\r
344 \r
345 \r
346         self.dmg_save = self.dmg_save + max(save - 10, 0);\r
347         self.dmg_take = self.dmg_take + max(take - 10, 0);\r
348         self.dmg_inflictor = inflictor;\r
349         if (self.health <= 2)\r
350         {\r
351                 PlayerKilled(FALSE, inflictor, attacker, damage, deathtype, hitloc, force);\r
352         }\r
353 }\r
354 \r