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