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