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