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