]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_player.c
added g_balance_falldamage_minspeed g_balance_falldamage_deadminspeed g_balance_falld...
[divverent/nexuiz.git] / qcsrc / gamec / cl_player.c
1 $frame die1 die2 draw duck duckwalk duckjump duckidle idle
2 $frame jump pain1 pain2 shoot taunt run runbackwards
3 $frame strafeleft straferight dead1 dead2 forwardright
4 $frame forwardleft backright backleft
5
6 // changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request
7 // merged player_run and player_stand to player_anim
8 // added death animations to player_anim
9 // can now spawn thrown weapons from anywhere, not just from players
10 // thrown weapons now fade out after 20 seconds
11 // created PlayerGib function
12 // PlayerDie no longer uses hitloc or damage
13 // PlayerDie now supports dying animations as well as gibbing
14 // cleaned up PlayerDie a lot
15 // added CopyBody
16
17 void CopyBody(float keepvelocity)
18 {
19         local entity oldself;
20         if (self.effects & EF_NODRAW)
21                 return;
22         oldself = self;
23         self = spawn();
24         self.iscreature = oldself.iscreature;
25         self.angles = oldself.angles;
26         self.avelocity = oldself.avelocity;
27         self.classname = "body";
28         self.damageforcescale = oldself.damageforcescale;
29         self.effects = oldself.effects;
30         self.event_damage = oldself.event_damage;
31         self.frame = oldself.frame;
32         self.health = oldself.health;
33         self.armorvalue = oldself.armorvalue;
34         self.armortype = oldself.armortype;
35         self.model = oldself.model;
36         self.modelindex = oldself.modelindex;
37         self.movetype = oldself.movetype;
38         self.nextthink = oldself.nextthink;
39         self.skin = oldself.skin;
40         self.solid = oldself.solid;
41         self.takedamage = oldself.takedamage;
42         self.think = oldself.think;
43         if (keepvelocity == 1)
44                 self.velocity = oldself.velocity;
45         self.oldvelocity = self.velocity;
46         self.fade_time = oldself.fade_time;
47         self.fade_rate = oldself.fade_rate;
48         //self.weapon = oldself.weapon;
49         setorigin(self, oldself.origin);
50         setsize(self, oldself.mins, oldself.maxs);//'-16 -16 -24',  '16 16 5');
51         self.oldorigin = oldself.origin;
52         self = oldself;
53 }
54
55 void player_anim (void)
56 {
57         if (self.deadflag != DEAD_NO)
58         {
59                 if (time > self.dead_time)
60                 {
61                         if (self.maxs_z > 5)
62                                 setsize(self, '-16 -16 -24', '16 16 5');
63                         self.frame = self.dead_frame;
64                 }
65                 else
66                         self.frame = self.die_frame;
67                 return;
68         }
69
70
71         if (self.crouch)
72         {
73                 if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20)
74                         self.frame = $duckwalk;
75                 else
76                         self.frame = $duckidle;
77         }
78         else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)
79         {
80                 if (self.movement_x > 0 && self.movement_y == 0)
81                         self.frame = $run;
82                 else if (self.movement_x < 0 && self.movement_y == 0)
83                         self.frame = $runbackwards;
84                 else if (self.movement_x == 0 && self.movement_y > 0)
85                         self.frame = $straferight;
86                 else if (self.movement_x == 0 && self.movement_y < 0)
87                         self.frame = $strafeleft;
88                 else if (self.movement_x > 0 && self.movement_y > 0)
89                         self.frame = $forwardright;
90                 else if (self.movement_x > 0 && self.movement_y < 0)
91                         self.frame = $forwardleft;
92                 else if (self.movement_x < 0 && self.movement_y > 0)
93                         self.frame = $backright;
94                 else if (self.movement_x < 0 && self.movement_y < 0)
95                         self.frame = $backleft;
96                 else
97                         self.frame = $run;
98         }
99         else if (self.pain_finished > time)
100                 self.frame = self.pain_frame;
101         else if (self.attack_finished > time)
102                 self.frame = $shoot;
103         else
104                 self.frame = $idle;
105
106         if (!(self.flags & FL_ONGROUND))
107                 self.frame = $jump;
108 }
109 //End change by Supajoe on 11:44 PM EST 11/16/03 (Subject: Player animations)
110
111 void SpawnThrownWeapon (vector org, float w)
112 {
113         local entity oldself;
114
115         if ((cvar("g_instagib") == 1) || (cvar("g_rocketarena") == 1))
116                 return;
117         if (w == IT_LASER)
118                 return;
119
120         oldself = self;
121         self = spawn();
122         // this will cause it to be removed later
123         self.classname = "droppedweapon";
124
125         setorigin(self, org);
126         self.velocity = randomvec() * 100 + '0 0 200';
127         SUB_SetFade(self, time + 20, 1);
128
129         if (w == WEP_UZI)
130                 weapon_uzi ();
131         else if (w == WEP_SHOTGUN)
132                 weapon_shotgun ();
133         else if (w == WEP_GRENADE_LAUNCHER)
134                 weapon_grenadelauncher ();
135         else if (w == WEP_ELECTRO)
136                 weapon_electro ();
137         else if (w == WEP_CRYLINK)
138                 weapon_crylink ();
139         else if (w == WEP_NEX)
140                 weapon_nex ();
141         else if (w == WEP_HAGAR)
142                 weapon_hagar ();
143         else if (w == WEP_ROCKET_LAUNCHER)
144                 weapon_rocketlauncher ();
145
146         // making absolutely sure...
147         self.classname = "droppedweapon";
148
149         self = oldself;
150 }
151
152 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
153 {
154         local float take, save;
155         te_blood (hitloc, force, damage);
156         // damage resistance (ignore most of the damage from a bullet or similar)
157         damage = max(damage - 5, 1);
158
159         save = bound(0, damage * cvar("g_balance_armor_blockpercent"), self.armorvalue);
160         take = bound(0, damage - save, damage);
161
162         if (save > 10)
163                 sound (self, CHAN_IMPACT, "misc/armorimpact.wav", 1, ATTN_NORM);
164         else if (take > 30)
165                 sound (self, CHAN_IMPACT, "misc/bodyimpact2.wav", 1, ATTN_NORM);
166         else if (take > 10)
167                 sound (self, CHAN_IMPACT, "misc/bodyimpact1.wav", 1, ATTN_NORM);
168
169         if (take > 50)
170                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);
171         if (take > 100)
172                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.2,1);
173
174         if (!(self.flags & FL_GODMODE))
175         {
176                 self.armorvalue = self.armorvalue - save;
177                 self.health = self.health - take;
178                 // pause regeneration for 5 seconds
179                 self.pauseregen_finished = max(self.pauseregen_finished, time + 5);
180         }
181         self.dmg_save = self.dmg_save + save;//max(save - 10, 0);
182         self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
183         self.dmg_inflictor = inflictor;
184
185         if (self.health <= -50)
186         {
187                 // don't use any animations as a gib
188                 self.frame = 0;
189                 self.dead_frame = 0;
190                 self.die_frame = 0;
191                 // view just above the floor
192                 self.view_ofs = '0 0 4';
193
194                 // make a juicy mess
195                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 800, 1000);
196                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 400, 1000);
197
198                 // make a meaty mess
199                 TossGib (self, "models/gibs/eye.md3", self.origin, self.velocity,0);
200                 TossGib (world, "models/gibs/bloodyskull.md3", self.origin, '0 0 600',0);
201
202                 TossGib (world, "models/gibs/gib1.md3", self.origin, self.velocity,0);
203                 TossGib (world, "models/gibs/gib2.md3", self.origin, self.velocity,0);
204                 TossGib (world, "models/gibs/gib3.md3", self.origin, self.velocity,0);
205                 TossGib (world, "models/gibs/gib4.md3", self.origin, self.velocity,0);
206
207                 // these destory on impact
208                 TossGib (world, "models/gibs/gib5.md3", self.origin, '-500 0 450',1);
209                 TossGib (world, "models/gibs/gib6.md3", self.origin, '0 500 450',1);
210                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 -500 450',1);
211                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '500 0 450',1);
212                 TossGib (world, "models/gibs/chunk.mdl", self.origin, self.velocity,1);
213                 TossGib (world, "models/gibs/chunk.mdl", self.origin, '0 0 450',1);
214
215                 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);
216         }
217 }
218
219 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
220 {
221         local float take, save;
222
223         te_blood (hitloc, force, damage);
224         if (self.pain_finished < time)          //Don't switch pain sequences like crazy
225         {
226                 if (random() > 0.5)
227                         self.pain_frame = $pain1;
228                 else
229                         self.pain_frame = $pain2;
230                 self.pain_finished = time + 0.5;        //Supajoe
231         }
232
233         save = bound(0, damage * cvar("g_balance_armor_blockpercent"), self.armorvalue);
234         take = bound(0, damage - save, damage);
235
236         if (save > 10)
237                 sound (self, CHAN_IMPACT, "misc/armorimpact.wav", 1, ATTN_NORM);
238         else if (take > 30)
239                 sound (self, CHAN_IMPACT, "misc/bodyimpact2.wav", 1, ATTN_NORM);
240         else if (take > 10)
241                 sound (self, CHAN_IMPACT, "misc/bodyimpact1.wav", 1, ATTN_NORM);
242
243         if (take > 50)
244                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);
245         if (take > 100)
246                 TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.2,1);
247
248         if (!(self.flags & FL_GODMODE))
249         {
250                 self.armorvalue = self.armorvalue - save;
251                 self.health = self.health - take;
252                 // pause regeneration for 5 seconds
253                 self.pauseregen_finished = max(self.pauseregen_finished, time + 5);
254         }
255         self.dmg_save = self.dmg_save + save;//max(save - 10, 0);
256         self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
257         self.dmg_inflictor = inflictor;
258         if (self.health <= 2)
259         {
260                 // throw a weapon
261                 SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.weapon);
262                 // print an obituary message
263                 Obituary (attacker, self, deathtype);
264                 // make the corpse upright (not tilted)
265                 self.angles_x = 0;
266                 self.angles_z = 0;
267                 // don't spin
268                 self.avelocity = '0 0 0';
269                 // no weapon when dead
270                 self.weaponmodel = "";
271                 w_clear();
272                 // view from the floor
273                 self.view_ofs = '0 0 -8';
274                 // toss the corpse
275                 self.movetype = MOVETYPE_TOSS;
276                 // shootable corpse
277                 self.solid = SOLID_CORPSE;
278                 // don't stick to the floor
279                 self.flags = self.flags - (self.flags & FL_ONGROUND);
280                 // dying animation
281                 self.deadflag = DEAD_DYING;
282                 // when to allow respawn
283                 self.death_time = time + 0.5;
284                 // when to switch to the dead_frame
285                 self.dead_time = time + 2;
286                 if (random() < 0.5)
287                 {
288                         self.die_frame = $die1;
289                         self.dead_frame = $dead1;
290                 }
291                 else
292                 {
293                         self.die_frame = $die2;
294                         self.dead_frame = $dead2;
295                 }
296                 // start the animation
297                 player_anim();
298                 // set damage function to corpse damage
299                 self.event_damage = PlayerCorpseDamage;
300                 // call the corpse damage function just in case it wants to gib
301                 self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);
302                 // set up to fade out later
303                 SUB_SetFade (self, time + 12 + random () * 4, 1);
304         }
305 }
306