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