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