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