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