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