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