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