]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_player.c
Added water drowning
[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()
18 {
19         local entity oldself;
20         if (self.effects & EF_NODRAW)
21                 return;
22         oldself = self;
23         self = spawn();
24         self.angles = oldself.angles;
25         self.avelocity = oldself.avelocity;
26         self.classname = "body";
27         self.damageforcescale = oldself.damageforcescale;
28         self.effects = oldself.effects;
29         self.event_damage = oldself.event_damage;
30         self.frame = oldself.frame;
31         self.health = oldself.health;
32         self.model = oldself.model;
33         self.modelindex = oldself.modelindex;
34         self.movetype = oldself.movetype;
35         self.nextthink = oldself.nextthink;
36         self.norespawn = TRUE;
37         self.skin = oldself.skin;
38         self.solid = oldself.solid;
39         self.takedamage = oldself.takedamage;
40         self.think = oldself.think;
41         self.velocity = oldself.velocity;
42         self.weapon = oldself.weapon;
43         setorigin(self, oldself.origin);
44         setsize(self, '-16 -16 -24',  '16 16 5');
45         self = oldself;
46 }
47
48 void player_anim (void)
49 {
50         if (self.deadflag != DEAD_NO)
51         {
52                 if (time > self.dead_time)
53                         self.frame = self.dead_frame;
54                 else
55                         self.frame = self.die_frame;
56                 return;
57         }
58
59
60         if (self.crouch)
61         {
62                 if (self.movement_x * self.movement_x + self.movement_y * self.movement_y > 20)
63                         self.frame = $duckwalk;
64                 else
65                         self.frame = $duckidle;
66         }
67         else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)
68         {
69                 if (self.movement_x > 0 && self.movement_y == 0)
70                         self.frame = $run;
71                 else if (self.movement_x < 0 && self.movement_y == 0)
72                         self.frame = $runbackwards;
73                 else if (self.movement_x == 0 && self.movement_y > 0)
74                         self.frame = $straferight;
75                 else if (self.movement_x == 0 && self.movement_y < 0)
76                         self.frame = $strafeleft;
77                 else if (self.movement_x > 0 && self.movement_y > 0)
78                         self.frame = $forwardright;
79                 else if (self.movement_x > 0 && self.movement_y < 0)
80                         self.frame = $forwardleft;
81                 else if (self.movement_x < 0 && self.movement_y > 0)
82                         self.frame = $backright;
83                 else if (self.movement_x < 0 && self.movement_y < 0)
84                         self.frame = $backleft;
85                 else
86                         self.frame = $run;
87         }
88         else if (self.pain_finished > time)
89                 self.frame = self.pain_frame;
90         else if (self.attack_finished > time)
91                 self.frame = $shoot;
92         else
93                 self.frame = $idle;
94
95         if (!(self.flags & FL_ONGROUND))
96                 self.frame = $idle;
97 }
98 //End change by Supajoe on 11:44 PM EST 11/16/03 (Subject: Player animations)
99
100 void SpawnThrownWeapon (vector org, float w)
101 {
102         local entity oldself;
103
104         if (game & (GAME_INSTAGIB | GAME_ROCKET_ARENA))
105                 return;
106         if (w == IT_LASER)
107                 return;
108
109         oldself = self;
110         self = spawn();
111
112         setorigin(self, org);
113         self.velocity = randomvec() * 100 + '0 0 200';
114         self.norespawn = 1;
115         //SUB_SetFade(self, time + 20);
116
117         if (w == WEP_UZI)
118                 weapon_uzi ();
119         else if (w == WEP_SHOTGUN)
120                 weapon_shotgun ();
121         else if (w == WEP_GRENADE_LAUNCHER)
122                 weapon_grenadelauncher ();
123         else if (w == WEP_ELECTRO)
124                 weapon_electro ();
125         else if (w == WEP_CRYLINK)
126                 weapon_crylink ();
127         else if (w == WEP_NEX)
128                 weapon_nex ();
129         else if (w == WEP_HAGAR)
130                 weapon_hagar ();
131         else if (w == WEP_ROCKET_LAUNCHER)
132                 weapon_rocketlauncher ();
133
134         self = oldself;
135 }
136
137 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
138 {
139         local float take, save;
140         te_blood (hitloc, force, damage);
141         // damage resistance (ignore most of the damage from a bullet or similar)
142         damage = max(damage - 5, 1);
143         save = bound(0, damage * 0.6, self.armorvalue);
144         take = bound(0, damage - save, damage);
145         self.armorvalue = self.armorvalue - save;
146         self.health = self.health - take;
147         self.dmg_save = self.dmg_save + save;
148         self.dmg_take = self.dmg_take + take;
149         self.dmg_inflictor = inflictor;
150         if (self.health <= -50)
151         {
152                 // don't use any animations as a gib
153                 self.frame = 0;
154                 self.dead_frame = 0;
155                 self.die_frame = 0;
156                 // view just above the floor
157                 self.view_ofs = '0 0 4';
158
159                 // make a juicy mess
160                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 800, 1000);
161                 te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 400, 1000);
162
163                 // make a meaty mess
164                 TossGib (world, "models/gibs/gib1.md3", self.origin, self.velocity);
165                 TossGib (world, "models/gibs/gib2.md3", self.origin, self.velocity);
166                 TossGib (world, "models/gibs/gib3.md3", self.origin, self.velocity);
167                 TossGib (self, "models/gibs/eye.md3", self.origin, self.velocity);
168
169                 TossGib (world, "models/gibs/gib4.mdl", self.origin, '500 0 450');
170                 TossGib (world, "models/gibs/gib4.mdl", self.origin, '-500 0 450');
171                 TossGib (world, "models/gibs/gib4.mdl", self.origin, '0 500 450');
172                 TossGib (world, "models/gibs/gib4.mdl", self.origin, '0 -500 450');
173
174                 TossGib (world, "models/gibs/bloodyskull.md3", self.origin, '0 0 600');
175
176                 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);
177         }
178 }
179
180 void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
181 {
182         local float take, save;
183         if (attacker == self)
184                 if (game & GAME_NO_SELF_DAMAGE)
185                         return;
186
187          te_blood (hitloc, force, damage);
188         if (self.pain_finished < time)          //Don't switch pain sequences like crazy
189         {
190                 if (random() > 0.5)
191                         self.pain_frame = $pain1;
192                 else
193                         self.pain_frame = $pain2;
194                 self.pain_finished = time + 0.5;        //Supajoe
195         }
196
197         save = bound(0, damage * 0.6, self.armorvalue);
198         take = bound(0, damage - save, damage);
199         self.armorvalue = self.armorvalue - save;
200
201         if (save > 10)
202                 sound (self, CHAN_BODY, "misc/armorimpact.wav", 1, ATTN_NORM);
203         if (take > 10)
204                 sound (self, CHAN_BODY, "misc/bodyimpact1.wav", 1, ATTN_NORM);
205         if (take > 30)
206                 sound (self, CHAN_BODY, "misc/bodyimpact2.wav", 1, ATTN_NORM);
207
208         if (take > 50)
209                 TossGib (world, "models/gibs/gib4.mdl", hitloc, force * -0.1);
210         if (take > 100)
211                 TossGib (world, "models/gibs/gib4.mdl", hitloc, force * -0.1);
212
213         self.health = self.health - take;
214         self.dmg_save = self.dmg_save + save * 0.25;
215         self.dmg_take = self.dmg_take + take * 0.25;
216         self.dmg_inflictor = inflictor;
217         if (self.health <= 0)
218         {
219                 // throw a weapon
220                 SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.weapon);
221                 // print an obituary message
222                 Obituary (attacker, self, deathtype);
223                 // make the corpse upright (not tilted)
224                 self.angles_x = 0;
225                 self.angles_z = 0;
226                 // don't spin
227                 self.avelocity = '0 0 0';
228                 // no weapon when dead
229                 self.weaponmodel = "";
230                 w_clear();
231                 // view from the floor
232                 self.view_ofs = '0 0 -8';
233                 // toss the corpse
234                 self.movetype = MOVETYPE_TOSS;
235                 // shootable corpse
236                 self.solid = SOLID_CORPSE;
237                 // don't stick to the floor
238                 self.flags = self.flags - (self.flags & FL_ONGROUND);
239                 // dying animation
240                 self.deadflag = DEAD_DYING;
241                 // when to allow respawn
242                 self.death_time = time + 0.5;
243                 // when to switch to the dead_frame
244                 self.dead_time = time + 1.5;
245                 if (random() < 0.5)
246                 {
247                         self.die_frame = $die1;
248                         self.dead_frame = $dead1;
249                 }
250                 else
251                 {
252                         self.die_frame = $die2;
253                         self.dead_frame = $dead2;
254                 }
255                 // start the animation
256                 player_anim();
257                 // set damage function to corpse damage
258                 self.event_damage = PlayerCorpseDamage;
259                 // call the corpse damage function just in case it wants to gib
260                 self.event_damage(inflictor, attacker, 0, deathtype, hitloc, force);
261                 // set up to fade out later
262                 SUB_SetFade (self, time + 12 + random () * 4);
263                 // Sajt - added this, but I'm not sure the powerups are even implemented? This might act strange because
264                 //        there is no code handled to disable powerups when their time is up...
265                 if (game & GAME_STRENGTH_GAIN)
266                 {
267                         if (attacker.strength_finished < time)
268                                 attacker.strength_finished = time;
269                         attacker.strength_finished = attacker.strength_finished + 5;
270                         attacker.items = attacker.items | IT_STRENGTH;
271                 }
272         }
273 }
274