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