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