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