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