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