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