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