]> git.jsancho.org Git - lugaru.git/blob - Source/Person.cpp
Add copyright notice and AUTHORS file for open source contributors
[lugaru.git] / Source / Person.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /**> HEADER FILES <**/
22 #include "Person.h"
23 #include "openal_wrapper.h"
24 #include "Animation.h"
25 #include "Sounds.h"
26 #include "Awards.h"
27 #include "Game.h"
28
29 extern float multiplier;
30 extern Terrain terrain;
31 extern float gravity;
32 extern int environment;
33 extern int detail;
34 extern FRUSTUM frustum;
35 extern XYZ viewer;
36 extern float realmultiplier;
37 extern int slomo;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
48 extern float woozy;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
52 extern bool decals;
53 extern float fadestart;
54 extern bool freeze;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
60 extern int test;
61 extern bool tilt2weird;
62 extern bool tiltweird;
63 extern bool midweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
75 extern bool cananger;
76 extern float damagedealt;
77 extern int hostile;
78 extern float hostiletime;
79
80 extern int indialogue;
81
82 extern bool gamestarted;
83
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
85
86 /* EFFECT
87  *
88  * USES:
89  * GameTick/doPlayerCollisions
90  */
91 void Person::CheckKick()
92 {
93     if (!(hasvictim
94             && (animTarget == rabbitkickanim
95                 && victim
96                 && victim != this->shared_from_this()
97                 && frameCurrent >= 2
98                 && animCurrent == rabbitkickanim)
99             && distsq(&coords, &victim->coords) < 1.2
100             && !victim->skeleton.free))
101         return;
102
103     if (animation[victim->animTarget].height != lowheight) {
104         float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
105         XYZ relative = velocity;
106         relative.y = 0;
107         Normalise(&relative);
108
109         victim->spurt = 1;
110         DoBlood(.2, 250);
111         if (tutoriallevel != 1)
112             emit_sound_at(heavyimpactsound, victim->coords);
113         victim->RagDoll(0);
114         for (int i = 0; i < victim->skeleton.num_joints; i++) {
115             victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
116         }
117         victim->Puff(neck);
118         victim->DoDamage(100 * damagemult / victim->protectionhigh);
119         if (id == 0)
120             camerashake += .4;
121
122         target = 0;
123         frameCurrent = 3;
124         animTarget = backflipanim;
125         frameTarget = 4;
126         velocity = facing * -10;
127         velocity.y = 5;
128         skeleton.free = 0;
129         if (id == 0)
130             resume_stream(whooshsound);
131
132         award_bonus(id, cannon);
133     } else if (victim->isCrouch()) {
134         animTarget = rabbitkickreversedanim;
135         animCurrent = rabbitkickreversedanim;
136         victim->animCurrent = rabbitkickreversalanim;
137         victim->animTarget = rabbitkickreversalanim;
138         targettilt2 = 0;
139         frameCurrent = 0;
140         frameTarget = 1;
141         target = 0;
142         velocity = 0;
143         victim->oldcoords = victim->coords;
144         coords = victim->coords;
145         victim->targetyaw = targetyaw;
146         victim->victim = this->shared_from_this();
147     }
148 }
149
150 /* EFFECT
151  *
152  * USES:
153  * GameTick/doPlayerCollisions - spread fire between players
154  * GameTick/doDebugKeys - press f to ignite
155  * Person::DoStuff - spread fire from lit campfires and bushes
156  */
157 void Person::CatchFire()
158 {
159     XYZ flatfacing, flatvelocity;
160     int howmany;
161     for (int i = 0; i < 10; i++) {
162         howmany = abs(Random() % (skeleton.num_joints));
163         if (!skeleton.free)
164             flatvelocity = velocity;
165         if (skeleton.free)
166             flatvelocity = skeleton.joints[howmany].velocity;
167         if (!skeleton.free)
168             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
169         if (skeleton.free)
170             flatfacing = skeleton.joints[howmany].position * scale + coords;
171         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
172     }
173
174     onfiredelay = 0.5;
175
176     emit_sound_at(firestartsound, coords);
177
178     emit_stream_at(stream_firesound, coords);
179
180     flamedelay = 0;
181
182     onfire = 1;
183 }
184
185 /* FUNCTION
186  * idle animation for this creature (depending on status)
187  */
188 int Person::getIdle()
189 {
190     if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
191         return talkidleanim;
192     if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
193         if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
194             victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
195             victim->id < Person::players.size())) {
196             if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
197                 if (creature == rabbittype)
198                     return fightidleanim;
199                 if (creature == wolftype)
200                     return wolfidle;
201             }
202             if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
203                 if (weapons[weaponids[weaponactive]].getType() == knife)
204                     return knifefightidleanim;
205                 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
206                     return swordfightidlebothanim;
207                 if (weapons[weaponids[weaponactive]].getType() == sword)
208                     return swordfightidleanim;
209                 if (weapons[weaponids[weaponactive]].getType() == staff)
210                     return swordfightidleanim;
211             }
212             if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
213                 return fightsidestep;
214         }
215     if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
216         return hurtidleanim;
217     if (howactive == typesitting) return sitanim;
218     if (howactive == typesittingwall) return sitwallanim;
219     if (howactive == typesleeping) return sleepanim;
220     if (howactive == typedead1) return dead1anim;
221     if (howactive == typedead2) return dead2anim;
222     if (howactive == typedead3) return dead3anim;
223     if (howactive == typedead4) return dead4anim;
224     if (creature == rabbittype) return bounceidleanim;
225     if (creature == wolftype) return wolfidle;
226     return 0;
227 }
228
229 /* FUNCTION
230  * crouch animation for this creature
231  */
232 int Person::getCrouch()
233 {
234     if (creature == rabbittype)
235         return crouchanim;
236     if (creature == wolftype)
237         return wolfcrouchanim;
238     return 0;
239 }
240
241 /* FUNCTION
242  * running animation for this creature (can be upright or all fours)
243  */
244 int Person::getRun()
245 {
246     if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
247         return runanim;
248     if (creature == wolftype && (!superruntoggle))
249         return wolfrunanim;
250
251     if (creature == rabbittype && (superruntoggle && weaponactive == -1))
252         return rabbitrunninganim;
253     if (creature == wolftype && (superruntoggle))
254         return wolfrunninganim;
255     return 0;
256 }
257
258 /* FUNCTION
259  */
260 int Person::getStop()
261 {
262     if (creature == rabbittype)
263         return stopanim;
264     if (creature == wolftype)
265         return wolfstopanim;
266     return 0;
267 }
268
269 /* FUNCTION
270  */
271 int Person::getLanding()
272 {
273     if (creature == rabbittype)
274         return landanim;
275     if (creature == wolftype)
276         return wolflandanim;
277     return 0;
278 }
279
280 /* FUNCTION
281  */
282 int Person::getLandhard()
283 {
284     if (creature == rabbittype)
285         return landhardanim;
286     if (creature == wolftype)
287         return wolflandhardanim;
288     return 0;
289 }
290
291 /* EFFECT
292  *
293  * USES:
294  * Person::DoAnimations
295  */
296 static void
297 SolidHitBonus(int playerid)
298 {
299     if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
300         award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
301     else
302         award_bonus(playerid, solidhit);
303 }
304
305 /* EFFECT
306  * spawns blood effects
307  */
308 void Person::DoBlood(float howmuch, int which)
309 {
310     // FIXME: should abstract out inputs
311     static int bleedxint, bleedyint;
312     static XYZ bloodvel;
313     if (bloodtoggle && tutoriallevel != 1) {
314         if (bleeding <= 0 && spurt) {
315             spurt = 0;
316             for (int i = 0; i < 3; i++) {
317                 // emit blood particles
318                 bloodvel = 0;
319                 if (!skeleton.free) {
320                     bloodvel.z = 10;
321                     bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
322                 }
323                 if (skeleton.free) {
324                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
325                 }
326                 if (skeleton.free)
327                     bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
328                 if (!skeleton.free)
329                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
330                 if (skeleton.free) {
331                     Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
332                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
333                 }
334                 if (!skeleton.free) {
335                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
336                     Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
337                 }
338             }
339             if (Random() % 2 == 0) // 50% chance
340                 for (int i = 0; i < 3; i++) {
341                     if (Random() % 2 != 0) {
342                         // emit teeth particles
343                         bloodvel = 0;
344                         if (skeleton.free) {
345                             bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
346                             bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
347                         } else {
348                             bloodvel.z = 10;
349                             bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
350                             bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
351                         }
352                         bloodvel *= .2;
353                         if (skeleton.free) {
354                             Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
355                         } else {
356                             Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
357                         }
358                         Sprite::setLastSpriteSpecial(3); // sets it to teeth
359                     }
360                 }
361         }
362         if (decals) {
363             // FIXME: manipulating attributes
364             bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
365             bleedxint = 0;
366             bleedyint = 0;
367             if (creature == rabbittype)
368                 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
369                     bleedxint = abs(Random() % 512);
370                     bleedyint = abs(Random() % 512);
371                 }
372             if (creature == wolftype)
373                 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
374                     bleedxint = abs(Random() % 512);
375                     bleedyint = abs(Random() % 512);
376                 }
377             bleedy = bleedxint;
378             bleedx = bleedyint;
379             bleedy /= realtexdetail;
380             bleedx /= realtexdetail;
381             direction = abs(Random() % 2) * 2 - 1;
382         }
383
384     }
385     if (bleeding > 2)
386         bleeding = 2;
387 }
388
389 /* EFFECT
390  * spawns big blood effects and ???
391  * modifies character's skin texture
392  */
393 void Person::DoBloodBig(float howmuch, int which)
394 {
395     static int bleedxint, bleedyint, i, j;
396     static XYZ bloodvel;
397     if (howmuch && id == 0)
398         blooddimamount = 1;
399
400     if (tutoriallevel != 1 || id == 0)
401         if (aitype != playercontrolled && howmuch > 0) {
402             // play pain sounds
403             int whichsound = -1;
404
405             // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
406             if (creature == wolftype) {
407                 int i = abs(Random() % 2);
408                 if (i == 0)
409                     whichsound = snarlsound;
410                 if (i == 1)
411                     whichsound = snarl2sound;
412                 envsound[numenvsounds] = coords;
413                 envsoundvol[numenvsounds] = 16;
414                 envsoundlife[numenvsounds] = .4;
415                 numenvsounds++;
416             }
417             if (creature == rabbittype) {
418                 int i = abs(Random() % 2);
419                 if (i == 0)
420                     whichsound = rabbitpainsound;
421                 if (i == 1 && howmuch >= 2)
422                     whichsound = rabbitpain1sound;
423                 envsound[numenvsounds] = coords;
424                 envsoundvol[numenvsounds] = 16;
425                 envsoundlife[numenvsounds] = .4;
426                 numenvsounds++;
427             }
428
429             if (whichsound != -1)
430                 emit_sound_at(whichsound, coords);
431         }
432
433     if (id == 0 && howmuch > 0) {
434         // FIXME: manipulating attributes
435         flashamount = .5;
436         flashr = 1;
437         flashg = 0;
438         flashb = 0;
439         flashdelay = 0;
440     }
441
442     if (bloodtoggle && decals && tutoriallevel != 1) {
443         if (bleeding <= 0 && spurt) {
444             spurt = 0;
445             for (int i = 0; i < 3; i++) {
446                 // emit blood particles
447                 // FIXME: copypaste from above
448                 bloodvel = 0;
449                 if (!skeleton.free) {
450                     bloodvel.z = 10;
451                     bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
452                 }
453                 if (skeleton.free) {
454                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
455                 }
456                 if (skeleton.free)
457                     bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
458                 if (!skeleton.free)
459                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
460                 if (skeleton.free) {
461                     Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
462                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
463                 }
464                 if (!skeleton.free) {
465                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
466                     Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
467                 }
468             }
469         }
470
471         // weird texture manipulation code follows.
472         // looks like this is painting blood onto the character's skin texture
473         // FIXME: surely there's a better way
474
475         int offsetx = 0, offsety = 0;
476         if (which == 225) {
477             offsety = Random() % 40;
478             offsetx = abs(Random() % 60);
479         }
480         if (which == 190 || which == 185) {
481             offsety = Random() % 40;
482             offsetx = abs(Random() % 100) - 20;
483         }
484         if (which == 175) {
485             offsety = Random() % 10;
486             offsetx = Random() % 10;
487         }
488         if (which == 170) {
489             offsety = Random() % 20;
490             offsetx = Random() % 20;
491         }
492         if (which == 220 || which == 215) {
493             offsetx = 20;
494         }
495
496
497         int startx = 512;
498         int starty = 512;
499         int endx = 0;
500         int endy = 0;
501         GLubyte color;
502         if (creature == rabbittype)
503             for (i = 0; i < 512; i++) {
504                 for (j = 0; j < 512; j++) {
505                     if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
506                         if (i < startx) startx = i;
507                         if (j < starty) starty = j;
508                         if (i > endx) endx = i;
509                         if (j > endy) endy = j;
510                     }
511                 }
512             }
513         if (creature == wolftype)
514             for (i = 0; i < 512; i++) {
515                 for (j = 0; j < 512; j++) {
516                     if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
517                         if (i < startx) startx = i;
518                         if (j < starty) starty = j;
519                         if (i > endx) endx = i;
520                         if (j > endy) endy = j;
521                     }
522                 }
523             }
524
525         startx += offsetx;
526         endx += offsetx;
527         starty += offsety;
528         endy += offsety;
529
530         if (startx < 0) startx = 0;
531         if (starty < 0) starty = 0;
532         if (endx > 512 - 1) endx = 512 - 1;
533         if (endy > 512 - 1) endy = 512 - 1;
534         if (endx < startx) endx = startx;
535         if (endy < starty) endy = starty;
536
537         startx /= realtexdetail;
538         starty /= realtexdetail;
539         endx /= realtexdetail;
540         endy /= realtexdetail;
541
542         int texdetailint = realtexdetail;
543         int where;
544         if (creature == rabbittype)
545             for (i = startx; i < endx; i++) {
546                 for (j = starty; j < endy; j++) {
547                     if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
548                         color = Random() % 85 + 170;
549                         where = i * skeleton.skinsize * 3 + j * 3;
550                         if (skeleton.skinText[where + 0] > color / 2)
551                             skeleton.skinText[where + 0] = color / 2;
552                         skeleton.skinText[where + 1] = 0;
553                         skeleton.skinText[where + 2] = 0;
554                     }
555                 }
556             }
557         if (creature == wolftype)
558             for (i = startx; i < endx; i++) {
559                 for (j = starty; j < endy; j++) {
560                     if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
561                         color = Random() % 85 + 170;
562                         where = i * skeleton.skinsize * 3 + j * 3;
563                         if (skeleton.skinText[where + 0] > color / 2)
564                             skeleton.skinText[where + 0] = color / 2;
565                         skeleton.skinText[where + 1] = 0;
566                         skeleton.skinText[where + 2] = 0;
567                     }
568                 }
569             }
570         skeleton.drawmodel.textureptr.bind();
571         DoMipmaps();
572
573         bleedxint = 0;
574         bleedyint = 0;
575         if (creature == rabbittype)
576             while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
577                 bleedxint = abs(Random() % 512);
578                 bleedyint = abs(Random() % 512);
579             }
580         if (creature == wolftype)
581             while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
582                 bleedxint = abs(Random() % 512);
583                 bleedyint = abs(Random() % 512);
584             }
585         bleedy = bleedxint + offsetx;
586         bleedx = bleedyint + offsety;
587         bleedy /= realtexdetail;
588         bleedx /= realtexdetail;
589         if (bleedx < 0)
590             bleedx = 0;
591         if (bleedy < 0)
592             bleedy = 0;
593         if (bleedx > skeleton.skinsize - 1)
594             bleedx = skeleton.skinsize - 1;
595         if (bleedy > skeleton.skinsize - 1)
596             bleedy = skeleton.skinsize - 1;
597         direction = abs(Random() % 2) * 2 - 1;
598
599     }
600     bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
601     deathbleeding += bleeding;
602     bloodloss += bleeding * 3;
603
604     if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
605         if (abs(Random() % 2) == 0) {
606             aitype = gethelptype;
607             lastseentime = 12;
608         } else
609             aitype = attacktypecutoff;
610         ally = 0;
611     }
612     if (bleeding > 2)
613         bleeding = 2;
614 }
615
616 /* EFFECT
617  * similar to DoBloodBig
618  */
619 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
620 {
621     static int i, j;
622     static XYZ bloodvel;
623     static XYZ startpoint, endpoint, colpoint, movepoint;
624     static float rotationpoint;
625     static int whichtri;
626     static XYZ p1, p2, p3, p0;
627     static XYZ N, temp;
628     XYZ bary;
629     XYZ gxx, gyy;
630     float coordsx, coordsy;
631     float total;
632
633     if (bloodtoggle && decals && tutoriallevel != 1) {
634         where -= coords;
635         if (!skeleton.free)
636             where = DoRotation(where, 0, -yaw, 0);
637         //where=scale;
638         startpoint = where;
639         startpoint.y += 100;
640         endpoint = where;
641         endpoint.y -= 100;
642         movepoint = 0;
643         rotationpoint = 0;
644         // ray testing for a tri in the character model
645         whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
646         if (whichtri != -1) {
647             // low level geometry math
648             p0 = colpoint;
649             p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
650             p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
651             p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
652             /*
653             CrossProduct(p2-p1,p3-p1,&N);
654             CrossProduct(p0-p1,p3-p1,&temp);
655             s =  dotproduct(&temp,&N)/findLength(&N);
656             CrossProduct(p2-p1,p1-p0,&temp);
657             t = dotproduct(&temp,&N)/findLength(&N);
658             r = 1 - (s + t);*/
659
660             bary.x = distsq(&p0, &p1);
661             bary.y = distsq(&p0, &p2);
662             bary.z = distsq(&p0, &p3);
663
664             total = bary.x + bary.y + bary.z;
665             bary.x /= total;
666             bary.y /= total;
667             bary.z /= total;
668
669             bary.x = 1 - bary.x;
670             bary.y = 1 - bary.y;
671             bary.z = 1 - bary.z;
672
673             total = bary.x + bary.y + bary.z;
674             bary.x /= total;
675             bary.y /= total;
676             bary.z /= total;
677
678
679             gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
680             gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
681             gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
682             gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
683             gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
684             gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
685             coordsx = skeleton.drawmodel.Triangles[whichtri].gx[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gx[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gx[2] * bary.z;
686             coordsy = skeleton.drawmodel.Triangles[whichtri].gy[0] * bary.x + skeleton.drawmodel.Triangles[whichtri].gy[1] * bary.y + skeleton.drawmodel.Triangles[whichtri].gy[2] * bary.z;
687
688             //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
689             //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
690
691             if (bleeding <= 0 && spurt) {
692                 spurt = 0;
693                 for (int i = 0; i < 3; i++) {
694                     // emit blood particles
695                     // FIXME: more copypaste code
696                     bloodvel = 0;
697                     if (!skeleton.free) {
698                         bloodvel.z = 10;
699                         bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
700                     }
701                     if (skeleton.free) {
702                         bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
703                     }
704                     if (skeleton.free)
705                         bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
706                     if (!skeleton.free)
707                         bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
708                     if (skeleton.free) {
709                         Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
710                         Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
711                     }
712                     if (!skeleton.free) {
713                         Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
714                         Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
715                     }
716                 }
717             }
718
719             // texture manipulation follows
720
721             int offsetx = 0, offsety = 0;
722             offsetx = (1 + coordsy) * 512 - 291;
723             offsety = coordsx * 512 - 437;
724
725             int startx = 512;
726             int starty = 512;
727             int endx = 0;
728             int endy = 0;
729             GLubyte color;
730             if (creature == rabbittype)
731                 for (i = 0; i < 512; i++) {
732                     for (j = 0; j < 512; j++) {
733                         if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
734                             if (i < startx) startx = i;
735                             if (j < starty) starty = j;
736                             if (i > endx) endx = i;
737                             if (j > endy) endy = j;
738                         }
739                     }
740                 }
741             if (creature == wolftype)
742                 for (i = 0; i < 512; i++) {
743                     for (j = 0; j < 512; j++) {
744                         if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
745                             if (i < startx) startx = i;
746                             if (j < starty) starty = j;
747                             if (i > endx) endx = i;
748                             if (j > endy) endy = j;
749                         }
750                     }
751                 }
752             startx += offsetx;
753             endx += offsetx;
754             starty += offsety;
755             endy += offsety;
756
757             if (startx < 0) startx = 0;
758             if (starty < 0) starty = 0;
759             if (endx > 512 - 1) endx = 512 - 1;
760             if (endy > 512 - 1) endy = 512 - 1;
761             if (endx < startx) endx = startx;
762             if (endy < starty) endy = starty;
763
764             startx /= realtexdetail;
765             starty /= realtexdetail;
766             endx /= realtexdetail;
767             endy /= realtexdetail;
768
769             int texdetailint = realtexdetail;
770             int where;
771             if (creature == rabbittype)
772                 for (i = startx; i < endx; i++) {
773                     for (j = starty; j < endy; j++) {
774                         if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
775                             color = Random() % 85 + 170;
776                             where = i * skeleton.skinsize * 3 + j * 3;
777                             if (skeleton.skinText[where + 0] > color / 2)
778                                 skeleton.skinText[where + 0] = color / 2;
779                             skeleton.skinText[where + 1] = 0;
780                             skeleton.skinText[where + 2] = 0;
781                         } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
782                             color = Random() % 85 + 170;
783                             where = i * skeleton.skinsize * 3 + j * 3;
784                             if (skeleton.skinText[where + 0] > color / 2)
785                                 skeleton.skinText[where + 0] = color / 2;
786                             skeleton.skinText[where + 1] = 0;
787                             skeleton.skinText[where + 2] = 0;
788                         }
789                     }
790                 }
791             if (creature == wolftype)
792                 for (i = startx; i < endx; i++) {
793                     for (j = starty; j < endy; j++) {
794                         if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
795                             color = Random() % 85 + 170;
796                             where = i * skeleton.skinsize * 3 + j * 3;
797                             if (skeleton.skinText[where + 0] > color / 2)
798                                 skeleton.skinText[where + 0] = color / 2;
799                             skeleton.skinText[where + 1] = 0;
800                             skeleton.skinText[where + 2] = 0;
801                         } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
802                             color = Random() % 85 + 170;
803                             where = i * skeleton.skinsize * 3 + j * 3;
804                             if (skeleton.skinText[where + 0] > color / 2)
805                                 skeleton.skinText[where + 0] = color / 2;
806                             skeleton.skinText[where + 1] = 0;
807                             skeleton.skinText[where + 2] = 0;
808                         }
809                     }
810                 }
811             skeleton.drawmodel.textureptr.bind();
812             DoMipmaps();
813
814             bleedy = (1 + coordsy) * 512;
815             bleedx = coordsx * 512;
816             bleedy /= realtexdetail;
817             bleedx /= realtexdetail;
818             if (bleedx < 0)
819                 bleedx = 0;
820             if (bleedy < 0)
821                 bleedy = 0;
822             if (bleedx > skeleton.skinsize - 1)
823                 bleedx = skeleton.skinsize - 1;
824             if (bleedy > skeleton.skinsize - 1)
825                 bleedy = skeleton.skinsize - 1;
826             direction = abs(Random() % 2) * 2 - 1;
827         }
828         if (whichtri == -1)
829             return 0;
830     }
831     bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
832     deathbleeding += bleeding;
833     bloodloss += bleeding * 3;
834
835     if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
836         if (abs(Random() % 2) == 0) {
837             aitype = gethelptype;
838             lastseentime = 12;
839         } else
840             aitype = attacktypecutoff;
841         ally = 0;
842     }
843     if (bleeding > 2)
844         bleeding = 2;
845     return 1;
846 }
847
848
849
850 /* EFFECT
851  * guessing this performs a reversal
852  */
853 void Person::Reverse()
854 {
855     if (!((victim->aitype == playercontrolled
856             || hostiletime > 1
857             || staggerdelay <= 0)
858             && victim->animTarget != jumpupanim
859             && victim->animTarget != jumpdownanim
860             && (tutoriallevel != 1 || cananger)
861             && hostile))
862         return;
863
864     if (normaldotproduct (victim->facing, victim->coords - coords) > 0
865             && (victim->id != 0 || difficulty >= 2)
866             && (creature != wolftype || victim->creature == wolftype))
867         return;
868
869     if (animTarget == sweepanim) {
870         animTarget = sweepreversedanim;
871         animCurrent = sweepreversedanim;
872         victim->animCurrent = sweepreversalanim;
873         victim->animTarget = sweepreversalanim;
874     }
875     if (animTarget == spinkickanim) {
876         animTarget = spinkickreversedanim;
877         animCurrent = spinkickreversedanim;
878         victim->animCurrent = spinkickreversalanim;
879         victim->animTarget = spinkickreversalanim;
880     }
881     if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
882         if (animTarget == rabbittacklinganim) {
883             frameCurrent = 6;
884             frameTarget = 7;
885             victim->frameCurrent = 6;
886             victim->frameTarget = 7;
887         }
888         animTarget = upunchreversedanim;
889         animCurrent = upunchreversedanim;
890         victim->animCurrent = upunchreversalanim;
891         victim->animTarget = upunchreversalanim;
892     }
893     if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
894         if (victim->weaponactive != -1) {
895             victim->throwtogglekeydown = 1;
896             weapons[victim->weaponids[0]].owner = -1;
897             weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
898             if (weapons[victim->weaponids[0]].velocity.x == 0)
899                 weapons[victim->weaponids[0]].velocity.x = .1;
900             weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
901             weapons[victim->weaponids[0]].missed = 1;
902             weapons[victim->weaponids[0]].freetime = 0;
903             weapons[victim->weaponids[0]].firstfree = 1;
904             weapons[victim->weaponids[0]].physics = 1;
905             victim->num_weapons--;
906             if (victim->num_weapons) {
907                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
908                 if (victim->weaponstuck == victim->num_weapons)
909                     victim->weaponstuck = 0;
910             }
911
912             victim->weaponactive = -1;
913             for (unsigned j = 0; j < Person::players.size(); j++) {
914                 Person::players[j]->wentforweapon = 0;
915             }
916         }
917
918         animTarget = staffhitreversedanim;
919         animCurrent = staffhitreversedanim;
920         victim->animCurrent = staffhitreversalanim;
921         victim->animTarget = staffhitreversalanim;
922     }
923     if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
924         if (victim->weaponactive != -1) {
925             victim->throwtogglekeydown = 1;
926             weapons[victim->weaponids[0]].owner = -1;
927             weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
928             if (weapons[victim->weaponids[0]].velocity.x == 0)
929                 weapons[victim->weaponids[0]].velocity.x = .1;
930             weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
931             weapons[victim->weaponids[0]].missed = 1;
932             weapons[victim->weaponids[0]].freetime = 0;
933             weapons[victim->weaponids[0]].firstfree = 1;
934             weapons[victim->weaponids[0]].physics = 1;
935             victim->num_weapons--;
936             if (victim->num_weapons) {
937                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
938                 if (victim->weaponstuck == victim->num_weapons)
939                     victim->weaponstuck = 0;
940             }
941
942             victim->weaponactive = -1;
943             for (unsigned j = 0; j < Person::players.size(); j++) {
944                 Person::players[j]->wentforweapon = 0;
945             }
946         }
947         animTarget = staffspinhitreversedanim;
948         animCurrent = staffspinhitreversedanim;
949         victim->animCurrent = staffspinhitreversalanim;
950         victim->animTarget = staffspinhitreversalanim;
951     }
952     if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
953         if (victim->weaponactive != -1) {
954             victim->throwtogglekeydown = 1;
955             weapons[victim->weaponids[0]].owner = -1;
956             weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
957             if (weapons[victim->weaponids[0]].velocity.x == 0)
958                 weapons[victim->weaponids[0]].velocity.x = .1;
959             weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
960             weapons[victim->weaponids[0]].missed = 1;
961             weapons[victim->weaponids[0]].freetime = 0;
962             weapons[victim->weaponids[0]].firstfree = 1;
963             weapons[victim->weaponids[0]].physics = 1;
964             victim->num_weapons--;
965             if (victim->num_weapons) {
966                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
967                 if (victim->weaponstuck == victim->num_weapons)
968                     victim->weaponstuck = 0;
969             }
970
971             victim->weaponactive = -1;
972             for (unsigned j = 0; j < Person::players.size(); j++) {
973                 Person::players[j]->wentforweapon = 0;
974             }
975         }
976         animTarget = swordslashreversedanim;
977         animCurrent = swordslashreversedanim;
978         victim->animCurrent = swordslashreversalanim;
979         victim->animTarget = swordslashreversalanim;
980     }
981     if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
982         if (victim->weaponactive != -1) {
983             victim->throwtogglekeydown = 1;
984             weapons[victim->weaponids[0]].owner = -1;
985             weapons[victim->weaponids[0]].velocity = victim->velocity * .2;
986             if (weapons[victim->weaponids[0]].velocity.x == 0)
987                 weapons[victim->weaponids[0]].velocity.x = .1;
988             weapons[victim->weaponids[0]].tipvelocity = weapons[victim->weaponids[0]].velocity;
989             weapons[victim->weaponids[0]].missed = 1;
990             weapons[victim->weaponids[0]].freetime = 0;
991             weapons[victim->weaponids[0]].firstfree = 1;
992             weapons[victim->weaponids[0]].physics = 1;
993             victim->num_weapons--;
994             if (victim->num_weapons) {
995                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
996                 if (victim->weaponstuck == victim->num_weapons)
997                     victim->weaponstuck = 0;
998             }
999
1000             victim->weaponactive = -1;
1001             for (unsigned j = 0; j < Person::players.size(); j++) {
1002                 Person::players[j]->wentforweapon = 0;
1003             }
1004         }
1005         animTarget = knifeslashreversedanim;
1006         animCurrent = knifeslashreversedanim;
1007         victim->animCurrent = knifeslashreversalanim;
1008         victim->animTarget = knifeslashreversalanim;
1009     }
1010     if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1011         victim->targettilt2 = targettilt2;
1012         victim->frameCurrent = frameCurrent;
1013         victim->frameTarget = frameTarget;
1014         victim->target = target;
1015         victim->velocity = 0;
1016         victim->oldcoords = victim->coords;
1017         victim->coords = coords;
1018         victim->targetyaw = targetyaw;
1019         victim->yaw = targetyaw;
1020         victim->victim = this->shared_from_this();
1021     }
1022     if (animTarget == winduppunchanim) {
1023         animTarget = winduppunchblockedanim;
1024         victim->animTarget = blockhighleftanim;
1025         victim->frameTarget = 1;
1026         victim->target = .5;
1027         victim->victim = this->shared_from_this();
1028         victim->targetyaw = targetyaw + 180;
1029     }
1030     if (animTarget == wolfslapanim) {
1031         animTarget = winduppunchblockedanim;
1032         victim->animTarget = blockhighleftanim;
1033         victim->frameTarget = 1;
1034         victim->target = .5;
1035         victim->victim = this->shared_from_this();
1036         victim->targetyaw = targetyaw + 180;
1037     }
1038     if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1039         animTarget = swordslashparriedanim;
1040         parriedrecently = .4;
1041         victim->parriedrecently = 0;
1042         victim->animTarget = swordslashparryanim;
1043         victim->frameTarget = 1;
1044         victim->target = .5;
1045         victim->victim = this->shared_from_this();
1046         victim->targetyaw = targetyaw + 180;
1047
1048         if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1049             if (victim->weaponactive != -1) {
1050                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1051                     if (weapons[victim->weaponids[0]].getType() == staff)
1052                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1053                     if (weapons[weaponids[0]].getType() == staff)
1054                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1055                     emit_sound_at(swordstaffsound, victim->coords);
1056                 } else {
1057                     emit_sound_at(metalhitsound, victim->coords);
1058                 }
1059             }
1060             XYZ aim;
1061             victim->Puff(righthand);
1062             victim->target = 0;
1063             victim->frameTarget = 0;
1064             victim->animTarget = staggerbackhighanim;
1065             victim->targetyaw = targetyaw + 180;
1066             victim->target = 0;
1067             weapons[victim->weaponids[0]].owner = -1;
1068             aim = DoRotation(facing, 0, 90, 0) * 21;
1069             aim.y += 7;
1070             weapons[victim->weaponids[0]].velocity = aim * -.2;
1071             weapons[victim->weaponids[0]].tipvelocity = aim;
1072             weapons[victim->weaponids[0]].missed = 1;
1073             weapons[victim->weaponids[0]].hitsomething = 0;
1074             weapons[victim->weaponids[0]].freetime = 0;
1075             weapons[victim->weaponids[0]].firstfree = 1;
1076             weapons[victim->weaponids[0]].physics = 1;
1077             victim->num_weapons--;
1078             if (victim->num_weapons) {
1079                 victim->weaponids[0] = victim->weaponids[num_weapons];
1080                 if (victim->weaponstuck == victim->num_weapons)
1081                     victim->weaponstuck = 0;
1082             }
1083             victim->weaponactive = -1;
1084             for (unsigned i = 0; i < Person::players.size(); i++) {
1085                 Person::players[i]->wentforweapon = 0;
1086             }
1087         }
1088
1089         if (abs(Random() % 20) == 0) {
1090             if (weaponactive != -1) {
1091                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1092                     if (weapons[victim->weaponids[0]].getType() == staff)
1093                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1094                     if (weapons[weaponids[0]].getType() == staff)
1095                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1096
1097                     emit_sound_at(swordstaffsound, coords);
1098                 } else {
1099                     emit_sound_at(metalhitsound, coords);
1100                 }
1101             }
1102
1103             XYZ aim;
1104             Puff(righthand);
1105             target = 0;
1106             frameTarget = 0;
1107             animTarget = staggerbackhighanim;
1108             targetyaw = targetyaw + 180;
1109             target = 0;
1110             weapons[weaponids[0]].owner = -1;
1111             aim = DoRotation(facing, 0, 90, 0) * 21;
1112             aim.y += 7;
1113             weapons[weaponids[0]].velocity = aim * -.2;
1114             weapons[weaponids[0]].tipvelocity = aim;
1115             weapons[weaponids[0]].hitsomething = 0;
1116             weapons[weaponids[0]].missed = 1;
1117             weapons[weaponids[0]].freetime = 0;
1118             weapons[weaponids[0]].firstfree = 1;
1119             weapons[weaponids[0]].physics = 1;
1120             num_weapons--;
1121             if (num_weapons) {
1122                 weaponids[0] = weaponids[num_weapons];
1123                 if (weaponstuck == num_weapons)
1124                     weaponstuck = 0;
1125             }
1126             weaponactive = -1;
1127             for (unsigned i = 0; i < Person::players.size(); i++) {
1128                 Person::players[i]->wentforweapon = 0;
1129             }
1130
1131
1132         }
1133     }
1134     if (hasvictim)
1135         if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1136             if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1137                 victim->animTarget = dodgebackanim;
1138                 victim->frameTarget = 0;
1139                 victim->target = 0;
1140
1141                 XYZ rotatetarget;
1142                 rotatetarget = coords - victim->coords;
1143                 Normalise(&rotatetarget);
1144                 victim->targetyaw = -asin(0 - rotatetarget.x);
1145                 victim->targetyaw *= 360 / 6.28;
1146                 if (rotatetarget.z < 0)
1147                     victim->targetyaw = 180 - victim->targetyaw;
1148
1149                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1150
1151                 victim->lastattack3 = victim->lastattack2;
1152                 victim->lastattack2 = victim->lastattack;
1153                 victim->lastattack = victim->animTarget;
1154             } else {
1155                 victim->animTarget = sweepanim;
1156                 victim->frameTarget = 0;
1157                 victim->target = 0;
1158
1159                 XYZ rotatetarget;
1160                 rotatetarget = coords - victim->coords;
1161                 Normalise(&rotatetarget);
1162                 victim->targetyaw = -asin(0 - rotatetarget.x);
1163                 victim->targetyaw *= 360 / 6.28;
1164                 if (rotatetarget.z < 0)
1165                     victim->targetyaw = 180 - victim->targetyaw;
1166
1167                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1168
1169                 victim->lastattack3 = victim->lastattack2;
1170                 victim->lastattack2 = victim->lastattack;
1171                 victim->lastattack = victim->animTarget;
1172             }
1173         }
1174
1175     velocity = 0;
1176     victim->velocity = 0;
1177
1178     if (aitype != playercontrolled)
1179         feint = 0;
1180     if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1181         feint = 1;
1182     if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1183         feint = 1;
1184     if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1185         feint = 1;
1186
1187     if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1188         numreversals++;
1189 }
1190
1191 /* EFFECT
1192  * get hurt
1193  */
1194 void Person::DoDamage(float howmuch)
1195 {
1196     // subtract health (temporary?)
1197     if (tutoriallevel != 1)
1198         damage += howmuch / power;
1199     // stats?
1200     if (id != 0)
1201         damagedealt += howmuch / power;
1202     if (id == 0)
1203         damagetaken += howmuch / power;
1204
1205     // reset bonuses
1206     if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1207         bonus = 0;
1208     // subtract health
1209     if (tutoriallevel != 1)
1210         permanentdamage += howmuch / 2 / power;
1211     if (tutoriallevel != 1)
1212         superpermanentdamage += howmuch / 4 / power;
1213     // visual effects
1214     if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1215         DoBlood(1, 255);
1216     if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1217         DoBlood(1, 255);
1218     spurt = 0;
1219     if (id == 0)
1220         camerashake += howmuch / 100;
1221     if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1222         blackout = damage / damagetolerance;
1223     if (blackout > 1)
1224         blackout = 1;
1225
1226     // cancel attack?
1227     if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1228         aitype = attacktypecutoff;
1229     if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1230         if (abs(Random() % 2) == 0) {
1231             aitype = gethelptype;
1232             lastseentime = 12;
1233         } else
1234             aitype = attacktypecutoff;
1235         ally = 0;
1236     }
1237
1238     if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1239         XYZ flatvelocity2;
1240         XYZ flatfacing2;
1241         for (int i = 0; i < skeleton.num_joints; i++) {
1242             if (!skeleton.free)
1243                 flatvelocity2 = velocity;
1244             if (skeleton.free)
1245                 flatvelocity2 = skeleton.joints[i].velocity;
1246             if (!skeleton.free)
1247                 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1248             if (skeleton.free)
1249                 flatfacing2 = skeleton.joints[i].position * scale + coords;
1250             flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1251             flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1252             flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1253             Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1254             Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1255             Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1256         }
1257
1258         emit_sound_at(splattersound, coords);
1259
1260         skeleton.free = 2;
1261         DoDamage(10000);
1262         RagDoll(0);
1263         if (!dead && creature == wolftype) {
1264             award_bonus(0, Wolfbonus);
1265         }
1266         dead = 2;
1267         coords = 20;
1268     }
1269
1270     // play sounds
1271     if (tutoriallevel != 1 || id == 0)
1272         if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1273             int whichsound = -1;
1274
1275             if (creature == wolftype) {
1276                 int i = abs(Random() % 2);
1277                 if (i == 0)
1278                     whichsound = snarlsound;
1279                 if (i == 1)
1280                     whichsound = snarl2sound;
1281                 envsound[numenvsounds] = coords;
1282                 envsoundvol[numenvsounds] = 16;
1283                 envsoundlife[numenvsounds] = .4;
1284                 numenvsounds++;
1285             }
1286             if (creature == rabbittype) {
1287                 int i = abs(Random() % 2);
1288                 if (i == 0)
1289                     whichsound = rabbitpainsound;
1290                 if (i == 1 && damage > damagetolerance)
1291                     whichsound = rabbitpain1sound;
1292                 envsound[numenvsounds] = coords;
1293                 envsoundvol[numenvsounds] = 16;
1294                 envsoundlife[numenvsounds] = .4;
1295                 numenvsounds++;
1296             }
1297
1298             if (whichsound != -1) {
1299                 emit_sound_at(whichsound, coords);
1300             }
1301         }
1302     speechdelay = .3;
1303 }
1304
1305 /* EFFECT
1306  * calculate/animate head facing direction?
1307  */
1308 void Person::DoHead()
1309 {
1310     static XYZ rotatearound;
1311     static XYZ facing;
1312     static float lookspeed = 500;
1313
1314     if (!freeze && !winfreeze) {
1315
1316         //head facing
1317         targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1318         targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1319
1320         while (targetheadyaw > 180)targetheadyaw -= 360;
1321         while (targetheadyaw < -180)targetheadyaw += 360;
1322
1323         if (targetheadyaw > 160)
1324             targetheadpitch = targetheadpitch * -1;
1325         if (targetheadyaw < -160)
1326             targetheadpitch = targetheadpitch * -1;
1327         if (targetheadyaw > 160)
1328             targetheadyaw = targetheadyaw - 180;
1329         if (targetheadyaw < -160)
1330             targetheadyaw = targetheadyaw + 180;
1331
1332         if (targetheadpitch > 120)
1333             targetheadpitch = 120;
1334         if (targetheadpitch < -120)
1335             targetheadpitch = -120;
1336         if (targetheadyaw > 120)
1337             targetheadyaw = 120;
1338         if (targetheadyaw < -120)
1339             targetheadyaw = -120;
1340
1341         if (!isIdle())
1342             targetheadpitch = 0;
1343         if (isIdle()) {
1344             if (targetheadyaw > 80)
1345                 targetheadyaw = 80;
1346             if (targetheadyaw < -80)
1347                 targetheadyaw = -80;
1348             if (targetheadpitch > 50)
1349                 targetheadpitch = 50;
1350             if (targetheadpitch < -50)
1351                 targetheadpitch = -50;
1352         }
1353
1354         if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1355             headyaw = targetheadyaw;
1356         else if (headyaw > targetheadyaw) {
1357             headyaw -= multiplier * lookspeed;
1358         } else if (headyaw < targetheadyaw) {
1359             headyaw += multiplier * lookspeed;
1360         }
1361
1362         if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1363             headpitch = targetheadpitch;
1364         else if (headpitch > targetheadpitch) {
1365             headpitch -= multiplier * lookspeed / 2;
1366         } else if (headpitch < targetheadpitch) {
1367             headpitch += multiplier * lookspeed / 2;
1368         }
1369
1370         rotatearound = jointPos(neck);
1371         jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1372
1373         facing = 0;
1374         facing.z = -1;
1375         if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1376             facing = DoRotation(facing, headpitch * .4, 0, 0);
1377             facing = DoRotation(facing, 0, headyaw * .4, 0);
1378         }
1379
1380         if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1381             facing = DoRotation(facing, headpitch * .8, 0, 0);
1382             facing = DoRotation(facing, 0, headyaw * .8, 0);
1383         }
1384
1385         if (animTarget == walkanim) {
1386             facing = DoRotation(facing, headpitch * .6, 0, 0);
1387             facing = DoRotation(facing, 0, headyaw * .6, 0);
1388         }
1389
1390         skeleton.specialforward[0] = facing;
1391         //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1392         for (int i = 0; i < skeleton.num_muscles; i++) {
1393             if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1394                 skeleton.FindRotationMuscle(i, animTarget);
1395             }
1396         }
1397     }
1398 }
1399
1400 /* EFFECT
1401  * ragdolls character?
1402  */
1403 void Person::RagDoll(bool checkcollision)
1404 {
1405     static XYZ change;
1406     static int l, i, j;
1407     static float speed;
1408     if (!skeleton.free) {
1409         if (id == 0)
1410             numfalls++;
1411         if (id == 0 && isFlip())
1412             numflipfail++;
1413
1414         escapednum = 0;
1415
1416         facing = 0;
1417         facing.z = 1;
1418         facing = DoRotation(facing, 0, yaw, 0);
1419
1420         skeleton.freetime = 0;
1421
1422         skeleton.longdead = 0;
1423
1424         skeleton.free = 1;
1425         skeleton.broken = 0;
1426         skeleton.spinny = 1;
1427         freefall = 1;
1428         skeleton.freefall = 1;
1429
1430         if (!isnormal(velocity.x)) velocity.x = 0;
1431         if (!isnormal(velocity.y)) velocity.y = 0;
1432         if (!isnormal(velocity.z)) velocity.z = 0;
1433         if (!isnormal(yaw)) yaw = 0;
1434         if (!isnormal(coords.x)) coords = 0;
1435         if (!isnormal(tilt)) tilt = 0;
1436         if (!isnormal(tilt2)) tilt2 = 0;
1437
1438         for (int i = 0; i < skeleton.num_joints; i++) {
1439             skeleton.joints[i].delay = 0;
1440             skeleton.joints[i].locked = 0;
1441             skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1442             if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1443             if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1444             skeleton.joints[i].position.y += .1;
1445             skeleton.joints[i].oldposition = skeleton.joints[i].position;
1446             skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1447         }
1448
1449         for (int i = 0; i < skeleton.num_joints; i++) {
1450             skeleton.joints[i].velocity = 0;
1451             skeleton.joints[i].velchange = 0;
1452         }
1453         skeleton.DoConstraints(&coords, &scale);
1454         if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1455             skeleton.DoConstraints(&coords, &scale);
1456             skeleton.DoConstraints(&coords, &scale);
1457             skeleton.DoConstraints(&coords, &scale);
1458             skeleton.DoConstraints(&coords, &scale);
1459         }
1460
1461         speed = animation[animTarget].speed[frameTarget] * 2;
1462         if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1463             speed = animation[animCurrent].speed[frameCurrent] * 2;
1464         }
1465         if (transspeed)
1466             speed = transspeed * 2;
1467
1468         speed *= speedmult;
1469
1470         for (int i = 0; i < skeleton.num_joints; i++) {
1471             if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1472                 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((animation[animTarget].position[i][frameTarget] - animation[animCurrent].position[i][frameCurrent]) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1473             else
1474                 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1475             change.x = (float)(Random() % 100) / 100;
1476             change.y = (float)(Random() % 100) / 100;
1477             change.z = (float)(Random() % 100) / 100;
1478             skeleton.joints[i].velocity += change;
1479             skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1480
1481             change.x = (float)(Random() % 100) / 100;
1482             change.y = (float)(Random() % 100) / 100;
1483             change.z = (float)(Random() % 100) / 100;
1484             skeleton.joints[i].velchange += change;
1485             skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1486         }
1487
1488         if (checkcollision) {
1489             XYZ average;
1490             XYZ lowpoint;
1491             XYZ colpoint;
1492             int howmany;
1493             average = 0;
1494             howmany = 0;
1495             for (j = 0; j < skeleton.num_joints; j++) {
1496                 average += skeleton.joints[j].position;
1497                 howmany++;
1498             }
1499             average /= howmany;
1500             coords += average * scale;
1501             for (j = 0; j < skeleton.num_joints; j++) {
1502                 skeleton.joints[j].position -= average;
1503             }
1504
1505             whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1506             whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1507             if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1508                 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1509                     i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1510                     lowpoint = coords;
1511                     lowpoint.y += 1;
1512                     if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1513                         coords.x = lowpoint.x;
1514                         coords.z = lowpoint.z;
1515                     }
1516                 }
1517         }
1518
1519         yaw = 0;
1520         updatedelay = 0;
1521
1522         velocity = 0;
1523         for (int i = 0; i < skeleton.num_joints; i++) {
1524             velocity += skeleton.joints[i].velocity * scale;
1525         }
1526         velocity /= skeleton.num_joints;
1527
1528         // drop weapon
1529         if (Random() % 2 == 0) {
1530             if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1531                 weapons[weaponids[0]].owner = -1;
1532                 weapons[weaponids[0]].hitsomething = 0;
1533                 weapons[weaponids[0]].velocity = jointVel(righthand) * scale * -.3;
1534                 weapons[weaponids[0]].velocity.x += .01;
1535                 weapons[weaponids[0]].tipvelocity = jointVel(righthand) * scale;
1536                 weapons[weaponids[0]].missed = 1;
1537                 weapons[weaponids[0]].freetime = 0;
1538                 weapons[weaponids[0]].firstfree = 1;
1539                 weapons[weaponids[0]].physics = 1;
1540                 num_weapons--;
1541                 if (num_weapons) {
1542                     weaponids[0] = weaponids[num_weapons];
1543                     if (weaponstuck == num_weapons)
1544                         weaponstuck = 0;
1545                 }
1546                 weaponactive = -1;
1547                 for (unsigned i = 0; i < Person::players.size(); i++) {
1548                     Person::players[i]->wentforweapon = 0;
1549                 }
1550             }
1551         }
1552
1553         animTarget = bounceidleanim;
1554         animCurrent = bounceidleanim;
1555         frameTarget = 0;
1556         frameCurrent = 0;
1557     }
1558 }
1559
1560
1561
1562 /* EFFECT
1563  */
1564 void Person::FootLand(int which, float opacity)
1565 {
1566     static XYZ terrainlight;
1567     static XYZ footvel, footpoint;
1568     if (opacity >= 1 || skiddelay <= 0)
1569         if (opacity > 1) {
1570             footvel = 0;
1571             if (which == 0)
1572                 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1573             if (which == 1)
1574                 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1575             //footpoint.y=coords.y;
1576             if (distsq(&footpoint, &viewer))
1577                 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1578         } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1579             footvel = velocity / 5;
1580             if (footvel.y < .8)
1581                 footvel.y = .8;
1582             if (which == 0)
1583                 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1584             if (which == 1)
1585                 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1586             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1587             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1588             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1589                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1590             if (opacity >= 1 || detail == 2)
1591                 if (detail == 2)
1592                     if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1593                         terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1594         } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1595             footvel = velocity / 5;
1596             if (footvel.y < .8)
1597                 footvel.y = .8;
1598             if (which == 0)
1599                 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1600             if (which == 1)
1601                 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1602             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1603             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1604             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1605                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1606         } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1607             footvel = velocity / 5;
1608             if (footvel.y < .8)
1609                 footvel.y = .8;
1610             if (which == 0)
1611                 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1612             if (which == 1)
1613                 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1614             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1615             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1616             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1617                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1618             if (opacity >= 1 || detail == 2)
1619                 if (detail == 2)
1620                     if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1621                         terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1622         } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1623             footvel = velocity / 5;
1624             if (footvel.y < .8)
1625                 footvel.y = .8;
1626             if (which == 0)
1627                 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1628             if (which == 1)
1629                 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1630             //footpoint.y=coords.y;
1631             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1632                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1633         }
1634 }
1635
1636 /* EFFECT
1637  * make a puff effect at a body part (dust effect?)
1638  */
1639 void Person::Puff(int whichlabel)
1640 {
1641     static XYZ footvel, footpoint;
1642
1643     footvel = 0;
1644     footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1645     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1646 }
1647
1648 /* EFFECT
1649  * I think I added this in an attempt to clean up code
1650  */
1651 void Person::setAnimation(int animation)
1652 {
1653     animTarget = animation;
1654     frameTarget = 0;
1655     target = 0;
1656 }
1657
1658 /* EFFECT
1659  * MONSTER
1660  * TODO: ???
1661  */
1662 void Person::DoAnimations()
1663 {
1664     if (!skeleton.free) {
1665         static float oldtarget;
1666
1667         if (isIdle() && animCurrent != getIdle())
1668             normalsupdatedelay = 0;
1669
1670         if (animTarget == tempanim || animCurrent == tempanim) {
1671             animation[tempanim] = tempanimation;
1672         }
1673         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1674             float gLoc[3];
1675             float vel[3];
1676             gLoc[0] = coords.x;
1677             gLoc[1] = coords.y;
1678             gLoc[2] = coords.z;
1679             vel[0] = velocity.x;
1680             vel[1] = velocity.y;
1681             vel[2] = velocity.z;
1682
1683             if (id == 0) {
1684                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1685                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1686             }
1687             if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1688                 landhard = 1;
1689             if (!crouchkeydown && velocity.y >= -15)
1690                 landhard = 0;
1691         }
1692         if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1693             XYZ targfacing;
1694             targfacing = 0;
1695             targfacing.z = 1;
1696
1697             targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1698
1699             if (normaldotproduct(targfacing, velocity) >= -.3)
1700                 animTarget = flipanim;
1701             else
1702                 animTarget = backflipanim;
1703             crouchtogglekeydown = 1;
1704             frameTarget = 0;
1705             target = 0;
1706
1707             if (id == 0)
1708                 numflipped++;
1709         }
1710
1711         if (animation[animTarget].attack != reversed)
1712             feint = 0;
1713         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1714             crouchtogglekeydown = 0;
1715             if (aitype == playercontrolled)
1716                 feint = 0;
1717         } else {
1718             if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1719                 feint = 1;
1720             if (!isFlip())
1721                 crouchtogglekeydown = 1;
1722         }
1723
1724
1725         if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1726             if (detail)
1727                 normalsupdatedelay = 0;
1728         }
1729
1730         if (target >= 1) {
1731             if (animTarget == rollanim && frameTarget == 3 && onfire) {
1732                 onfire = 0;
1733                 emit_sound_at(fireendsound, coords);
1734                 pause_sound(stream_firesound);
1735                 deathbleeding = 0;
1736             }
1737
1738             if (animTarget == rabbittacklinganim && frameTarget == 1) {
1739                 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1740                     Reverse();
1741                 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1742                     if (normaldotproduct(victim->facing, facing) > 0)
1743                         victim->animTarget = rabbittackledbackanim;
1744                     else
1745                         victim->animTarget = rabbittackledfrontanim;
1746                     victim->frameTarget = 2;
1747                     victim->target = 0;
1748                     victim->yaw = yaw;
1749                     victim->targetyaw = yaw;
1750                     if (victim->aitype == gethelptype)
1751                         victim->DoDamage(victim->damagetolerance - victim->damage);
1752                     //victim->DoDamage(30);
1753                     if (creature == wolftype) {
1754                         DoBloodBig(0, 255);
1755                         emit_sound_at(clawslicesound, victim->coords);
1756                         victim->spurt = 1;
1757                         victim->DoBloodBig(1 / victim->armorhead, 210);
1758                     }
1759                     award_bonus(id, TackleBonus,
1760                                 victim->aitype == gethelptype ? 50 : 0);
1761                 }
1762             }
1763
1764             if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1765                 if (weapons[weaponids[0]].getType() == knife) {
1766                     if (weaponactive == -1)
1767                         weaponactive = 0;
1768                     else if (weaponactive == 0)
1769                         weaponactive = -1;
1770
1771                     if (weaponactive == -1) {
1772                         emit_sound_at(knifesheathesound, coords);
1773                     }
1774                     if (weaponactive != -1) {
1775                         emit_sound_at(knifedrawsound, coords, 128);
1776                     }
1777                 }
1778                 drawtogglekeydown = 1;
1779             }
1780             //Footstep sounds
1781             if (tutoriallevel != 1 || id == 0)
1782                 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1783                     int whichsound;
1784                     if (onterrain) {
1785                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
1786                             if (animation[animTarget].label[frameTarget] == 1)
1787                                 whichsound = footstepsound;
1788                             else
1789                                 whichsound = footstepsound2;
1790                             if (animation[animTarget].label[frameTarget] == 1)
1791                                 FootLand(0, 1);
1792                             if (animation[animTarget].label[frameTarget] == 2)
1793                                 FootLand(1, 1);
1794                             if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1795                                 FootLand(1, 1);
1796                                 FootLand(0, 1);
1797                             }
1798
1799                         }
1800                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1801                             if (animation[animTarget].label[frameTarget] == 1)
1802                                 whichsound = footstepsound3;
1803                             else
1804                                 whichsound = footstepsound4;
1805                         }
1806                     }
1807                     if (!onterrain) {
1808                         if (animation[animTarget].label[frameTarget] == 1)
1809                             whichsound = footstepsound3;
1810                         else
1811                             whichsound = footstepsound4;
1812                     }
1813                     if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1814                         if (animation[animTarget].attack != neutral) {
1815                             unsigned r = abs(Random() % 3);
1816                             if (r == 0)
1817                                 whichsound = lowwhooshsound;
1818                             if (r == 1)
1819                                 whichsound = midwhooshsound;
1820                             if (r == 2)
1821                                 whichsound = highwhooshsound;
1822                         }
1823                         if (animation[animTarget].attack == neutral)
1824                             whichsound = movewhooshsound;
1825                     } else if (animation[animTarget].label[frameTarget] == 4)
1826                         whichsound = knifeswishsound;
1827                     if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1828                         whichsound = landsound2;
1829
1830                     emit_sound_at(whichsound, coords, 256.);
1831
1832                     if (id == 0)
1833                         if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1834                             envsound[numenvsounds] = coords;
1835                             if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1836                                 envsoundvol[numenvsounds] = 15;
1837                             else
1838                                 envsoundvol[numenvsounds] = 6;
1839                             envsoundlife[numenvsounds] = .4;
1840                             numenvsounds++;
1841                         }
1842
1843                     if (animation[animTarget].label[frameTarget] == 3) {
1844                         whichsound--;
1845                         emit_sound_at(whichsound, coords, 128.);
1846                     }
1847                 }
1848
1849             //Combat sounds
1850             if (tutoriallevel != 1 || id == 0)
1851                 if (speechdelay <= 0)
1852                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1853                         if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1854                             int whichsound = -1;
1855                             if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1856                                 if (animation[animTarget].attack != neutral) {
1857                                     unsigned r = abs(Random() % 4);
1858                                     if (creature == rabbittype) {
1859                                         if (r == 0) whichsound = rabbitattacksound;
1860                                         if (r == 1) whichsound = rabbitattack2sound;
1861                                         if (r == 2) whichsound = rabbitattack3sound;
1862                                         if (r == 3) whichsound = rabbitattack4sound;
1863                                     }
1864                                     if (creature == wolftype) {
1865                                         if (r == 0) whichsound = barksound;
1866                                         if (r == 1) whichsound = bark2sound;
1867                                         if (r == 2) whichsound = bark3sound;
1868                                         if (r == 3) whichsound = barkgrowlsound;
1869                                     }
1870                                     speechdelay = .3;
1871                                 }
1872                             }
1873
1874                             if (whichsound != -1) {
1875                                 emit_sound_at(whichsound, coords);
1876                             }
1877                         }
1878
1879
1880
1881             if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1882                 FootLand(0, 1);
1883                 FootLand(1, 1);
1884             }
1885
1886             transspeed = 0;
1887             currentoffset = targetoffset;
1888             frameTarget = frameCurrent;
1889             animCurrent = animTarget;
1890             frameTarget++;
1891
1892             if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1893                 for (unsigned i = 0; i < weapons.size(); i++) {
1894                     if (weapons[i].owner == -1)
1895                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1896                             if (distsq(&coords, &weapons[i].position) >= 1) {
1897                                 if (weapons[i].getType() != staff) {
1898                                     emit_sound_at(knifedrawsound, coords, 128.);
1899                                 }
1900
1901                                 weaponactive = 0;
1902                                 weapons[i].owner = id;
1903                                 if (num_weapons > 0) {
1904                                     weaponids[num_weapons] = weaponids[0];
1905                                 }
1906                                 num_weapons++;
1907                                 weaponids[0] = i;
1908                             }
1909                         }
1910                 }
1911             }
1912
1913             if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1914                 for (unsigned i = 0; i < weapons.size(); i++) {
1915                     bool willwork = true;
1916                     if (weapons[i].owner != -1)
1917                         if (Person::players[weapons[i].owner]->weaponstuck != -1)
1918                             if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
1919                                 if (Person::players[weapons[i].owner]->num_weapons > 1)
1920                                     willwork = 0;
1921                     if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
1922                         if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1923                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1924                                 bool fleshstuck = false;
1925                                 if (weapons[i].owner != -1)
1926                                     if (victim->weaponstuck != -1) {
1927                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
1928                                             fleshstuck = true;
1929                                         }
1930                                     }
1931                                 if (fleshstuck) {
1932                                     emit_sound_at(fleshstabremovesound, coords, 128.);
1933                                 } else {
1934                                     if (weapons[i].getType() != staff) {
1935                                         emit_sound_at(knifedrawsound, coords, 128.);
1936                                     }
1937                                 }
1938                                 weaponactive = 0;
1939                                 if (weapons[i].owner != -1) {
1940
1941                                     victim = Person::players[weapons[i].owner];
1942                                     if (victim->num_weapons == 1)
1943                                         victim->num_weapons = 0;
1944                                     else
1945                                         victim->num_weapons = 1;
1946
1947                                     //victim->weaponactive=-1;
1948                                     victim->skeleton.longdead = 0;
1949                                     victim->skeleton.free = 1;
1950                                     victim->skeleton.broken = 0;
1951
1952                                     for (int j = 0; j < victim->skeleton.num_joints; j++) {
1953                                         victim->skeleton.joints[j].velchange = 0;
1954                                         victim->skeleton.joints[j].locked = 0;
1955                                     }
1956
1957                                     XYZ relative;
1958                                     relative = 0;
1959                                     relative.y = 10;
1960                                     Normalise(&relative);
1961                                     XYZ footvel, footpoint;
1962                                     footvel = 0;
1963                                     footpoint = weapons[i].position;
1964                                     if (victim->weaponstuck != -1) {
1965                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
1966                                             if (bloodtoggle)
1967                                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
1968                                             weapons[i].bloody = 2;
1969                                             weapons[i].blooddrip = 5;
1970                                             victim->weaponstuck = -1;
1971                                         }
1972                                     }
1973                                     if (victim->num_weapons > 0) {
1974                                         if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
1975                                             victim->weaponstuck = 0;
1976                                         if (victim->weaponids[0] == int(i))
1977                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1978                                     }
1979
1980                                     victim->jointVel(abdomen) += relative * 6;
1981                                     victim->jointVel(neck) += relative * 6;
1982                                     victim->jointVel(rightshoulder) += relative * 6;
1983                                     victim->jointVel(leftshoulder) += relative * 6;
1984                                 }
1985                                 weapons[i].owner = id;
1986                                 if (num_weapons > 0) {
1987                                     weaponids[num_weapons] = weaponids[0];
1988                                 }
1989                                 num_weapons++;
1990                                 weaponids[0] = i;
1991                             }
1992                         }
1993                 }
1994             }
1995
1996             if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
1997                 if (weaponactive == -1)
1998                     weaponactive = 0;
1999                 else if (weaponactive == 0) {
2000                     weaponactive = -1;
2001                     if (num_weapons == 2) {
2002                         int buffer;
2003                         buffer = weaponids[0];
2004                         weaponids[0] = weaponids[1];
2005                         weaponids[1] = buffer;
2006                     }
2007                 }
2008                 if (weaponactive == -1) {
2009                     emit_sound_at(knifesheathesound, coords, 128.);
2010                 }
2011                 if (weaponactive != -1) {
2012                     emit_sound_at(knifedrawsound, coords, 128.);
2013                 }
2014             }
2015
2016
2017             if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2018                 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2019                 Normalise(&rotatetarget);
2020                 targetyaw = -asin(0 - rotatetarget.x);
2021                 targetyaw *= 360 / 6.28;
2022                 if (rotatetarget.z < 0)
2023                     targetyaw = 180 - targetyaw;
2024
2025                 if (animTarget == walljumprightkickanim)
2026                     targetyaw += 40;
2027                 if (animTarget == walljumpleftkickanim)
2028                     targetyaw -= 40;
2029             }
2030
2031             bool dojumpattack;
2032             dojumpattack = 0;
2033             if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2034                 dojumpattack = 1;
2035             if (hasvictim)
2036                 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2037                     dojumpattack = 1;
2038             if (!hostile)
2039                 dojumpattack = 0;
2040             if (dojumpattack) {
2041                 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2042                     animTarget = rabbittackleanim;
2043                     frameTarget = 0;
2044                     emit_sound_at(jumpsound, coords);
2045                 }
2046
2047                 float closestdist;
2048                 closestdist = 0;
2049                 int closestid;
2050                 closestid = -1;
2051                 XYZ targetloc;
2052                 targetloc = velocity;
2053                 Normalise(&targetloc);
2054                 targetloc += coords;
2055                 for (unsigned i = 0; i < Person::players.size(); i++) {
2056                     if (i != id)
2057                         if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2058                             closestdist = distsq(&targetloc, &Person::players[i]->coords);
2059                             closestid = i;
2060                         }
2061                 }
2062                 if (closestid != -1)
2063                     if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2064                         hasvictim = 1;
2065                         victim = Person::players[closestid];
2066                         coords = victim->coords;
2067                         animCurrent = rabbittacklinganim;
2068                         animTarget = rabbittacklinganim;
2069                         frameCurrent = 0;
2070                         frameTarget = 1;
2071                         XYZ rotatetarget;
2072                         if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2073                             rotatetarget = coords - victim->coords;
2074                             Normalise(&rotatetarget);
2075                             targetyaw = -asin(0 - rotatetarget.x);
2076                             targetyaw *= 360 / 6.28;
2077                             if (rotatetarget.z < 0)
2078                                 targetyaw = 180 - targetyaw;
2079                         }
2080                         if (animTarget != rabbitrunninganim) {
2081                             emit_sound_at(jumpsound, coords, 128.);
2082                         }
2083                     }
2084             }
2085
2086             //Move impacts
2087             float damagemult = 1 * power;
2088             if (creature == wolftype)
2089                 damagemult = 2.5 * power;
2090             if (hasvictim) {
2091                 damagemult /= victim->damagetolerance / 200;
2092             }
2093             if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2094                 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2095                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2096                         escapednum = 0;
2097                         if (id == 0)
2098                             camerashake += .4;
2099                         if (Random() % 2 || creature == wolftype) {
2100                             victim->spurt = 1;
2101                             DoBlood(.2, 250);
2102                             if (creature == wolftype)
2103                                 DoBloodBig(0, 250);
2104                         }
2105                         if (tutoriallevel != 1) {
2106                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
2107                         }
2108                         if (creature == wolftype) {
2109                             emit_sound_at(clawslicesound, victim->coords, 128.);
2110                             victim->spurt = 1;
2111                             victim->DoBloodBig(2 / victim->armorhead, 175);
2112                         }
2113                         victim->RagDoll(0);
2114                         XYZ relative;
2115                         relative = victim->coords - coords;
2116                         relative.y = 0;
2117                         Normalise(&relative);
2118                         relative = DoRotation(relative, 0, -90, 0);
2119                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2120                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2121                         }
2122                         victim->jointVel(head) += relative * damagemult * 200;
2123                         //FootLand(1,2);
2124                         victim->Puff(head);
2125                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
2126
2127                         SolidHitBonus(id);
2128                     }
2129                 }
2130
2131                 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2132                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2133                         escapednum = 0;
2134                         if (id == 0)
2135                             camerashake += .4;
2136                         if (Random() % 2 || creature == wolftype) {
2137                             victim->spurt = 1;
2138                             if (creature == wolftype)
2139                                 DoBloodBig(0, 235);
2140                         }
2141                         emit_sound_at(whooshhitsound, victim->coords);
2142                         if (creature == wolftype) {
2143                             emit_sound_at(clawslicesound, victim->coords, 128.);
2144                             victim->spurt = 1;
2145                             victim->DoBloodBig(2, 175);
2146                         }
2147                         victim->RagDoll(0);
2148                         XYZ relative;
2149                         relative = victim->coords - coords;
2150                         relative.y = 0;
2151                         Normalise(&relative);
2152                         relative.y -= 1;
2153                         Normalise(&relative);
2154                         relative = DoRotation(relative, 0, 90, 0);
2155                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2156                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2157                         }
2158                         victim->jointVel(head) += relative * damagemult * 100;
2159                         //FootLand(1,2);
2160                         victim->Puff(head);
2161                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2162                     }
2163                 }
2164
2165                 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2166                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2167                         escapednum = 0;
2168                         if (id == 0)
2169                             camerashake += .4;
2170                         victim->spurt = 1;
2171                         DoBlood(.2, 250);
2172                         if (tutoriallevel != 1) {
2173                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2174                         }
2175                         if (creature == wolftype) {
2176                             emit_sound_at(clawslicesound, victim->coords, 128.);
2177                             victim->spurt = 1;
2178                             victim->DoBloodBig(2 / victim->armorhead, 175);
2179                         }
2180                         victim->RagDoll(0);
2181                         XYZ relative;
2182                         relative = facing;
2183                         relative.y = 0;
2184                         Normalise(&relative);
2185                         relative = DoRotation(relative, 0, -90, 0);
2186                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2187                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2188                         }
2189                         victim->jointVel(head) += relative * damagemult * 200;
2190                         //FootLand(1,2);
2191                         victim->Puff(head);
2192                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2193
2194                         if (victim->damage > victim->damagetolerance)
2195                             award_bonus(id, style);
2196                         else
2197                             SolidHitBonus(id);
2198                     }
2199                 }
2200
2201                 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2202                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2203                         escapednum = 0;
2204                         if (id == 0)
2205                             camerashake += .4;
2206                         victim->spurt = 1;
2207                         DoBlood(.2, 250);
2208                         if (tutoriallevel != 1) {
2209                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2210                         }
2211                         if (creature == wolftype) {
2212                             emit_sound_at(clawslicesound, victim->coords, 128.);
2213                             victim->spurt = 1;
2214                             victim->DoBloodBig(2 / victim->armorhead, 175);
2215                         }
2216                         victim->RagDoll(0);
2217                         XYZ relative;
2218                         relative = facing;
2219                         relative.y = 0;
2220                         Normalise(&relative);
2221                         relative = DoRotation(relative, 0, 90, 0);
2222                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2223                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2224                         }
2225                         victim->jointVel(head) += relative * damagemult * 200;
2226                         //FootLand(1,2);
2227                         victim->Puff(head);
2228                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2229
2230                         if (victim->damage > victim->damagetolerance)
2231                             award_bonus(id, style);
2232                         else
2233                             SolidHitBonus(id);
2234                     }
2235                 }
2236
2237                 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2238                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2239                         escapednum = 0;
2240                         if (id == 0)
2241                             camerashake += .4;
2242                         if (Random() % 2) {
2243                             victim->spurt = 1;
2244                             DoBlood(.2, 235);
2245                         }
2246                         emit_sound_at(whooshhitsound, victim->coords);
2247                         victim->RagDoll(0);
2248                         XYZ relative;
2249                         relative = victim->coords - coords;
2250                         relative.y = 0;
2251                         Normalise(&relative);
2252                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2253                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2254                         }
2255                         victim->jointVel(head) += relative * damagemult * 100;
2256                         //FootLand(1,2);
2257                         victim->Puff(head);
2258                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2259                     }
2260                 }
2261
2262                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2263                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2264                         escapednum = 0;
2265                         if (id == 0)
2266                             camerashake += .2;
2267                         emit_sound_at(whooshhitsound, victim->coords, 128.);
2268
2269                         victim->skeleton.longdead = 0;
2270                         victim->skeleton.free = 1;
2271                         victim->skeleton.broken = 0;
2272                         victim->skeleton.spinny = 1;
2273
2274                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2275                             victim->skeleton.joints[i].velchange = 0;
2276                             victim->skeleton.joints[i].delay = 0;
2277                             victim->skeleton.joints[i].locked = 0;
2278                             //victim->skeleton.joints[i].velocity=0;
2279                         }
2280
2281                         XYZ relative;
2282                         relative = 0;
2283                         relative.y = 1;
2284                         Normalise(&relative);
2285                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2286                             victim->skeleton.joints[i].velocity.y = relative.y * 10;
2287                             victim->skeleton.joints[i].position.y += relative.y * .3;
2288                             victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2289                             victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2290                         }
2291                         victim->Puff(abdomen);
2292                         victim->jointVel(abdomen).y = relative.y * 400;
2293                     }
2294                 }
2295
2296                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2297                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2298                         escapednum = 0;
2299                         if (id == 0)
2300                             camerashake += .4;
2301                         if (tutoriallevel != 1) {
2302                             emit_sound_at(heavyimpactsound, coords, 128.);
2303                         }
2304                         XYZ relative;
2305                         relative = victim->coords - coords;
2306                         relative.y = 0;
2307                         Normalise(&relative);
2308                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2309                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2310                         }
2311                         victim->Puff(abdomen);
2312                         if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2313                             slomo = 1;
2314                             slomodelay = .2;
2315                         }
2316                         victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2317                         victim->jointVel(abdomen) += relative * damagemult * 300;
2318                     }
2319                 }
2320
2321                 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2322                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2323                         escapednum = 0;
2324                         if (id == 0)
2325                             camerashake += .4;
2326                         if (tutoriallevel != 1) {
2327                             emit_sound_at(thudsound, coords);
2328                         }
2329
2330                         victim->skeleton.longdead = 0;
2331                         victim->skeleton.free = 1;
2332                         victim->skeleton.broken = 0;
2333                         victim->skeleton.spinny = 1;
2334
2335                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2336                             victim->skeleton.joints[i].velchange = 0;
2337                             //victim->skeleton.joints[i].delay=0;
2338                             victim->skeleton.joints[i].locked = 0;
2339                         }
2340                         XYZ relative;
2341                         relative = victim->coords - coords;
2342                         Normalise(&relative);
2343                         relative.y += .3;
2344                         Normalise(&relative);
2345                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2346                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2347                         }
2348                         if (!victim->dead)
2349                             SolidHitBonus(id);
2350
2351                         victim->Puff(abdomen);
2352                         victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2353                         victim->jointVel(abdomen) += relative * damagemult * 200;
2354                         staggerdelay = .5;
2355                         if (!victim->dead)
2356                             staggerdelay = 1.2;
2357
2358
2359                     }
2360                 }
2361
2362                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2363
2364                     if (hasvictim)
2365                         if (!victim->skeleton.free)
2366                             hasvictim = 0;
2367
2368                     if (!hasvictim) {
2369                         terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2370                         emit_sound_at(knifesheathesound, coords, 128.);
2371                     }
2372
2373                     if (victim && hasvictim) {
2374                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2375
2376                             XYZ where, startpoint, endpoint, movepoint, colpoint;
2377                             float rotationpoint;
2378                             int whichtri;
2379                             if (weapons[weaponids[weaponactive]].getType() == knife) {
2380                                 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2381                                 where -= victim->coords;
2382                                 if (!victim->skeleton.free)
2383                                     where = DoRotation(where, 0, -victim->yaw, 0);
2384                                 //where=scale;
2385                                 startpoint = where;
2386                                 startpoint.y += 100;
2387                                 endpoint = where;
2388                                 endpoint.y -= 100;
2389                             }
2390                             if (weapons[weaponids[weaponactive]].getType() == sword) {
2391                                 where = weapons[weaponids[weaponactive]].position;
2392                                 where -= victim->coords;
2393                                 if (!victim->skeleton.free)
2394                                     where = DoRotation(where, 0, -victim->yaw, 0);
2395                                 startpoint = where;
2396                                 where = weapons[weaponids[weaponactive]].tippoint;
2397                                 where -= victim->coords;
2398                                 if (!victim->skeleton.free)
2399                                     where = DoRotation(where, 0, -victim->yaw, 0);
2400                                 endpoint = where;
2401                             }
2402                             if (weapons[weaponids[weaponactive]].getType() == staff) {
2403                                 where = weapons[weaponids[weaponactive]].position;
2404                                 where -= victim->coords;
2405                                 if (!victim->skeleton.free)
2406                                     where = DoRotation(where, 0, -victim->yaw, 0);
2407                                 startpoint = where;
2408                                 where = weapons[weaponids[weaponactive]].tippoint;
2409                                 where -= victim->coords;
2410                                 if (!victim->skeleton.free)
2411                                     where = DoRotation(where, 0, -victim->yaw, 0);
2412                                 endpoint = where;
2413                             }
2414                             movepoint = 0;
2415                             rotationpoint = 0;
2416                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2417
2418                             if (whichtri != -1) {
2419                                 if (victim->dead != 2) {
2420                                     victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2421                                     if (!victim->dead)
2422                                         award_bonus(id, FinishedBonus);
2423                                 }
2424                                 if (bloodtoggle)
2425                                     weapons[weaponids[weaponactive]].bloody = 2;
2426
2427                                 victim->skeleton.longdead = 0;
2428                                 victim->skeleton.free = 1;
2429                                 victim->skeleton.broken = 0;
2430
2431                                 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2432                                     victim->skeleton.joints[i].velchange = 0;
2433                                     victim->skeleton.joints[i].locked = 0;
2434                                     //victim->skeleton.joints[i].velocity=0;
2435                                 }
2436                                 emit_sound_at(fleshstabsound, coords, 128);
2437
2438                             }
2439                             if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2440                                 weapons[weaponids[weaponactive]].blooddrip += 5;
2441                                 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2442                             }
2443                             if (whichtri == -1) {
2444                                 hasvictim = 0;
2445                                 emit_sound_at(knifesheathesound, coords, 128.);
2446                             }
2447                         }
2448                     }
2449                 }
2450
2451                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2452                     if (!hasvictim) {
2453                         emit_sound_at(knifedrawsound, coords, 128);
2454                     }
2455
2456                     if (victim && hasvictim) {
2457                         XYZ footvel, footpoint;
2458
2459                         emit_sound_at(fleshstabremovesound, coords, 128.);
2460
2461                         footvel = 0;
2462                         footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2463
2464                         if (weapons[weaponids[weaponactive]].getType() == sword) {
2465                             XYZ where, startpoint, endpoint, movepoint;
2466                             float rotationpoint;
2467                             int whichtri;
2468
2469                             where = weapons[weaponids[weaponactive]].position;
2470                             where -= victim->coords;
2471                             if (!victim->skeleton.free)
2472                                 where = DoRotation(where, 0, -victim->yaw, 0);
2473                             startpoint = where;
2474                             where = weapons[weaponids[weaponactive]].tippoint;
2475                             where -= victim->coords;
2476                             if (!victim->skeleton.free)
2477                                 where = DoRotation(where, 0, -victim->yaw, 0);
2478                             endpoint = where;
2479
2480                             movepoint = 0;
2481                             rotationpoint = 0;
2482                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2483                             footpoint += victim->coords;
2484
2485                             if (whichtri == -1) {
2486                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2487                             }
2488                         }
2489                         if (weapons[weaponids[weaponactive]].getType() == staff) {
2490                             XYZ where, startpoint, endpoint, movepoint;
2491                             float rotationpoint;
2492                             int whichtri;
2493
2494                             where = weapons[weaponids[weaponactive]].position;
2495                             where -= victim->coords;
2496                             if (!victim->skeleton.free)
2497                                 where = DoRotation(where, 0, -victim->yaw, 0);
2498                             startpoint = where;
2499                             where = weapons[weaponids[weaponactive]].tippoint;
2500                             where -= victim->coords;
2501                             if (!victim->skeleton.free)
2502                                 where = DoRotation(where, 0, -victim->yaw, 0);
2503                             endpoint = where;
2504
2505                             movepoint = 0;
2506                             rotationpoint = 0;
2507                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2508                             footpoint += victim->coords;
2509
2510                             if (whichtri == -1) {
2511                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2512                             }
2513                         }
2514                         hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2515                         if (hasvictim) {
2516                             if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2517                                 victim->skeleton.longdead = 0;
2518                                 victim->skeleton.free = 1;
2519                                 victim->skeleton.broken = 0;
2520
2521                                 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2522                                     victim->skeleton.joints[i].velchange = 0;
2523                                     victim->skeleton.joints[i].locked = 0;
2524                                     //victim->skeleton.joints[i].velocity=0;
2525                                 }
2526
2527                                 XYZ relative;
2528                                 relative = 0;
2529                                 relative.y = 10;
2530                                 Normalise(&relative);
2531                                 //victim->Puff(abdomen);
2532                                 if (bloodtoggle)
2533                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2534
2535                                 if (victim->bloodloss < victim->damagetolerance) {
2536                                     victim->bloodloss += 1000;
2537                                     victim->bled = 0;
2538                                 }
2539
2540                                 victim->jointVel(abdomen) += relative * damagemult * 20;
2541                             }
2542                         }
2543                     }
2544                     if (!hasvictim && onterrain) {
2545                         weapons[weaponids[weaponactive]].bloody = 0;
2546                         weapons[weaponids[weaponactive]].blooddrip = 0;
2547                     }
2548                 }
2549
2550                 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2551                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2552                         escapednum = 0;
2553                         if (id == 0)
2554                             camerashake += .4;
2555                         if (Random() % 2) {
2556                             victim->spurt = 1;
2557                             DoBlood(.2, 235);
2558                         }
2559                         if (tutoriallevel != 1) {
2560                             emit_sound_at(heavyimpactsound, victim->coords, 128);
2561                         }
2562
2563                         victim->RagDoll(0);
2564                         XYZ relative;
2565                         relative = victim->coords - coords;
2566                         relative.y = 0;
2567                         Normalise(&relative);
2568                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2569                             victim->skeleton.joints[i].velocity = relative * 30;
2570                         }
2571                         victim->jointVel(head) += relative * damagemult * 150;
2572
2573                         victim->frameTarget = 0;
2574                         victim->animTarget = staggerbackhardanim;
2575                         victim->targetyaw = targetyaw + 180;
2576                         victim->target = 0;
2577                         victim->stunned = 1;
2578
2579                         victim->Puff(head);
2580                         victim->Puff(abdomen);
2581                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2582
2583                         SolidHitBonus(id);
2584                     }
2585                 }
2586
2587
2588                 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2589                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2590                         escapednum = 0;
2591                         if (id == 0)
2592                             camerashake += .4;
2593                         if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2594                             if (tutoriallevel != 1) {
2595                                 emit_sound_at(thudsound, victim->coords);
2596                             }
2597                         } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2598                             if (tutoriallevel != 1) {
2599                                 emit_sound_at(whooshhitsound, victim->coords);
2600                             }
2601                         } else {
2602                             if (tutoriallevel != 1) {
2603                                 emit_sound_at(heavyimpactsound, victim->coords);
2604                             }
2605                         }
2606
2607                         if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2608                             victim->RagDoll(0);
2609                         XYZ relative;
2610                         relative = victim->coords - coords;
2611                         relative.y = 0;
2612                         Normalise(&relative);
2613                         relative.y = .3;
2614                         Normalise(&relative);
2615                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2616                             victim->skeleton.joints[i].velocity = relative * 5;
2617                         }
2618                         victim->jointVel(abdomen) += relative * damagemult * 400;
2619
2620                         victim->frameTarget = 0;
2621                         victim->animTarget = staggerbackhardanim;
2622                         victim->targetyaw = targetyaw + 180;
2623                         victim->target = 0;
2624                         victim->stunned = 1;
2625
2626                         victim->Puff(abdomen);
2627                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2628
2629                         SolidHitBonus(id);
2630                     }
2631                 }
2632
2633                 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2634                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2635                         if (victim->id == 0)
2636                             camerashake += .4;
2637                         emit_sound_at(landsound2, victim->coords);
2638
2639                         Puff(righthand);
2640                     }
2641                 }
2642
2643                 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2644                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2645                         if (victim->id == 0)
2646                             camerashake += .4;
2647
2648                         if (weaponactive != -1) {
2649                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2650                                 if (weapons[victim->weaponids[0]].getType() == staff)
2651                                     weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2652                                 if (weapons[weaponids[0]].getType() == staff)
2653                                     weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2654
2655                                 emit_sound_at(swordstaffsound, victim->coords);
2656                             } else {
2657                                 emit_sound_at(metalhitsound, victim->coords);
2658                             }
2659                         }
2660
2661                         //Puff(righthand);
2662                     }
2663                 }
2664
2665                 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2666                     if (weaponactive != -1) {
2667                         escapednum = 0;
2668                         XYZ aim;
2669                         weapons[weaponids[0]].owner = -1;
2670                         aim = victim->coords + DoRotation(victim->jointPos(abdomen), 0, victim->yaw, 0) * victim->scale + victim->velocity * findDistance(&victim->coords, &coords) / 50 - (coords + DoRotation(jointPos(righthand), 0, yaw, 0) * scale);
2671                         Normalise(&aim);
2672                         weapons[weaponids[0]].velocity = aim * 50;
2673                         weapons[weaponids[0]].tipvelocity = aim * 50;
2674                         weapons[weaponids[0]].missed = 0;
2675                         weapons[weaponids[0]].hitsomething = 0;
2676                         weapons[weaponids[0]].freetime = 0;
2677                         weapons[weaponids[0]].firstfree = 1;
2678                         weapons[weaponids[0]].physics = 0;
2679                         num_weapons--;
2680                         if (num_weapons) {
2681                             weaponids[0] = weaponids[num_weapons];
2682                         }
2683                         weaponactive = -1;
2684                     }
2685                 }
2686
2687                 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2688                     if (hasvictim)
2689                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2690                             escapednum = 0;
2691                             if (tutoriallevel != 1)
2692                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2693
2694                             award_bonus(id, Slicebonus);
2695                             if (tutoriallevel != 1) {
2696                                 emit_sound_at(knifeslicesound, victim->coords);
2697                             }
2698                             //victim->jointVel(abdomen)+=relative*damagemult*200;
2699                             if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2700                                 if (victim->id != 0 || difficulty == 2) {
2701                                     victim->frameTarget = 0;
2702                                     victim->animTarget = staggerbackhardanim;
2703                                     victim->targetyaw = targetyaw + 180;
2704                                     victim->target = 0;
2705                                 }
2706                             }
2707                             victim->lowreversaldelay = 0;
2708                             victim->highreversaldelay = 0;
2709                             if (aitype != playercontrolled)
2710                                 weaponmissdelay = .6;
2711
2712                             if (tutoriallevel != 1)
2713                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2714                                     weapons[weaponids[weaponactive]].bloody = 1;
2715                             if (tutoriallevel != 1)
2716                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2717
2718                             XYZ footvel, footpoint;
2719                             footvel = 0;
2720                             if (skeleton.free) {
2721                                 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2722                             }
2723                             if (!skeleton.free) {
2724                                 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2725                             }
2726                             if (tutoriallevel != 1) {
2727                                 if (bloodtoggle)
2728                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2729                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2730                                 //footvel.y-=.3;
2731                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2732                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2733                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2734                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2735                             }
2736                             if (tutoriallevel == 1) {
2737                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2738                             }
2739                             victim->DoDamage(damagemult * 0);
2740                         }
2741                 }
2742                 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2743                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2744                         if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2745                             award_bonus(id, Slashbonus);
2746                             escapednum = 0;
2747                             if (tutoriallevel != 1) {
2748                                 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2749                                     victim->DoBloodBig(2 / victim->armorhigh, 190);
2750                                 else
2751                                     victim->DoBloodBig(2 / victim->armorhigh, 185);
2752                                 victim->deathbleeding = 1;
2753                                 emit_sound_at(swordslicesound, victim->coords);
2754                             }
2755                             //victim->jointVel(abdomen)+=relative*damagemult*200;
2756                             if (tutoriallevel != 1) {
2757                                 victim->frameTarget = 0;
2758                                 victim->animTarget = staggerbackhardanim;
2759                                 victim->targetyaw = targetyaw + 180;
2760                                 victim->target = 0;
2761                             }
2762
2763                             if (tutoriallevel != 1) {
2764                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2765                                     weapons[weaponids[weaponactive]].bloody = 1;
2766                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2767
2768                                 float bloodlossamount;
2769                                 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2770                                 victim->bloodloss += bloodlossamount / victim->armorhigh;
2771                                 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2772                                 victim->DoDamage(damagemult * 0);
2773
2774                                 XYZ footvel, footpoint;
2775                                 footvel = 0;
2776                                 if (skeleton.free) {
2777                                     footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2778                                 }
2779                                 if (!skeleton.free) {
2780                                     footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2781                                 }
2782                                 if (bloodtoggle)
2783                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2784                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2785                                 footvel.y -= .3;
2786                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2787                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2788                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2789                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2790                             }
2791                         } else {
2792                             if (victim->weaponactive != -1) {
2793                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2794                                     if (weapons[victim->weaponids[0]].getType() == staff)
2795                                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2796                                     if (weapons[weaponids[0]].getType() == staff)
2797                                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2798
2799                                     emit_sound_at(swordstaffsound, victim->coords);
2800                                 } else {
2801                                     emit_sound_at(metalhitsound, victim->coords);
2802                                 }
2803                             }
2804
2805
2806                             XYZ aim;
2807                             victim->Puff(righthand);
2808                             victim->target = 0;
2809                             victim->frameTarget = 0;
2810                             victim->animTarget = staggerbackhighanim;
2811                             victim->targetyaw = targetyaw + 180;
2812                             victim->target = 0;
2813                             weapons[victim->weaponids[0]].owner = -1;
2814                             aim = DoRotation(facing, 0, 90, 0) * 21;
2815                             aim.y += 7;
2816                             weapons[victim->weaponids[0]].velocity = aim * -.2;
2817                             weapons[victim->weaponids[0]].tipvelocity = aim;
2818                             weapons[victim->weaponids[0]].missed = 1;
2819                             weapons[weaponids[0]].hitsomething = 0;
2820                             weapons[victim->weaponids[0]].freetime = 0;
2821                             weapons[victim->weaponids[0]].firstfree = 1;
2822                             weapons[victim->weaponids[0]].physics = 1;
2823                             victim->num_weapons--;
2824                             if (victim->num_weapons) {
2825                                 victim->weaponids[0] = victim->weaponids[num_weapons];
2826                                 if (victim->weaponstuck == victim->num_weapons)
2827                                     victim->weaponstuck = 0;
2828                             }
2829                             victim->weaponactive = -1;
2830                             for (unsigned i = 0; i < Person::players.size(); i++) {
2831                                 Person::players[i]->wentforweapon = 0;
2832                             }
2833
2834                         }
2835                     }
2836                 }
2837
2838                 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2839                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2840                         if (tutoriallevel != 1) {
2841                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2842                             escapednum = 0;
2843                             if (id == 0)
2844                                 camerashake += .4;
2845                             if (Random() % 2 || creature == wolftype) {
2846                                 victim->spurt = 1;
2847                             }
2848                             emit_sound_at(staffheadsound, victim->coords);
2849                         }
2850                         victim->RagDoll(0);
2851                         XYZ relative;
2852                         relative = victim->coords - coords;
2853                         relative.y = 0;
2854                         Normalise(&relative);
2855                         relative = DoRotation(relative, 0, 90, 0);
2856                         relative.y -= 1;
2857                         Normalise(&relative);
2858                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2859                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2860                         }
2861                         victim->jointVel(head) += relative * damagemult * 230;
2862                         victim->jointVel(neck) += relative * damagemult * 230;
2863                         //FootLand(1,2);
2864                         victim->Puff(head);
2865                         if (tutoriallevel != 1) {
2866                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2867
2868                             award_bonus(id, solidhit, 30);
2869                         }
2870                     }
2871                 }
2872
2873                 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2874                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2875                         if (tutoriallevel != 1) {
2876                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2877                             escapednum = 0;
2878                             if (id == 0)
2879                                 camerashake += .4;
2880                             if (Random() % 2 || creature == wolftype) {
2881                                 victim->spurt = 1;
2882                             }
2883                             emit_sound_at(staffheadsound, victim->coords);
2884                         }
2885                         victim->RagDoll(0);
2886                         XYZ relative;
2887                         relative = victim->coords - coords;
2888                         relative.y = 0;
2889                         Normalise(&relative);
2890                         relative = DoRotation(relative, 0, -90, 0);
2891                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2892                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2893                         }
2894                         victim->jointVel(head) += relative * damagemult * 220;
2895                         victim->jointVel(neck) += relative * damagemult * 220;
2896                         //FootLand(1,2);
2897                         victim->Puff(head);
2898                         if (tutoriallevel != 1) {
2899                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
2900
2901                             award_bonus(id, solidhit, 60);
2902                         }
2903                     }
2904                 }
2905
2906                 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2907                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2908                         escapednum = 0;
2909                         if (tutoriallevel != 1) {
2910                             if (!victim->dead)
2911                                 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2912                             if (id == 0)
2913                                 camerashake += .4;
2914                             if (Random() % 2 || creature == wolftype) {
2915                                 victim->spurt = 1;
2916                             }
2917                             emit_sound_at(staffbodysound, victim->coords);
2918                         }
2919                         victim->skeleton.longdead = 0;
2920                         victim->skeleton.free = 1;
2921                         victim->skeleton.broken = 0;
2922
2923                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2924                             victim->skeleton.joints[i].velchange = 0;
2925                             victim->skeleton.joints[i].locked = 0;
2926                             //victim->skeleton.joints[i].velocity=0;
2927                         }
2928
2929                         victim->RagDoll(0);
2930                         XYZ relative;
2931                         relative = 0;
2932                         /*relative=victim->coords-coords;
2933                         relative.y=0;
2934                         Normalise(&relative);
2935                         relative=DoRotation(relative,0,90,0);*/
2936                         relative.y = -1;
2937                         Normalise(&relative);
2938                         if (!victim->dead) {
2939                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
2940                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2941                             }
2942                             //FootLand(1,2);
2943                             victim->jointVel(abdomen) += relative * damagemult * 40;
2944                         }
2945                         if (victim->dead) {
2946                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
2947                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2948                             }
2949                             //FootLand(1,2);
2950                             //victim->jointVel(abdomen)+=relative*damagemult*20;
2951                         }
2952                         victim->Puff(abdomen);
2953                         if (tutoriallevel != 1) {
2954                             victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2955
2956                             if (!victim->dead) {
2957                                 award_bonus(id, solidhit, 40);
2958                             }
2959                         }
2960                     }
2961                 }
2962
2963                 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
2964                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
2965                         escapednum = 0;
2966                         if (id == 0)
2967                             camerashake += .4;
2968                         XYZ relative;
2969                         relative = victim->coords - coords;
2970                         relative.y = 0;
2971                         Normalise(&relative);
2972
2973                         SolidHitBonus(id);
2974
2975                         if (animation[victim->animTarget].height == lowheight) {
2976                             if (Random() % 2) {
2977                                 victim->spurt = 1;
2978                                 DoBlood(.2, 250);
2979                             }
2980                             victim->RagDoll(0);
2981                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
2982                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2983                             }
2984                             victim->jointVel(head) += relative * damagemult * 200;
2985                             if (tutoriallevel != 1) {
2986                                 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2987                             }
2988                             victim->Puff(head);
2989                             victim->DoDamage(damagemult * 100 / victim->protectionhead);
2990                             if (victim->howactive == typesleeping)
2991                                 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2992                             if (creature == wolftype) {
2993                                 emit_sound_at(clawslicesound, victim->coords, 128.);
2994                                 victim->spurt = 1;
2995                                 victim->DoBloodBig(2 / victim->armorhead, 175);
2996                             }
2997                         } else {
2998                             if (victim->damage >= victim->damagetolerance)
2999                                 victim->RagDoll(0);
3000                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3001                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3002                             }
3003                             victim->jointVel(abdomen) += relative * damagemult * 200;
3004                             victim->frameTarget = 0;
3005                             victim->animTarget = staggerbackhighanim;
3006                             victim->targetyaw = targetyaw + 180;
3007                             victim->target = 0;
3008                             if (tutoriallevel != 1) {
3009                                 emit_sound_at(landsound2, victim->coords, 128.);
3010                             }
3011                             victim->Puff(abdomen);
3012                             victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3013                             if (creature == wolftype) {
3014                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3015                                 victim->spurt = 1;
3016                                 victim->DoBloodBig(2 / victim->armorhigh, 170);
3017                             }
3018                         }
3019
3020                     }
3021                 }
3022
3023                 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3024                     if ((victim->animTarget != jumpupanim) &&
3025                         (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3026                         (victim != this->shared_from_this())) {
3027                         escapednum = 0;
3028                         if (id == 0)
3029                             camerashake += .2;
3030                         if (tutoriallevel != 1) {
3031                             emit_sound_at(landsound2, victim->coords, 128.);
3032                         }
3033                         XYZ relative;
3034                         relative = victim->coords - coords;
3035                         relative.y = 0;
3036                         Normalise(&relative);
3037
3038                         if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3039                             victim->RagDoll(0);
3040
3041                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3042                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3043                             }
3044                             relative = DoRotation(relative, 0, -90, 0);
3045                             relative.y += .1;
3046                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3047                                 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
3048                                     victim->skeleton.joints[i].velocity = relative * 80;
3049                             }
3050                             victim->Puff(rightankle);
3051                             victim->Puff(leftankle);
3052                             victim->DoDamage(damagemult * 40 / victim->protectionlow);
3053                         } else {
3054                             if (victim->damage >= victim->damagetolerance)
3055                                 victim->RagDoll(0);
3056                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3057                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3058                             }
3059                             relative = DoRotation(relative, 0, -90, 0);
3060                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3061                                 if (victim->skeleton.joints[i].label == leftfoot || victim->skeleton.joints[i].label == rightfoot || victim->skeleton.joints[i].label == leftankle || victim->skeleton.joints[i].label == rightankle)
3062                                     victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3063                             }
3064                             victim->jointVel(abdomen) += relative * damagemult * 200;
3065                             victim->frameTarget = 0;
3066                             victim->animTarget = staggerbackhighanim;
3067                             victim->targetyaw = targetyaw + 180;
3068                             victim->target = 0;
3069                             if (tutoriallevel != 1) {
3070                                 emit_sound_at(landsound2, victim->coords, 128.);
3071                             }
3072                             victim->Puff(abdomen);
3073                             victim->DoDamage(damagemult * 30 / victim->protectionlow);
3074                         }
3075
3076                         SolidHitBonus(id);
3077
3078                     }
3079                 }
3080             }
3081             if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3082                 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3083                     escapednum = 0;
3084                     if (id == 0)
3085                         camerashake += .4;
3086                     if (Random() % 2) {
3087                         victim->spurt = 1;
3088                         DoBlood(.2, 230);
3089                     }
3090                     if (tutoriallevel != 1) {
3091                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3092                     }
3093                     if (creature == wolftype) {
3094                         emit_sound_at(clawslicesound, victim->coords, 128);
3095                         victim->spurt = 1;
3096                         victim->DoBloodBig(2 / victim->armorhigh, 170);
3097                     }
3098                     victim->RagDoll(0);
3099                     XYZ relative;
3100                     relative = victim->coords - oldcoords;
3101                     relative.y = 0;
3102                     Normalise(&relative);
3103                     //relative=DoRotation(relative,0,-90,0);
3104                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3105                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3106                     }
3107                     victim->jointVel(abdomen) += relative * damagemult * 200;
3108                     //FootLand(1,2);
3109                     victim->Puff(abdomen);
3110                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3111
3112                     award_bonus(id, Reversal);
3113                 }
3114
3115                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3116                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3117                         if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3118                             weapons[victim->weaponids[victim->weaponactive]].owner = id;
3119                             weaponactive = 0;
3120                             if (num_weapons > 0) {
3121                                 weaponids[num_weapons] = weaponids[victim->weaponactive];
3122                             }
3123                             num_weapons++;
3124                             weaponids[0] = victim->weaponids[victim->weaponactive];
3125                             victim->num_weapons--;
3126                             if (victim->num_weapons > 0) {
3127                                 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3128                             }
3129                             victim->weaponactive = -1;
3130                         }
3131                     }
3132                 }
3133
3134                 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3135                     escapednum = 0;
3136                     if (id == 0)
3137                         camerashake += .4;
3138                     if (Random() % 2) {
3139                         victim->spurt = 1;
3140                         DoBlood(.2, 230);
3141                     }
3142                     emit_sound_at(whooshhitsound, victim->coords, 128.);
3143                     victim->RagDoll(0);
3144                     XYZ relative;
3145                     relative = victim->coords - oldcoords;
3146                     relative.y = 0;
3147                     Normalise(&relative);
3148                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3149                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3150                     }
3151                     victim->jointVel(abdomen) += relative * damagemult * 200;
3152                     victim->Puff(head);
3153                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3154                 }
3155
3156                 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3157                     escapednum = 0;
3158                     if (id == 0)
3159                         camerashake += .4;
3160                     if (Random() % 2) {
3161                         victim->spurt = 1;
3162                         DoBlood(.2, 230);
3163                     }
3164
3165                     award_bonus(id, staffreversebonus);
3166
3167                     if (tutoriallevel != 1) {
3168                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3169                     }
3170                     victim->RagDoll(0);
3171                     award_bonus(id, staffreversebonus); // Huh, again?
3172
3173                     XYZ relative;
3174                     relative = victim->coords - oldcoords;
3175                     relative.y = 0;
3176                     Normalise(&relative);
3177                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3178                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3179                     }
3180                     victim->jointVel(abdomen) += relative * damagemult * 200;
3181                     victim->Puff(head);
3182                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3183                 }
3184
3185                 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3186                     escapednum = 0;
3187                     victim->RagDoll(1);
3188                     XYZ relative;
3189                     relative = facing;
3190                     relative.y = 0;
3191                     Normalise(&relative);
3192                     relative.y -= .1;
3193                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3194                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3195                     }
3196                     victim->jointVel(lefthand) *= .1;
3197                     victim->jointVel(leftwrist) *= .2;
3198                     victim->jointVel(leftelbow) *= .5;
3199                     victim->jointVel(leftshoulder) *= .7;
3200                     victim->jointVel(righthand) *= .1;
3201                     victim->jointVel(rightwrist) *= .2;
3202                     victim->jointVel(rightelbow) *= .5;
3203                     victim->jointVel(rightshoulder) *= .7;
3204
3205                     victim->Puff(abdomen);
3206                     victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3207
3208                     award_bonus(id, Reversal);
3209
3210                     bool doslice;
3211                     doslice = 0;
3212                     if (weaponactive != -1 || creature == wolftype)
3213                         doslice = 1;
3214                     if (creature == rabbittype && weaponactive != -1)
3215                         if (weapons[weaponids[0]].getType() == staff)
3216                             doslice = 0;
3217                     if (doslice) {
3218                         if (weaponactive != -1) {
3219                             victim->DoBloodBig(2 / victim->armorhigh, 225);
3220                             emit_sound_at(knifeslicesound, victim->coords);
3221                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3222                                 weapons[weaponids[weaponactive]].bloody = 1;
3223                             weapons[weaponids[weaponactive]].blooddrip += 3;
3224                         }
3225                         if (weaponactive == -1 && creature == wolftype) {
3226                             ;
3227                             emit_sound_at(clawslicesound, victim->coords, 128.);
3228                             victim->spurt = 1;
3229                             victim->DoBloodBig(2 / victim->armorhigh, 175);
3230                         }
3231                     }
3232                 }
3233
3234
3235
3236                 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3237                     escapednum = 0;
3238                     victim->RagDoll(1);
3239                     XYZ relative;
3240                     relative = facing;
3241                     relative.y = 0;
3242                     Normalise(&relative);
3243                     relative.y -= .1;
3244                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3245                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3246                     }
3247                     victim->jointVel(lefthand) *= .1 - 1;
3248                     victim->jointVel(leftwrist) *= .2 - 1;
3249                     victim->jointVel(leftelbow) *= .5 - 1;
3250                     victim->jointVel(leftshoulder) *= .7 - 1;
3251                     victim->jointVel(righthand) *= .1 - 1;
3252                     victim->jointVel(rightwrist) *= .2 - 1;
3253                     victim->jointVel(rightelbow) *= .5 - 1;
3254                     victim->jointVel(rightshoulder) *= .7 - 1;
3255
3256                     award_bonus(id, swordreversebonus);
3257                 }
3258
3259                 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3260                     escapednum = 0;
3261                     if (id == 0)
3262                         camerashake += .4;
3263                     if (Random() % 2) {
3264                         victim->spurt = 1;
3265                         DoBlood(.2, 230);
3266                     }
3267                     if (tutoriallevel != 1) {
3268                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3269                     }
3270                     victim->RagDoll(0);
3271                     XYZ relative;
3272                     relative = victim->coords - oldcoords;
3273                     relative.y = 0;
3274                     Normalise(&relative);
3275                     relative = DoRotation(relative, 0, -90, 0);
3276                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3277                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3278                     }
3279                     victim->jointVel(abdomen) += relative * damagemult * 200;
3280                     victim->Puff(abdomen);
3281                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3282
3283                     award_bonus(id, Reversal);
3284                 }
3285
3286                 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3287                     escapednum = 0;
3288                     victim->RagDoll(0);
3289                     victim->skeleton.spinny = 0;
3290                     XYZ relative;
3291                     relative = facing * -1;
3292                     relative.y = -3;
3293                     Normalise(&relative);
3294                     if (victim->id == 0)
3295                         relative /= 30;
3296                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3297                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3298                     }
3299                     victim->damage = victim->damagetolerance;
3300                     victim->permanentdamage = victim->damagetolerance - 1;
3301                     bool doslice;
3302                     doslice = 0;
3303                     if (weaponactive != -1 || creature == wolftype)
3304                         doslice = 1;
3305                     if (creature == rabbittype && weaponactive != -1)
3306                         if (weapons[weaponids[0]].getType() == staff)
3307                             doslice = 0;
3308                     if (doslice) {
3309                         if (weaponactive != -1) {
3310                             victim->DoBloodBig(200, 225);
3311                             emit_sound_at(knifeslicesound, victim->coords);
3312                             if (bloodtoggle)
3313                                 weapons[weaponids[weaponactive]].bloody = 2;
3314                             weapons[weaponids[weaponactive]].blooddrip += 5;
3315                         }
3316
3317                         if (creature == wolftype && weaponactive == -1) {
3318                             emit_sound_at(clawslicesound, victim->coords, 128.);
3319                             victim->spurt = 1;
3320                             victim->DoBloodBig(2, 175);
3321                         }
3322                     }
3323                     award_bonus(id, spinecrusher);
3324                 }
3325
3326                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3327                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3328                         escapednum = 0;
3329                         if (animTarget == knifefollowanim)
3330                             victim->DoBloodBig(200, 210);
3331                         if (animTarget == knifesneakattackanim) {
3332                             XYZ footvel, footpoint;
3333                             footvel = 0;
3334                             footpoint = weapons[weaponids[0]].tippoint;
3335                             if (bloodtoggle)
3336                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3337                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3338                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3339                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3340                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3341                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3342                             victim->DoBloodBig(200, 195);
3343                             award_bonus(id, tracheotomy);
3344                         }
3345                         if (animTarget == knifefollowanim) {
3346                             award_bonus(id, Stabbonus);
3347                             XYZ footvel, footpoint;
3348                             footvel = 0;
3349                             footpoint = weapons[weaponids[0]].tippoint;
3350                             if (bloodtoggle)
3351                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3352                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3353                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3354                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3355                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3356                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3357
3358                         }
3359                         victim->bloodloss += 10000;
3360                         victim->velocity = 0;
3361                         emit_sound_at(fleshstabsound, victim->coords);
3362                         if (bloodtoggle)
3363                             weapons[weaponids[weaponactive]].bloody = 2;
3364                         weapons[weaponids[weaponactive]].blooddrip += 5;
3365                     }
3366                 }
3367
3368                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3369                     escapednum = 0;
3370                     victim->velocity = 0;
3371                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3372                         victim->skeleton.joints[i].velocity = 0;
3373                     }
3374                     if (animTarget == knifefollowanim) {
3375                         victim->RagDoll(0);
3376                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3377                             victim->skeleton.joints[i].velocity = 0;
3378                         }
3379                     }
3380                     if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3381                         emit_sound_at(fleshstabremovesound, victim->coords);
3382                         if (bloodtoggle)
3383                             weapons[weaponids[weaponactive]].bloody = 2;
3384                         weapons[weaponids[weaponactive]].blooddrip += 5;
3385
3386                         XYZ footvel, footpoint;
3387                         footvel = 0;
3388                         footpoint = weapons[weaponids[0]].tippoint;
3389                         if (bloodtoggle)
3390                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3391                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3392                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3393                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3394                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3395                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3396                     }
3397                 }
3398
3399                 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3400                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3401                         award_bonus(id, backstab);
3402
3403                         escapednum = 0;
3404
3405                         XYZ footvel, footpoint;
3406                         footvel = 0;
3407                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3408                         if (bloodtoggle)
3409                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3410                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3411                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3412                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3413                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3414                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3415                         victim->DoBloodBig(200, 180);
3416                         victim->DoBloodBig(200, 215);
3417                         victim->bloodloss += 10000;
3418                         victim->velocity = 0;
3419                         emit_sound_at(fleshstabsound, victim->coords);
3420                         if (bloodtoggle)
3421                             weapons[weaponids[weaponactive]].bloody = 2;
3422                         weapons[weaponids[weaponactive]].blooddrip += 5;
3423                     }
3424                 }
3425
3426                 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3427                     escapednum = 0;
3428                     victim->velocity = 0;
3429                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3430                         victim->skeleton.joints[i].velocity = 0;
3431                     }
3432                     if (weaponactive != -1) {
3433                         emit_sound_at(fleshstabremovesound, victim->coords);
3434                         if (bloodtoggle)
3435                             weapons[weaponids[weaponactive]].bloody = 2;
3436                         weapons[weaponids[weaponactive]].blooddrip += 5;
3437
3438                         XYZ footvel, footpoint;
3439                         footvel = 0;
3440                         footpoint = weapons[weaponids[0]].tippoint;
3441                         if (bloodtoggle)
3442                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3443                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3444                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3445                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3446                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3447                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3448                     }
3449                 }
3450
3451                 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3452                     escapednum = 0;
3453                     if (id == 0)
3454                         camerashake += .4;
3455                     if (Random() % 2) {
3456                         victim->spurt = 1;
3457                         DoBlood(.2, 240);
3458                     }
3459                     if (weaponactive == -1) {
3460                         if (tutoriallevel != 1) {
3461                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
3462                         }
3463                     }
3464                     bool doslice;
3465                     doslice = 0;
3466                     if (weaponactive != -1 || creature == wolftype)
3467                         doslice = 1;
3468                     if (creature == rabbittype && weaponactive != -1)
3469                         if (weapons[weaponids[0]].getType() == staff)
3470                             doslice = 0;
3471                     if (doslice) {
3472                         if (weaponactive != -1) {
3473                             victim->DoBloodBig(2 / victim->armorhead, 225);
3474                             emit_sound_at(knifeslicesound, victim->coords);
3475                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3476                                 weapons[weaponids[weaponactive]].bloody = 1;
3477                             weapons[weaponids[weaponactive]].blooddrip += 3;
3478                         }
3479                         if (weaponactive == -1 && creature == wolftype) {
3480                             emit_sound_at(clawslicesound, victim->coords, 128.);
3481                             victim->spurt = 1;
3482                             victim->DoBloodBig(2 / victim->armorhead, 175);
3483                         }
3484                     }
3485
3486                     award_bonus(id, Reversal);
3487
3488                     victim->Puff(neck);
3489
3490                     XYZ relative;
3491                     relative = facing * -1;
3492                     relative.y = 0;
3493                     Normalise(&relative);
3494                     relative = DoRotation(relative, 0, 90, 0);
3495                     relative.y = .5;
3496                     Normalise(&relative);
3497                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3498                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3499                     }
3500                     victim->jointVel(head) += relative * damagemult * 200;
3501                     if (victim->damage < victim->damagetolerance - 100)
3502                         victim->velocity = relative * 200;
3503                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
3504                     victim->velocity = 0;
3505                 }
3506
3507                 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3508                     escapednum = 0;
3509                     victim->RagDoll(0);
3510                     XYZ relative;
3511                     relative = facing * -1;
3512                     relative.y = 0;
3513                     Normalise(&relative);
3514                     relative = DoRotation(relative, 0, 90, 0);
3515                     relative.y = .5;
3516                     Normalise(&relative);
3517                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3518                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3519                     }
3520                     victim->jointVel(head) += relative * damagemult * 200;
3521                 }
3522
3523                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3524                     if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3525                         award_bonus(id, reverseko);
3526                     }
3527             }
3528
3529
3530             //Animation end
3531             if (frameTarget > animation[animCurrent].numframes - 1) {
3532                 frameTarget = 0;
3533                 if (wasStop()) {
3534                     animTarget = getIdle();
3535                     FootLand(0, 1);
3536                     FootLand(1, 1);
3537                 }
3538                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3539                     animTarget = rollanim;
3540                     frameTarget = 3;
3541                     emit_sound_at(movewhooshsound, coords, 128.);
3542                 }
3543                 if (animCurrent == staggerbackhighanim) {
3544                     animTarget = getIdle();
3545                 }
3546                 if (animCurrent == staggerbackhardanim) {
3547                     animTarget = getIdle();
3548                 }
3549                 if (animCurrent == removeknifeanim) {
3550                     animTarget = getIdle();
3551                 }
3552                 if (animCurrent == crouchremoveknifeanim) {
3553                     animTarget = getCrouch();
3554                 }
3555                 if (animCurrent == backhandspringanim) {
3556                     animTarget = getIdle();
3557                 }
3558                 if (animCurrent == dodgebackanim) {
3559                     animTarget = getIdle();
3560                 }
3561                 if (animCurrent == drawleftanim) {
3562                     animTarget = getIdle();
3563                 }
3564                 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3565                     animTarget = getIdle();
3566                     if (animCurrent == crouchdrawrightanim) {
3567                         animTarget = getCrouch();
3568                     }
3569                     if (weaponactive == -1)
3570                         weaponactive = 0;
3571                     else if (weaponactive == 0) {
3572                         weaponactive = -1;
3573                         if (num_weapons == 2) {
3574                             int buffer;
3575                             buffer = weaponids[0];
3576                             weaponids[0] = weaponids[1];
3577                             weaponids[1] = buffer;
3578                         }
3579                     }
3580
3581                     if (weaponactive == -1) {
3582                         emit_sound_at(knifesheathesound, coords, 128.);
3583                     }
3584                     if (weaponactive != -1) {
3585                         emit_sound_at(knifedrawsound, coords, 128.);
3586                     }
3587                 }
3588                 if (animCurrent == rollanim) {
3589                     animTarget = getCrouch();
3590                     FootLand(0, 1);
3591                     FootLand(1, 1);
3592                 }
3593                 if (isFlip()) {
3594                     if (animTarget == walljumprightkickanim) {
3595                         targetrot = -190;
3596                     }
3597                     if (animTarget == walljumpleftkickanim) {
3598                         targetrot = 190;
3599                     }
3600                     animTarget = jumpdownanim;
3601                 }
3602                 if (animCurrent == climbanim) {
3603                     animTarget = getCrouch();
3604                     frameTarget = 1;
3605                     coords += facing * .1;
3606                     if (!isnormal(coords.x))
3607                         coords = oldcoords;
3608                     oldcoords = coords;
3609                     collided = 0;
3610                     targetoffset = 0;
3611                     currentoffset = 0;
3612                     grabdelay = 1;
3613                     velocity = 0;
3614                     collided = 0;
3615                     avoidcollided = 0;
3616                 }
3617                 if (animTarget == rabbitkickreversalanim) {
3618                     animTarget = getCrouch();
3619                     lastfeint = 0;
3620                 }
3621                 if (animTarget == jumpreversalanim) {
3622                     animTarget = getCrouch();
3623                     lastfeint = 0;
3624                 }
3625                 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3626                     if (attackkeydown && animTarget != walljumpfrontanim) {
3627                         int closest = -1;
3628                         float closestdist = -1;
3629                         float distance;
3630                         if (Person::players.size() > 1)
3631                             for (unsigned i = 0; i < Person::players.size(); i++) {
3632                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3633                                     distance = distsq(&Person::players[i]->coords, &coords);
3634                                     if (closestdist == -1 || distance < closestdist) {
3635                                         closestdist = distance;
3636                                         closest = i;
3637                                     }
3638                                 }
3639                             }
3640                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3641                             victim = Person::players[closest];
3642                             animTarget = walljumprightkickanim;
3643                             frameTarget = 0;
3644                             XYZ rotatetarget = victim->coords - coords;
3645                             Normalise(&rotatetarget);
3646                             yaw = -asin(0 - rotatetarget.x);
3647                             yaw *= 360 / 6.28;
3648                             if (rotatetarget.z < 0)
3649                                 yaw = 180 - yaw;
3650                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3651                             velocity = (victim->coords - coords) * 4;
3652                             velocity.y += 2;
3653                             transspeed = 40;
3654                         }
3655                     }
3656                     if (animTarget == walljumpbackanim) {
3657                         animTarget = backflipanim;
3658                         frameTarget = 3;
3659                         velocity = facing * -8;
3660                         velocity.y = 4;
3661                         if (id == 0)
3662                             resume_stream(whooshsound);
3663                     }
3664                     if (animTarget == walljumprightanim) {
3665                         animTarget = rightflipanim;
3666                         frameTarget = 4;
3667                         targetyaw -= 90;
3668                         yaw -= 90;
3669                         velocity = DoRotation(facing, 0, 30, 0) * -8;
3670                         velocity.y = 4;
3671                     }
3672                     if (animTarget == walljumpfrontanim) {
3673                         animTarget = frontflipanim;
3674                         frameTarget = 2;
3675                         //targetyaw-=180;
3676                         ////yaw-=180;
3677                         velocity = facing * 8;
3678                         velocity.y = 4;
3679                     }
3680                     if (id == 0)
3681                         resume_stream(whooshsound);
3682                 }
3683                 if (animTarget == walljumpleftanim) {
3684                     if (attackkeydown) {
3685                         int closest = -1;
3686                         float closestdist = -1;
3687                         float distance;
3688                         if (Person::players.size() > 1)
3689                             for (unsigned i = 0; i < Person::players.size(); i++) {
3690                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3691                                     distance = distsq(&Person::players[i]->coords, &coords);
3692                                     if (closestdist == -1 || distance < closestdist) {
3693                                         closestdist = distance;
3694                                         closest = i;
3695                                     }
3696                                 }
3697                             }
3698                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3699                             victim = Person::players[closest];
3700                             animTarget = walljumpleftkickanim;
3701                             frameTarget = 0;
3702                             XYZ rotatetarget = victim->coords - coords;
3703                             Normalise(&rotatetarget);
3704                             yaw = -asin(0 - rotatetarget.x);
3705                             yaw *= 360 / 6.28;
3706                             if (rotatetarget.z < 0)
3707                                 yaw = 180 - yaw;
3708                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3709                             velocity = (victim->coords - coords) * 4;
3710                             velocity.y += 2;
3711                             transspeed = 40;
3712                         }
3713                     }
3714                     if (animTarget != walljumpleftkickanim) {
3715                         animTarget = leftflipanim;
3716                         frameTarget = 4;
3717                         targetyaw += 90;
3718                         yaw += 90;
3719                         velocity = DoRotation(facing, 0, -30, 0) * -8;
3720                         velocity.y = 4;
3721                     }
3722                     if (id == 0)
3723                         resume_stream(whooshsound);
3724                 }
3725                 if (animTarget == sneakattackanim) {
3726                     animCurrent = getCrouch();
3727                     animTarget = getCrouch();
3728                     frameTarget = 1;
3729                     frameCurrent = 0;
3730                     targetyaw += 180;
3731                     yaw += 180;
3732                     targettilt2 *= -1;
3733                     tilt2 *= -1;
3734                     transspeed = 1000000;
3735                     targetheadyaw += 180;
3736                     coords -= facing * .7;
3737                     if (onterrain)
3738                         coords.y = terrain.getHeight(coords.x, coords.z);
3739
3740                     lastfeint = 0;
3741                 }
3742                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3743                     animTarget = getIdle();
3744                     frameTarget = 0;
3745                     if (onterrain)
3746                         coords.y = terrain.getHeight(coords.x, coords.z);
3747
3748                     lastfeint = 0;
3749                 }
3750                 if (animCurrent == knifefollowanim) {
3751                     animTarget = getIdle();
3752                     lastfeint = 0;
3753                 }
3754                 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3755                     float ycoords = oldcoords.y;
3756                     animTarget = getStop();
3757                     targetyaw += 180;
3758                     yaw += 180;
3759                     targettilt2 *= -1;
3760                     tilt2 *= -1;
3761                     transspeed = 1000000;
3762                     targetheadyaw += 180;
3763                     if (!isnormal(coords.x))
3764                         coords = oldcoords;
3765                     if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3766                         oldcoords = coords + facing * .5;
3767                     else if (animCurrent == sweepreversalanim)
3768                         oldcoords = coords + facing * 1.1;
3769                     else if (animCurrent == upunchreversalanim) {
3770                         oldcoords = coords + facing * 1.5;
3771                         targetyaw += 180;
3772                         yaw += 180;
3773                         targetheadyaw += 180;
3774                         targettilt2 *= -1;
3775                         tilt2 *= -1;
3776                     } else if (animCurrent == knifeslashreversalanim) {
3777                         oldcoords = coords + facing * .5;
3778                         targetyaw += 90;
3779                         yaw += 90;
3780                         targetheadyaw += 90;
3781                         targettilt2 = 0;
3782                         tilt2 = 0;
3783                     } else if (animCurrent == staffspinhitreversalanim) {
3784                         targetyaw += 180;
3785                         yaw += 180;
3786                         targetheadyaw += 180;
3787                         targettilt2 = 0;
3788                         tilt2 = 0;
3789                     }
3790                     if (onterrain)
3791                         oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3792                     else
3793                         oldcoords.y = ycoords;
3794                     currentoffset = coords - oldcoords;
3795                     targetoffset = 0;
3796                     coords = oldcoords;
3797
3798                     lastfeint = 0;
3799                 }
3800                 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3801                     velocity = 0;
3802                     velocity.y = -5;
3803                     RagDoll(0);
3804                 }
3805                 if (animation[animTarget].attack == reversed) {
3806                     escapednum++;
3807                     if (animTarget == sweepreversedanim)
3808                         targetyaw += 90;
3809                     animTarget = backhandspringanim;
3810                     frameTarget = 2;
3811                     emit_sound_at(landsound, coords, 128);
3812
3813                     if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3814                         animTarget = rollanim;
3815                         frameTarget = 5;
3816                         oldcoords = coords;
3817                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3818                         coords.y = oldcoords.y;
3819                     }
3820                     if (animCurrent == knifeslashreversedanim) {
3821                         animTarget = rollanim;
3822                         frameTarget = 0;
3823                         targetyaw += 90;
3824                         yaw += 90;
3825                         oldcoords = coords;
3826                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3827                         coords.y = oldcoords.y;
3828                     }
3829                 }
3830                 if (wasFlip()) {
3831                     animTarget = jumpdownanim;
3832                 }
3833                 if (wasLanding())
3834                     animTarget = getIdle();
3835                 if (wasLandhard())
3836                     animTarget = getIdle();
3837                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3838                     animTarget = getIdle();
3839                     oldcoords = coords;
3840                     coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3841                     coords.y = oldcoords.y;
3842                     //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3843                     targetoffset.y = coords.y;
3844                     if (onterrain)
3845                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
3846                     currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3847                     currentoffset.y -= (coords.y - targetoffset.y);
3848                     coords.y = targetoffset.y;
3849                     targetoffset = 0;
3850                     normalsupdatedelay = 0;
3851                 }
3852                 if (animCurrent == upunchanim) {
3853                     animTarget = getStop();
3854                     normalsupdatedelay = 0;
3855                     lastfeint = 0;
3856                 }
3857                 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3858                     targetyaw = yaw;
3859                     bool hasstaff;
3860                     hasstaff = 0;
3861                     if (num_weapons > 0)
3862                         if (weapons[0].getType() == staff)
3863                             hasstaff = 1;
3864                     if (!hasstaff)
3865                         DoDamage(35);
3866                     RagDoll(0);
3867                     lastfeint = 0;
3868                     rabbitkickragdoll = 1;
3869                 }
3870                 if (animCurrent == rabbitkickreversedanim) {
3871                     if (!feint) {
3872                         velocity = 0;
3873                         velocity.y = -10;
3874                         //DoDamage(100);
3875                         RagDoll(0);
3876                         skeleton.spinny = 0;
3877                         SolidHitBonus(!id); // FIXME: tricky id
3878                     }
3879                     if (feint) {
3880                         escapednum++;
3881                         animTarget = rollanim;
3882                         coords += facing;
3883                         if (id == 0)
3884                             pause_sound(whooshsound);
3885                     }
3886                     lastfeint = 0;
3887                 }
3888                 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3889                     velocity = 0;
3890                     velocity.y = -10;
3891                     RagDoll(0);
3892                     skeleton.spinny = 0;
3893                 }
3894                 if (animCurrent == jumpreversedanim) {
3895                     if (!feint) {
3896                         velocity = 0;
3897                         velocity.y = -10;
3898                         //DoDamage(100);
3899                         RagDoll(0);
3900                         skeleton.spinny = 0;
3901                         SolidHitBonus(!id); // FIXME: tricky id
3902                     }
3903                     if (feint) {
3904                         escapednum++;
3905                         animTarget = rollanim;
3906                         coords += facing * 2;
3907                         if (id == 0)
3908                             pause_sound(whooshsound);
3909                     }
3910                     lastfeint = 0;
3911                 }
3912
3913                 if (animation[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
3914                     animTarget = getupfromfrontanim;
3915                     lastfeint = 0;
3916                 } else if (animation[animCurrent].attack == normalattack) {
3917                     animTarget = getIdle();
3918                     lastfeint = 0;
3919                 }
3920                 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3921                     animTarget = blockhighleftstrikeanim;
3922                 }
3923                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3924                     animTarget = getIdle();
3925                     lastfeint = 0;
3926                 }
3927                 if (animCurrent == spinkickanim && victim->skeleton.free) {
3928                     if (creature == rabbittype)
3929                         animTarget = fightidleanim;
3930                 }
3931             }
3932             target = 0;
3933
3934             if (isIdle() && !wasIdle())
3935                 normalsupdatedelay = 0;
3936
3937             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3938                 animTarget = jumpdownanim;
3939             }
3940         }
3941         if (!skeleton.free) {
3942             oldtarget = target;
3943             if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
3944                 if (!isRun() || !wasRun()) {
3945                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3946                         target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
3947                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3948                         target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
3949                 }
3950                 if (isRun() && wasRun()) {
3951                     float tempspeed;
3952                     tempspeed = velspeed;
3953                     if (tempspeed < 10 * speedmult)
3954                         tempspeed = 10 * speedmult;
3955                     target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
3956                 }
3957             } else if (transspeed)
3958                 target += multiplier * transspeed * speed * 2;
3959             else {
3960                 if (!isRun() || !wasRun()) {
3961                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3962                         target += multiplier * animation[animTarget].speed[frameTarget] * 2;
3963                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3964                         target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
3965                 }
3966             }
3967
3968             if (animCurrent != animTarget)
3969                 target = (target + oldtarget) / 2;
3970
3971             if (target > 1) {
3972                 frameCurrent = frameTarget;
3973                 target = 1;
3974             }
3975             oldrot = rot;
3976             rot = targetrot * target;
3977             yaw += rot - oldrot;
3978             if (target == 1) {
3979                 rot = 0;
3980                 oldrot = 0;
3981                 targetrot = 0;
3982             }
3983             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
3984                 //Old rotates
3985                 for (int i = 0; i < skeleton.num_joints; i++) {
3986                     skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
3987                 }
3988
3989                 skeleton.FindForwards();
3990
3991                 for (int i = 0; i < skeleton.num_muscles; i++) {
3992                     if (skeleton.muscles[i].visible) {
3993                         skeleton.FindRotationMuscle(i, animTarget);
3994                     }
3995                 }
3996                 for (int i = 0; i < skeleton.num_muscles; i++) {
3997                     if (skeleton.muscles[i].visible) {
3998                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3999                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4000                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4001                             skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4002                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4003                             skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4004                     }
4005                 }
4006
4007                 //New rotates
4008                 for (int i = 0; i < skeleton.num_joints; i++) {
4009                     skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4010                 }
4011
4012                 skeleton.FindForwards();
4013
4014                 for (int i = 0; i < skeleton.num_muscles; i++) {
4015                     if (skeleton.muscles[i].visible) {
4016                         skeleton.FindRotationMuscle(i, animTarget);
4017                     }
4018                 }
4019                 for (int i = 0; i < skeleton.num_muscles; i++) {
4020                     if (skeleton.muscles[i].visible) {
4021                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4022                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4023                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4024                             skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4025                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4026                             skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4027                         if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4028                         if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4029                         if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4030                         if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4031                         if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4032                         if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4033                     }
4034                 }
4035             }
4036             if (frameCurrent >= animation[animCurrent].numframes)
4037                 frameCurrent = animation[animCurrent].numframes - 1;
4038
4039             oldanimCurrent = animCurrent;
4040             oldanimTarget = animTarget;
4041             oldframeTarget = frameTarget;
4042             oldframeCurrent = frameCurrent;
4043
4044             for (int i = 0; i < skeleton.num_joints; i++) {
4045                 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4046                 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4047             }
4048             offset = currentoffset * (1 - target) + targetoffset * target;
4049             for (int i = 0; i < skeleton.num_muscles; i++) {
4050                 if (skeleton.muscles[i].visible) {
4051                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4052                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4053                     skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4054                 }
4055             }
4056         }
4057
4058         if (isLanding() && landhard) {
4059             if (id == 0)
4060                 camerashake += .4;
4061             animTarget = getLandhard();
4062             frameTarget = 0;
4063             target = 0;
4064             landhard = 0;
4065             transspeed = 15;
4066         }
4067     }
4068 }
4069
4070 /* EFFECT
4071  * MONSTER
4072  * TODO
4073  */
4074 void Person::DoStuff()
4075 {
4076     static XYZ terrainnormal;
4077     static XYZ flatfacing;
4078     static XYZ flatvelocity;
4079     static float flatvelspeed;
4080     static int i, j, l;
4081     static XYZ average;
4082     static int howmany;
4083     static int bloodsize;
4084     static int startx, starty, endx, endy;
4085     static GLubyte color;
4086     static XYZ bloodvel;
4087
4088     onfiredelay -= multiplier;
4089     if (onfiredelay < 0 && onfire) {
4090         if (Random() % 2 == 0) {
4091             crouchkeydown = 1;
4092         }
4093         onfiredelay = 0.3;
4094     }
4095
4096     crouchkeydowntime += multiplier;
4097     if (!crouchkeydown)
4098         crouchkeydowntime = 0;
4099     jumpkeydowntime += multiplier;
4100     if (!jumpkeydown && skeleton.free)
4101         jumpkeydowntime = 0;
4102
4103     if (hostile || damage > 0 || bloodloss > 0)
4104         immobile = 0;
4105
4106     if (isIdle() || isRun())
4107         targetoffset = 0;
4108
4109     if (num_weapons == 1 && weaponactive != -1)
4110         weaponstuck = -1;
4111
4112     if (id == 0)
4113         blooddimamount -= multiplier * .3;
4114     speechdelay -= multiplier;
4115     texupdatedelay -= multiplier;
4116     interestdelay -= multiplier;
4117     flamedelay -= multiplier;
4118     parriedrecently -= multiplier;
4119     if (!victim) {
4120         victim = this->shared_from_this();
4121         hasvictim = 0;
4122     }
4123
4124     if (id == 0)
4125         speed = 1.1 * speedmult;
4126     else
4127         speed = 1.0 * speedmult;
4128     if (!skeleton.free)
4129         rabbitkickragdoll = 0;
4130
4131     speed *= speedmult;
4132
4133     if (id != 0 && (creature == rabbittype || difficulty != 2))
4134         superruntoggle = 0;
4135     if (id != 0 && creature == wolftype && difficulty == 2) {
4136         superruntoggle = 0;
4137         if (aitype != passivetype) {
4138             superruntoggle = 1;
4139             if (aitype == attacktypecutoff && (Person::players[0]->isIdle() || Person::players[0]->isCrouch() || Person::players[0]->skeleton.free || Person::players[0]->animTarget == getupfrombackanim || Person::players[0]->animTarget == getupfromfrontanim || Person::players[0]->animTarget == sneakanim) && distsq(&coords, &Person::players[0]->coords) < 16) {
4140                 superruntoggle = 0;
4141             }
4142         }
4143         if (scale < 0.2)
4144             superruntoggle = 0;
4145         if (animTarget == wolfrunninganim && !superruntoggle) {
4146             animTarget = getRun();
4147             frameTarget = 0;
4148         }
4149     }
4150     if (weaponactive == -1 && num_weapons > 0) {
4151         if (weapons[weaponids[0]].getType() == staff) {
4152             weaponactive = 0;
4153         }
4154     }
4155
4156     if (onfire) {
4157         burnt += multiplier;
4158         deathbleeding = 1;
4159         if (burnt > .6)
4160             burnt = .6;
4161         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4162
4163         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4164             float gLoc[3];
4165             float vel[3];
4166             gLoc[0] = coords.x;
4167             gLoc[1] = coords.y;
4168             gLoc[2] = coords.z;
4169             vel[0] = velocity.x;
4170             vel[1] = velocity.y;
4171             vel[2] = velocity.z;
4172
4173             if (id == 0) {
4174                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4175                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4176             }
4177         }
4178     }
4179     while (flamedelay < 0 && onfire) {
4180         flamedelay += .006;
4181         howmany = abs(Random() % (skeleton.num_joints));
4182         if (!skeleton.free)
4183             flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4184         if (skeleton.free)
4185             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4186         if (!skeleton.free)
4187             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4188         if (skeleton.free)
4189             flatfacing = skeleton.joints[howmany].position * scale + coords;
4190         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4191     }
4192
4193     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4194         flamedelay += .05;
4195         howmany = abs(Random() % (skeleton.num_joints));
4196         if (!skeleton.free)
4197             flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4198         if (skeleton.free)
4199             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4200         if (!skeleton.free)
4201             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4202         if (skeleton.free)
4203             flatfacing = skeleton.joints[howmany].position * scale + coords;
4204         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4205     }
4206
4207     if (bleeding > 0) {
4208         bleeding -= multiplier * .3;
4209         if (bloodtoggle == 2) {
4210             skeleton.drawmodel.textureptr.bind();
4211             if ((bleeding <= 0) && (detail != 2))
4212                 DoMipmaps();
4213         }
4214     }
4215
4216     if (neckspurtamount > 0) {
4217         neckspurtamount -= multiplier;
4218         neckspurtdelay -= multiplier * 3;
4219         neckspurtparticledelay -= multiplier * 3;
4220         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4221             spurt = 0;
4222             bloodvel = 0;
4223             if (!skeleton.free) {
4224                 bloodvel.z = 5 * neckspurtamount;
4225                 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4226             }
4227             if (skeleton.free) {
4228                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4229             }
4230             if (skeleton.free)
4231                 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4232             if (!skeleton.free)
4233                 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4234             if (skeleton.free)
4235                 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4236             if (!skeleton.free)
4237                 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4238             neckspurtparticledelay = .05;
4239         }
4240         if (neckspurtdelay < 0) {
4241             neckspurtdelay = 3;
4242         }
4243     }
4244
4245     if (deathbleeding > 0 && dead != 2) {
4246         if (deathbleeding < 5)
4247             bleeddelay -= deathbleeding * multiplier / 4;
4248         else
4249             bleeddelay -= 5 * multiplier / 4;
4250         if (bleeddelay < 0 && bloodtoggle) {
4251             bleeddelay = 1;
4252             XYZ bloodvel;
4253             if (bloodtoggle) {
4254                 bloodvel = 0;
4255                 if (skeleton.free)
4256                     bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4257                 if (!skeleton.free)
4258                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4259                 if (skeleton.free)
4260                     Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4261                 if (!skeleton.free)
4262                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4263             }
4264         }
4265         bloodloss += deathbleeding * multiplier * 80;
4266         deathbleeding -= multiplier * 1.6;
4267         if (deathbleeding < 0)
4268             deathbleeding = 0;
4269         if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4270             if (weaponactive != -1) {
4271                 weapons[weaponids[0]].owner = -1;
4272                 weapons[weaponids[0]].velocity = velocity * scale * -.3;
4273                 weapons[weaponids[0]].velocity.x += .01;
4274                 weapons[weaponids[0]].tipvelocity = velocity * scale;
4275                 weapons[weaponids[0]].missed = 1;
4276                 weapons[weaponids[0]].hitsomething = 0;
4277                 weapons[weaponids[0]].freetime = 0;
4278                 weapons[weaponids[0]].firstfree = 1;
4279                 weapons[weaponids[0]].physics = 1;
4280                 num_weapons--;
4281                 if (num_weapons) {
4282                     weaponids[0] = weaponids[num_weapons];
4283                     if (weaponstuck == num_weapons)
4284                         weaponstuck = 0;
4285                 }
4286                 weaponactive = -1;
4287                 for (unsigned i = 0; i < Person::players.size(); i++) {
4288                     Person::players[i]->wentforweapon = 0;
4289                 }
4290
4291                 if (id == 0) {
4292                     flashamount = .5;
4293                     flashr = 1;
4294                     flashg = 0;
4295                     flashb = 0;
4296                     flashdelay = 0;
4297                 }
4298             }
4299
4300             if (!dead && creature == wolftype) {
4301                 award_bonus(0, Wolfbonus);
4302             }
4303             dead = 2;
4304             if (animTarget == knifefollowedanim && !skeleton.free) {
4305                 for (int i = 0; i < skeleton.num_joints; i++) {
4306                     skeleton.joints[i].velocity = 0;
4307                     skeleton.joints[i].velocity.y = -2;
4308                 }
4309             }
4310             if (id != 0 && unconscioustime > .1) {
4311                 numafterkill++;
4312             }
4313
4314             RagDoll(0);
4315         }
4316     }
4317
4318     if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4319         texupdatedelay = .12;
4320
4321         bloodsize = 5 - realtexdetail;
4322
4323         startx = 0;
4324         starty = 0;
4325         startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4326         starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4327         endx = startx + bloodsize;
4328         endy = starty + bloodsize;
4329
4330         if (startx < 0) {
4331             startx = 0;
4332             bleeding = 0;
4333         }
4334         if (starty < 0) {
4335             starty = 0;
4336             bleeding = 0;
4337         }
4338         if (endx > skeleton.skinsize - 1) {
4339             endx = skeleton.skinsize - 1;
4340             bleeding = 0;
4341         }
4342         if (endy > skeleton.skinsize - 1) {
4343             endy = skeleton.skinsize - 1;
4344             bleeding = 0;
4345         }
4346         if (endx < startx)
4347             endx = startx;
4348         if (endy < starty)
4349             endy = starty;
4350
4351         for (i = startx; i < endx; i++) {
4352             for (j = starty; j < endy; j++) {
4353                 if (Random() % 2 == 0) {
4354                     color = Random() % 85 + 170;
4355                     if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4356                         skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4357                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4358                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4359                 }
4360             }
4361         }
4362         if (detail > 1) {
4363             skeleton.drawmodel.textureptr.bind();
4364             DoMipmaps();
4365         }
4366
4367         if (!skeleton.free) {
4368             bleedy -= 4 / realtexdetail;
4369             if (detail == 2)
4370                 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4371             else
4372                 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4373         }
4374         if (skeleton.free) {
4375             bleedx += 4 * direction / realtexdetail;
4376             if (detail == 2)
4377                 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4378             else
4379                 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4380         }
4381     }
4382
4383     if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4384         righthandmorphness = targetrighthandmorphness;
4385         righthandmorphstart = righthandmorphend;
4386     } else if (righthandmorphness > targetrighthandmorphness) {
4387         righthandmorphness -= multiplier * 4;
4388     } else if (righthandmorphness < targetrighthandmorphness) {
4389         righthandmorphness += multiplier * 4;
4390     }
4391
4392     if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4393         lefthandmorphness = targetlefthandmorphness;
4394         lefthandmorphstart = lefthandmorphend;
4395     } else if (lefthandmorphness > targetlefthandmorphness) {
4396         lefthandmorphness -= multiplier * 4;
4397     } else if (lefthandmorphness < targetlefthandmorphness) {
4398         lefthandmorphness += multiplier * 4;
4399     }
4400
4401     if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4402         if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4403             tailmorphness = targettailmorphness;
4404             tailmorphstart = tailmorphend;
4405         } else if (tailmorphness > targettailmorphness) {
4406             tailmorphness -= multiplier * 10;
4407         } else if (tailmorphness < targettailmorphness) {
4408             tailmorphness += multiplier * 10;
4409         }
4410     }
4411
4412     if (creature == wolftype) {
4413         if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4414             tailmorphness = targettailmorphness;
4415             tailmorphstart = tailmorphend;
4416         } else if (tailmorphness > targettailmorphness) {
4417             tailmorphness -= multiplier * 2;
4418         } else if (tailmorphness < targettailmorphness) {
4419             tailmorphness += multiplier * 2;
4420         }
4421     }
4422
4423     if (headmorphend == 3 || headmorphstart == 3) {
4424         if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4425             headmorphness = targetheadmorphness;
4426             headmorphstart = headmorphend;
4427         } else if (headmorphness > targetheadmorphness) {
4428             headmorphness -= multiplier * 7;
4429         } else if (headmorphness < targetheadmorphness) {
4430             headmorphness += multiplier * 7;
4431         }
4432     } else if (headmorphend == 5 || headmorphstart == 5) {
4433         if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4434             headmorphness = targetheadmorphness;
4435             headmorphstart = headmorphend;
4436         } else if (headmorphness > targetheadmorphness) {
4437             headmorphness -= multiplier * 10;
4438         } else if (headmorphness < targetheadmorphness) {
4439             headmorphness += multiplier * 10;
4440         }
4441     } else {
4442         if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4443             headmorphness = targetheadmorphness;
4444             headmorphstart = headmorphend;
4445         } else if (headmorphness > targetheadmorphness) {
4446             headmorphness -= multiplier * 4;
4447         } else if (headmorphness < targetheadmorphness) {
4448             headmorphness += multiplier * 4;
4449         }
4450     }
4451
4452     if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4453         chestmorphness = targetchestmorphness;
4454         chestmorphstart = chestmorphend;
4455     } else if (chestmorphness > targetchestmorphness) {
4456         chestmorphness -= multiplier;
4457     } else if (chestmorphness < targetchestmorphness) {
4458         chestmorphness += multiplier;
4459     }
4460
4461     if (dead != 2 && howactive <= typesleeping) {
4462         if (chestmorphstart == 0 && chestmorphend == 0) {
4463             chestmorphness = 0;
4464             targetchestmorphness = 1;
4465             chestmorphend = 3;
4466         }
4467         if (chestmorphstart != 0 && chestmorphend != 0) {
4468             chestmorphness = 0;
4469             targetchestmorphness = 1;
4470             chestmorphend = 0;
4471             if (environment == snowyenvironment) {
4472                 XYZ footpoint;
4473                 XYZ footvel;
4474                 if (!skeleton.free)
4475                     footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4476                 if (skeleton.free)
4477                     footvel = skeleton.specialforward[0] * -1;
4478                 if (!skeleton.free)
4479                     footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4480                 if (skeleton.free)
4481                     footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4482                 if (animTarget == sleepanim)
4483                     footvel = DoRotation(footvel, 0, 90, 0);
4484                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4485             }
4486         }
4487
4488         if (!dead && howactive < typesleeping) {
4489             blinkdelay -= multiplier * 2;
4490             if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4491                 headmorphness = 0;
4492                 targetheadmorphness = 1;
4493                 headmorphend = 3;
4494                 blinkdelay = (float)(abs(Random() % 40)) / 5;
4495             }
4496             if (headmorphstart == 3 && headmorphend == 3) {
4497                 headmorphness = 0;
4498                 targetheadmorphness = 1;
4499                 headmorphend = 0;
4500             }
4501         }
4502         if (!dead) {
4503             twitchdelay -= multiplier * 1.5;
4504             if (animTarget != hurtidleanim) {
4505                 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4506                     headmorphness = 0;
4507                     targetheadmorphness = 1;
4508                     headmorphend = 5;
4509                     twitchdelay = (float)(abs(Random() % 40)) / 5;
4510                 }
4511                 if (headmorphstart == 5 && headmorphend == 5) {
4512                     headmorphness = 0;
4513                     targetheadmorphness = 1;
4514                     headmorphend = 0;
4515                 }
4516             }
4517             if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4518                 twitchdelay3 -= multiplier * 1;
4519                 if (Random() % 2 == 0) {
4520                     if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4521                         righthandmorphness = 0;
4522                         targetrighthandmorphness = 1;
4523                         righthandmorphend = 1;
4524                         if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4525                     }
4526                     if (righthandmorphstart == 1 && righthandmorphend == 1) {
4527                         righthandmorphness = 0;
4528                         targetrighthandmorphness = 1;
4529                         righthandmorphend = 0;
4530                     }
4531                 }
4532                 if (Random() % 2 == 0) {
4533                     if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4534                         lefthandmorphness = 0;
4535                         targetlefthandmorphness = 1;
4536                         lefthandmorphend = 1;
4537                         twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4538                     }
4539                     if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4540                         lefthandmorphness = 0;
4541                         targetlefthandmorphness = 1;
4542                         lefthandmorphend = 0;
4543                     }
4544                 }
4545             }
4546         }
4547         if (!dead) {
4548             if (creature == rabbittype) {
4549                 if (howactive < typesleeping)
4550                     twitchdelay2 -= multiplier * 1.5;
4551                 else
4552                     twitchdelay2 -= multiplier * 0.5;
4553                 if (howactive <= typesleeping) {
4554                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4555                         tailmorphness = 0;
4556                         targettailmorphness = 1;
4557                         tailmorphend = 1;
4558                         twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4559                     }
4560                     if (tailmorphstart == 1 && tailmorphend == 1) {
4561                         tailmorphness = 0;
4562                         targettailmorphness = 1;
4563                         tailmorphend = 2;
4564                     }
4565                     if (tailmorphstart == 2 && tailmorphend == 2) {
4566                         tailmorphness = 0;
4567                         targettailmorphness = 1;
4568                         tailmorphend = 0;
4569                     }
4570                 }
4571             }
4572         }
4573     }
4574     if (creature == wolftype) {
4575         twitchdelay2 -= multiplier * 1.5;
4576         if (tailmorphend != 0)
4577             if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4578                 tailmorphness = 0;
4579                 targettailmorphness = 1;
4580                 tailmorphend = 0;
4581                 twitchdelay2 = .1;
4582             }
4583         if (tailmorphend != 5)
4584             if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4585                 tailmorphness = 0;
4586                 targettailmorphness = 1;
4587                 tailmorphend = 5;
4588                 twitchdelay2 = .1;
4589             }
4590         if (twitchdelay2 <= 0) {
4591             if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4592                 tailmorphness = 0;
4593                 targettailmorphness = 1;
4594                 tailmorphend = 1;
4595             }
4596             if (tailmorphstart == 1 && tailmorphend == 1) {
4597                 tailmorphness = 0;
4598                 targettailmorphness = 1;
4599                 tailmorphend = 2;
4600             }
4601             if (tailmorphstart == 2 && tailmorphend == 2) {
4602                 tailmorphness = 0;
4603                 targettailmorphness = 1;
4604                 tailmorphend = 3;
4605             }
4606             if (tailmorphstart == 3 && tailmorphend == 3) {
4607                 tailmorphness = 0;
4608                 targettailmorphness = 1;
4609                 tailmorphend = 4;
4610             }
4611             if (tailmorphstart == 4 && tailmorphend == 4) {
4612                 tailmorphness = 0;
4613                 targettailmorphness = 1;
4614                 tailmorphend = 1;
4615             }
4616         }
4617     }
4618
4619     if (dead != 1)
4620         unconscioustime = 0;
4621
4622     if (dead == 1 || howactive == typesleeping) {
4623         unconscioustime += multiplier;
4624         //If unconscious, close eyes and mouth
4625         if (righthandmorphend != 0)
4626             righthandmorphness = 0;
4627         righthandmorphend = 0;
4628         targetrighthandmorphness = 1;
4629
4630         if (lefthandmorphend != 0)
4631             lefthandmorphness = 0;
4632         lefthandmorphend = 0;
4633         targetlefthandmorphness = 1;
4634
4635         if (headmorphend != 3 && headmorphend != 5)
4636             headmorphness = 0;
4637         headmorphend = 3;
4638         targetheadmorphness = 1;
4639     }
4640
4641
4642     if (howactive > typesleeping) {
4643         XYZ headpoint;
4644         headpoint = coords;
4645         if (bloodtoggle && !bled) {
4646             terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4647         }
4648         if (bloodtoggle && !bled)
4649             for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4650                 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4651                 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4652                 float size = .8;
4653                 float opacity = .6;
4654                 float yaw = 0;
4655                 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4656             }
4657         bled = 1;
4658     }
4659
4660     if (dead == 2 || howactive > typesleeping) {
4661         //If dead, open mouth and hands
4662         if (righthandmorphend != 0)
4663             righthandmorphness = 0;
4664         righthandmorphend = 0;
4665         targetrighthandmorphness = 1;
4666
4667         if (lefthandmorphend != 0)
4668             lefthandmorphness = 0;
4669         lefthandmorphend = 0;
4670         targetlefthandmorphness = 1;
4671
4672         if (headmorphend != 2)
4673             headmorphness = 0;
4674         headmorphend = 2;
4675         targetheadmorphness = 1;
4676     }
4677
4678     if (stunned > 0 && !dead && headmorphend != 2) {
4679         if (headmorphend != 4)
4680             headmorphness = 0;
4681         headmorphend = 4;
4682         targetheadmorphness = 1;
4683     }
4684
4685     if (damage > damagetolerance && !dead) {
4686
4687         dead = 1;
4688         unconscioustime = 0;
4689
4690         if (creature == wolftype) {
4691             award_bonus(0, Wolfbonus);
4692         }
4693
4694         RagDoll(0);
4695
4696         if (weaponactive != -1) {
4697             weapons[weaponids[0]].owner = -1;
4698             weapons[weaponids[0]].velocity = velocity * scale * -.3;
4699             weapons[weaponids[0]].velocity.x += .01;
4700             weapons[weaponids[0]].tipvelocity = velocity * scale;
4701             weapons[weaponids[0]].missed = 1;
4702             weapons[weaponids[0]].hitsomething = 0;
4703             weapons[weaponids[0]].freetime = 0;
4704             weapons[weaponids[0]].firstfree = 1;
4705             weapons[weaponids[0]].physics = 1;
4706             num_weapons--;
4707             if (num_weapons) {
4708                 weaponids[0] = weaponids[num_weapons];
4709                 if (weaponstuck == num_weapons)
4710                     weaponstuck = 0;
4711             }
4712             weaponactive = -1;
4713             for (unsigned i = 0; i < Person::players.size(); i++) {
4714                 Person::players[i]->wentforweapon = 0;
4715             }
4716         }
4717
4718
4719
4720         if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4721             slomo = 1;
4722             slomodelay = .2;
4723         }
4724
4725         damage += 20;
4726     }
4727
4728     if (!dead)
4729         damage -= multiplier * 13;
4730     if (!dead)
4731         permanentdamage -= multiplier * 4;
4732     if (isIdle() || isCrouch()) {
4733         if (!dead)
4734             permanentdamage -= multiplier * 4;
4735     }
4736     if (damage < 0)
4737         damage = 0;
4738     if (permanentdamage < 0)
4739         permanentdamage = 0;
4740     if (superpermanentdamage < 0)
4741         superpermanentdamage = 0;
4742     if (permanentdamage < superpermanentdamage) {
4743         permanentdamage = superpermanentdamage;
4744     }
4745     if (damage < permanentdamage) {
4746         damage = permanentdamage;
4747     }
4748     if (dead == 1 && damage < damagetolerance) {
4749         dead = 0;
4750         skeleton.free = 1;
4751         damage -= 20;
4752         for (int i = 0; i < skeleton.num_joints; i++) {
4753             skeleton.joints[i].velocity = 0;
4754         }
4755     }
4756     if (permanentdamage > damagetolerance && dead != 2) {
4757         DoBlood(1, 255);
4758
4759         if (weaponactive != -1) {
4760             weapons[weaponids[0]].owner = -1;
4761             weapons[weaponids[0]].velocity = velocity * scale * -.3;
4762             weapons[weaponids[0]].velocity.x += .01;
4763             weapons[weaponids[0]].tipvelocity = velocity * scale;
4764             weapons[weaponids[0]].missed = 1;
4765             weapons[weaponids[0]].hitsomething = 0;
4766             weapons[weaponids[0]].freetime = 0;
4767             weapons[weaponids[0]].firstfree = 1;
4768             weapons[weaponids[0]].physics = 1;
4769             num_weapons--;
4770             if (num_weapons) {
4771                 weaponids[0] = weaponids[num_weapons];
4772                 if (weaponstuck == num_weapons)
4773                     weaponstuck = 0;
4774             }
4775             weaponactive = -1;
4776             for (unsigned i = 0; i < Person::players.size(); i++) {
4777                 Person::players[i]->wentforweapon = 0;
4778             }
4779         }
4780
4781         bled = 0;
4782
4783         if (!dead && creature == wolftype) {
4784             award_bonus(0, Wolfbonus);
4785         }
4786
4787         if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4788             award_bonus(id, touchofdeath);
4789         if (id != 0 && unconscioustime > .1) {
4790             numafterkill++;
4791         }
4792
4793         dead = 2;
4794
4795         skeleton.free = 1;
4796
4797         emit_sound_at(breaksound, coords);
4798     }
4799
4800     if (skeleton.free == 1) {
4801         if (id == 0)
4802             pause_sound(whooshsound);
4803
4804         if (!dead) {
4805             //If knocked over, open hands and close mouth
4806             if (righthandmorphend != 0)
4807                 righthandmorphness = 0;
4808             righthandmorphend = 0;
4809             targetrighthandmorphness = 1;
4810
4811             if (lefthandmorphend != 0)
4812                 lefthandmorphness = 0;
4813             lefthandmorphend = 0;
4814             targetlefthandmorphness = 1;
4815
4816             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4817                 if (headmorphend != 0)
4818                     headmorphness = 0;
4819                 headmorphend = 0;
4820                 targetheadmorphness = 1;
4821             }
4822         }
4823
4824         skeleton.DoGravity(&scale);
4825         float damageamount;
4826         damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4827         if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4828             award_bonus(id, deepimpact);
4829         DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4830
4831         average = 0;
4832         howmany = 0;
4833         for (j = 0; j < skeleton.num_joints; j++) {
4834             average += skeleton.joints[j].position;
4835             howmany++;
4836         }
4837         average /= howmany;
4838         coords += average * scale;
4839         for (j = 0; j < skeleton.num_joints; j++) {
4840             skeleton.joints[j].position -= average;
4841         }
4842         average /= multiplier;
4843
4844         //velocity=jointVel(groin)*scale;
4845         velocity = 0;
4846         for (int i = 0; i < skeleton.num_joints; i++) {
4847             velocity += skeleton.joints[i].velocity * scale;
4848         }
4849         velocity /= skeleton.num_joints;
4850
4851         if (!isnormal(velocity.x) && velocity.x) {
4852             velocity = 0;
4853         }
4854
4855         if (findLength(&average) < 10 && dead && skeleton.free) {
4856             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4857             if (skeleton.longdead > 2000) {
4858                 if (skeleton.longdead > 6000) {
4859                     if (id == 0)
4860                         pause_sound(whooshsound);
4861                     skeleton.free = 3;
4862                     DrawSkeleton();
4863                     skeleton.free = 2;
4864                 }
4865                 if (dead == 2 && bloodloss < damagetolerance) {
4866                     XYZ headpoint;
4867                     headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4868                     DoBlood(1, 255);
4869                     if (bloodtoggle && !bled) {
4870                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4871                     }
4872                     if (bloodtoggle && !bled)
4873                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4874                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4875                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4876                             float size = .2 * 1.2;
4877                             float opacity = .6;
4878                             float yaw = 0;
4879                             objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4880                         }
4881                     bled = 1;
4882                 }
4883                 if (dead == 2 && bloodloss >= damagetolerance) {
4884                     XYZ headpoint;
4885                     headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4886                     if (bleeding <= 0)
4887                         DoBlood(1, 255);
4888                     if (bloodtoggle && !bled) {
4889                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4890                     }
4891                     if (bloodtoggle && !bled)
4892                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4893                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4894                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4895                             float size = .8;
4896                             float opacity = .6;
4897                             float yaw = 0;
4898                             objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4899                         }
4900                     bled = 1;
4901                 }
4902             }
4903         }
4904
4905         if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4906             bool canrecover = 1;
4907             XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4908             startpoint = coords;
4909             endpoint = coords;
4910             endpoint.y -= .7;
4911             if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4912                 canrecover = 0;
4913             if (velocity.y < -30)
4914                 canrecover = 0;
4915             for (i = 0; i < objects.numobjects; i++) {
4916                 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4917                     colviewer = startpoint;
4918                     coltarget = endpoint;
4919                     if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4920                         canrecover = 0;
4921                 }
4922             }
4923             if (canrecover) {
4924                 skeleton.free = 0;
4925                 XYZ middle;
4926                 middle = 0;
4927
4928                 terrainnormal = jointPos(groin) - jointPos(abdomen);
4929                 if (joint(groin).locked && joint(abdomen).locked) {
4930                     terrainnormal = jointPos(groin) - jointPos(abdomen);
4931                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4932                 }
4933                 if (joint(abdomen).locked && joint(neck).locked) {
4934                     terrainnormal = jointPos(abdomen) - jointPos(neck);
4935                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4936                 }
4937                 if (joint(groin).locked && joint(neck).locked) {
4938                     terrainnormal = jointPos(groin) - jointPos(neck);
4939                     middle = (jointPos(groin) + jointPos(neck)) / 2;
4940                 }
4941                 Normalise(&terrainnormal);
4942
4943                 targetyaw = -asin(0 - terrainnormal.x);
4944                 targetyaw *= 360 / 6.28;
4945                 if (terrainnormal.z < 0)
4946                     targetyaw = 180 - targetyaw;
4947                 yaw = targetyaw;
4948
4949                 frameTarget = 0;
4950                 animTarget = flipanim;
4951                 crouchtogglekeydown = 1;
4952                 target = 0;
4953                 tilt2 = 0;
4954                 targettilt2 = 0;
4955
4956                 animCurrent = tempanim;
4957                 frameCurrent = 0;
4958                 target = 0;
4959
4960                 for (int i = 0; i < skeleton.num_joints; i++) {
4961                     tempanimation.position[i][0] = skeleton.joints[i].position;
4962                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4963                 }
4964             }
4965         }
4966
4967         if (findLength(&average) < 10 && !dead && skeleton.free) {
4968             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4969             if (skeleton.longdead > (damage + 500) * 1.5) {
4970                 if (id == 0)
4971                     pause_sound(whooshsound);
4972                 skeleton.free = 0;
4973                 velocity = 0;
4974                 XYZ middle;
4975                 middle = 0;
4976
4977                 terrainnormal = jointPos(groin) - jointPos(abdomen);
4978                 if (joint(groin).locked && joint(abdomen).locked) {
4979                     terrainnormal = jointPos(groin) - jointPos(abdomen);
4980                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4981                 }
4982                 if (joint(abdomen).locked && joint(neck).locked) {
4983                     terrainnormal = jointPos(abdomen) - jointPos(neck);
4984                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4985                 }
4986                 if (joint(groin).locked && joint(neck).locked) {
4987                     terrainnormal = jointPos(groin) - jointPos(neck);
4988                     middle = (jointPos(groin) + jointPos(neck)) / 2;
4989                 }
4990                 Normalise(&terrainnormal);
4991
4992                 targetyaw = -asin(0 - terrainnormal.x);
4993                 targetyaw *= 360 / 6.28;
4994                 if (terrainnormal.z < 0)
4995                     targetyaw = 180 - targetyaw;
4996                 yaw = targetyaw;
4997
4998                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
4999
5000
5001                 if (skeleton.forward.y < 0) {
5002                     animTarget = getupfrombackanim;
5003                     frameTarget = 0;
5004                     targettilt2 = 0;
5005                 }
5006                 if (skeleton.forward.y > -.3) {
5007                     animTarget = getupfromfrontanim;
5008                     yaw += 180;
5009                     targetyaw += 180;
5010                     targettilt2 *= -1;
5011                     frameTarget = 0;
5012                     targettilt2 = 0;
5013                 }
5014
5015                 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5016                     animTarget = rollanim;
5017                     targetyaw = lookyaw;
5018                     if (id == 0) {
5019                         if (rightkeydown) {
5020                             targetyaw -= 90;
5021                             if (forwardkeydown)
5022                                 targetyaw += 45;
5023                             if (backkeydown)
5024                                 targetyaw -= 45;
5025                         }
5026                         if (leftkeydown) {
5027                             targetyaw += 90;
5028                             if (forwardkeydown)
5029                                 targetyaw -= 45;
5030                             if (backkeydown)
5031                                 targetyaw += 45;
5032                         }
5033                         if (backkeydown) {
5034                             if ( !leftkeydown && !rightkeydown)
5035                                 targetyaw += 180;
5036                         }
5037                         targetyaw += 180;
5038                     }
5039                 }
5040
5041                 if (abs(targettilt2) > 50)
5042                     targettilt2 = 0;
5043                 animCurrent = tempanim;
5044                 frameCurrent = 0;
5045                 target = 0;
5046                 tilt2 = targettilt2;
5047
5048                 if (middle.y > 0 && animTarget != rollanim)
5049                     targetoffset.y = middle.y + 1;
5050
5051                 for (int i = 0; i < skeleton.num_joints; i++) {
5052                     tempanimation.position[i][0] = skeleton.joints[i].position;
5053                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5054                 }
5055             }
5056         }
5057
5058         bool hasstaff;
5059         hasstaff = 0;
5060         if (num_weapons > 0)
5061             if (weapons[0].getType() == staff)
5062                 hasstaff = 1;
5063         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5064             if (velocity.y > -30) {
5065                 XYZ tempvelocity;
5066                 tempvelocity = velocity;
5067                 Normalise(&tempvelocity);
5068                 targetyaw = -asin(0 - tempvelocity.x);
5069                 targetyaw *= 360 / 6.28;
5070                 if (velocity.z < 0)
5071                     targetyaw = 180 - targetyaw;
5072                 //targetyaw+=180;
5073
5074                 skeleton.free = 0;
5075                 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5076                     animTarget = rollanim;
5077                     frameTarget = 2;
5078                 } else {
5079                     animTarget = backhandspringanim;
5080                     targetyaw += 180;
5081                     frameTarget = 6;
5082                 }
5083                 target = 0;
5084
5085                 emit_sound_at(movewhooshsound, coords, 128.);
5086
5087                 animCurrent = animTarget;
5088                 frameCurrent = frameTarget - 1;
5089                 target = 0;
5090
5091                 velocity = 0;
5092
5093                 yaw = targetyaw;
5094                 tilt = 0;
5095                 targettilt = 0;
5096                 tilt2 = 0;
5097                 targettilt2 = 0;
5098             }
5099         }
5100         if (skeleton.freefall == 0)
5101             freefall = 0;
5102
5103     }
5104
5105     if (aitype != passivetype || skeleton.free == 1)
5106         if (findLengthfast(&velocity) > .1)
5107             for (i = 0; i < objects.numobjects; i++) {
5108                 if (objects.type[i] == firetype)
5109                     if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5110                         if (onfire) {
5111                             if (!objects.onfire[i]) {
5112                                 emit_sound_at(firestartsound, objects.position[i]);
5113                             }
5114                             objects.onfire[i] = 1;
5115                         }
5116                         if (!onfire) {
5117                             if (objects.onfire[i]) {
5118                                 CatchFire();
5119                             }
5120                         }
5121                     }
5122                 if (objects.type[i] == bushtype)
5123                     if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5124                         if (onfire) {
5125                             if (!objects.onfire[i]) {
5126                                 emit_sound_at(firestartsound, objects.position[i]);
5127                             }
5128                             objects.onfire[i] = 1;
5129                         }
5130
5131                         if (!onfire) {
5132                             if (objects.onfire[i]) {
5133                                 CatchFire();
5134                             }
5135                         }
5136                         if (objects.messedwith[i] <= 0) {
5137                             XYZ tempvel;
5138                             XYZ pos;
5139
5140                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5141
5142                             if (id == 0) {
5143                                 envsound[numenvsounds] = coords;
5144                                 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5145                                 envsoundlife[numenvsounds] = .4;
5146                                 numenvsounds++;
5147                             }
5148
5149                             int howmany;
5150                             if (environment == grassyenvironment)
5151                                 howmany = findLength(&velocity) * 4;
5152                             if (environment == snowyenvironment)
5153                                 howmany = findLength(&velocity) * 2;
5154                             if (detail == 2)
5155                                 if (environment != desertenvironment)
5156                                     for (j = 0; j < howmany; j++) {
5157                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5158                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5159                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5160                                         pos = coords;
5161                                         pos.y += 1;
5162                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5163                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5164                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5165                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .5 + velocity * float(abs(Random() % 100)) / 100, 165 / 255 + float(abs(Random() % 100) - 50) / 400, 0, 0, .2 + float(abs(Random() % 100) - 50) / 1300, 1);
5166                                         Sprite::setLastSpriteSpecial(1);
5167                                     }
5168                             howmany = findLength(&velocity) * 4;
5169                             if (detail == 2)
5170                                 if (environment == snowyenvironment)
5171                                     for (j = 0; j < howmany; j++) {
5172                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5173                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5174                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5175                                         pos = coords;
5176                                         pos.y += 1;
5177                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5178                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5179                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5180                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5181                                         Sprite::setLastSpriteSpecial(2);
5182                                     }
5183                         }
5184                         objects.rotx[i] += velocity.x * multiplier * 6;
5185                         objects.roty[i] += velocity.z * multiplier * 6;
5186                         objects.messedwith[i] = .5;
5187                     }
5188                 XYZ tempcoord;
5189                 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5190                     if (objects.pitch[i] == 0)
5191                         tempcoord = coords;
5192                     else {
5193                         tempcoord = coords - objects.position[i];
5194                         tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5195                         tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5196                         tempcoord += objects.position[i];
5197                     }
5198                     if (distsqflat(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 8 && distsq(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 300 && tempcoord.y > objects.position[i].y + 3 * objects.scale[i]) {
5199                         if (objects.messedwith[i] <= 0) {
5200                             XYZ tempvel;
5201                             XYZ pos;
5202
5203                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5204
5205                             if (id == 0) {
5206                                 envsound[numenvsounds] = coords;
5207                                 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5208                                 envsoundlife[numenvsounds] = .4;
5209                                 numenvsounds++;
5210                             }
5211
5212                             int howmany;
5213                             if (environment == grassyenvironment)
5214                                 howmany = findLength(&velocity) * 4;
5215                             if (environment == snowyenvironment)
5216                                 howmany = findLength(&velocity) * 2;
5217                             if (detail == 2)
5218                                 if (environment != desertenvironment)
5219                                     for (j = 0; j < howmany; j++) {
5220                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5221                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5222                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5223                                         pos = coords;
5224                                         pos += velocity * .1;
5225                                         pos.y += 1;
5226                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5227                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5228                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5229                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .5 + velocity * float(abs(Random() % 100)) / 100, 165 / 255 + float(abs(Random() % 100) - 50) / 400, 0, 0, .2 + float(abs(Random() % 100) - 50) / 1300, 1);
5230                                         Sprite::setLastSpriteSpecial(1);
5231                                     }
5232                             howmany = findLength(&velocity) * 4;
5233                             if (detail == 2)
5234                                 if (environment == snowyenvironment)
5235                                     for (j = 0; j < howmany; j++) {
5236                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5237                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5238                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5239                                         pos = coords;
5240                                         pos += velocity * .1;
5241                                         pos.y += 1;
5242                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5243                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5244                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5245                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5246                                         Sprite::setLastSpriteSpecial(2);
5247                                     }
5248                         }
5249                         objects.messedwith[i] = .5;
5250                     }
5251                 }
5252             }
5253
5254     if (!skeleton.free) {
5255         bool play;
5256         play = 0;
5257         if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5258             play = 1;
5259         if (hasvictim)
5260             if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5261                 play = 1;
5262         if (tutoriallevel == 1 && id != 0)
5263             play = 0;
5264         if (play && aitype != playercontrolled) {
5265             int whichsound = -1;
5266             i = abs(Random() % 4);
5267             if (speechdelay <= 0) {
5268                 if (creature == rabbittype) {
5269                     if (i == 0)
5270                         whichsound = rabbitchitter;
5271                     if (i == 1)
5272                         whichsound = rabbitchitter2;
5273                 }
5274                 if (creature == wolftype) {
5275                     if (i == 0)
5276                         whichsound = growlsound;
5277                     if (i == 1)
5278                         whichsound = growl2sound;
5279                 }
5280             }
5281             speechdelay = .3;
5282
5283             if (whichsound != -1) {
5284                 emit_sound_at(whichsound, coords);
5285             }
5286         }
5287
5288         if (animTarget == staggerbackhighanim)
5289             staggerdelay = 1;
5290         if (animTarget == staggerbackhardanim)
5291             staggerdelay = 1;
5292         staggerdelay -= multiplier;
5293         if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5294             hasvictim = 1;
5295         if (velocity.y < -30 && animTarget == jumpdownanim)
5296             RagDoll(0);
5297         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5298             animTarget = getIdle();
5299             frameTarget = 0;
5300             target = 0;
5301         }
5302         weaponmissdelay -= multiplier;
5303         highreversaldelay -= multiplier;
5304         lowreversaldelay -= multiplier;
5305         lastcollide -= multiplier;
5306         skiddelay -= multiplier;
5307         if (!isnormal(velocity.x) && velocity.x) {
5308             velocity = 0;
5309         }
5310         if (!isnormal(targettilt) && targettilt) {
5311             targettilt = 0;
5312         }
5313         if (!isnormal(targettilt2) && targettilt2) {
5314             targettilt2 = 0;
5315         }
5316         if (!isnormal(targetyaw) && targetyaw) {
5317             targetyaw = 0;
5318         }
5319
5320         if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5321             //open hands and close mouth
5322             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5323                 righthandmorphness = 0;
5324                 righthandmorphend = 0;
5325                 targetrighthandmorphness = 1;
5326             }
5327
5328             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5329                 lefthandmorphness = 0;
5330                 lefthandmorphend = 0;
5331                 targetlefthandmorphness = 1;
5332             }
5333
5334             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5335                 headmorphness = 0;
5336                 headmorphend = 0;
5337                 targetheadmorphness = 1;
5338             }
5339         }
5340
5341         if (animTarget == rollanim || animTarget == dodgebackanim || animTarget == removeknifeanim || animTarget == knifefightidleanim || animTarget == swordfightidleanim || animTarget == blockhighleftstrikeanim || animTarget == crouchremoveknifeanim || animTarget == sneakanim || animTarget == sweepanim || animTarget == spinkickreversedanim || animTarget == jumpdownanim || isWallJump() || isFlip() || animTarget == climbanim || isRun() || animTarget == getupfrombackanim || animTarget == getupfromfrontanim) {
5342             //open hands and mouth
5343             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5344                 righthandmorphness = 0;
5345                 righthandmorphend = 0;
5346                 targetrighthandmorphness = 1;
5347             }
5348
5349             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5350                 lefthandmorphness = 0;
5351                 lefthandmorphend = 0;
5352                 targetlefthandmorphness = 1;
5353             }
5354
5355             if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5356                 headmorphness = 0;
5357                 headmorphend = 1;
5358                 targetheadmorphness = 1;
5359             }
5360         }
5361
5362         if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5363             //close hands and mouth
5364             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5365                 righthandmorphness = 0;
5366                 righthandmorphend = 1;
5367                 targetrighthandmorphness = 1;
5368             }
5369
5370             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5371                 lefthandmorphness = 0;
5372                 lefthandmorphend = 1;
5373                 targetlefthandmorphness = 1;
5374             }
5375
5376             if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5377                 headmorphness = 0;
5378                 headmorphend = 0;
5379                 targetheadmorphness = 1;
5380             }
5381         }
5382
5383         if (animTarget == spinkickanim || animTarget == staffspinhitreversalanim || animTarget == staffspinhitreversedanim || animTarget == staffhitreversalanim || animTarget == staffhitreversedanim || animTarget == hurtidleanim || animTarget == winduppunchanim || animTarget == swordslashreversalanim || animTarget == swordslashreversedanim || animTarget == knifeslashreversalanim || animTarget == knifeslashreversedanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == knifefollowedanim || animTarget == killanim || animTarget == dropkickanim || animTarget == upunchanim || animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim || animTarget == staffgroundsmashanim || animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == lowkickanim || animTarget == sweepreversedanim || animTarget == rabbitkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversalanim || animTarget == jumpreversedanim) {
5384             //close hands and yell
5385             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5386                 righthandmorphness = 0;
5387                 righthandmorphend = 1;
5388                 targetrighthandmorphness = 1;
5389             }
5390
5391             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5392                 lefthandmorphness = 0;
5393                 lefthandmorphend = 1;
5394                 targetlefthandmorphness = 1;
5395             }
5396
5397             if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5398                 headmorphness = 1;
5399                 headmorphend = 2;
5400                 targetheadmorphness = 1;
5401             }
5402         }
5403
5404         bool behind;
5405         behind = 0;
5406         if (hasvictim) {
5407             if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5408                 (victim->aitype != searchtype) && (aitype != passivetype) &&
5409                 (aitype != searchtype) && (victim->id < Person::players.size()) && (aitype != passivetype)) {
5410                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5411             }
5412         }
5413
5414         if (!dead && animTarget != hurtidleanim)
5415             if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5416                 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5417                     headmorphend = 4;
5418                     //headmorphness=1;
5419                     targetheadmorphness = 1;
5420                 }
5421             }
5422
5423         if (weaponactive != -1) {
5424             if (weapons[weaponids[weaponactive]].getType() != staff) {
5425                 righthandmorphstart = 1;
5426                 righthandmorphend = 1;
5427             }
5428             if (weapons[weaponids[weaponactive]].getType() == staff) {
5429                 righthandmorphstart = 2;
5430                 righthandmorphend = 2;
5431             }
5432             targetrighthandmorphness = 1;
5433         }
5434
5435         terrainnormal = terrain.getNormal(coords.x, coords.z);
5436
5437         if (animation[animTarget].attack != reversal) {
5438             if (!isnormal(coords.x))
5439                 coords = oldcoords;
5440             oldcoords = coords;
5441         }
5442
5443         flatfacing = 0;
5444         flatfacing.z = 1;
5445
5446         flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5447         facing = flatfacing;
5448         ReflectVector(&facing, terrainnormal);
5449         Normalise(&facing);
5450
5451         if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5452             if (onterrain)
5453                 targettilt2 = -facing.y * 20;
5454             else
5455                 targettilt2 = 0;
5456         }
5457         onterrain = 0;
5458         if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5459             targettilt2 = 0;
5460         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5461             flatvelocity = velocity;
5462             flatvelocity.y = 0;
5463             flatvelspeed = findLength(&flatvelocity);
5464             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5465             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5466             if (velocity.y < 0)
5467                 targettilt2 *= -1;
5468             if (velocity.y < 0)
5469                 targettilt *= -1;
5470             if (targettilt > 25)
5471                 targettilt = 25;
5472             if (targettilt < -25)
5473                 targettilt = -25;
5474         }
5475
5476         if (targettilt2 > 45)
5477             targettilt2 = 45;
5478         if (targettilt2 < -45)
5479             targettilt2 = -45;
5480         if (abs(tilt2 - targettilt2) < multiplier * 400)
5481             tilt2 = targettilt2;
5482         else if (tilt2 > targettilt2) {
5483             tilt2 -= multiplier * 400;
5484         } else if (tilt2 < targettilt2) {
5485             tilt2 += multiplier * 400;
5486         }
5487         if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5488             if (tilt2 > 25)
5489                 tilt2 = 25;
5490             if (tilt2 < -25)
5491                 tilt2 = -25;
5492         }
5493
5494         if (!isnormal(targettilt) && targettilt) {
5495             targettilt = 0;
5496         }
5497         if (!isnormal(targettilt2) && targettilt2) {
5498             targettilt2 = 0;
5499         }
5500
5501         //Running velocity
5502         if (animTarget == rabbittackleanim) {
5503             velocity += facing * multiplier * speed * 700 * scale;
5504             velspeed = findLength(&velocity);
5505             if (velspeed > speed * 65 * scale) {
5506                 velocity /= velspeed;
5507                 velspeed = speed * 65 * scale;
5508                 velocity *= velspeed;
5509             }
5510             velocity.y += gravity * multiplier * 20;
5511             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5512             velspeed = findLength(&velocity);
5513             velocity = flatfacing * velspeed;
5514         }
5515         if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5516             if (isRun() || animTarget == rabbitkickanim) {
5517                 velocity += facing * multiplier * speed * 700 * scale;
5518                 velspeed = findLength(&velocity);
5519                 if (velspeed > speed * 45 * scale) {
5520                     velocity /= velspeed;
5521                     velspeed = speed * 45 * scale;
5522                     velocity *= velspeed;
5523                 }
5524                 velocity.y += gravity * multiplier * 20;
5525                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5526                 velspeed = findLength(&velocity);
5527                 if (velspeed < speed * 30 * scale)
5528                     velspeed = speed * 30 * scale;
5529                 velocity = flatfacing * velspeed;
5530             }
5531         } else if (isRun()) {
5532             velocity += facing * multiplier * speed * 700 * scale;
5533             velspeed = findLength(&velocity);
5534             if (creature == rabbittype) {
5535                 if (velspeed > speed * 55 * scale) {
5536                     velocity /= velspeed;
5537                     velspeed = speed * 55 * scale;
5538                     velocity *= velspeed;
5539                 }
5540             }
5541             if (creature == wolftype) {
5542                 if (velspeed > speed * 75 * scale) {
5543                     velocity /= velspeed;
5544                     velspeed = speed * 75 * scale;
5545                     velocity *= velspeed;
5546                 }
5547             }
5548             velocity.y += gravity * multiplier * 20;
5549             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5550             velspeed = findLength(&velocity);
5551             velocity = flatfacing * velspeed;
5552         }
5553
5554         if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5555             velocity += facing * multiplier * speed * 700 * scale;
5556             velspeed = findLength(&velocity);
5557             if (velspeed > speed * 45 * scale) {
5558                 velocity /= velspeed;
5559                 velspeed = speed * 45 * scale;
5560                 velocity *= velspeed;
5561             }
5562             velocity.y += gravity * multiplier * 20;
5563             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5564             velspeed = findLength(&velocity);
5565             velocity = flatfacing * velspeed;
5566         }
5567
5568         if (animTarget == sneakanim || animTarget == walkanim) {
5569             velocity += facing * multiplier * speed * 700 * scale;
5570             velspeed = findLength(&velocity);
5571             if (velspeed > speed * 12 * scale) {
5572                 velocity /= velspeed;
5573                 velspeed = speed * 12 * scale;
5574                 velocity *= velspeed;
5575             }
5576             velocity.y += gravity * multiplier * 20;
5577             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5578             velspeed = findLength(&velocity);
5579             velocity = flatfacing * velspeed;
5580         }
5581
5582         if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5583             velocity += facing * multiplier * speed * 700 * scale;
5584             velspeed = findLength(&velocity);
5585             if (velspeed > speed * 2 * scale) {
5586                 velocity /= velspeed;
5587                 velspeed = speed * 2 * scale;
5588                 velocity *= velspeed;
5589             }
5590             velocity.y += gravity * multiplier * 20;
5591             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5592             velspeed = findLength(&velocity);
5593             velocity = flatfacing * velspeed;
5594         }
5595
5596
5597         if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5598             velocity -= facing * multiplier * speed * 700 * scale;
5599             velspeed = findLength(&velocity);
5600             if (velspeed > speed * 2 * scale) {
5601                 velocity /= velspeed;
5602                 velspeed = speed * 2 * scale;
5603                 velocity *= velspeed;
5604             }
5605             velocity.y += gravity * multiplier * 20;
5606             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5607             velspeed = findLength(&velocity);
5608             velocity = flatfacing * velspeed * -1;
5609         }
5610
5611         if (animTarget == fightsidestep) {
5612             velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5613             velspeed = findLength(&velocity);
5614             if (velspeed > speed * 12 * scale) {
5615                 velocity /= velspeed;
5616                 velspeed = speed * 12 * scale;
5617                 velocity *= velspeed;
5618             }
5619             velocity.y += gravity * multiplier * 20;
5620             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5621             velspeed = findLength(&velocity);
5622             velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5623         }
5624
5625         if (animTarget == staggerbackhighanim) {
5626             coords -= facing * multiplier * speed * 16 * scale;
5627             velocity = 0;
5628         }
5629         if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5630             coords -= facing * multiplier * speed * 20 * scale;
5631             velocity = 0;
5632         }
5633
5634         if (animTarget == backhandspringanim) {
5635             //coords-=facing*multiplier*50*scale;
5636             velocity += facing * multiplier * speed * 700 * scale * -1;
5637             velspeed = findLength(&velocity);
5638             if (velspeed > speed * 50 * scale) {
5639                 velocity /= velspeed;
5640                 velspeed = speed * 50 * scale;
5641                 velocity *= velspeed;
5642             }
5643             velocity.y += gravity * multiplier * 20;
5644             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5645             velspeed = findLength(&velocity);
5646             velocity = flatfacing * velspeed * -1;
5647         }
5648         if (animTarget == dodgebackanim) {
5649             //coords-=facing*multiplier*50*scale;
5650             velocity += facing * multiplier * speed * 700 * scale * -1;
5651             velspeed = findLength(&velocity);
5652             if (velspeed > speed * 60 * scale) {
5653                 velocity /= velspeed;
5654                 velspeed = speed * 60 * scale;
5655                 velocity *= velspeed;
5656             }
5657             velocity.y += gravity * multiplier * 20;
5658             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5659             velspeed = findLength(&velocity);
5660             velocity = flatfacing * velspeed * -1;
5661         }
5662
5663         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5664             velspeed = findLength(&velocity);
5665         }
5666
5667
5668         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5669             velocity.y += gravity * multiplier;
5670         }
5671
5672         if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5673             coords += velocity * multiplier;
5674
5675         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5676             if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5677                 RagDoll(0);
5678
5679             if (animTarget == jumpupanim) {
5680                 jumppower = -4;
5681                 animTarget = getIdle();
5682             }
5683             target = 0;
5684             frameTarget = 0;
5685             onterrain = 1;
5686
5687             if (id == 0) {
5688                 pause_sound(whooshsound);
5689                 OPENAL_SetVolume(channels[whooshsound], 0);
5690             }
5691
5692             if (animTarget == jumpdownanim || isFlip()) {
5693                 if (isFlip())jumppower = -4;
5694                 animTarget = getLanding();
5695                 emit_sound_at(landsound, coords, 128.);
5696
5697                 if (id == 0) {
5698                     envsound[numenvsounds] = coords;
5699                     envsoundvol[numenvsounds] = 16;
5700                     envsoundlife[numenvsounds] = .4;
5701                     numenvsounds++;
5702                 }
5703             }
5704         }
5705
5706         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5707             coords.y += gravity * multiplier * 2;
5708         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5709             coords.y = terrain.getHeight(coords.x, coords.z);
5710             onterrain = 1;
5711         }
5712
5713
5714         if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || animation[animTarget].attack || (animTarget == rollanim && animation[animTarget].label[frameTarget] == 6)) {
5715             velspeed = findLength(&velocity);
5716             velocity.y = 0;
5717             if (velspeed < multiplier * 300 * scale) {
5718                 velocity = 0;
5719             } else
5720                 velocity -= velocity / velspeed * multiplier * 300 * scale;
5721             if (velspeed > 5 && (isLanding() || isLandhard())) {
5722                 skiddingdelay += multiplier;
5723                 if (skiddelay <= 0) {
5724                     FootLand(0, .5);
5725                     FootLand(1, .5);
5726                     skiddelay = .02;
5727                 }
5728             } else
5729                 skiddingdelay = 0;
5730         }
5731
5732         if (isLandhard()) {
5733             velspeed = findLength(&velocity);
5734             velocity.y = 0;
5735             if (velspeed < multiplier * 600 * scale) {
5736                 velocity = 0;
5737             } else
5738                 velocity -= velocity / velspeed * multiplier * 600 * scale;
5739             velocity = 0;
5740             if (velspeed > 5 && (isLanding() || isLandhard())) {
5741                 skiddingdelay += multiplier;
5742                 if (skiddelay <= 0) {
5743                     FootLand(0, .5);
5744                     FootLand(1, .5);
5745                     skiddelay = .02;
5746                 }
5747             } else
5748                 skiddingdelay = 0;
5749         }
5750
5751         if (skiddingdelay < 0)
5752             skiddingdelay += multiplier;
5753         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5754             skiddingdelay = -1;
5755             if (!onterrain || environment == grassyenvironment) {
5756                 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5757             } else {
5758                 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5759             }
5760         }
5761
5762         if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5763             terrainnormal = victim->coords - coords;
5764             Normalise(&terrainnormal);
5765             targetyaw = -asin(0 - terrainnormal.x);
5766             targetyaw *= 360 / 6.28;
5767             if (terrainnormal.z < 0)
5768                 targetyaw = 180 - targetyaw;
5769             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5770         }
5771
5772         if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5773             targetyaw = victim->targetyaw;
5774         }
5775         if (animTarget == rabbittacklinganim) {
5776             coords = victim->coords;
5777         }
5778     }
5779     skeleton.oldfree = skeleton.free;
5780
5781     XYZ midterrain;
5782     midterrain = 0;
5783     midterrain.x = terrain.size * terrain.scale / 2;
5784     midterrain.z = terrain.size * terrain.scale / 2;
5785     if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5786         XYZ tempposit;
5787         tempposit = coords - midterrain;
5788         tempposit.y = 0;
5789         Normalise(&tempposit);
5790         tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5791         coords.x = tempposit.x + midterrain.x;
5792         coords.z = tempposit.z + midterrain.z;
5793     }
5794 }
5795
5796
5797 /* EFFECT
5798  * inverse kinematics helper function
5799  */
5800 void IKHelper(Person *p, float interp)
5801 {
5802     XYZ point, newpoint, change, change2;
5803     float heightleft, heightright;
5804
5805     // TODO: implement localToWorld and worldToLocal
5806     //       but keep in mind it won't be the same math if player is ragdolled or something
5807     //       - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5808     //       then comb through code for places where to use it
5809
5810     // point = localToWorld(jointPos(leftfoot))
5811     point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5812     // adjust height of foot
5813     heightleft = terrain.getHeight(point.x, point.z) + .04;
5814     point.y = heightleft;
5815     change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5816     change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5817     // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5818     p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5819     // move ankle along with foot
5820     p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5821     // average knee pos between old and new pos
5822     p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5823
5824     // do same as above for right leg
5825     point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5826     heightright = terrain.getHeight(point.x, point.z) + .04;
5827     point.y = heightright;
5828     change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5829     change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5830     p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5831     p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5832     p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5833
5834     // fix up skeleton now that we've moved body parts?
5835     p->skeleton.DoConstraints(&p->coords, &p->scale);
5836 }
5837
5838 /* EFFECT
5839  * MONSTER
5840  * TODO: ???
5841  */
5842 int Person::DrawSkeleton()
5843 {
5844     int oldplayerdetail;
5845     if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5846         if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5847             calcrot = 1;
5848         }
5849
5850         if (headless) {
5851             headmorphness = 0;
5852             headmorphstart = 6;
5853             headmorphend = 6;
5854         }
5855
5856         glAlphaFunc(GL_GREATER, 0.0001);
5857         XYZ terrainlight;
5858         float terrainheight;
5859         float distance;
5860         if (!isnormal(yaw))
5861             yaw = 0;
5862         if (!isnormal(tilt))
5863             tilt = 0;
5864         if (!isnormal(tilt2))
5865             tilt2 = 0;
5866         oldplayerdetail = playerdetail;
5867         playerdetail = 0;
5868         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5869             playerdetail = 1;
5870         }
5871         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5872             playerdetail = 1;
5873         }
5874         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5875             playerdetail = 1;
5876         }
5877         if (id == 0)
5878             playerdetail = 1;
5879         if (playerdetail != oldplayerdetail) {
5880             updatedelay = 0;
5881             normalsupdatedelay = 0;
5882         }
5883         static float updatedelaychange;
5884         static float morphness;
5885         static float framemult;
5886         if (calcrot) {
5887             skeleton.FindForwards();
5888             if (howactive == typesittingwall) {
5889                 skeleton.specialforward[1] = 0;
5890                 skeleton.specialforward[1].z = 1;
5891             }
5892         }
5893         static XYZ mid;
5894         static float M[16];
5895         static int i, j, k;
5896         static int weaponattachmuscle;
5897         static int weaponrotatemuscle;
5898         static XYZ weaponpoint;
5899         static int start, endthing;
5900         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5901             if (!isSleeping() && !isSitting()) {
5902                 // TODO: give these meaningful names
5903                 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5904                                     || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5905                 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5906                                     || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5907
5908                 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5909                     IKHelper(this, 1);
5910                     if (creature == wolftype)
5911                         IKHelper(this, 1);
5912                 }
5913
5914                 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5915                     IKHelper(this, target);
5916                     if (creature == wolftype)
5917                         IKHelper(this, target);
5918                 }
5919
5920                 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5921                     IKHelper(this, 1 - target);
5922                     if (creature == wolftype)
5923                         IKHelper(this, 1 - target);
5924                 }
5925             }
5926
5927             if (!skeleton.free && (!animation[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || animation[animTarget].label[frameTarget] == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
5928                 DoHead();
5929             else {
5930                 targetheadyaw = -targetyaw;
5931                 targetheadpitch = 0;
5932                 if (animation[animTarget].attack == 3)
5933                     targetheadyaw += 180;
5934             }
5935             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5936                 skeleton.drawmodel.vertex[i] = 0;
5937                 skeleton.drawmodel.vertex[i].y = 999;
5938             }
5939             for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5940                 skeleton.drawmodellow.vertex[i] = 0;
5941                 skeleton.drawmodellow.vertex[i].y = 999;
5942             }
5943             for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5944                 skeleton.drawmodelclothes.vertex[i] = 0;
5945                 skeleton.drawmodelclothes.vertex[i].y = 999;
5946             }
5947             for (int i = 0; i < skeleton.num_muscles; i++) {
5948                 // convenience renames
5949                 const int p1 = skeleton.muscles[i].parent1->label;
5950                 const int p2 = skeleton.muscles[i].parent2->label;
5951
5952                 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
5953                     morphness = 0;
5954                     start = 0;
5955                     endthing = 0;
5956
5957                     if (p1 == righthand || p2 == righthand) {
5958                         morphness = righthandmorphness;
5959                         start = righthandmorphstart;
5960                         endthing = righthandmorphend;
5961                     }
5962                     if (p1 == lefthand || p2 == lefthand) {
5963                         morphness = lefthandmorphness;
5964                         start = lefthandmorphstart;
5965                         endthing = lefthandmorphend;
5966                     }
5967                     if (p1 == head || p2 == head) {
5968                         morphness = headmorphness;
5969                         start = headmorphstart;
5970                         endthing = headmorphend;
5971                     }
5972                     if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
5973                         morphness = chestmorphness;
5974                         start = chestmorphstart;
5975                         endthing = chestmorphend;
5976                     }
5977                     if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
5978                         morphness = tailmorphness;
5979                         start = tailmorphstart;
5980                         endthing = tailmorphend;
5981                     }
5982                     if (calcrot)
5983                         skeleton.FindRotationMuscle(i, animTarget);
5984                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5985                     glMatrixMode(GL_MODELVIEW);
5986                     glPushMatrix();
5987                     glLoadIdentity();
5988                     if (!skeleton.free)
5989                         glRotatef(tilt2, 1, 0, 0);
5990                     if (!skeleton.free)
5991                         glRotatef(tilt, 0, 0, 1);
5992
5993
5994                     glTranslatef(mid.x, mid.y, mid.z);
5995
5996                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5997                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5998
5999                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6000                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6001
6002                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6003                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6004
6005                     if (playerdetail || skeleton.free == 3) {
6006                         for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6007                             XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6008                             XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6009                             glMatrixMode(GL_MODELVIEW);
6010                             glPushMatrix();
6011                             if (p1 == abdomen || p2 == abdomen)
6012                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6013                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6014                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6015                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6016                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6017                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6018                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6019                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6020                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6021                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6022                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6023                             if (p1 == head || p2 == head)
6024                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6025                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6026                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6027                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6028                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6029                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6030                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6031                             glPopMatrix();
6032                         }
6033                     }
6034                     if (!playerdetail || skeleton.free == 3) {
6035                         for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6036                             XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6037                             glMatrixMode(GL_MODELVIEW);
6038                             glPushMatrix();
6039                             if (p1 == abdomen || p2 == abdomen)
6040                                 glTranslatef(v0.x * proportionbody.x,
6041                                              v0.y * proportionbody.y,
6042                                              v0.z * proportionbody.z);
6043                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6044                                 glTranslatef(v0.x * proportionarms.x,
6045                                              v0.y * proportionarms.y,
6046                                              v0.z * proportionarms.z);
6047                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6048                                 glTranslatef(v0.x * proportionlegs.x,
6049                                              v0.y * proportionlegs.y,
6050                                              v0.z * proportionlegs.z);
6051                             if (p1 == head || p2 == head)
6052                                 glTranslatef(v0.x * proportionhead.x,
6053                                              v0.y * proportionhead.y,
6054                                              v0.z * proportionhead.z);
6055
6056                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6057                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6058                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6059                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6060                             glPopMatrix();
6061                         }
6062                     }
6063                     glPopMatrix();
6064                 }
6065                 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6066                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6067
6068                     glMatrixMode(GL_MODELVIEW);
6069                     glPushMatrix();
6070                     glLoadIdentity();
6071                     if (!skeleton.free)
6072                         glRotatef(tilt2, 1, 0, 0);
6073                     if (!skeleton.free)
6074                         glRotatef(tilt, 0, 0, 1);
6075                     glTranslatef(mid.x, mid.y, mid.z);
6076                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6077                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6078
6079                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6080                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6081
6082                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6083                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6084
6085                     for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6086                         XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6087                         glMatrixMode(GL_MODELVIEW);
6088                         glPushMatrix();
6089                         if (p1 == abdomen || p2 == abdomen)
6090                             glTranslatef(v0.x * proportionbody.x,
6091                                          v0.y * proportionbody.y,
6092                                          v0.z * proportionbody.z);
6093                         if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6094                             glTranslatef(v0.x * proportionarms.x,
6095                                          v0.y * proportionarms.y,
6096                                          v0.z * proportionarms.z);
6097                         if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6098                             glTranslatef(v0.x * proportionlegs.x,
6099                                          v0.y * proportionlegs.y,
6100                                          v0.z * proportionlegs.z);
6101                         if (p1 == head || p2 == head)
6102                             glTranslatef(v0.x * proportionhead.x,
6103                                          v0.y * proportionhead.y,
6104                                          v0.z * proportionhead.z);
6105                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
6106                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6107                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6108                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6109                         glPopMatrix();
6110                     }
6111                     glPopMatrix();
6112                 }
6113                 updatedelay = 1 + (float)(Random() % 100) / 1000;
6114             }
6115             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6116                 normalsupdatedelay = 1;
6117                 if (playerdetail || skeleton.free == 3)
6118                     skeleton.drawmodel.CalculateNormals(0);
6119                 if (!playerdetail || skeleton.free == 3)
6120                     skeleton.drawmodellow.CalculateNormals(0);
6121                 if (skeleton.clothes)
6122                     skeleton.drawmodelclothes.CalculateNormals(0);
6123             } else {
6124                 if (playerdetail || skeleton.free == 3)
6125                     skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6126                 if (!playerdetail || skeleton.free == 3)
6127                     skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6128                 if (skeleton.clothes) {
6129                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6130                 }
6131             }
6132         }
6133         framemult = .01;
6134         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6135         if (updatedelaychange > -realmultiplier * 30)
6136             updatedelaychange = -realmultiplier * 30;
6137         if (updatedelaychange > -framemult * 4)
6138             updatedelaychange = -framemult * 4;
6139         if (skeleton.free == 1)
6140             updatedelaychange *= 6;
6141         if (id == 0)
6142             updatedelaychange *= 8;
6143         updatedelay += updatedelaychange;
6144
6145         glMatrixMode(GL_MODELVIEW);
6146         glPushMatrix();
6147         if (!skeleton.free)
6148             glTranslatef(coords.x, coords.y - .02, coords.z);
6149         if (skeleton.free)
6150             glTranslatef(coords.x, coords.y - .02, coords.z);
6151         if (!skeleton.free)
6152             glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6153         if (!skeleton.free)
6154             glRotatef(yaw, 0, 1, 0);
6155         if (showpoints) {
6156             glPointSize(5);
6157             glColor4f(.4, 1, .4, 1);
6158             glDisable(GL_LIGHTING);
6159             glDisable(GL_TEXTURE_2D);
6160             glBegin(GL_POINTS);
6161             if (playerdetail)
6162                 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6163                     XYZ &v0 = skeleton.drawmodel.vertex[i];
6164                     glVertex3f(v0.x, v0.y, v0.z);
6165                 }
6166             glEnd();
6167             glBegin(GL_LINES);
6168
6169             if (playerdetail)
6170                 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6171                     XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6172                     XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6173                     XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6174                     glVertex3f(v0.x, v0.y, v0.z);
6175                     glVertex3f(v1.x, v1.y, v1.z);
6176                     glVertex3f(v1.x, v1.y, v1.z);
6177                     glVertex3f(v2.x, v2.y, v2.z);
6178                     glVertex3f(v2.x, v2.y, v2.z);
6179                     glVertex3f(v0.x, v0.y, v0.z);
6180                 }
6181
6182             glEnd();
6183         }
6184
6185         terrainlight = terrain.getLighting(coords.x, coords.z);
6186         distance = distsq(&viewer, &coords);
6187         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6188         if (distance > 1)
6189             distance = 1;
6190         if (distance > 0) {
6191             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6192             if (terrainheight < 1)
6193                 terrainheight = 1;
6194             if (terrainheight > 1.7)
6195                 terrainheight = 1.7;
6196
6197             //burnt=0;
6198             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6199             glDisable(GL_BLEND);
6200             glAlphaFunc(GL_GREATER, 0.0001);
6201             glEnable(GL_TEXTURE_2D);
6202             if (cellophane) {
6203                 glDisable(GL_TEXTURE_2D);
6204                 glColor4f(.7, .35, 0, .5);
6205                 glDepthMask(0);
6206                 glEnable(GL_LIGHTING);
6207                 glEnable(GL_BLEND);
6208             }
6209             if (tutoriallevel && id != 0) {
6210                 glColor4f(.7, .7, .7, 0.6);
6211                 glDepthMask(0);
6212                 glEnable(GL_LIGHTING);
6213                 glEnable(GL_BLEND);
6214                 if (canattack && cananger)
6215                     if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6216                         glDisable(GL_TEXTURE_2D);
6217                         glColor4f(1, 0, 0, 0.8);
6218                     }
6219                 glMatrixMode(GL_TEXTURE);
6220                 glPushMatrix();
6221                 glTranslatef(0, -smoketex, 0);
6222                 glTranslatef(-smoketex, 0, 0);
6223             }
6224             if (playerdetail) {
6225                 if (!showpoints) {
6226                     if ((tutoriallevel && id != 0))
6227                         skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6228                     else
6229                         skeleton.drawmodel.draw();
6230                 }
6231             }
6232             if (!playerdetail) {
6233                 if ((tutoriallevel && id != 0))
6234                     skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6235                 else
6236                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6237             }
6238
6239             if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6240                 if (tutoriallevel && id != 0) {
6241                     glPopMatrix();
6242                     glMatrixMode(GL_MODELVIEW);
6243                     glEnable(GL_TEXTURE_2D);
6244                     glColor4f(.7, .7, .7, 0.6);
6245                     glDepthMask(0);
6246                     glEnable(GL_LIGHTING);
6247                     glEnable(GL_BLEND);
6248                     if (canattack && cananger)
6249                         if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6250                             glDisable(GL_TEXTURE_2D);
6251                             glColor4f(1, 0, 0, 0.8);
6252                         }
6253                     glMatrixMode(GL_TEXTURE);
6254                     glPushMatrix();
6255                     glTranslatef(0, -smoketex * .6, 0);
6256                     glTranslatef(smoketex * .6, 0, 0);
6257                     if (playerdetail) {
6258                         if (!showpoints) {
6259                             if ((tutoriallevel && id != 0))
6260                                 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6261                             else
6262                                 skeleton.drawmodel.draw();
6263                         }
6264                     }
6265                     if (!playerdetail) {
6266                         if ((tutoriallevel && id != 0))
6267                             skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6268                         else
6269                             skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6270                     }
6271                 }
6272
6273
6274             if (tutoriallevel && id != 0) {
6275                 glPopMatrix();
6276                 glMatrixMode(GL_MODELVIEW);
6277                 glEnable(GL_TEXTURE_2D);
6278             }
6279             if (skeleton.clothes) {
6280                 glDepthMask(0);
6281                 glEnable(GL_BLEND);
6282                 if (!immediate)
6283                     skeleton.drawmodelclothes.draw();
6284                 if (immediate)
6285                     skeleton.drawmodelclothes.drawimmediate();
6286                 glDepthMask(1);
6287             }
6288         }
6289         glPopMatrix();
6290
6291         if (num_weapons > 0) {
6292             for (k = 0; k < num_weapons; k++) {
6293                 i = weaponids[k];
6294                 if (weaponactive == k) {
6295                     if (weapons[i].getType() != staff) {
6296                         for (j = 0; j < skeleton.num_muscles; j++) {
6297                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6298                                 weaponattachmuscle = j;
6299                             }
6300                         }
6301                         for (j = 0; j < skeleton.num_muscles; j++) {
6302                             if ((skeleton.muscles[j].parent1->label == rightwrist || skeleton.muscles[j].parent2->label == rightwrist) && (skeleton.muscles[j].parent1->label != righthand && skeleton.muscles[j].parent2->label != righthand) && skeleton.muscles[j].numvertices > 0) {
6303                                 weaponrotatemuscle = j;
6304                             }
6305                         }
6306                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6307                         if (creature == wolftype)
6308                             weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6309                     }
6310                     if (weapons[i].getType() == staff) {
6311                         for (j = 0; j < skeleton.num_muscles; j++) {
6312                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6313                                 weaponattachmuscle = j;
6314                             }
6315                         }
6316                         for (j = 0; j < skeleton.num_muscles; j++) {
6317                             if ((skeleton.muscles[j].parent1->label == rightelbow || skeleton.muscles[j].parent2->label == rightelbow) && (skeleton.muscles[j].parent1->label != rightshoulder && skeleton.muscles[j].parent2->label != rightshoulder) && skeleton.muscles[j].numvertices > 0) {
6318                                 weaponrotatemuscle = j;
6319                             }
6320                         }
6321                         //weaponpoint=jointPos(rightwrist);
6322                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6323                         //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6324                         XYZ tempnormthing, vec1, vec2;
6325                         vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6326                         vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6327                         CrossProduct(&vec1, &vec2, &tempnormthing);
6328                         Normalise(&tempnormthing);
6329                         if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6330                             weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6331                     }
6332                 }
6333                 if (weaponactive != k && weaponstuck != k) {
6334                     if (weapons[i].getType() == knife)
6335                         weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6336                     if (weapons[i].getType() == sword)
6337                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6338                     if (weapons[i].getType() == staff)
6339                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6340                     for (j = 0; j < skeleton.num_muscles; j++) {
6341                         if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
6342                             weaponrotatemuscle = j;
6343                         }
6344                     }
6345                 }
6346                 if (weaponstuck == k) {
6347                     if (weaponstuckwhere == 0)
6348                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6349                     else
6350                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6351                     for (j = 0; j < skeleton.num_muscles; j++) {
6352                         if ((skeleton.muscles[j].parent1->label == abdomen || skeleton.muscles[j].parent2->label == abdomen) && (skeleton.muscles[j].parent1->label == neck || skeleton.muscles[j].parent2->label == neck) && skeleton.muscles[j].numvertices > 0) {
6353                             weaponrotatemuscle = j;
6354                         }
6355                     }
6356                 }
6357                 if (skeleton.free) {
6358                     weapons[i].position = weaponpoint * scale + coords;
6359                     weapons[i].bigrotation = 0;
6360                     weapons[i].bigtilt = 0;
6361                     weapons[i].bigtilt2 = 0;
6362                 } else {
6363                     weapons[i].position = DoRotation(DoRotation(DoRotation(weaponpoint, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords + currentoffset * (1 - target) * scale + targetoffset * target * scale;
6364                     weapons[i].bigrotation = yaw;
6365                     weapons[i].bigtilt = tilt;
6366                     weapons[i].bigtilt2 = tilt2;
6367                 }
6368                 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6369                 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6370                 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6371                 if (weaponactive == k) {
6372                     if (weapons[i].getType() == knife) {
6373                         weapons[i].smallrotation = 180;
6374                         weapons[i].smallrotation2 = 0;
6375                         if (isCrouch() || wasCrouch()) {
6376                             weapons[i].smallrotation2 = 20;
6377                         }
6378                         if (animTarget == hurtidleanim) {
6379                             weapons[i].smallrotation2 = 50;
6380                         }
6381                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6382                             XYZ temppoint1, temppoint2, tempforward;
6383                             float distance;
6384
6385                             temppoint1 = jointPos(righthand);
6386                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6387                             distance = findDistance(&temppoint1, &temppoint2);
6388                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6389                             weapons[i].rotation2 *= 360 / 6.28;
6390                             temppoint1.y = 0;
6391                             temppoint2.y = 0;
6392                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6393                             weapons[i].rotation1 *= 360 / 6.28;
6394                             weapons[i].rotation3 = 0;
6395                             weapons[i].smallrotation = -90;
6396                             weapons[i].smallrotation2 = 0;
6397                             if (temppoint1.x > temppoint2.x)
6398                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6399                         }
6400                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6401                             XYZ temppoint1, temppoint2, tempforward;
6402                             float distance;
6403
6404                             temppoint1 = jointPos(righthand);
6405                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6406                             distance = findDistance(&temppoint1, &temppoint2);
6407                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6408                             weapons[i].rotation2 *= 360 / 6.28;
6409                             temppoint1.y = 0;
6410                             temppoint2.y = 0;
6411                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6412                             weapons[i].rotation1 *= 360 / 6.28;
6413                             weapons[i].rotation3 = 0;
6414                             weapons[i].smallrotation = 90;
6415                             weapons[i].smallrotation2 = 0;
6416                             if (temppoint1.x > temppoint2.x)
6417                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6418                         }
6419                         if (animTarget == knifethrowanim) {
6420                             weapons[i].smallrotation = 90;
6421                             //weapons[i].smallrotation2=-90;
6422                             weapons[i].smallrotation2 = 0;
6423                             weapons[i].rotation1 = 0;
6424                             weapons[i].rotation2 = 0;
6425                             weapons[i].rotation3 = 0;
6426                         }
6427                         if (animTarget == knifesneakattackanim && frameTarget < 5) {
6428                             weapons[i].smallrotation = -90;
6429                             weapons[i].rotation1 = 0;
6430                             weapons[i].rotation2 = 0;
6431                             weapons[i].rotation3 = 0;
6432                         }
6433                     }
6434                     if (weapons[i].getType() == sword) {
6435                         weapons[i].smallrotation = 0;
6436                         weapons[i].smallrotation2 = 0;
6437                         if (animTarget == knifethrowanim) {
6438                             weapons[i].smallrotation = -90;
6439                             weapons[i].smallrotation2 = 0;
6440                             weapons[i].rotation1 = 0;
6441                             weapons[i].rotation2 = 0;
6442                             weapons[i].rotation3 = 0;
6443                         }
6444                         if ((animTarget == swordgroundstabanim && animCurrent == swordgroundstabanim) || (animTarget == swordsneakattackanim && animCurrent == swordsneakattackanim) || (animTarget == swordslashparryanim && animCurrent == swordslashparryanim) || (animTarget == swordslashparriedanim && animCurrent == swordslashparriedanim) || (animTarget == swordslashreversalanim && animCurrent == swordslashreversalanim) || (animTarget == swordslashreversedanim && animCurrent == swordslashreversedanim) || (animTarget == knifeslashreversalanim && animCurrent == knifeslashreversalanim) || (animTarget == knifeslashreversedanim && animCurrent == knifeslashreversedanim) || (animTarget == swordslashanim && animCurrent == swordslashanim) || (animTarget == drawleftanim && animCurrent == drawleftanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6445                             XYZ temppoint1, temppoint2, tempforward;
6446                             float distance;
6447
6448                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6449                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6450                             distance = findDistance(&temppoint1, &temppoint2);
6451                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6452                             weapons[i].rotation2 *= 360 / 6.28;
6453                             temppoint1.y = 0;
6454                             temppoint2.y = 0;
6455                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6456                             weapons[i].rotation1 *= 360 / 6.28;
6457                             weapons[i].rotation3 = 0;
6458                             weapons[i].smallrotation = 90;
6459                             weapons[i].smallrotation2 = 0;
6460                             if (temppoint1.x > temppoint2.x)
6461                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6462                         }
6463                     }
6464                     if (weapons[i].getType() == staff) {
6465                         weapons[i].smallrotation = 100;
6466                         weapons[i].smallrotation2 = 0;
6467                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6468                             XYZ temppoint1, temppoint2, tempforward;
6469                             float distance;
6470
6471                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6472                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6473                             distance = findDistance(&temppoint1, &temppoint2);
6474                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6475                             weapons[i].rotation2 *= 360 / 6.28;
6476                             temppoint1.y = 0;
6477                             temppoint2.y = 0;
6478                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6479                             weapons[i].rotation1 *= 360 / 6.28;
6480                             weapons[i].rotation3 = 0;
6481                             weapons[i].smallrotation = 90;
6482                             weapons[i].smallrotation2 = 0;
6483                             if (temppoint1.x > temppoint2.x)
6484                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6485                         }
6486                     }
6487                 }
6488                 if (weaponactive != k && weaponstuck != k) {
6489                     if (weapons[i].getType() == knife) {
6490                         weapons[i].smallrotation = -70;
6491                         weapons[i].smallrotation2 = 10;
6492                     }
6493                     if (weapons[i].getType() == sword) {
6494                         weapons[i].smallrotation = -100;
6495                         weapons[i].smallrotation2 = -8;
6496                     }
6497                     if (weapons[i].getType() == staff) {
6498                         weapons[i].smallrotation = -100;
6499                         weapons[i].smallrotation2 = -8;
6500                     }
6501                 }
6502                 if (weaponstuck == k) {
6503                     if (weaponstuckwhere == 0)
6504                         weapons[i].smallrotation = 180;
6505                     else
6506                         weapons[i].smallrotation = 0;
6507                     weapons[i].smallrotation2 = 10;
6508                 }
6509             }
6510         }
6511     }
6512
6513     calcrot = 0;
6514     if (skeleton.free)
6515         calcrot = 1;
6516     if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isFlip() || isWallJump())
6517         calcrot = 1;
6518     if (animCurrent != animTarget)
6519         calcrot = 1;
6520     if (skeleton.free == 2)
6521         calcrot = 0;
6522
6523     return 0;
6524 }
6525
6526
6527 /* FUNCTION?
6528  */
6529 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6530 {
6531     static int i, j;
6532     static float distance;
6533     static float olddistance;
6534     static int intersecting;
6535     static int firstintersecting;
6536     static XYZ point;
6537     static XYZ oldp1;
6538     static XYZ start, end;
6539     static float slopethreshold = -.4;
6540
6541     firstintersecting = -1;
6542
6543     oldp1 = *p1;
6544     *p1 = *p1 - *move;
6545     if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6546         return -1;
6547     if (*rotate)
6548         *p1 = DoRotation(*p1, 0, -*rotate, 0);
6549     for (i = 0; i < 4; i++) {
6550         for (j = 0; j < model->TriangleNum; j++) {
6551             if (model->facenormals[j].y <= slopethreshold) {
6552                 intersecting = 0;
6553                 distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
6554                 if (distance < radius) {
6555                     point = *p1 - model->facenormals[j] * distance;
6556                     if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6557                         intersecting = 1;
6558                     if (!intersecting)
6559                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6560                                                                 &model->vertex[model->Triangles[j].vertex[1]],
6561                                                                 p1, &radius);
6562                     if (!intersecting)
6563                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6564                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6565                                                                 p1, &radius);
6566                     if (!intersecting)
6567                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6568                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6569                                                                 p1, &radius);
6570                     end = *p1 - point;
6571                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6572                         start = *p1;
6573                         end = *p1;
6574                         end.y -= radius;
6575                         if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->facenormals[j], &point)) {
6576                             p1->y = point.y + radius;
6577                             if ((animTarget == jumpdownanim || isFlip())) {
6578                                 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6579                                     RagDoll(0);
6580
6581                                 if (animTarget == jumpupanim) {
6582                                     jumppower = -4;
6583                                     animTarget = getIdle();
6584                                 }
6585                                 target = 0;
6586                                 frameTarget = 0;
6587                                 onterrain = 1;
6588
6589                                 if (id == 0) {
6590                                     pause_sound(whooshsound);
6591                                     OPENAL_SetVolume(channels[whooshsound], 0);
6592                                 }
6593
6594                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6595                                     if (isFlip())
6596                                         jumppower = -4;
6597                                     animTarget = getLanding();
6598                                     emit_sound_at(landsound, coords, 128.);
6599
6600                                     if (id == 0) {
6601                                         envsound[numenvsounds] = coords;
6602                                         envsoundvol[numenvsounds] = 16;
6603                                         envsoundlife[numenvsounds] = .4;
6604                                         numenvsounds++;
6605                                     }
6606                                 }
6607                             }
6608                         }
6609                     }
6610                 }
6611                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6612                     olddistance = distance;
6613                     firstintersecting = j;
6614                     *p = point;
6615                 }
6616             }
6617         }
6618         for (j = 0; j < model->TriangleNum; j++) {
6619             if (model->facenormals[j].y > slopethreshold) {
6620                 intersecting = 0;
6621                 start = *p1;
6622                 start.y -= radius / 4;
6623                 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6624                 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6625                 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6626                 distance = abs((model->facenormals[j].x * start.x)
6627                                + (model->facenormals[j].y * start.y)
6628                                + (model->facenormals[j].z * start.z)
6629                                - ((model->facenormals[j].x * v0.x)
6630                                   + (model->facenormals[j].y * v0.y)
6631                                   + (model->facenormals[j].z * v0.z)));
6632                 if (distance < radius * .5) {
6633                     point = start - model->facenormals[j] * distance;
6634                     if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6635                         intersecting = 1;
6636                     if (!intersecting)
6637                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6638                     if (!intersecting)
6639                         intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6640                     if (!intersecting)
6641                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6642                     end = *p1 - point;
6643                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6644                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6645                             start = velocity;
6646                             velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6647                             if (findLengthfast(&start) < findLengthfast(&velocity))
6648                                 velocity = start;
6649                         }
6650                         *p1 += model->facenormals[j] * (distance - radius * .5);
6651                     }
6652                 }
6653                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6654                     olddistance = distance;
6655                     firstintersecting = j;
6656                     *p = point;
6657                 }
6658             }
6659         }
6660     }
6661     if (*rotate)
6662         *p = DoRotation(*p, 0, *rotate, 0);
6663     *p = *p + *move;
6664     if (*rotate)
6665         *p1 = DoRotation(*p1, 0, *rotate, 0);
6666     *p1 += *move;
6667     return firstintersecting;
6668 }
6669