]> git.jsancho.org Git - lugaru.git/blob - Source/Person.cpp
Cleaned a bit flashing by using a function
[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                             ;
3321                             emit_sound_at(clawslicesound, victim->coords, 128.);
3322                             victim->spurt = 1;
3323                             victim->DoBloodBig(2 / victim->armorhigh, 175);
3324                         }
3325                     }
3326                 }
3327
3328
3329
3330                 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3331                     escapednum = 0;
3332                     victim->RagDoll(1);
3333                     XYZ relative;
3334                     relative = facing;
3335                     relative.y = 0;
3336                     Normalise(&relative);
3337                     relative.y -= .1;
3338                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3339                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3340                     }
3341                     victim->jointVel(lefthand) *= .1 - 1;
3342                     victim->jointVel(leftwrist) *= .2 - 1;
3343                     victim->jointVel(leftelbow) *= .5 - 1;
3344                     victim->jointVel(leftshoulder) *= .7 - 1;
3345                     victim->jointVel(righthand) *= .1 - 1;
3346                     victim->jointVel(rightwrist) *= .2 - 1;
3347                     victim->jointVel(rightelbow) *= .5 - 1;
3348                     victim->jointVel(rightshoulder) *= .7 - 1;
3349
3350                     award_bonus(id, swordreversebonus);
3351                 }
3352
3353                 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3354                     escapednum = 0;
3355                     if (id == 0)
3356                         camerashake += .4;
3357                     if (Random() % 2) {
3358                         victim->spurt = 1;
3359                         DoBlood(.2, 230);
3360                     }
3361                     if (tutoriallevel != 1) {
3362                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3363                     }
3364                     victim->RagDoll(0);
3365                     XYZ relative;
3366                     relative = victim->coords - oldcoords;
3367                     relative.y = 0;
3368                     Normalise(&relative);
3369                     relative = DoRotation(relative, 0, -90, 0);
3370                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3371                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3372                     }
3373                     victim->jointVel(abdomen) += relative * damagemult * 200;
3374                     victim->Puff(abdomen);
3375                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3376
3377                     award_bonus(id, Reversal);
3378                 }
3379
3380                 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3381                     escapednum = 0;
3382                     victim->RagDoll(0);
3383                     victim->skeleton.spinny = 0;
3384                     XYZ relative;
3385                     relative = facing * -1;
3386                     relative.y = -3;
3387                     Normalise(&relative);
3388                     if (victim->id == 0)
3389                         relative /= 30;
3390                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3391                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3392                     }
3393                     victim->damage = victim->damagetolerance;
3394                     victim->permanentdamage = victim->damagetolerance - 1;
3395                     bool doslice;
3396                     doslice = 0;
3397                     if (weaponactive != -1 || creature == wolftype)
3398                         doslice = 1;
3399                     if (creature == rabbittype && weaponactive != -1)
3400                         if (weapons[weaponids[0]].getType() == staff)
3401                             doslice = 0;
3402                     if (doslice) {
3403                         if (weaponactive != -1) {
3404                             victim->DoBloodBig(200, 225);
3405                             emit_sound_at(knifeslicesound, victim->coords);
3406                             if (bloodtoggle)
3407                                 weapons[weaponids[weaponactive]].bloody = 2;
3408                             weapons[weaponids[weaponactive]].blooddrip += 5;
3409                         }
3410
3411                         if (creature == wolftype && weaponactive == -1) {
3412                             emit_sound_at(clawslicesound, victim->coords, 128.);
3413                             victim->spurt = 1;
3414                             victim->DoBloodBig(2, 175);
3415                         }
3416                     }
3417                     award_bonus(id, spinecrusher);
3418                 }
3419
3420                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3421                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3422                         escapednum = 0;
3423                         if (animTarget == knifefollowanim)
3424                             victim->DoBloodBig(200, 210);
3425                         if (animTarget == knifesneakattackanim) {
3426                             XYZ footvel, footpoint;
3427                             footvel = 0;
3428                             footpoint = weapons[weaponids[0]].tippoint;
3429                             if (bloodtoggle)
3430                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3431                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3432                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3433                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3434                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3435                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3436                             victim->DoBloodBig(200, 195);
3437                             award_bonus(id, tracheotomy);
3438                         }
3439                         if (animTarget == knifefollowanim) {
3440                             award_bonus(id, Stabbonus);
3441                             XYZ footvel, footpoint;
3442                             footvel = 0;
3443                             footpoint = weapons[weaponids[0]].tippoint;
3444                             if (bloodtoggle)
3445                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3446                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3447                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3448                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3449                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3450                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3451
3452                         }
3453                         victim->bloodloss += 10000;
3454                         victim->velocity = 0;
3455                         emit_sound_at(fleshstabsound, victim->coords);
3456                         if (bloodtoggle)
3457                             weapons[weaponids[weaponactive]].bloody = 2;
3458                         weapons[weaponids[weaponactive]].blooddrip += 5;
3459                     }
3460                 }
3461
3462                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3463                     escapednum = 0;
3464                     victim->velocity = 0;
3465                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3466                         victim->skeleton.joints[i].velocity = 0;
3467                     }
3468                     if (animTarget == knifefollowanim) {
3469                         victim->RagDoll(0);
3470                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3471                             victim->skeleton.joints[i].velocity = 0;
3472                         }
3473                     }
3474                     if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3475                         emit_sound_at(fleshstabremovesound, victim->coords);
3476                         if (bloodtoggle)
3477                             weapons[weaponids[weaponactive]].bloody = 2;
3478                         weapons[weaponids[weaponactive]].blooddrip += 5;
3479
3480                         XYZ footvel, footpoint;
3481                         footvel = 0;
3482                         footpoint = weapons[weaponids[0]].tippoint;
3483                         if (bloodtoggle)
3484                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3485                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3486                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3487                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3488                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3489                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3490                     }
3491                 }
3492
3493                 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3494                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3495                         award_bonus(id, backstab);
3496
3497                         escapednum = 0;
3498
3499                         XYZ footvel, footpoint;
3500                         footvel = 0;
3501                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3502                         if (bloodtoggle)
3503                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3504                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3505                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3506                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3507                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3508                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3509                         victim->DoBloodBig(200, 180);
3510                         victim->DoBloodBig(200, 215);
3511                         victim->bloodloss += 10000;
3512                         victim->velocity = 0;
3513                         emit_sound_at(fleshstabsound, victim->coords);
3514                         if (bloodtoggle)
3515                             weapons[weaponids[weaponactive]].bloody = 2;
3516                         weapons[weaponids[weaponactive]].blooddrip += 5;
3517                     }
3518                 }
3519
3520                 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3521                     escapednum = 0;
3522                     victim->velocity = 0;
3523                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3524                         victim->skeleton.joints[i].velocity = 0;
3525                     }
3526                     if (weaponactive != -1) {
3527                         emit_sound_at(fleshstabremovesound, victim->coords);
3528                         if (bloodtoggle)
3529                             weapons[weaponids[weaponactive]].bloody = 2;
3530                         weapons[weaponids[weaponactive]].blooddrip += 5;
3531
3532                         XYZ footvel, footpoint;
3533                         footvel = 0;
3534                         footpoint = weapons[weaponids[0]].tippoint;
3535                         if (bloodtoggle)
3536                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3537                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3538                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3541                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3542                     }
3543                 }
3544
3545                 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3546                     escapednum = 0;
3547                     if (id == 0)
3548                         camerashake += .4;
3549                     if (Random() % 2) {
3550                         victim->spurt = 1;
3551                         DoBlood(.2, 240);
3552                     }
3553                     if (weaponactive == -1) {
3554                         if (tutoriallevel != 1) {
3555                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
3556                         }
3557                     }
3558                     bool doslice;
3559                     doslice = 0;
3560                     if (weaponactive != -1 || creature == wolftype)
3561                         doslice = 1;
3562                     if (creature == rabbittype && weaponactive != -1)
3563                         if (weapons[weaponids[0]].getType() == staff)
3564                             doslice = 0;
3565                     if (doslice) {
3566                         if (weaponactive != -1) {
3567                             victim->DoBloodBig(2 / victim->armorhead, 225);
3568                             emit_sound_at(knifeslicesound, victim->coords);
3569                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3570                                 weapons[weaponids[weaponactive]].bloody = 1;
3571                             weapons[weaponids[weaponactive]].blooddrip += 3;
3572                         }
3573                         if (weaponactive == -1 && creature == wolftype) {
3574                             emit_sound_at(clawslicesound, victim->coords, 128.);
3575                             victim->spurt = 1;
3576                             victim->DoBloodBig(2 / victim->armorhead, 175);
3577                         }
3578                     }
3579
3580                     award_bonus(id, Reversal);
3581
3582                     victim->Puff(neck);
3583
3584                     XYZ relative;
3585                     relative = facing * -1;
3586                     relative.y = 0;
3587                     Normalise(&relative);
3588                     relative = DoRotation(relative, 0, 90, 0);
3589                     relative.y = .5;
3590                     Normalise(&relative);
3591                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3592                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3593                     }
3594                     victim->jointVel(head) += relative * damagemult * 200;
3595                     if (victim->damage < victim->damagetolerance - 100)
3596                         victim->velocity = relative * 200;
3597                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
3598                     victim->velocity = 0;
3599                 }
3600
3601                 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3602                     escapednum = 0;
3603                     victim->RagDoll(0);
3604                     XYZ relative;
3605                     relative = facing * -1;
3606                     relative.y = 0;
3607                     Normalise(&relative);
3608                     relative = DoRotation(relative, 0, 90, 0);
3609                     relative.y = .5;
3610                     Normalise(&relative);
3611                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3612                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3613                     }
3614                     victim->jointVel(head) += relative * damagemult * 200;
3615                 }
3616
3617                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3618                     if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3619                         award_bonus(id, reverseko);
3620                     }
3621             }
3622
3623
3624             //Animation end
3625             if (frameTarget > animation[animCurrent].numframes - 1) {
3626                 frameTarget = 0;
3627                 if (wasStop()) {
3628                     animTarget = getIdle();
3629                     FootLand(0, 1);
3630                     FootLand(1, 1);
3631                 }
3632                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3633                     animTarget = rollanim;
3634                     frameTarget = 3;
3635                     emit_sound_at(movewhooshsound, coords, 128.);
3636                 }
3637                 if (animCurrent == staggerbackhighanim) {
3638                     animTarget = getIdle();
3639                 }
3640                 if (animCurrent == staggerbackhardanim) {
3641                     animTarget = getIdle();
3642                 }
3643                 if (animCurrent == removeknifeanim) {
3644                     animTarget = getIdle();
3645                 }
3646                 if (animCurrent == crouchremoveknifeanim) {
3647                     animTarget = getCrouch();
3648                 }
3649                 if (animCurrent == backhandspringanim) {
3650                     animTarget = getIdle();
3651                 }
3652                 if (animCurrent == dodgebackanim) {
3653                     animTarget = getIdle();
3654                 }
3655                 if (animCurrent == drawleftanim) {
3656                     animTarget = getIdle();
3657                 }
3658                 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3659                     animTarget = getIdle();
3660                     if (animCurrent == crouchdrawrightanim) {
3661                         animTarget = getCrouch();
3662                     }
3663                     if (weaponactive == -1)
3664                         weaponactive = 0;
3665                     else if (weaponactive == 0) {
3666                         weaponactive = -1;
3667                         if (num_weapons == 2) {
3668                             int buffer;
3669                             buffer = weaponids[0];
3670                             weaponids[0] = weaponids[1];
3671                             weaponids[1] = buffer;
3672                         }
3673                     }
3674
3675                     if (weaponactive == -1) {
3676                         emit_sound_at(knifesheathesound, coords, 128.);
3677                     }
3678                     if (weaponactive != -1) {
3679                         emit_sound_at(knifedrawsound, coords, 128.);
3680                     }
3681                 }
3682                 if (animCurrent == rollanim) {
3683                     animTarget = getCrouch();
3684                     FootLand(0, 1);
3685                     FootLand(1, 1);
3686                 }
3687                 if (isFlip()) {
3688                     if (animTarget == walljumprightkickanim) {
3689                         targetrot = -190;
3690                     }
3691                     if (animTarget == walljumpleftkickanim) {
3692                         targetrot = 190;
3693                     }
3694                     animTarget = jumpdownanim;
3695                 }
3696                 if (animCurrent == climbanim) {
3697                     animTarget = getCrouch();
3698                     frameTarget = 1;
3699                     coords += facing * .1;
3700                     if (!isnormal(coords.x))
3701                         coords = oldcoords;
3702                     oldcoords = coords;
3703                     collided = 0;
3704                     targetoffset = 0;
3705                     currentoffset = 0;
3706                     grabdelay = 1;
3707                     velocity = 0;
3708                     collided = 0;
3709                     avoidcollided = 0;
3710                 }
3711                 if (animTarget == rabbitkickreversalanim) {
3712                     animTarget = getCrouch();
3713                     lastfeint = 0;
3714                 }
3715                 if (animTarget == jumpreversalanim) {
3716                     animTarget = getCrouch();
3717                     lastfeint = 0;
3718                 }
3719                 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3720                     if (attackkeydown && animTarget != walljumpfrontanim) {
3721                         int closest = -1;
3722                         float closestdist = -1;
3723                         float distance;
3724                         if (Person::players.size() > 1)
3725                             for (unsigned i = 0; i < Person::players.size(); i++) {
3726                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3727                                     distance = distsq(&Person::players[i]->coords, &coords);
3728                                     if (closestdist == -1 || distance < closestdist) {
3729                                         closestdist = distance;
3730                                         closest = i;
3731                                     }
3732                                 }
3733                             }
3734                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3735                             victim = Person::players[closest];
3736                             animTarget = walljumprightkickanim;
3737                             frameTarget = 0;
3738                             XYZ rotatetarget = victim->coords - coords;
3739                             Normalise(&rotatetarget);
3740                             yaw = -asin(0 - rotatetarget.x);
3741                             yaw *= 360 / 6.28;
3742                             if (rotatetarget.z < 0)
3743                                 yaw = 180 - yaw;
3744                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3745                             velocity = (victim->coords - coords) * 4;
3746                             velocity.y += 2;
3747                             transspeed = 40;
3748                         }
3749                     }
3750                     if (animTarget == walljumpbackanim) {
3751                         animTarget = backflipanim;
3752                         frameTarget = 3;
3753                         velocity = facing * -8;
3754                         velocity.y = 4;
3755                         if (id == 0)
3756                             resume_stream(whooshsound);
3757                     }
3758                     if (animTarget == walljumprightanim) {
3759                         animTarget = rightflipanim;
3760                         frameTarget = 4;
3761                         targetyaw -= 90;
3762                         yaw -= 90;
3763                         velocity = DoRotation(facing, 0, 30, 0) * -8;
3764                         velocity.y = 4;
3765                     }
3766                     if (animTarget == walljumpfrontanim) {
3767                         animTarget = frontflipanim;
3768                         frameTarget = 2;
3769                         //targetyaw-=180;
3770                         ////yaw-=180;
3771                         velocity = facing * 8;
3772                         velocity.y = 4;
3773                     }
3774                     if (id == 0)
3775                         resume_stream(whooshsound);
3776                 }
3777                 if (animTarget == walljumpleftanim) {
3778                     if (attackkeydown) {
3779                         int closest = -1;
3780                         float closestdist = -1;
3781                         float distance;
3782                         if (Person::players.size() > 1)
3783                             for (unsigned i = 0; i < Person::players.size(); i++) {
3784                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3785                                     distance = distsq(&Person::players[i]->coords, &coords);
3786                                     if (closestdist == -1 || distance < closestdist) {
3787                                         closestdist = distance;
3788                                         closest = i;
3789                                     }
3790                                 }
3791                             }
3792                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3793                             victim = Person::players[closest];
3794                             animTarget = walljumpleftkickanim;
3795                             frameTarget = 0;
3796                             XYZ rotatetarget = victim->coords - coords;
3797                             Normalise(&rotatetarget);
3798                             yaw = -asin(0 - rotatetarget.x);
3799                             yaw *= 360 / 6.28;
3800                             if (rotatetarget.z < 0)
3801                                 yaw = 180 - yaw;
3802                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3803                             velocity = (victim->coords - coords) * 4;
3804                             velocity.y += 2;
3805                             transspeed = 40;
3806                         }
3807                     }
3808                     if (animTarget != walljumpleftkickanim) {
3809                         animTarget = leftflipanim;
3810                         frameTarget = 4;
3811                         targetyaw += 90;
3812                         yaw += 90;
3813                         velocity = DoRotation(facing, 0, -30, 0) * -8;
3814                         velocity.y = 4;
3815                     }
3816                     if (id == 0)
3817                         resume_stream(whooshsound);
3818                 }
3819                 if (animTarget == sneakattackanim) {
3820                     animCurrent = getCrouch();
3821                     animTarget = getCrouch();
3822                     frameTarget = 1;
3823                     frameCurrent = 0;
3824                     targetyaw += 180;
3825                     yaw += 180;
3826                     targettilt2 *= -1;
3827                     tilt2 *= -1;
3828                     transspeed = 1000000;
3829                     targetheadyaw += 180;
3830                     coords -= facing * .7;
3831                     if (onterrain)
3832                         coords.y = terrain.getHeight(coords.x, coords.z);
3833
3834                     lastfeint = 0;
3835                 }
3836                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3837                     animTarget = getIdle();
3838                     frameTarget = 0;
3839                     if (onterrain)
3840                         coords.y = terrain.getHeight(coords.x, coords.z);
3841
3842                     lastfeint = 0;
3843                 }
3844                 if (animCurrent == knifefollowanim) {
3845                     animTarget = getIdle();
3846                     lastfeint = 0;
3847                 }
3848                 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3849                     float ycoords = oldcoords.y;
3850                     animTarget = getStop();
3851                     targetyaw += 180;
3852                     yaw += 180;
3853                     targettilt2 *= -1;
3854                     tilt2 *= -1;
3855                     transspeed = 1000000;
3856                     targetheadyaw += 180;
3857                     if (!isnormal(coords.x))
3858                         coords = oldcoords;
3859                     if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3860                         oldcoords = coords + facing * .5;
3861                     else if (animCurrent == sweepreversalanim)
3862                         oldcoords = coords + facing * 1.1;
3863                     else if (animCurrent == upunchreversalanim) {
3864                         oldcoords = coords + facing * 1.5;
3865                         targetyaw += 180;
3866                         yaw += 180;
3867                         targetheadyaw += 180;
3868                         targettilt2 *= -1;
3869                         tilt2 *= -1;
3870                     } else if (animCurrent == knifeslashreversalanim) {
3871                         oldcoords = coords + facing * .5;
3872                         targetyaw += 90;
3873                         yaw += 90;
3874                         targetheadyaw += 90;
3875                         targettilt2 = 0;
3876                         tilt2 = 0;
3877                     } else if (animCurrent == staffspinhitreversalanim) {
3878                         targetyaw += 180;
3879                         yaw += 180;
3880                         targetheadyaw += 180;
3881                         targettilt2 = 0;
3882                         tilt2 = 0;
3883                     }
3884                     if (onterrain)
3885                         oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3886                     else
3887                         oldcoords.y = ycoords;
3888                     currentoffset = coords - oldcoords;
3889                     targetoffset = 0;
3890                     coords = oldcoords;
3891
3892                     lastfeint = 0;
3893                 }
3894                 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3895                     velocity = 0;
3896                     velocity.y = -5;
3897                     RagDoll(0);
3898                 }
3899                 if (animation[animTarget].attack == reversed) {
3900                     escapednum++;
3901                     if (animTarget == sweepreversedanim)
3902                         targetyaw += 90;
3903                     animTarget = backhandspringanim;
3904                     frameTarget = 2;
3905                     emit_sound_at(landsound, coords, 128);
3906
3907                     if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3908                         animTarget = rollanim;
3909                         frameTarget = 5;
3910                         oldcoords = coords;
3911                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3912                         coords.y = oldcoords.y;
3913                     }
3914                     if (animCurrent == knifeslashreversedanim) {
3915                         animTarget = rollanim;
3916                         frameTarget = 0;
3917                         targetyaw += 90;
3918                         yaw += 90;
3919                         oldcoords = coords;
3920                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3921                         coords.y = oldcoords.y;
3922                     }
3923                 }
3924                 if (wasFlip()) {
3925                     animTarget = jumpdownanim;
3926                 }
3927                 if (wasLanding())
3928                     animTarget = getIdle();
3929                 if (wasLandhard())
3930                     animTarget = getIdle();
3931                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3932                     animTarget = getIdle();
3933                     oldcoords = coords;
3934                     coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3935                     coords.y = oldcoords.y;
3936                     //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3937                     targetoffset.y = coords.y;
3938                     if (onterrain)
3939                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
3940                     currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3941                     currentoffset.y -= (coords.y - targetoffset.y);
3942                     coords.y = targetoffset.y;
3943                     targetoffset = 0;
3944                     normalsupdatedelay = 0;
3945                 }
3946                 if (animCurrent == upunchanim) {
3947                     animTarget = getStop();
3948                     normalsupdatedelay = 0;
3949                     lastfeint = 0;
3950                 }
3951                 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3952                     targetyaw = yaw;
3953                     bool hasstaff;
3954                     hasstaff = 0;
3955                     if (num_weapons > 0)
3956                         if (weapons[0].getType() == staff)
3957                             hasstaff = 1;
3958                     if (!hasstaff)
3959                         DoDamage(35);
3960                     RagDoll(0);
3961                     lastfeint = 0;
3962                     rabbitkickragdoll = 1;
3963                 }
3964                 if (animCurrent == rabbitkickreversedanim) {
3965                     if (!feint) {
3966                         velocity = 0;
3967                         velocity.y = -10;
3968                         //DoDamage(100);
3969                         RagDoll(0);
3970                         skeleton.spinny = 0;
3971                         SolidHitBonus(!id); // FIXME: tricky id
3972                     }
3973                     if (feint) {
3974                         escapednum++;
3975                         animTarget = rollanim;
3976                         coords += facing;
3977                         if (id == 0)
3978                             pause_sound(whooshsound);
3979                     }
3980                     lastfeint = 0;
3981                 }
3982                 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3983                     velocity = 0;
3984                     velocity.y = -10;
3985                     RagDoll(0);
3986                     skeleton.spinny = 0;
3987                 }
3988                 if (animCurrent == jumpreversedanim) {
3989                     if (!feint) {
3990                         velocity = 0;
3991                         velocity.y = -10;
3992                         //DoDamage(100);
3993                         RagDoll(0);
3994                         skeleton.spinny = 0;
3995                         SolidHitBonus(!id); // FIXME: tricky id
3996                     }
3997                     if (feint) {
3998                         escapednum++;
3999                         animTarget = rollanim;
4000                         coords += facing * 2;
4001                         if (id == 0)
4002                             pause_sound(whooshsound);
4003                     }
4004                     lastfeint = 0;
4005                 }
4006
4007                 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) {
4008                     animTarget = getupfromfrontanim;
4009                     lastfeint = 0;
4010                 } else if (animation[animCurrent].attack == normalattack) {
4011                     animTarget = getIdle();
4012                     lastfeint = 0;
4013                 }
4014                 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4015                     animTarget = blockhighleftstrikeanim;
4016                 }
4017                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4018                     animTarget = getIdle();
4019                     lastfeint = 0;
4020                 }
4021                 if (animCurrent == spinkickanim && victim->skeleton.free) {
4022                     if (creature == rabbittype)
4023                         animTarget = fightidleanim;
4024                 }
4025             }
4026             target = 0;
4027
4028             if (isIdle() && !wasIdle())
4029                 normalsupdatedelay = 0;
4030
4031             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4032                 animTarget = jumpdownanim;
4033             }
4034         }
4035         if (!skeleton.free) {
4036             oldtarget = target;
4037             if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4038                 if (!isRun() || !wasRun()) {
4039                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4040                         target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4041                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4042                         target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4043                 }
4044                 if (isRun() && wasRun()) {
4045                     float tempspeed;
4046                     tempspeed = velspeed;
4047                     if (tempspeed < 10 * speedmult)
4048                         tempspeed = 10 * speedmult;
4049                     target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4050                 }
4051             } else if (transspeed)
4052                 target += multiplier * transspeed * speed * 2;
4053             else {
4054                 if (!isRun() || !wasRun()) {
4055                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4056                         target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4057                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4058                         target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4059                 }
4060             }
4061
4062             if (animCurrent != animTarget)
4063                 target = (target + oldtarget) / 2;
4064
4065             if (target > 1) {
4066                 frameCurrent = frameTarget;
4067                 target = 1;
4068             }
4069             oldrot = rot;
4070             rot = targetrot * target;
4071             yaw += rot - oldrot;
4072             if (target == 1) {
4073                 rot = 0;
4074                 oldrot = 0;
4075                 targetrot = 0;
4076             }
4077             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4078                 //Old rotates
4079                 for (int i = 0; i < skeleton.num_joints; i++) {
4080                     skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4081                 }
4082
4083                 skeleton.FindForwards();
4084
4085                 for (int i = 0; i < skeleton.num_muscles; i++) {
4086                     if (skeleton.muscles[i].visible) {
4087                         skeleton.FindRotationMuscle(i, animTarget);
4088                     }
4089                 }
4090                 for (int i = 0; i < skeleton.num_muscles; i++) {
4091                     if (skeleton.muscles[i].visible) {
4092                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4093                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4094                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4095                             skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4096                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4097                             skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4098                     }
4099                 }
4100
4101                 //New rotates
4102                 for (int i = 0; i < skeleton.num_joints; i++) {
4103                     skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4104                 }
4105
4106                 skeleton.FindForwards();
4107
4108                 for (int i = 0; i < skeleton.num_muscles; i++) {
4109                     if (skeleton.muscles[i].visible) {
4110                         skeleton.FindRotationMuscle(i, animTarget);
4111                     }
4112                 }
4113                 for (int i = 0; i < skeleton.num_muscles; i++) {
4114                     if (skeleton.muscles[i].visible) {
4115                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4116                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4117                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4118                             skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4119                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4120                             skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4121                         if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4122                         if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4123                         if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4124                         if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4125                         if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4126                         if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4127                     }
4128                 }
4129             }
4130             if (frameCurrent >= animation[animCurrent].numframes)
4131                 frameCurrent = animation[animCurrent].numframes - 1;
4132
4133             oldanimCurrent = animCurrent;
4134             oldanimTarget = animTarget;
4135             oldframeTarget = frameTarget;
4136             oldframeCurrent = frameCurrent;
4137
4138             for (int i = 0; i < skeleton.num_joints; i++) {
4139                 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4140                 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4141             }
4142             offset = currentoffset * (1 - target) + targetoffset * target;
4143             for (int i = 0; i < skeleton.num_muscles; i++) {
4144                 if (skeleton.muscles[i].visible) {
4145                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4146                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4147                     skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4148                 }
4149             }
4150         }
4151
4152         if (isLanding() && landhard) {
4153             if (id == 0)
4154                 camerashake += .4;
4155             animTarget = getLandhard();
4156             frameTarget = 0;
4157             target = 0;
4158             landhard = 0;
4159             transspeed = 15;
4160         }
4161     }
4162 }
4163
4164 /* EFFECT
4165  * MONSTER
4166  * TODO
4167  */
4168 void Person::DoStuff()
4169 {
4170     static XYZ terrainnormal;
4171     static XYZ flatfacing;
4172     static XYZ flatvelocity;
4173     static float flatvelspeed;
4174     static int i, j, l;
4175     static XYZ average;
4176     static int howmany;
4177     static int bloodsize;
4178     static int startx, starty, endx, endy;
4179     static GLubyte color;
4180     static XYZ bloodvel;
4181
4182     onfiredelay -= multiplier;
4183     if (onfiredelay < 0 && onfire) {
4184         if (Random() % 2 == 0) {
4185             crouchkeydown = 1;
4186         }
4187         onfiredelay = 0.3;
4188     }
4189
4190     crouchkeydowntime += multiplier;
4191     if (!crouchkeydown)
4192         crouchkeydowntime = 0;
4193     jumpkeydowntime += multiplier;
4194     if (!jumpkeydown && skeleton.free)
4195         jumpkeydowntime = 0;
4196
4197     if (hostile || damage > 0 || bloodloss > 0)
4198         immobile = 0;
4199
4200     if (isIdle() || isRun())
4201         targetoffset = 0;
4202
4203     if (num_weapons == 1 && weaponactive != -1)
4204         weaponstuck = -1;
4205
4206     if (id == 0)
4207         blooddimamount -= multiplier * .3;
4208     speechdelay -= multiplier;
4209     texupdatedelay -= multiplier;
4210     interestdelay -= multiplier;
4211     flamedelay -= multiplier;
4212     parriedrecently -= multiplier;
4213     if (!victim) {
4214         victim = this->shared_from_this();
4215         hasvictim = 0;
4216     }
4217
4218     if (id == 0)
4219         speed = 1.1 * speedmult;
4220     else
4221         speed = 1.0 * speedmult;
4222     if (!skeleton.free)
4223         rabbitkickragdoll = 0;
4224
4225     speed *= speedmult;
4226
4227     if (id != 0 && (creature == rabbittype || difficulty != 2))
4228         superruntoggle = 0;
4229     if (id != 0 && creature == wolftype && difficulty == 2) {
4230         superruntoggle = 0;
4231         if (aitype != passivetype) {
4232             superruntoggle = 1;
4233             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) {
4234                 superruntoggle = 0;
4235             }
4236         }
4237         if (scale < 0.2)
4238             superruntoggle = 0;
4239         if (animTarget == wolfrunninganim && !superruntoggle) {
4240             animTarget = getRun();
4241             frameTarget = 0;
4242         }
4243     }
4244     if (weaponactive == -1 && num_weapons > 0) {
4245         if (weapons[weaponids[0]].getType() == staff) {
4246             weaponactive = 0;
4247         }
4248     }
4249
4250     if (onfire) {
4251         burnt += multiplier;
4252         deathbleeding = 1;
4253         if (burnt > .6)
4254             burnt = .6;
4255         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4256
4257         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4258             float gLoc[3];
4259             float vel[3];
4260             gLoc[0] = coords.x;
4261             gLoc[1] = coords.y;
4262             gLoc[2] = coords.z;
4263             vel[0] = velocity.x;
4264             vel[1] = velocity.y;
4265             vel[2] = velocity.z;
4266
4267             if (id == 0) {
4268                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4269                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4270             }
4271         }
4272     }
4273     while (flamedelay < 0 && onfire) {
4274         flamedelay += .006;
4275         howmany = abs(Random() % (skeleton.num_joints));
4276         if (skeleton.free) {
4277             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4278             flatfacing = skeleton.joints[howmany].position * scale + coords;
4279         } else {
4280             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4281             flatvelocity = (coords - oldcoords) / multiplier / 2;
4282         }
4283         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4284     }
4285
4286     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4287         flamedelay += .05;
4288         howmany = abs(Random() % (skeleton.num_joints));
4289         if (skeleton.free) {
4290             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4291             flatfacing = skeleton.joints[howmany].position * scale + coords;
4292         } else {
4293             flatvelocity = (coords - oldcoords) / multiplier / 2;
4294             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4295         }
4296         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4297     }
4298
4299     if (bleeding > 0) {
4300         bleeding -= multiplier * .3;
4301         if (bloodtoggle == 2) {
4302             skeleton.drawmodel.textureptr.bind();
4303             if ((bleeding <= 0) && (detail != 2))
4304                 DoMipmaps();
4305         }
4306     }
4307
4308     if (neckspurtamount > 0) {
4309         neckspurtamount -= multiplier;
4310         neckspurtdelay -= multiplier * 3;
4311         neckspurtparticledelay -= multiplier * 3;
4312         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4313             spurt = 0;
4314             bloodvel = 0;
4315             if (skeleton.free) {
4316                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4317                 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4318                 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4319             } else {
4320                 bloodvel.z = 5 * neckspurtamount;
4321                 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4322                 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4323                 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4324             }
4325             neckspurtparticledelay = .05;
4326         }
4327         if (neckspurtdelay < 0) {
4328             neckspurtdelay = 3;
4329         }
4330     }
4331
4332     if (deathbleeding > 0 && dead != 2) {
4333         if (deathbleeding < 5)
4334             bleeddelay -= deathbleeding * multiplier / 4;
4335         else
4336             bleeddelay -= 5 * multiplier / 4;
4337         if (bleeddelay < 0 && bloodtoggle) {
4338             bleeddelay = 1;
4339             XYZ bloodvel;
4340             if (bloodtoggle) {
4341                 bloodvel = 0;
4342                 if (skeleton.free) {
4343                     bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4344                     Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4345                 } else {
4346                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4347                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4348                 }
4349             }
4350         }
4351         bloodloss += deathbleeding * multiplier * 80;
4352         deathbleeding -= multiplier * 1.6;
4353         if (deathbleeding < 0)
4354             deathbleeding = 0;
4355         if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4356             if (weaponactive != -1) {
4357                 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4358                 weapons[weaponids[0]].velocity.x += .01;
4359                 num_weapons--;
4360                 if (num_weapons) {
4361                     weaponids[0] = weaponids[num_weapons];
4362                     if (weaponstuck == num_weapons)
4363                         weaponstuck = 0;
4364                 }
4365                 weaponactive = -1;
4366                 for (unsigned i = 0; i < Person::players.size(); i++) {
4367                     Person::players[i]->wentforweapon = 0;
4368                 }
4369
4370                 if (id == 0) {
4371                     Game::flash(.5, 0);
4372                 }
4373             }
4374
4375             if (!dead && creature == wolftype) {
4376                 award_bonus(0, Wolfbonus);
4377             }
4378             dead = 2;
4379             if (animTarget == knifefollowedanim && !skeleton.free) {
4380                 for (int i = 0; i < skeleton.num_joints; i++) {
4381                     skeleton.joints[i].velocity = 0;
4382                     skeleton.joints[i].velocity.y = -2;
4383                 }
4384             }
4385             if (id != 0 && unconscioustime > .1) {
4386                 numafterkill++;
4387             }
4388
4389             RagDoll(0);
4390         }
4391     }
4392
4393     if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4394         texupdatedelay = .12;
4395
4396         bloodsize = 5 - realtexdetail;
4397
4398         startx = 0;
4399         starty = 0;
4400         startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4401         starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4402         endx = startx + bloodsize;
4403         endy = starty + bloodsize;
4404
4405         if (startx < 0) {
4406             startx = 0;
4407             bleeding = 0;
4408         }
4409         if (starty < 0) {
4410             starty = 0;
4411             bleeding = 0;
4412         }
4413         if (endx > skeleton.skinsize - 1) {
4414             endx = skeleton.skinsize - 1;
4415             bleeding = 0;
4416         }
4417         if (endy > skeleton.skinsize - 1) {
4418             endy = skeleton.skinsize - 1;
4419             bleeding = 0;
4420         }
4421         if (endx < startx)
4422             endx = startx;
4423         if (endy < starty)
4424             endy = starty;
4425
4426         for (i = startx; i < endx; i++) {
4427             for (j = starty; j < endy; j++) {
4428                 if (Random() % 2 == 0) {
4429                     color = Random() % 85 + 170;
4430                     if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4431                         skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4432                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4433                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4434                 }
4435             }
4436         }
4437         if (detail > 1) {
4438             skeleton.drawmodel.textureptr.bind();
4439             DoMipmaps();
4440         }
4441
4442         if (skeleton.free) {
4443             bleedx += 4 * direction / realtexdetail;
4444             if (detail == 2)
4445                 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4446             else
4447                 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4448         } else {
4449             bleedy -= 4 / realtexdetail;
4450             if (detail == 2)
4451                 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4452             else
4453                 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4454         }
4455     }
4456
4457     if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4458         righthandmorphness = targetrighthandmorphness;
4459         righthandmorphstart = righthandmorphend;
4460     } else if (righthandmorphness > targetrighthandmorphness) {
4461         righthandmorphness -= multiplier * 4;
4462     } else if (righthandmorphness < targetrighthandmorphness) {
4463         righthandmorphness += multiplier * 4;
4464     }
4465
4466     if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4467         lefthandmorphness = targetlefthandmorphness;
4468         lefthandmorphstart = lefthandmorphend;
4469     } else if (lefthandmorphness > targetlefthandmorphness) {
4470         lefthandmorphness -= multiplier * 4;
4471     } else if (lefthandmorphness < targetlefthandmorphness) {
4472         lefthandmorphness += multiplier * 4;
4473     }
4474
4475     if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4476         if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4477             tailmorphness = targettailmorphness;
4478             tailmorphstart = tailmorphend;
4479         } else if (tailmorphness > targettailmorphness) {
4480             tailmorphness -= multiplier * 10;
4481         } else if (tailmorphness < targettailmorphness) {
4482             tailmorphness += multiplier * 10;
4483         }
4484     }
4485
4486     if (creature == wolftype) {
4487         if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4488             tailmorphness = targettailmorphness;
4489             tailmorphstart = tailmorphend;
4490         } else if (tailmorphness > targettailmorphness) {
4491             tailmorphness -= multiplier * 2;
4492         } else if (tailmorphness < targettailmorphness) {
4493             tailmorphness += multiplier * 2;
4494         }
4495     }
4496
4497     if (headmorphend == 3 || headmorphstart == 3) {
4498         if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4499             headmorphness = targetheadmorphness;
4500             headmorphstart = headmorphend;
4501         } else if (headmorphness > targetheadmorphness) {
4502             headmorphness -= multiplier * 7;
4503         } else if (headmorphness < targetheadmorphness) {
4504             headmorphness += multiplier * 7;
4505         }
4506     } else if (headmorphend == 5 || headmorphstart == 5) {
4507         if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4508             headmorphness = targetheadmorphness;
4509             headmorphstart = headmorphend;
4510         } else if (headmorphness > targetheadmorphness) {
4511             headmorphness -= multiplier * 10;
4512         } else if (headmorphness < targetheadmorphness) {
4513             headmorphness += multiplier * 10;
4514         }
4515     } else {
4516         if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4517             headmorphness = targetheadmorphness;
4518             headmorphstart = headmorphend;
4519         } else if (headmorphness > targetheadmorphness) {
4520             headmorphness -= multiplier * 4;
4521         } else if (headmorphness < targetheadmorphness) {
4522             headmorphness += multiplier * 4;
4523         }
4524     }
4525
4526     if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4527         chestmorphness = targetchestmorphness;
4528         chestmorphstart = chestmorphend;
4529     } else if (chestmorphness > targetchestmorphness) {
4530         chestmorphness -= multiplier;
4531     } else if (chestmorphness < targetchestmorphness) {
4532         chestmorphness += multiplier;
4533     }
4534
4535     if (dead != 2 && howactive <= typesleeping) {
4536         if (chestmorphstart == 0 && chestmorphend == 0) {
4537             chestmorphness = 0;
4538             targetchestmorphness = 1;
4539             chestmorphend = 3;
4540         }
4541         if (chestmorphstart != 0 && chestmorphend != 0) {
4542             chestmorphness = 0;
4543             targetchestmorphness = 1;
4544             chestmorphend = 0;
4545             if (environment == snowyenvironment) {
4546                 XYZ footpoint;
4547                 XYZ footvel;
4548                 if (skeleton.free) {
4549                     footvel = skeleton.specialforward[0] * -1;
4550                     footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4551                 } else {
4552                     footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4553                     footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4554                 }
4555                 if (animTarget == sleepanim)
4556                     footvel = DoRotation(footvel, 0, 90, 0);
4557                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4558             }
4559         }
4560
4561         if (!dead && howactive < typesleeping) {
4562             blinkdelay -= multiplier * 2;
4563             if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4564                 headmorphness = 0;
4565                 targetheadmorphness = 1;
4566                 headmorphend = 3;
4567                 blinkdelay = (float)(abs(Random() % 40)) / 5;
4568             }
4569             if (headmorphstart == 3 && headmorphend == 3) {
4570                 headmorphness = 0;
4571                 targetheadmorphness = 1;
4572                 headmorphend = 0;
4573             }
4574         }
4575         if (!dead) {
4576             twitchdelay -= multiplier * 1.5;
4577             if (animTarget != hurtidleanim) {
4578                 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4579                     headmorphness = 0;
4580                     targetheadmorphness = 1;
4581                     headmorphend = 5;
4582                     twitchdelay = (float)(abs(Random() % 40)) / 5;
4583                 }
4584                 if (headmorphstart == 5 && headmorphend == 5) {
4585                     headmorphness = 0;
4586                     targetheadmorphness = 1;
4587                     headmorphend = 0;
4588                 }
4589             }
4590             if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4591                 twitchdelay3 -= multiplier * 1;
4592                 if (Random() % 2 == 0) {
4593                     if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4594                         righthandmorphness = 0;
4595                         targetrighthandmorphness = 1;
4596                         righthandmorphend = 1;
4597                         if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4598                     }
4599                     if (righthandmorphstart == 1 && righthandmorphend == 1) {
4600                         righthandmorphness = 0;
4601                         targetrighthandmorphness = 1;
4602                         righthandmorphend = 0;
4603                     }
4604                 }
4605                 if (Random() % 2 == 0) {
4606                     if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4607                         lefthandmorphness = 0;
4608                         targetlefthandmorphness = 1;
4609                         lefthandmorphend = 1;
4610                         twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4611                     }
4612                     if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4613                         lefthandmorphness = 0;
4614                         targetlefthandmorphness = 1;
4615                         lefthandmorphend = 0;
4616                     }
4617                 }
4618             }
4619         }
4620         if (!dead) {
4621             if (creature == rabbittype) {
4622                 if (howactive < typesleeping)
4623                     twitchdelay2 -= multiplier * 1.5;
4624                 else
4625                     twitchdelay2 -= multiplier * 0.5;
4626                 if (howactive <= typesleeping) {
4627                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4628                         tailmorphness = 0;
4629                         targettailmorphness = 1;
4630                         tailmorphend = 1;
4631                         twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4632                     }
4633                     if (tailmorphstart == 1 && tailmorphend == 1) {
4634                         tailmorphness = 0;
4635                         targettailmorphness = 1;
4636                         tailmorphend = 2;
4637                     }
4638                     if (tailmorphstart == 2 && tailmorphend == 2) {
4639                         tailmorphness = 0;
4640                         targettailmorphness = 1;
4641                         tailmorphend = 0;
4642                     }
4643                 }
4644             }
4645         }
4646     }
4647     if (creature == wolftype) {
4648         twitchdelay2 -= multiplier * 1.5;
4649         if (tailmorphend != 0)
4650             if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4651                 tailmorphness = 0;
4652                 targettailmorphness = 1;
4653                 tailmorphend = 0;
4654                 twitchdelay2 = .1;
4655             }
4656         if (tailmorphend != 5)
4657             if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4658                 tailmorphness = 0;
4659                 targettailmorphness = 1;
4660                 tailmorphend = 5;
4661                 twitchdelay2 = .1;
4662             }
4663         if (twitchdelay2 <= 0) {
4664             if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4665                 tailmorphness = 0;
4666                 targettailmorphness = 1;
4667                 tailmorphend = 1;
4668             }
4669             if (tailmorphstart == 1 && tailmorphend == 1) {
4670                 tailmorphness = 0;
4671                 targettailmorphness = 1;
4672                 tailmorphend = 2;
4673             }
4674             if (tailmorphstart == 2 && tailmorphend == 2) {
4675                 tailmorphness = 0;
4676                 targettailmorphness = 1;
4677                 tailmorphend = 3;
4678             }
4679             if (tailmorphstart == 3 && tailmorphend == 3) {
4680                 tailmorphness = 0;
4681                 targettailmorphness = 1;
4682                 tailmorphend = 4;
4683             }
4684             if (tailmorphstart == 4 && tailmorphend == 4) {
4685                 tailmorphness = 0;
4686                 targettailmorphness = 1;
4687                 tailmorphend = 1;
4688             }
4689         }
4690     }
4691
4692     if (dead != 1)
4693         unconscioustime = 0;
4694
4695     if (dead == 1 || howactive == typesleeping) {
4696         unconscioustime += multiplier;
4697         //If unconscious, close eyes and mouth
4698         if (righthandmorphend != 0)
4699             righthandmorphness = 0;
4700         righthandmorphend = 0;
4701         targetrighthandmorphness = 1;
4702
4703         if (lefthandmorphend != 0)
4704             lefthandmorphness = 0;
4705         lefthandmorphend = 0;
4706         targetlefthandmorphness = 1;
4707
4708         if (headmorphend != 3 && headmorphend != 5)
4709             headmorphness = 0;
4710         headmorphend = 3;
4711         targetheadmorphness = 1;
4712     }
4713
4714
4715     if (howactive > typesleeping) {
4716         XYZ headpoint;
4717         headpoint = coords;
4718         if (bloodtoggle && !bled) {
4719             terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4720         }
4721         if (bloodtoggle && !bled)
4722             for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4723                 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4724                 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4725                 float size = .8;
4726                 float opacity = .6;
4727                 float yaw = 0;
4728                 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4729             }
4730         bled = 1;
4731     }
4732
4733     if (dead == 2 || howactive > typesleeping) {
4734         //If dead, open mouth and hands
4735         if (righthandmorphend != 0)
4736             righthandmorphness = 0;
4737         righthandmorphend = 0;
4738         targetrighthandmorphness = 1;
4739
4740         if (lefthandmorphend != 0)
4741             lefthandmorphness = 0;
4742         lefthandmorphend = 0;
4743         targetlefthandmorphness = 1;
4744
4745         if (headmorphend != 2)
4746             headmorphness = 0;
4747         headmorphend = 2;
4748         targetheadmorphness = 1;
4749     }
4750
4751     if (stunned > 0 && !dead && headmorphend != 2) {
4752         if (headmorphend != 4)
4753             headmorphness = 0;
4754         headmorphend = 4;
4755         targetheadmorphness = 1;
4756     }
4757
4758     if (damage > damagetolerance && !dead) {
4759
4760         dead = 1;
4761         unconscioustime = 0;
4762
4763         if (creature == wolftype) {
4764             award_bonus(0, Wolfbonus);
4765         }
4766
4767         RagDoll(0);
4768
4769         if (weaponactive != -1) {
4770             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4771             weapons[weaponids[0]].velocity.x += .01;
4772             num_weapons--;
4773             if (num_weapons) {
4774                 weaponids[0] = weaponids[num_weapons];
4775                 if (weaponstuck == num_weapons)
4776                     weaponstuck = 0;
4777             }
4778             weaponactive = -1;
4779             for (unsigned i = 0; i < Person::players.size(); i++) {
4780                 Person::players[i]->wentforweapon = 0;
4781             }
4782         }
4783
4784
4785
4786         if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4787             slomo = 1;
4788             slomodelay = .2;
4789         }
4790
4791         damage += 20;
4792     }
4793
4794     if (!dead)
4795         damage -= multiplier * 13;
4796     if (!dead)
4797         permanentdamage -= multiplier * 4;
4798     if (isIdle() || isCrouch()) {
4799         if (!dead)
4800             permanentdamage -= multiplier * 4;
4801     }
4802     if (damage < 0)
4803         damage = 0;
4804     if (permanentdamage < 0)
4805         permanentdamage = 0;
4806     if (superpermanentdamage < 0)
4807         superpermanentdamage = 0;
4808     if (permanentdamage < superpermanentdamage) {
4809         permanentdamage = superpermanentdamage;
4810     }
4811     if (damage < permanentdamage) {
4812         damage = permanentdamage;
4813     }
4814     if (dead == 1 && damage < damagetolerance) {
4815         dead = 0;
4816         skeleton.free = 1;
4817         damage -= 20;
4818         for (int i = 0; i < skeleton.num_joints; i++) {
4819             skeleton.joints[i].velocity = 0;
4820         }
4821     }
4822     if (permanentdamage > damagetolerance && dead != 2) {
4823         DoBlood(1, 255);
4824
4825         if (weaponactive != -1) {
4826             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4827             weapons[weaponids[0]].velocity.x += .01;
4828             num_weapons--;
4829             if (num_weapons) {
4830                 weaponids[0] = weaponids[num_weapons];
4831                 if (weaponstuck == num_weapons)
4832                     weaponstuck = 0;
4833             }
4834             weaponactive = -1;
4835             for (unsigned i = 0; i < Person::players.size(); i++) {
4836                 Person::players[i]->wentforweapon = 0;
4837             }
4838         }
4839
4840         bled = 0;
4841
4842         if (!dead && creature == wolftype) {
4843             award_bonus(0, Wolfbonus);
4844         }
4845
4846         if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4847             award_bonus(id, touchofdeath);
4848         if (id != 0 && unconscioustime > .1) {
4849             numafterkill++;
4850         }
4851
4852         dead = 2;
4853
4854         skeleton.free = 1;
4855
4856         emit_sound_at(breaksound, coords);
4857     }
4858
4859     if (skeleton.free == 1) {
4860         if (id == 0)
4861             pause_sound(whooshsound);
4862
4863         if (!dead) {
4864             //If knocked over, open hands and close mouth
4865             if (righthandmorphend != 0)
4866                 righthandmorphness = 0;
4867             righthandmorphend = 0;
4868             targetrighthandmorphness = 1;
4869
4870             if (lefthandmorphend != 0)
4871                 lefthandmorphness = 0;
4872             lefthandmorphend = 0;
4873             targetlefthandmorphness = 1;
4874
4875             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4876                 if (headmorphend != 0)
4877                     headmorphness = 0;
4878                 headmorphend = 0;
4879                 targetheadmorphness = 1;
4880             }
4881         }
4882
4883         skeleton.DoGravity(&scale);
4884         float damageamount;
4885         damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4886         if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4887             award_bonus(id, deepimpact);
4888         DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4889
4890         average = 0;
4891         howmany = 0;
4892         for (j = 0; j < skeleton.num_joints; j++) {
4893             average += skeleton.joints[j].position;
4894             howmany++;
4895         }
4896         average /= howmany;
4897         coords += average * scale;
4898         for (j = 0; j < skeleton.num_joints; j++) {
4899             skeleton.joints[j].position -= average;
4900         }
4901         average /= multiplier;
4902
4903         velocity = 0;
4904         for (int i = 0; i < skeleton.num_joints; i++) {
4905             velocity += skeleton.joints[i].velocity * scale;
4906         }
4907         velocity /= skeleton.num_joints;
4908
4909         if (!isnormal(velocity.x) && velocity.x) {
4910             velocity = 0;
4911         }
4912
4913         if (findLength(&average) < 10 && dead && skeleton.free) {
4914             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4915             if (skeleton.longdead > 2000) {
4916                 if (skeleton.longdead > 6000) {
4917                     if (id == 0)
4918                         pause_sound(whooshsound);
4919                     skeleton.free = 3;
4920                     DrawSkeleton();
4921                     skeleton.free = 2;
4922                 }
4923                 if (dead == 2 && bloodloss < damagetolerance) {
4924                     XYZ headpoint;
4925                     headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4926                     DoBlood(1, 255);
4927                     if (bloodtoggle && !bled) {
4928                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4929                     }
4930                     if (bloodtoggle && !bled)
4931                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4932                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4933                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4934                             float size = .2 * 1.2;
4935                             float opacity = .6;
4936                             float yaw = 0;
4937                             objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4938                         }
4939                     bled = 1;
4940                 }
4941                 if (dead == 2 && bloodloss >= damagetolerance) {
4942                     XYZ headpoint;
4943                     headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4944                     if (bleeding <= 0)
4945                         DoBlood(1, 255);
4946                     if (bloodtoggle && !bled) {
4947                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4948                     }
4949                     if (bloodtoggle && !bled)
4950                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4951                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4952                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4953                             float size = .8;
4954                             float opacity = .6;
4955                             float yaw = 0;
4956                             objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4957                         }
4958                     bled = 1;
4959                 }
4960             }
4961         }
4962
4963         if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4964             bool canrecover = 1;
4965             XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4966             startpoint = coords;
4967             endpoint = coords;
4968             endpoint.y -= .7;
4969             if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4970                 canrecover = 0;
4971             if (velocity.y < -30)
4972                 canrecover = 0;
4973             for (i = 0; i < objects.numobjects; i++) {
4974                 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4975                     colviewer = startpoint;
4976                     coltarget = endpoint;
4977                     if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4978                         canrecover = 0;
4979                 }
4980             }
4981             if (canrecover) {
4982                 skeleton.free = 0;
4983                 XYZ middle;
4984                 middle = 0;
4985
4986                 terrainnormal = jointPos(groin) - jointPos(abdomen);
4987                 if (joint(groin).locked && joint(abdomen).locked) {
4988                     terrainnormal = jointPos(groin) - jointPos(abdomen);
4989                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4990                 }
4991                 if (joint(abdomen).locked && joint(neck).locked) {
4992                     terrainnormal = jointPos(abdomen) - jointPos(neck);
4993                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4994                 }
4995                 if (joint(groin).locked && joint(neck).locked) {
4996                     terrainnormal = jointPos(groin) - jointPos(neck);
4997                     middle = (jointPos(groin) + jointPos(neck)) / 2;
4998                 }
4999                 Normalise(&terrainnormal);
5000
5001                 targetyaw = -asin(0 - terrainnormal.x);
5002                 targetyaw *= 360 / 6.28;
5003                 if (terrainnormal.z < 0)
5004                     targetyaw = 180 - targetyaw;
5005                 yaw = targetyaw;
5006
5007                 frameTarget = 0;
5008                 animTarget = flipanim;
5009                 crouchtogglekeydown = 1;
5010                 target = 0;
5011                 tilt2 = 0;
5012                 targettilt2 = 0;
5013
5014                 animCurrent = tempanim;
5015                 frameCurrent = 0;
5016                 target = 0;
5017
5018                 for (int i = 0; i < skeleton.num_joints; i++) {
5019                     tempanimation.position[i][0] = skeleton.joints[i].position;
5020                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5021                 }
5022             }
5023         }
5024
5025         if (findLength(&average) < 10 && !dead && skeleton.free) {
5026             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5027             if (skeleton.longdead > (damage + 500) * 1.5) {
5028                 if (id == 0)
5029                     pause_sound(whooshsound);
5030                 skeleton.free = 0;
5031                 velocity = 0;
5032                 XYZ middle;
5033                 middle = 0;
5034
5035                 terrainnormal = jointPos(groin) - jointPos(abdomen);
5036                 if (joint(groin).locked && joint(abdomen).locked) {
5037                     terrainnormal = jointPos(groin) - jointPos(abdomen);
5038                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5039                 }
5040                 if (joint(abdomen).locked && joint(neck).locked) {
5041                     terrainnormal = jointPos(abdomen) - jointPos(neck);
5042                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5043                 }
5044                 if (joint(groin).locked && joint(neck).locked) {
5045                     terrainnormal = jointPos(groin) - jointPos(neck);
5046                     middle = (jointPos(groin) + jointPos(neck)) / 2;
5047                 }
5048                 Normalise(&terrainnormal);
5049
5050                 targetyaw = -asin(0 - terrainnormal.x);
5051                 targetyaw *= 360 / 6.28;
5052                 if (terrainnormal.z < 0)
5053                     targetyaw = 180 - targetyaw;
5054                 yaw = targetyaw;
5055
5056                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5057
5058
5059                 if (skeleton.forward.y < 0) {
5060                     animTarget = getupfrombackanim;
5061                     frameTarget = 0;
5062                     targettilt2 = 0;
5063                 }
5064                 if (skeleton.forward.y > -.3) {
5065                     animTarget = getupfromfrontanim;
5066                     yaw += 180;
5067                     targetyaw += 180;
5068                     targettilt2 *= -1;
5069                     frameTarget = 0;
5070                     targettilt2 = 0;
5071                 }
5072
5073                 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5074                     animTarget = rollanim;
5075                     targetyaw = lookyaw;
5076                     if (id == 0) {
5077                         if (rightkeydown) {
5078                             targetyaw -= 90;
5079                             if (forwardkeydown)
5080                                 targetyaw += 45;
5081                             if (backkeydown)
5082                                 targetyaw -= 45;
5083                         }
5084                         if (leftkeydown) {
5085                             targetyaw += 90;
5086                             if (forwardkeydown)
5087                                 targetyaw -= 45;
5088                             if (backkeydown)
5089                                 targetyaw += 45;
5090                         }
5091                         if (backkeydown) {
5092                             if ( !leftkeydown && !rightkeydown)
5093                                 targetyaw += 180;
5094                         }
5095                         targetyaw += 180;
5096                     }
5097                 }
5098
5099                 if (abs(targettilt2) > 50)
5100                     targettilt2 = 0;
5101                 animCurrent = tempanim;
5102                 frameCurrent = 0;
5103                 target = 0;
5104                 tilt2 = targettilt2;
5105
5106                 if (middle.y > 0 && animTarget != rollanim)
5107                     targetoffset.y = middle.y + 1;
5108
5109                 for (int i = 0; i < skeleton.num_joints; i++) {
5110                     tempanimation.position[i][0] = skeleton.joints[i].position;
5111                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5112                 }
5113             }
5114         }
5115
5116         bool hasstaff;
5117         hasstaff = 0;
5118         if (num_weapons > 0)
5119             if (weapons[0].getType() == staff)
5120                 hasstaff = 1;
5121         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5122             if (velocity.y > -30) {
5123                 XYZ tempvelocity;
5124                 tempvelocity = velocity;
5125                 Normalise(&tempvelocity);
5126                 targetyaw = -asin(0 - tempvelocity.x);
5127                 targetyaw *= 360 / 6.28;
5128                 if (velocity.z < 0)
5129                     targetyaw = 180 - targetyaw;
5130                 //targetyaw+=180;
5131
5132                 skeleton.free = 0;
5133                 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5134                     animTarget = rollanim;
5135                     frameTarget = 2;
5136                 } else {
5137                     animTarget = backhandspringanim;
5138                     targetyaw += 180;
5139                     frameTarget = 6;
5140                 }
5141                 target = 0;
5142
5143                 emit_sound_at(movewhooshsound, coords, 128.);
5144
5145                 animCurrent = animTarget;
5146                 frameCurrent = frameTarget - 1;
5147                 target = 0;
5148
5149                 velocity = 0;
5150
5151                 yaw = targetyaw;
5152                 tilt = 0;
5153                 targettilt = 0;
5154                 tilt2 = 0;
5155                 targettilt2 = 0;
5156             }
5157         }
5158         if (skeleton.freefall == 0)
5159             freefall = 0;
5160
5161     }
5162
5163     if (aitype != passivetype || skeleton.free == 1)
5164         if (findLengthfast(&velocity) > .1)
5165             for (i = 0; i < objects.numobjects; i++) {
5166                 if (objects.type[i] == firetype)
5167                     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) {
5168                         if (onfire) {
5169                             if (!objects.onfire[i]) {
5170                                 emit_sound_at(firestartsound, objects.position[i]);
5171                             }
5172                             objects.onfire[i] = 1;
5173                         }
5174                         if (!onfire) {
5175                             if (objects.onfire[i]) {
5176                                 CatchFire();
5177                             }
5178                         }
5179                     }
5180                 if (objects.type[i] == bushtype)
5181                     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) {
5182                         if (onfire) {
5183                             if (!objects.onfire[i]) {
5184                                 emit_sound_at(firestartsound, objects.position[i]);
5185                             }
5186                             objects.onfire[i] = 1;
5187                         }
5188
5189                         if (!onfire) {
5190                             if (objects.onfire[i]) {
5191                                 CatchFire();
5192                             }
5193                         }
5194                         if (objects.messedwith[i] <= 0) {
5195                             XYZ tempvel;
5196                             XYZ pos;
5197
5198                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5199
5200                             if (id == 0) {
5201                                 addEnvSound(coords, 4 * findLength(&velocity));
5202                             }
5203
5204                             int howmany;
5205                             if (environment == grassyenvironment)
5206                                 howmany = findLength(&velocity) * 4;
5207                             if (environment == snowyenvironment)
5208                                 howmany = findLength(&velocity) * 2;
5209                             if (detail == 2)
5210                                 if (environment != desertenvironment)
5211                                     for (j = 0; j < howmany; j++) {
5212                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5213                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5214                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5215                                         pos = coords;
5216                                         pos.y += 1;
5217                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5218                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5219                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5220                                         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);
5221                                         Sprite::setLastSpriteSpecial(1);
5222                                     }
5223                             howmany = findLength(&velocity) * 4;
5224                             if (detail == 2)
5225                                 if (environment == snowyenvironment)
5226                                     for (j = 0; j < howmany; j++) {
5227                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5228                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5229                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5230                                         pos = coords;
5231                                         pos.y += 1;
5232                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5233                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5234                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5235                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5236                                         Sprite::setLastSpriteSpecial(2);
5237                                     }
5238                         }
5239                         objects.rotx[i] += velocity.x * multiplier * 6;
5240                         objects.roty[i] += velocity.z * multiplier * 6;
5241                         objects.messedwith[i] = .5;
5242                     }
5243                 XYZ tempcoord;
5244                 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5245                     if (objects.pitch[i] == 0)
5246                         tempcoord = coords;
5247                     else {
5248                         tempcoord = coords - objects.position[i];
5249                         tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5250                         tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5251                         tempcoord += objects.position[i];
5252                     }
5253                     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]) {
5254                         if (objects.messedwith[i] <= 0) {
5255                             XYZ tempvel;
5256                             XYZ pos;
5257
5258                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5259
5260                             if (id == 0) {
5261                                 addEnvSound(coords, 4 * findLength(&velocity));
5262                             }
5263
5264                             int howmany;
5265                             if (environment == grassyenvironment)
5266                                 howmany = findLength(&velocity) * 4;
5267                             if (environment == snowyenvironment)
5268                                 howmany = findLength(&velocity) * 2;
5269                             if (detail == 2)
5270                                 if (environment != desertenvironment)
5271                                     for (j = 0; j < howmany; j++) {
5272                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5273                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5274                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5275                                         pos = coords;
5276                                         pos += velocity * .1;
5277                                         pos.y += 1;
5278                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5279                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5280                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5281                                         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);
5282                                         Sprite::setLastSpriteSpecial(1);
5283                                     }
5284                             howmany = findLength(&velocity) * 4;
5285                             if (detail == 2)
5286                                 if (environment == snowyenvironment)
5287                                     for (j = 0; j < howmany; j++) {
5288                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5289                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5290                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5291                                         pos = coords;
5292                                         pos += velocity * .1;
5293                                         pos.y += 1;
5294                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5295                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5296                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5297                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5298                                         Sprite::setLastSpriteSpecial(2);
5299                                     }
5300                         }
5301                         objects.messedwith[i] = .5;
5302                     }
5303                 }
5304             }
5305
5306     if (!skeleton.free) {
5307         bool play;
5308         play = 0;
5309         if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5310             play = 1;
5311         if (hasvictim)
5312             if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5313                 play = 1;
5314         if (tutoriallevel == 1 && id != 0)
5315             play = 0;
5316         if (play && aitype != playercontrolled) {
5317             int whichsound = -1;
5318             i = abs(Random() % 4);
5319             if (speechdelay <= 0) {
5320                 if (creature == rabbittype) {
5321                     if (i == 0)
5322                         whichsound = rabbitchitter;
5323                     if (i == 1)
5324                         whichsound = rabbitchitter2;
5325                 }
5326                 if (creature == wolftype) {
5327                     if (i == 0)
5328                         whichsound = growlsound;
5329                     if (i == 1)
5330                         whichsound = growl2sound;
5331                 }
5332             }
5333             speechdelay = .3;
5334
5335             if (whichsound != -1) {
5336                 emit_sound_at(whichsound, coords);
5337             }
5338         }
5339
5340         if (animTarget == staggerbackhighanim)
5341             staggerdelay = 1;
5342         if (animTarget == staggerbackhardanim)
5343             staggerdelay = 1;
5344         staggerdelay -= multiplier;
5345         if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5346             hasvictim = 1;
5347         if (velocity.y < -30 && animTarget == jumpdownanim)
5348             RagDoll(0);
5349         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5350             animTarget = getIdle();
5351             frameTarget = 0;
5352             target = 0;
5353         }
5354         weaponmissdelay -= multiplier;
5355         highreversaldelay -= multiplier;
5356         lowreversaldelay -= multiplier;
5357         lastcollide -= multiplier;
5358         skiddelay -= multiplier;
5359         if (!isnormal(velocity.x) && velocity.x) {
5360             velocity = 0;
5361         }
5362         if (!isnormal(targettilt) && targettilt) {
5363             targettilt = 0;
5364         }
5365         if (!isnormal(targettilt2) && targettilt2) {
5366             targettilt2 = 0;
5367         }
5368         if (!isnormal(targetyaw) && targetyaw) {
5369             targetyaw = 0;
5370         }
5371
5372         if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5373             //open hands and close mouth
5374             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5375                 righthandmorphness = 0;
5376                 righthandmorphend = 0;
5377                 targetrighthandmorphness = 1;
5378             }
5379
5380             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5381                 lefthandmorphness = 0;
5382                 lefthandmorphend = 0;
5383                 targetlefthandmorphness = 1;
5384             }
5385
5386             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5387                 headmorphness = 0;
5388                 headmorphend = 0;
5389                 targetheadmorphness = 1;
5390             }
5391         }
5392
5393         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) {
5394             //open hands and mouth
5395             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5396                 righthandmorphness = 0;
5397                 righthandmorphend = 0;
5398                 targetrighthandmorphness = 1;
5399             }
5400
5401             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5402                 lefthandmorphness = 0;
5403                 lefthandmorphend = 0;
5404                 targetlefthandmorphness = 1;
5405             }
5406
5407             if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5408                 headmorphness = 0;
5409                 headmorphend = 1;
5410                 targetheadmorphness = 1;
5411             }
5412         }
5413
5414         if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5415             //close hands and mouth
5416             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5417                 righthandmorphness = 0;
5418                 righthandmorphend = 1;
5419                 targetrighthandmorphness = 1;
5420             }
5421
5422             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5423                 lefthandmorphness = 0;
5424                 lefthandmorphend = 1;
5425                 targetlefthandmorphness = 1;
5426             }
5427
5428             if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5429                 headmorphness = 0;
5430                 headmorphend = 0;
5431                 targetheadmorphness = 1;
5432             }
5433         }
5434
5435         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) {
5436             //close hands and yell
5437             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5438                 righthandmorphness = 0;
5439                 righthandmorphend = 1;
5440                 targetrighthandmorphness = 1;
5441             }
5442
5443             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5444                 lefthandmorphness = 0;
5445                 lefthandmorphend = 1;
5446                 targetlefthandmorphness = 1;
5447             }
5448
5449             if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5450                 headmorphness = 1;
5451                 headmorphend = 2;
5452                 targetheadmorphness = 1;
5453             }
5454         }
5455
5456         bool behind;
5457         behind = 0;
5458         if (hasvictim) {
5459             if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5460                 (victim->aitype != searchtype) && (aitype != passivetype) &&
5461                 (aitype != searchtype) && (victim->id < Person::players.size())) {
5462                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5463             }
5464         }
5465
5466         if (!dead && animTarget != hurtidleanim)
5467             if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5468                 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5469                     headmorphend = 4;
5470                     //headmorphness=1;
5471                     targetheadmorphness = 1;
5472                 }
5473             }
5474
5475         if (weaponactive != -1) {
5476             if (weapons[weaponids[weaponactive]].getType() != staff) {
5477                 righthandmorphstart = 1;
5478                 righthandmorphend = 1;
5479             }
5480             if (weapons[weaponids[weaponactive]].getType() == staff) {
5481                 righthandmorphstart = 2;
5482                 righthandmorphend = 2;
5483             }
5484             targetrighthandmorphness = 1;
5485         }
5486
5487         terrainnormal = terrain.getNormal(coords.x, coords.z);
5488
5489         if (animation[animTarget].attack != reversal) {
5490             if (!isnormal(coords.x))
5491                 coords = oldcoords;
5492             oldcoords = coords;
5493         }
5494
5495         flatfacing = 0;
5496         flatfacing.z = 1;
5497
5498         flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5499         facing = flatfacing;
5500         ReflectVector(&facing, terrainnormal);
5501         Normalise(&facing);
5502
5503         if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5504             if (onterrain)
5505                 targettilt2 = -facing.y * 20;
5506             else
5507                 targettilt2 = 0;
5508         }
5509         onterrain = 0;
5510         if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5511             targettilt2 = 0;
5512         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5513             flatvelocity = velocity;
5514             flatvelocity.y = 0;
5515             flatvelspeed = findLength(&flatvelocity);
5516             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5517             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5518             if (velocity.y < 0)
5519                 targettilt2 *= -1;
5520             if (velocity.y < 0)
5521                 targettilt *= -1;
5522             if (targettilt > 25)
5523                 targettilt = 25;
5524             if (targettilt < -25)
5525                 targettilt = -25;
5526         }
5527
5528         if (targettilt2 > 45)
5529             targettilt2 = 45;
5530         if (targettilt2 < -45)
5531             targettilt2 = -45;
5532         if (abs(tilt2 - targettilt2) < multiplier * 400)
5533             tilt2 = targettilt2;
5534         else if (tilt2 > targettilt2) {
5535             tilt2 -= multiplier * 400;
5536         } else if (tilt2 < targettilt2) {
5537             tilt2 += multiplier * 400;
5538         }
5539         if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5540             if (tilt2 > 25)
5541                 tilt2 = 25;
5542             if (tilt2 < -25)
5543                 tilt2 = -25;
5544         }
5545
5546         if (!isnormal(targettilt) && targettilt) {
5547             targettilt = 0;
5548         }
5549         if (!isnormal(targettilt2) && targettilt2) {
5550             targettilt2 = 0;
5551         }
5552
5553         //Running velocity
5554         if (animTarget == rabbittackleanim) {
5555             velocity += facing * multiplier * speed * 700 * scale;
5556             velspeed = findLength(&velocity);
5557             if (velspeed > speed * 65 * scale) {
5558                 velocity /= velspeed;
5559                 velspeed = speed * 65 * scale;
5560                 velocity *= velspeed;
5561             }
5562             velocity.y += gravity * multiplier * 20;
5563             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5564             velspeed = findLength(&velocity);
5565             velocity = flatfacing * velspeed;
5566         }
5567         if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5568             if (isRun() || animTarget == rabbitkickanim) {
5569                 velocity += facing * multiplier * speed * 700 * scale;
5570                 velspeed = findLength(&velocity);
5571                 if (velspeed > speed * 45 * scale) {
5572                     velocity /= velspeed;
5573                     velspeed = speed * 45 * scale;
5574                     velocity *= velspeed;
5575                 }
5576                 velocity.y += gravity * multiplier * 20;
5577                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5578                 velspeed = findLength(&velocity);
5579                 if (velspeed < speed * 30 * scale)
5580                     velspeed = speed * 30 * scale;
5581                 velocity = flatfacing * velspeed;
5582             }
5583         } else if (isRun()) {
5584             velocity += facing * multiplier * speed * 700 * scale;
5585             velspeed = findLength(&velocity);
5586             if (creature == rabbittype) {
5587                 if (velspeed > speed * 55 * scale) {
5588                     velocity /= velspeed;
5589                     velspeed = speed * 55 * scale;
5590                     velocity *= velspeed;
5591                 }
5592             }
5593             if (creature == wolftype) {
5594                 if (velspeed > speed * 75 * scale) {
5595                     velocity /= velspeed;
5596                     velspeed = speed * 75 * scale;
5597                     velocity *= velspeed;
5598                 }
5599             }
5600             velocity.y += gravity * multiplier * 20;
5601             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5602             velspeed = findLength(&velocity);
5603             velocity = flatfacing * velspeed;
5604         }
5605
5606         if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5607             velocity += facing * multiplier * speed * 700 * scale;
5608             velspeed = findLength(&velocity);
5609             if (velspeed > speed * 45 * scale) {
5610                 velocity /= velspeed;
5611                 velspeed = speed * 45 * scale;
5612                 velocity *= velspeed;
5613             }
5614             velocity.y += gravity * multiplier * 20;
5615             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5616             velspeed = findLength(&velocity);
5617             velocity = flatfacing * velspeed;
5618         }
5619
5620         if (animTarget == sneakanim || animTarget == walkanim) {
5621             velocity += facing * multiplier * speed * 700 * scale;
5622             velspeed = findLength(&velocity);
5623             if (velspeed > speed * 12 * scale) {
5624                 velocity /= velspeed;
5625                 velspeed = speed * 12 * scale;
5626                 velocity *= velspeed;
5627             }
5628             velocity.y += gravity * multiplier * 20;
5629             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5630             velspeed = findLength(&velocity);
5631             velocity = flatfacing * velspeed;
5632         }
5633
5634         if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5635             velocity += facing * multiplier * speed * 700 * scale;
5636             velspeed = findLength(&velocity);
5637             if (velspeed > speed * 2 * scale) {
5638                 velocity /= velspeed;
5639                 velspeed = speed * 2 * scale;
5640                 velocity *= velspeed;
5641             }
5642             velocity.y += gravity * multiplier * 20;
5643             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5644             velspeed = findLength(&velocity);
5645             velocity = flatfacing * velspeed;
5646         }
5647
5648
5649         if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5650             velocity -= facing * multiplier * speed * 700 * scale;
5651             velspeed = findLength(&velocity);
5652             if (velspeed > speed * 2 * scale) {
5653                 velocity /= velspeed;
5654                 velspeed = speed * 2 * scale;
5655                 velocity *= velspeed;
5656             }
5657             velocity.y += gravity * multiplier * 20;
5658             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5659             velspeed = findLength(&velocity);
5660             velocity = flatfacing * velspeed * -1;
5661         }
5662
5663         if (animTarget == fightsidestep) {
5664             velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5665             velspeed = findLength(&velocity);
5666             if (velspeed > speed * 12 * scale) {
5667                 velocity /= velspeed;
5668                 velspeed = speed * 12 * scale;
5669                 velocity *= velspeed;
5670             }
5671             velocity.y += gravity * multiplier * 20;
5672             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5673             velspeed = findLength(&velocity);
5674             velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5675         }
5676
5677         if (animTarget == staggerbackhighanim) {
5678             coords -= facing * multiplier * speed * 16 * scale;
5679             velocity = 0;
5680         }
5681         if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5682             coords -= facing * multiplier * speed * 20 * scale;
5683             velocity = 0;
5684         }
5685
5686         if (animTarget == backhandspringanim) {
5687             //coords-=facing*multiplier*50*scale;
5688             velocity += facing * multiplier * speed * 700 * scale * -1;
5689             velspeed = findLength(&velocity);
5690             if (velspeed > speed * 50 * scale) {
5691                 velocity /= velspeed;
5692                 velspeed = speed * 50 * scale;
5693                 velocity *= velspeed;
5694             }
5695             velocity.y += gravity * multiplier * 20;
5696             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5697             velspeed = findLength(&velocity);
5698             velocity = flatfacing * velspeed * -1;
5699         }
5700         if (animTarget == dodgebackanim) {
5701             //coords-=facing*multiplier*50*scale;
5702             velocity += facing * multiplier * speed * 700 * scale * -1;
5703             velspeed = findLength(&velocity);
5704             if (velspeed > speed * 60 * scale) {
5705                 velocity /= velspeed;
5706                 velspeed = speed * 60 * scale;
5707                 velocity *= velspeed;
5708             }
5709             velocity.y += gravity * multiplier * 20;
5710             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5711             velspeed = findLength(&velocity);
5712             velocity = flatfacing * velspeed * -1;
5713         }
5714
5715         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5716             velspeed = findLength(&velocity);
5717         }
5718
5719
5720         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5721             velocity.y += gravity * multiplier;
5722         }
5723
5724         if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5725             coords += velocity * multiplier;
5726
5727         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5728             if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5729                 RagDoll(0);
5730
5731             if (animTarget == jumpupanim) {
5732                 jumppower = -4;
5733                 animTarget = getIdle();
5734             }
5735             target = 0;
5736             frameTarget = 0;
5737             onterrain = 1;
5738
5739             if (id == 0) {
5740                 pause_sound(whooshsound);
5741                 OPENAL_SetVolume(channels[whooshsound], 0);
5742             }
5743
5744             if (animTarget == jumpdownanim || isFlip()) {
5745                 if (isFlip())jumppower = -4;
5746                 animTarget = getLanding();
5747                 emit_sound_at(landsound, coords, 128.);
5748
5749                 if (id == 0) {
5750                     addEnvSound(coords);
5751                 }
5752             }
5753         }
5754
5755         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5756             coords.y += gravity * multiplier * 2;
5757         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5758             coords.y = terrain.getHeight(coords.x, coords.z);
5759             onterrain = 1;
5760         }
5761
5762
5763         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)) {
5764             velspeed = findLength(&velocity);
5765             velocity.y = 0;
5766             if (velspeed < multiplier * 300 * scale) {
5767                 velocity = 0;
5768             } else
5769                 velocity -= velocity / velspeed * multiplier * 300 * scale;
5770             if (velspeed > 5 && (isLanding() || isLandhard())) {
5771                 skiddingdelay += multiplier;
5772                 if (skiddelay <= 0) {
5773                     FootLand(0, .5);
5774                     FootLand(1, .5);
5775                     skiddelay = .02;
5776                 }
5777             } else
5778                 skiddingdelay = 0;
5779         }
5780
5781         if (isLandhard()) {
5782             velspeed = findLength(&velocity);
5783             velocity.y = 0;
5784             if (velspeed < multiplier * 600 * scale) {
5785                 velocity = 0;
5786             } else
5787                 velocity -= velocity / velspeed * multiplier * 600 * scale;
5788             velocity = 0;
5789             if (velspeed > 5 && (isLanding() || isLandhard())) {
5790                 skiddingdelay += multiplier;
5791                 if (skiddelay <= 0) {
5792                     FootLand(0, .5);
5793                     FootLand(1, .5);
5794                     skiddelay = .02;
5795                 }
5796             } else
5797                 skiddingdelay = 0;
5798         }
5799
5800         if (skiddingdelay < 0)
5801             skiddingdelay += multiplier;
5802         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5803             skiddingdelay = -1;
5804             if (!onterrain || environment == grassyenvironment) {
5805                 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5806             } else {
5807                 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5808             }
5809         }
5810
5811         if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5812             terrainnormal = victim->coords - coords;
5813             Normalise(&terrainnormal);
5814             targetyaw = -asin(0 - terrainnormal.x);
5815             targetyaw *= 360 / 6.28;
5816             if (terrainnormal.z < 0)
5817                 targetyaw = 180 - targetyaw;
5818             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5819         }
5820
5821         if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5822             targetyaw = victim->targetyaw;
5823         }
5824         if (animTarget == rabbittacklinganim) {
5825             coords = victim->coords;
5826         }
5827     }
5828     skeleton.oldfree = skeleton.free;
5829
5830     XYZ midterrain;
5831     midterrain = 0;
5832     midterrain.x = terrain.size * terrain.scale / 2;
5833     midterrain.z = terrain.size * terrain.scale / 2;
5834     if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5835         XYZ tempposit;
5836         tempposit = coords - midterrain;
5837         tempposit.y = 0;
5838         Normalise(&tempposit);
5839         tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5840         coords.x = tempposit.x + midterrain.x;
5841         coords.z = tempposit.z + midterrain.z;
5842     }
5843 }
5844
5845
5846 /* EFFECT
5847  * inverse kinematics helper function
5848  */
5849 void IKHelper(Person *p, float interp)
5850 {
5851     XYZ point, change, change2;
5852     float heightleft, heightright;
5853
5854     // TODO: implement localToWorld and worldToLocal
5855     //       but keep in mind it won't be the same math if player is ragdolled or something
5856     //       - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5857     //       then comb through code for places where to use it
5858
5859     // point = localToWorld(jointPos(leftfoot))
5860     point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5861     // adjust height of foot
5862     heightleft = terrain.getHeight(point.x, point.z) + .04;
5863     point.y = heightleft;
5864     change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5865     change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5866     // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5867     p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5868     // move ankle along with foot
5869     p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5870     // average knee pos between old and new pos
5871     p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5872
5873     // do same as above for right leg
5874     point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5875     heightright = terrain.getHeight(point.x, point.z) + .04;
5876     point.y = heightright;
5877     change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5878     change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5879     p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5880     p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5881     p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5882
5883     // fix up skeleton now that we've moved body parts?
5884     p->skeleton.DoConstraints(&p->coords, &p->scale);
5885 }
5886
5887 /* EFFECT
5888  * MONSTER
5889  * TODO: ???
5890  */
5891 int Person::DrawSkeleton()
5892 {
5893     int oldplayerdetail;
5894     if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5895         if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5896             calcrot = 1;
5897         }
5898
5899         if (headless) {
5900             headmorphness = 0;
5901             headmorphstart = 6;
5902             headmorphend = 6;
5903         }
5904
5905         glAlphaFunc(GL_GREATER, 0.0001);
5906         XYZ terrainlight;
5907         float terrainheight;
5908         float distance;
5909         if (!isnormal(yaw))
5910             yaw = 0;
5911         if (!isnormal(tilt))
5912             tilt = 0;
5913         if (!isnormal(tilt2))
5914             tilt2 = 0;
5915         oldplayerdetail = playerdetail;
5916         playerdetail = 0;
5917         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5918             playerdetail = 1;
5919         }
5920         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5921             playerdetail = 1;
5922         }
5923         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5924             playerdetail = 1;
5925         }
5926         if (id == 0)
5927             playerdetail = 1;
5928         if (playerdetail != oldplayerdetail) {
5929             updatedelay = 0;
5930             normalsupdatedelay = 0;
5931         }
5932         static float updatedelaychange;
5933         static float morphness;
5934         static float framemult;
5935         if (calcrot) {
5936             skeleton.FindForwards();
5937             if (howactive == typesittingwall) {
5938                 skeleton.specialforward[1] = 0;
5939                 skeleton.specialforward[1].z = 1;
5940             }
5941         }
5942         static XYZ mid;
5943         static float M[16];
5944         static int i, j, k;
5945         static int weaponattachmuscle;
5946         static int weaponrotatemuscle;
5947         static XYZ weaponpoint;
5948         static int start, endthing;
5949         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5950             if (!isSleeping() && !isSitting()) {
5951                 // TODO: give these meaningful names
5952                 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5953                                     || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5954                 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5955                                     || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5956
5957                 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5958                     IKHelper(this, 1);
5959                     if (creature == wolftype)
5960                         IKHelper(this, 1);
5961                 }
5962
5963                 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5964                     IKHelper(this, target);
5965                     if (creature == wolftype)
5966                         IKHelper(this, target);
5967                 }
5968
5969                 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5970                     IKHelper(this, 1 - target);
5971                     if (creature == wolftype)
5972                         IKHelper(this, 1 - target);
5973                 }
5974             }
5975
5976             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()))
5977                 DoHead();
5978             else {
5979                 targetheadyaw = -targetyaw;
5980                 targetheadpitch = 0;
5981                 if (animation[animTarget].attack == 3)
5982                     targetheadyaw += 180;
5983             }
5984             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5985                 skeleton.drawmodel.vertex[i] = 0;
5986                 skeleton.drawmodel.vertex[i].y = 999;
5987             }
5988             for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5989                 skeleton.drawmodellow.vertex[i] = 0;
5990                 skeleton.drawmodellow.vertex[i].y = 999;
5991             }
5992             for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5993                 skeleton.drawmodelclothes.vertex[i] = 0;
5994                 skeleton.drawmodelclothes.vertex[i].y = 999;
5995             }
5996             for (int i = 0; i < skeleton.num_muscles; i++) {
5997                 // convenience renames
5998                 const int p1 = skeleton.muscles[i].parent1->label;
5999                 const int p2 = skeleton.muscles[i].parent2->label;
6000
6001                 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6002                     morphness = 0;
6003                     start = 0;
6004                     endthing = 0;
6005
6006                     if (p1 == righthand || p2 == righthand) {
6007                         morphness = righthandmorphness;
6008                         start = righthandmorphstart;
6009                         endthing = righthandmorphend;
6010                     }
6011                     if (p1 == lefthand || p2 == lefthand) {
6012                         morphness = lefthandmorphness;
6013                         start = lefthandmorphstart;
6014                         endthing = lefthandmorphend;
6015                     }
6016                     if (p1 == head || p2 == head) {
6017                         morphness = headmorphness;
6018                         start = headmorphstart;
6019                         endthing = headmorphend;
6020                     }
6021                     if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6022                         morphness = chestmorphness;
6023                         start = chestmorphstart;
6024                         endthing = chestmorphend;
6025                     }
6026                     if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6027                         morphness = tailmorphness;
6028                         start = tailmorphstart;
6029                         endthing = tailmorphend;
6030                     }
6031                     if (calcrot)
6032                         skeleton.FindRotationMuscle(i, animTarget);
6033                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6034                     glMatrixMode(GL_MODELVIEW);
6035                     glPushMatrix();
6036                     glLoadIdentity();
6037                     if (!skeleton.free)
6038                         glRotatef(tilt2, 1, 0, 0);
6039                     if (!skeleton.free)
6040                         glRotatef(tilt, 0, 0, 1);
6041
6042
6043                     glTranslatef(mid.x, mid.y, mid.z);
6044
6045                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6046                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6047
6048                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6049                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6050
6051                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6052                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6053
6054                     if (playerdetail || skeleton.free == 3) {
6055                         for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6056                             XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6057                             XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6058                             glMatrixMode(GL_MODELVIEW);
6059                             glPushMatrix();
6060                             if (p1 == abdomen || p2 == abdomen)
6061                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6062                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6063                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6064                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6065                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6066                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6067                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6068                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6069                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6070                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6071                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6072                             if (p1 == head || p2 == head)
6073                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6074                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6075                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6076                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6077                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6078                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6079                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6080                             glPopMatrix();
6081                         }
6082                     }
6083                     if (!playerdetail || skeleton.free == 3) {
6084                         for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6085                             XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6086                             glMatrixMode(GL_MODELVIEW);
6087                             glPushMatrix();
6088                             if (p1 == abdomen || p2 == abdomen)
6089                                 glTranslatef(v0.x * proportionbody.x,
6090                                              v0.y * proportionbody.y,
6091                                              v0.z * proportionbody.z);
6092                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6093                                 glTranslatef(v0.x * proportionarms.x,
6094                                              v0.y * proportionarms.y,
6095                                              v0.z * proportionarms.z);
6096                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6097                                 glTranslatef(v0.x * proportionlegs.x,
6098                                              v0.y * proportionlegs.y,
6099                                              v0.z * proportionlegs.z);
6100                             if (p1 == head || p2 == head)
6101                                 glTranslatef(v0.x * proportionhead.x,
6102                                              v0.y * proportionhead.y,
6103                                              v0.z * proportionhead.z);
6104
6105                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6106                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6107                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6108                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6109                             glPopMatrix();
6110                         }
6111                     }
6112                     glPopMatrix();
6113                 }
6114                 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6115                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6116
6117                     glMatrixMode(GL_MODELVIEW);
6118                     glPushMatrix();
6119                     glLoadIdentity();
6120                     if (!skeleton.free)
6121                         glRotatef(tilt2, 1, 0, 0);
6122                     if (!skeleton.free)
6123                         glRotatef(tilt, 0, 0, 1);
6124                     glTranslatef(mid.x, mid.y, mid.z);
6125                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6126                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6127
6128                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6129                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6130
6131                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6132                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6133
6134                     for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6135                         XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6136                         glMatrixMode(GL_MODELVIEW);
6137                         glPushMatrix();
6138                         if (p1 == abdomen || p2 == abdomen)
6139                             glTranslatef(v0.x * proportionbody.x,
6140                                          v0.y * proportionbody.y,
6141                                          v0.z * proportionbody.z);
6142                         if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6143                             glTranslatef(v0.x * proportionarms.x,
6144                                          v0.y * proportionarms.y,
6145                                          v0.z * proportionarms.z);
6146                         if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6147                             glTranslatef(v0.x * proportionlegs.x,
6148                                          v0.y * proportionlegs.y,
6149                                          v0.z * proportionlegs.z);
6150                         if (p1 == head || p2 == head)
6151                             glTranslatef(v0.x * proportionhead.x,
6152                                          v0.y * proportionhead.y,
6153                                          v0.z * proportionhead.z);
6154                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
6155                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6156                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6157                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6158                         glPopMatrix();
6159                     }
6160                     glPopMatrix();
6161                 }
6162                 updatedelay = 1 + (float)(Random() % 100) / 1000;
6163             }
6164             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6165                 normalsupdatedelay = 1;
6166                 if (playerdetail || skeleton.free == 3)
6167                     skeleton.drawmodel.CalculateNormals(0);
6168                 if (!playerdetail || skeleton.free == 3)
6169                     skeleton.drawmodellow.CalculateNormals(0);
6170                 if (skeleton.clothes)
6171                     skeleton.drawmodelclothes.CalculateNormals(0);
6172             } else {
6173                 if (playerdetail || skeleton.free == 3)
6174                     skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6175                 if (!playerdetail || skeleton.free == 3)
6176                     skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6177                 if (skeleton.clothes) {
6178                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6179                 }
6180             }
6181         }
6182         framemult = .01;
6183         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6184         if (updatedelaychange > -realmultiplier * 30)
6185             updatedelaychange = -realmultiplier * 30;
6186         if (updatedelaychange > -framemult * 4)
6187             updatedelaychange = -framemult * 4;
6188         if (skeleton.free == 1)
6189             updatedelaychange *= 6;
6190         if (id == 0)
6191             updatedelaychange *= 8;
6192         updatedelay += updatedelaychange;
6193
6194         glMatrixMode(GL_MODELVIEW);
6195         glPushMatrix();
6196         glTranslatef(coords.x, coords.y - .02, coords.z);
6197         if (!skeleton.free) {
6198             glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6199             glRotatef(yaw, 0, 1, 0);
6200         }
6201         if (showpoints) {
6202             glPointSize(5);
6203             glColor4f(.4, 1, .4, 1);
6204             glDisable(GL_LIGHTING);
6205             glDisable(GL_TEXTURE_2D);
6206             glBegin(GL_POINTS);
6207             if (playerdetail)
6208                 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6209                     XYZ &v0 = skeleton.drawmodel.vertex[i];
6210                     glVertex3f(v0.x, v0.y, v0.z);
6211                 }
6212             glEnd();
6213             glBegin(GL_LINES);
6214
6215             if (playerdetail)
6216                 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6217                     XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6218                     XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6219                     XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6220                     glVertex3f(v0.x, v0.y, v0.z);
6221                     glVertex3f(v1.x, v1.y, v1.z);
6222                     glVertex3f(v1.x, v1.y, v1.z);
6223                     glVertex3f(v2.x, v2.y, v2.z);
6224                     glVertex3f(v2.x, v2.y, v2.z);
6225                     glVertex3f(v0.x, v0.y, v0.z);
6226                 }
6227
6228             glEnd();
6229         }
6230
6231         terrainlight = terrain.getLighting(coords.x, coords.z);
6232         distance = distsq(&viewer, &coords);
6233         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6234         if (distance > 1)
6235             distance = 1;
6236         if (distance > 0) {
6237             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6238             if (terrainheight < 1)
6239                 terrainheight = 1;
6240             if (terrainheight > 1.7)
6241                 terrainheight = 1.7;
6242
6243             //burnt=0;
6244             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6245             glDisable(GL_BLEND);
6246             glAlphaFunc(GL_GREATER, 0.0001);
6247             glEnable(GL_TEXTURE_2D);
6248             if (cellophane) {
6249                 glDisable(GL_TEXTURE_2D);
6250                 glColor4f(.7, .35, 0, .5);
6251                 glDepthMask(0);
6252                 glEnable(GL_LIGHTING);
6253                 glEnable(GL_BLEND);
6254             }
6255             if (tutoriallevel && id != 0) {
6256                 glColor4f(.7, .7, .7, 0.6);
6257                 glDepthMask(0);
6258                 glEnable(GL_LIGHTING);
6259                 glEnable(GL_BLEND);
6260                 if (canattack && cananger)
6261                     if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6262                         glDisable(GL_TEXTURE_2D);
6263                         glColor4f(1, 0, 0, 0.8);
6264                     }
6265                 glMatrixMode(GL_TEXTURE);
6266                 glPushMatrix();
6267                 glTranslatef(0, -smoketex, 0);
6268                 glTranslatef(-smoketex, 0, 0);
6269             }
6270             if (playerdetail) {
6271                 if (!showpoints) {
6272                     if ((tutoriallevel && id != 0))
6273                         skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6274                     else
6275                         skeleton.drawmodel.draw();
6276                 }
6277             }
6278             if (!playerdetail) {
6279                 if ((tutoriallevel && id != 0))
6280                     skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6281                 else
6282                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6283             }
6284
6285             if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6286                 if (tutoriallevel && id != 0) {
6287                     glPopMatrix();
6288                     glMatrixMode(GL_MODELVIEW);
6289                     glEnable(GL_TEXTURE_2D);
6290                     glColor4f(.7, .7, .7, 0.6);
6291                     glDepthMask(0);
6292                     glEnable(GL_LIGHTING);
6293                     glEnable(GL_BLEND);
6294                     if (canattack && cananger)
6295                         if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6296                             glDisable(GL_TEXTURE_2D);
6297                             glColor4f(1, 0, 0, 0.8);
6298                         }
6299                     glMatrixMode(GL_TEXTURE);
6300                     glPushMatrix();
6301                     glTranslatef(0, -smoketex * .6, 0);
6302                     glTranslatef(smoketex * .6, 0, 0);
6303                     if (playerdetail) {
6304                         if (!showpoints) {
6305                             if ((tutoriallevel && id != 0))
6306                                 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6307                             else
6308                                 skeleton.drawmodel.draw();
6309                         }
6310                     }
6311                     if (!playerdetail) {
6312                         if ((tutoriallevel && id != 0))
6313                             skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6314                         else
6315                             skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6316                     }
6317                 }
6318
6319
6320             if (tutoriallevel && id != 0) {
6321                 glPopMatrix();
6322                 glMatrixMode(GL_MODELVIEW);
6323                 glEnable(GL_TEXTURE_2D);
6324             }
6325             if (skeleton.clothes) {
6326                 glDepthMask(0);
6327                 glEnable(GL_BLEND);
6328                 if (!immediate)
6329                     skeleton.drawmodelclothes.draw();
6330                 if (immediate)
6331                     skeleton.drawmodelclothes.drawimmediate();
6332                 glDepthMask(1);
6333             }
6334         }
6335         glPopMatrix();
6336
6337         if (num_weapons > 0) {
6338             for (k = 0; k < num_weapons; k++) {
6339                 i = weaponids[k];
6340                 if (weaponactive == k) {
6341                     if (weapons[i].getType() != staff) {
6342                         for (j = 0; j < skeleton.num_muscles; j++) {
6343                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6344                                 weaponattachmuscle = j;
6345                             }
6346                         }
6347                         for (j = 0; j < skeleton.num_muscles; j++) {
6348                             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) {
6349                                 weaponrotatemuscle = j;
6350                             }
6351                         }
6352                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6353                         if (creature == wolftype)
6354                             weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6355                     }
6356                     if (weapons[i].getType() == staff) {
6357                         for (j = 0; j < skeleton.num_muscles; j++) {
6358                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6359                                 weaponattachmuscle = j;
6360                             }
6361                         }
6362                         for (j = 0; j < skeleton.num_muscles; j++) {
6363                             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) {
6364                                 weaponrotatemuscle = j;
6365                             }
6366                         }
6367                         //weaponpoint=jointPos(rightwrist);
6368                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6369                         //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6370                         XYZ tempnormthing, vec1, vec2;
6371                         vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6372                         vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6373                         CrossProduct(&vec1, &vec2, &tempnormthing);
6374                         Normalise(&tempnormthing);
6375                         if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6376                             weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6377                     }
6378                 }
6379                 if (weaponactive != k && weaponstuck != k) {
6380                     if (weapons[i].getType() == knife)
6381                         weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6382                     if (weapons[i].getType() == sword)
6383                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6384                     if (weapons[i].getType() == staff)
6385                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6386                     for (j = 0; j < skeleton.num_muscles; j++) {
6387                         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) {
6388                             weaponrotatemuscle = j;
6389                         }
6390                     }
6391                 }
6392                 if (weaponstuck == k) {
6393                     if (weaponstuckwhere == 0)
6394                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6395                     else
6396                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6397                     for (j = 0; j < skeleton.num_muscles; j++) {
6398                         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) {
6399                             weaponrotatemuscle = j;
6400                         }
6401                     }
6402                 }
6403                 if (skeleton.free) {
6404                     weapons[i].position = weaponpoint * scale + coords;
6405                     weapons[i].bigrotation = 0;
6406                     weapons[i].bigtilt = 0;
6407                     weapons[i].bigtilt2 = 0;
6408                 } else {
6409                     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;
6410                     weapons[i].bigrotation = yaw;
6411                     weapons[i].bigtilt = tilt;
6412                     weapons[i].bigtilt2 = tilt2;
6413                 }
6414                 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6415                 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6416                 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6417                 if (weaponactive == k) {
6418                     if (weapons[i].getType() == knife) {
6419                         weapons[i].smallrotation = 180;
6420                         weapons[i].smallrotation2 = 0;
6421                         if (isCrouch() || wasCrouch()) {
6422                             weapons[i].smallrotation2 = 20;
6423                         }
6424                         if (animTarget == hurtidleanim) {
6425                             weapons[i].smallrotation2 = 50;
6426                         }
6427                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6428                             XYZ temppoint1, temppoint2;
6429                             float distance;
6430
6431                             temppoint1 = jointPos(righthand);
6432                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6433                             distance = findDistance(&temppoint1, &temppoint2);
6434                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6435                             weapons[i].rotation2 *= 360 / 6.28;
6436                             temppoint1.y = 0;
6437                             temppoint2.y = 0;
6438                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6439                             weapons[i].rotation1 *= 360 / 6.28;
6440                             weapons[i].rotation3 = 0;
6441                             weapons[i].smallrotation = -90;
6442                             weapons[i].smallrotation2 = 0;
6443                             if (temppoint1.x > temppoint2.x)
6444                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6445                         }
6446                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6447                             XYZ temppoint1, temppoint2;
6448                             float distance;
6449
6450                             temppoint1 = jointPos(righthand);
6451                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6452                             distance = findDistance(&temppoint1, &temppoint2);
6453                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6454                             weapons[i].rotation2 *= 360 / 6.28;
6455                             temppoint1.y = 0;
6456                             temppoint2.y = 0;
6457                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6458                             weapons[i].rotation1 *= 360 / 6.28;
6459                             weapons[i].rotation3 = 0;
6460                             weapons[i].smallrotation = 90;
6461                             weapons[i].smallrotation2 = 0;
6462                             if (temppoint1.x > temppoint2.x)
6463                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6464                         }
6465                         if (animTarget == knifethrowanim) {
6466                             weapons[i].smallrotation = 90;
6467                             //weapons[i].smallrotation2=-90;
6468                             weapons[i].smallrotation2 = 0;
6469                             weapons[i].rotation1 = 0;
6470                             weapons[i].rotation2 = 0;
6471                             weapons[i].rotation3 = 0;
6472                         }
6473                         if (animTarget == knifesneakattackanim && frameTarget < 5) {
6474                             weapons[i].smallrotation = -90;
6475                             weapons[i].rotation1 = 0;
6476                             weapons[i].rotation2 = 0;
6477                             weapons[i].rotation3 = 0;
6478                         }
6479                     }
6480                     if (weapons[i].getType() == sword) {
6481                         weapons[i].smallrotation = 0;
6482                         weapons[i].smallrotation2 = 0;
6483                         if (animTarget == knifethrowanim) {
6484                             weapons[i].smallrotation = -90;
6485                             weapons[i].smallrotation2 = 0;
6486                             weapons[i].rotation1 = 0;
6487                             weapons[i].rotation2 = 0;
6488                             weapons[i].rotation3 = 0;
6489                         }
6490                         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)) {
6491                             XYZ temppoint1, temppoint2;
6492                             float distance;
6493
6494                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6495                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6496                             distance = findDistance(&temppoint1, &temppoint2);
6497                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6498                             weapons[i].rotation2 *= 360 / 6.28;
6499                             temppoint1.y = 0;
6500                             temppoint2.y = 0;
6501                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6502                             weapons[i].rotation1 *= 360 / 6.28;
6503                             weapons[i].rotation3 = 0;
6504                             weapons[i].smallrotation = 90;
6505                             weapons[i].smallrotation2 = 0;
6506                             if (temppoint1.x > temppoint2.x)
6507                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6508                         }
6509                     }
6510                     if (weapons[i].getType() == staff) {
6511                         weapons[i].smallrotation = 100;
6512                         weapons[i].smallrotation2 = 0;
6513                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6514                             XYZ temppoint1, temppoint2;
6515                             float distance;
6516
6517                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6518                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6519                             distance = findDistance(&temppoint1, &temppoint2);
6520                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6521                             weapons[i].rotation2 *= 360 / 6.28;
6522                             temppoint1.y = 0;
6523                             temppoint2.y = 0;
6524                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6525                             weapons[i].rotation1 *= 360 / 6.28;
6526                             weapons[i].rotation3 = 0;
6527                             weapons[i].smallrotation = 90;
6528                             weapons[i].smallrotation2 = 0;
6529                             if (temppoint1.x > temppoint2.x)
6530                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6531                         }
6532                     }
6533                 }
6534                 if (weaponactive != k && weaponstuck != k) {
6535                     if (weapons[i].getType() == knife) {
6536                         weapons[i].smallrotation = -70;
6537                         weapons[i].smallrotation2 = 10;
6538                     }
6539                     if (weapons[i].getType() == sword) {
6540                         weapons[i].smallrotation = -100;
6541                         weapons[i].smallrotation2 = -8;
6542                     }
6543                     if (weapons[i].getType() == staff) {
6544                         weapons[i].smallrotation = -100;
6545                         weapons[i].smallrotation2 = -8;
6546                     }
6547                 }
6548                 if (weaponstuck == k) {
6549                     if (weaponstuckwhere == 0)
6550                         weapons[i].smallrotation = 180;
6551                     else
6552                         weapons[i].smallrotation = 0;
6553                     weapons[i].smallrotation2 = 10;
6554                 }
6555             }
6556         }
6557     }
6558
6559     calcrot = 0;
6560     if (skeleton.free)
6561         calcrot = 1;
6562     if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6563         calcrot = 1;
6564     if (animCurrent != animTarget)
6565         calcrot = 1;
6566     if (skeleton.free == 2)
6567         calcrot = 0;
6568
6569     return 0;
6570 }
6571
6572
6573 /* FUNCTION?
6574  */
6575 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6576 {
6577     static int i, j;
6578     static float distance;
6579     static float olddistance;
6580     static int intersecting;
6581     static int firstintersecting;
6582     static XYZ point;
6583     static XYZ oldp1;
6584     static XYZ start, end;
6585     static float slopethreshold = -.4;
6586
6587     firstintersecting = -1;
6588
6589     oldp1 = *p1;
6590     *p1 = *p1 - *move;
6591     if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6592         return -1;
6593     if (*rotate)
6594         *p1 = DoRotation(*p1, 0, -*rotate, 0);
6595     for (i = 0; i < 4; i++) {
6596         for (j = 0; j < model->TriangleNum; j++) {
6597             if (model->facenormals[j].y <= slopethreshold) {
6598                 intersecting = 0;
6599                 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)));
6600                 if (distance < radius) {
6601                     point = *p1 - model->facenormals[j] * distance;
6602                     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]]))
6603                         intersecting = 1;
6604                     if (!intersecting)
6605                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6606                                                                 &model->vertex[model->Triangles[j].vertex[1]],
6607                                                                 p1, &radius);
6608                     if (!intersecting)
6609                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6610                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6611                                                                 p1, &radius);
6612                     if (!intersecting)
6613                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6614                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6615                                                                 p1, &radius);
6616                     end = *p1 - point;
6617                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6618                         start = *p1;
6619                         end = *p1;
6620                         end.y -= radius;
6621                         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)) {
6622                             p1->y = point.y + radius;
6623                             if ((animTarget == jumpdownanim || isFlip())) {
6624                                 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6625                                     RagDoll(0);
6626
6627                                 if (animTarget == jumpupanim) {
6628                                     jumppower = -4;
6629                                     animTarget = getIdle();
6630                                 }
6631                                 target = 0;
6632                                 frameTarget = 0;
6633                                 onterrain = 1;
6634
6635                                 if (id == 0) {
6636                                     pause_sound(whooshsound);
6637                                     OPENAL_SetVolume(channels[whooshsound], 0);
6638                                 }
6639
6640                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6641                                     if (isFlip())
6642                                         jumppower = -4;
6643                                     animTarget = getLanding();
6644                                     emit_sound_at(landsound, coords, 128.);
6645
6646                                     if (id == 0) {
6647                                         addEnvSound(coords);
6648                                     }
6649                                 }
6650                             }
6651                         }
6652                     }
6653                 }
6654                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6655                     olddistance = distance;
6656                     firstintersecting = j;
6657                     *p = point;
6658                 }
6659             }
6660         }
6661         for (j = 0; j < model->TriangleNum; j++) {
6662             if (model->facenormals[j].y > slopethreshold) {
6663                 intersecting = 0;
6664                 start = *p1;
6665                 start.y -= radius / 4;
6666                 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6667                 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6668                 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6669                 distance = abs((model->facenormals[j].x * start.x)
6670                                + (model->facenormals[j].y * start.y)
6671                                + (model->facenormals[j].z * start.z)
6672                                - ((model->facenormals[j].x * v0.x)
6673                                   + (model->facenormals[j].y * v0.y)
6674                                   + (model->facenormals[j].z * v0.z)));
6675                 if (distance < radius * .5) {
6676                     point = start - model->facenormals[j] * distance;
6677                     if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6678                         intersecting = 1;
6679                     if (!intersecting)
6680                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6681                     if (!intersecting)
6682                         intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6683                     if (!intersecting)
6684                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6685                     end = *p1 - point;
6686                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6687                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6688                             start = velocity;
6689                             velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6690                             if (findLengthfast(&start) < findLengthfast(&velocity))
6691                                 velocity = start;
6692                         }
6693                         *p1 += model->facenormals[j] * (distance - radius * .5);
6694                     }
6695                 }
6696                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6697                     olddistance = distance;
6698                     firstintersecting = j;
6699                     *p = point;
6700                 }
6701             }
6702         }
6703     }
6704     if (*rotate)
6705         *p = DoRotation(*p, 0, *rotate, 0);
6706     *p = *p + *move;
6707     if (*rotate)
6708         *p1 = DoRotation(*p1, 0, *rotate, 0);
6709     *p1 += *move;
6710     return firstintersecting;
6711 }
6712
6713 void Person::takeWeapon(int weaponId)
6714 {
6715     weaponactive = 0;
6716     weapons[weaponId].owner = id;
6717     if (num_weapons > 0) {
6718         weaponids[num_weapons] = weaponids[0];
6719     }
6720     num_weapons++;
6721     weaponids[0] = weaponId;
6722 }
6723
6724 void Person::addClothes()
6725 {
6726     if (numclothes > 0) {
6727         for (int i = 0; i < numclothes; i++) {
6728             addClothes(i);
6729         }
6730         DoMipmaps();
6731     }
6732 }
6733
6734 bool Person::addClothes(const int& clothesId)
6735 {
6736     LOGFUNC;
6737     const char* fileName = clothes[clothesId];
6738
6739     GLubyte* array = &skeleton.skinText[0];
6740
6741     //Load Image
6742     ImageRec texture;
6743     bool opened = load_image(fileName, texture);
6744
6745     float alphanum;
6746     //Is it valid?
6747     if (opened) {
6748         float tintr = clothestintr[clothesId];
6749         float tintg = clothestintg[clothesId];
6750         float tintb = clothestintb[clothesId];
6751
6752         if (tintr > 1) tintr = 1;
6753         if (tintg > 1) tintg = 1;
6754         if (tintb > 1) tintb = 1;
6755
6756         if (tintr < 0) tintr = 0;
6757         if (tintg < 0) tintg = 0;
6758         if (tintb < 0) tintb = 0;
6759
6760         int bytesPerPixel = texture.bpp / 8;
6761
6762         int tempnum = 0;
6763         alphanum = 255;
6764         for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6765             if (bytesPerPixel == 3)
6766                 alphanum = 255;
6767             else if ((i + 1) % 4 == 0)
6768                 alphanum = texture.data[i];
6769             if ((i + 1) % 4 || bytesPerPixel == 3) {
6770                 if ((i % 4) == 0)
6771                     texture.data[i] *= tintr;
6772                 if ((i % 4) == 1)
6773                     texture.data[i] *= tintg;
6774                 if ((i % 4) == 2)
6775                     texture.data[i] *= tintb;
6776                 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6777                 tempnum++;
6778             }
6779         }
6780         return 1;
6781     } else {
6782         return 0;
6783     }
6784 }