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