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