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