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