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