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