]> git.jsancho.org Git - lugaru.git/blob - Source/Person.cpp
Cleaned up FootLand method
[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(bodyparts whichfoot, float opacity)
1790 {
1791     if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1792         cerr << "FootLand called on wrong bodypart" << endl;
1793         return;
1794     }
1795     static XYZ terrainlight;
1796     static XYZ footvel, footpoint;
1797     if (opacity >= 1 || skiddelay <= 0) {
1798         if (opacity > 1) {
1799             footvel = 0;
1800             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1801             if (distsq(&footpoint, &viewer))
1802                 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1803         } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1804             footvel = velocity / 5;
1805             if (footvel.y < .8)
1806                 footvel.y = .8;
1807             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1808             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1809             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1810             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1811                 if (environment == snowyenvironment) {
1812                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1813                     if (detail == 2) {
1814                         terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1815                     }
1816                 } else if (environment == grassyenvironment) {
1817                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1818                 } else if (environment == desertenvironment) {
1819                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1820                     if (detail == 2) {
1821                         terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1822                     }
1823                 }
1824             }
1825         } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1826             footvel = velocity / 5;
1827             if (footvel.y < .8)
1828                 footvel.y = .8;
1829             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1830             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1831                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1832             }
1833         }
1834     }
1835 }
1836
1837 /* EFFECT
1838  * make a puff effect at a body part (dust effect?)
1839  */
1840 void Person::Puff(int whichlabel)
1841 {
1842     static XYZ footvel, footpoint;
1843
1844     footvel = 0;
1845     footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1846     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1847 }
1848
1849 /* EFFECT
1850  * I think I added this in an attempt to clean up code
1851  */
1852 void Person::setAnimation(int animation)
1853 {
1854     animTarget = animation;
1855     frameTarget = 0;
1856     target = 0;
1857 }
1858
1859 /* EFFECT
1860  * MONSTER
1861  * TODO: ???
1862  */
1863 void Person::DoAnimations()
1864 {
1865     if (!skeleton.free) {
1866         static float oldtarget;
1867
1868         if (isIdle() && animCurrent != getIdle())
1869             normalsupdatedelay = 0;
1870
1871         if (animTarget == tempanim || animCurrent == tempanim) {
1872             animation[tempanim] = tempanimation;
1873         }
1874         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1875             float gLoc[3];
1876             float vel[3];
1877             gLoc[0] = coords.x;
1878             gLoc[1] = coords.y;
1879             gLoc[2] = coords.z;
1880             vel[0] = velocity.x;
1881             vel[1] = velocity.y;
1882             vel[2] = velocity.z;
1883
1884             if (id == 0) {
1885                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1886                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1887             }
1888             if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1889                 landhard = 1;
1890             if (!crouchkeydown && velocity.y >= -15)
1891                 landhard = 0;
1892         }
1893         if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1894             XYZ targfacing;
1895             targfacing = 0;
1896             targfacing.z = 1;
1897
1898             targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1899
1900             if (normaldotproduct(targfacing, velocity) >= -.3)
1901                 animTarget = flipanim;
1902             else
1903                 animTarget = backflipanim;
1904             crouchtogglekeydown = 1;
1905             frameTarget = 0;
1906             target = 0;
1907
1908             if (id == 0)
1909                 numflipped++;
1910         }
1911
1912         if (animation[animTarget].attack != reversed)
1913             feint = 0;
1914         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1915             crouchtogglekeydown = 0;
1916             if (aitype == playercontrolled)
1917                 feint = 0;
1918         } else {
1919             if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1920                 feint = 1;
1921             if (!isFlip())
1922                 crouchtogglekeydown = 1;
1923         }
1924
1925
1926         if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1927             if (detail)
1928                 normalsupdatedelay = 0;
1929         }
1930
1931         if (target >= 1) {
1932             if (animTarget == rollanim && frameTarget == 3 && onfire) {
1933                 onfire = 0;
1934                 emit_sound_at(fireendsound, coords);
1935                 pause_sound(stream_firesound);
1936                 deathbleeding = 0;
1937             }
1938
1939             if (animTarget == rabbittacklinganim && frameTarget == 1) {
1940                 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1941                     Reverse();
1942                 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1943                     if (normaldotproduct(victim->facing, facing) > 0)
1944                         victim->animTarget = rabbittackledbackanim;
1945                     else
1946                         victim->animTarget = rabbittackledfrontanim;
1947                     victim->frameTarget = 2;
1948                     victim->target = 0;
1949                     victim->yaw = yaw;
1950                     victim->targetyaw = yaw;
1951                     if (victim->aitype == gethelptype)
1952                         victim->DoDamage(victim->damagetolerance - victim->damage);
1953                     //victim->DoDamage(30);
1954                     if (creature == wolftype) {
1955                         DoBloodBig(0, 255);
1956                         emit_sound_at(clawslicesound, victim->coords);
1957                         victim->spurt = 1;
1958                         victim->DoBloodBig(1 / victim->armorhead, 210);
1959                     }
1960                     award_bonus(id, TackleBonus,
1961                                 victim->aitype == gethelptype ? 50 : 0);
1962                 }
1963             }
1964
1965             if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1966                 if (weapons[weaponids[0]].getType() == knife) {
1967                     if (weaponactive == -1)
1968                         weaponactive = 0;
1969                     else if (weaponactive == 0)
1970                         weaponactive = -1;
1971
1972                     if (weaponactive == -1) {
1973                         emit_sound_at(knifesheathesound, coords);
1974                     }
1975                     if (weaponactive != -1) {
1976                         emit_sound_at(knifedrawsound, coords, 128);
1977                     }
1978                 }
1979                 drawtogglekeydown = 1;
1980             }
1981             //Footstep sounds
1982             if (tutoriallevel != 1 || id == 0)
1983                 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1984                     int whichsound;
1985                     if (onterrain) {
1986                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
1987                             if (animation[animTarget].label[frameTarget] == 1)
1988                                 whichsound = footstepsound;
1989                             else
1990                                 whichsound = footstepsound2;
1991                             if (animation[animTarget].label[frameTarget] == 1)
1992                                 FootLand(leftfoot, 1);
1993                             if (animation[animTarget].label[frameTarget] == 2)
1994                                 FootLand(rightfoot, 1);
1995                             if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1996                                 FootLand(rightfoot, 1);
1997                                 FootLand(leftfoot, 1);
1998                             }
1999
2000                         }
2001                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2002                             if (animation[animTarget].label[frameTarget] == 1)
2003                                 whichsound = footstepsound3;
2004                             else
2005                                 whichsound = footstepsound4;
2006                         }
2007                     }
2008                     if (!onterrain) {
2009                         if (animation[animTarget].label[frameTarget] == 1)
2010                             whichsound = footstepsound3;
2011                         else
2012                             whichsound = footstepsound4;
2013                     }
2014                     if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2015                         if (animation[animTarget].attack != neutral) {
2016                             unsigned r = abs(Random() % 3);
2017                             if (r == 0)
2018                                 whichsound = lowwhooshsound;
2019                             if (r == 1)
2020                                 whichsound = midwhooshsound;
2021                             if (r == 2)
2022                                 whichsound = highwhooshsound;
2023                         }
2024                         if (animation[animTarget].attack == neutral)
2025                             whichsound = movewhooshsound;
2026                     } else if (animation[animTarget].label[frameTarget] == 4)
2027                         whichsound = knifeswishsound;
2028                     if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2029                         whichsound = landsound2;
2030
2031                     emit_sound_at(whichsound, coords, 256.);
2032
2033                     if (id == 0)
2034                         if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2035                             if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2036                                 addEnvSound(coords, 15);
2037                             } else {
2038                                 addEnvSound(coords, 6);
2039                             }
2040                         }
2041
2042                     if (animation[animTarget].label[frameTarget] == 3) {
2043                         whichsound--;
2044                         emit_sound_at(whichsound, coords, 128.);
2045                     }
2046                 }
2047
2048             //Combat sounds
2049             if (tutoriallevel != 1 || id == 0)
2050                 if (speechdelay <= 0)
2051                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2052                         if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2053                             int whichsound = -1;
2054                             if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2055                                 if (animation[animTarget].attack != neutral) {
2056                                     unsigned r = abs(Random() % 4);
2057                                     if (creature == rabbittype) {
2058                                         if (r == 0) whichsound = rabbitattacksound;
2059                                         if (r == 1) whichsound = rabbitattack2sound;
2060                                         if (r == 2) whichsound = rabbitattack3sound;
2061                                         if (r == 3) whichsound = rabbitattack4sound;
2062                                     }
2063                                     if (creature == wolftype) {
2064                                         if (r == 0) whichsound = barksound;
2065                                         if (r == 1) whichsound = bark2sound;
2066                                         if (r == 2) whichsound = bark3sound;
2067                                         if (r == 3) whichsound = barkgrowlsound;
2068                                     }
2069                                     speechdelay = .3;
2070                                 }
2071                             }
2072
2073                             if (whichsound != -1) {
2074                                 emit_sound_at(whichsound, coords);
2075                             }
2076                         }
2077
2078
2079
2080             if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2081                 FootLand(leftfoot, 1);
2082                 FootLand(rightfoot, 1);
2083             }
2084
2085             transspeed = 0;
2086             currentoffset = targetoffset;
2087             frameTarget = frameCurrent;
2088             animCurrent = animTarget;
2089             frameTarget++;
2090
2091             if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2092                 for (unsigned i = 0; i < weapons.size(); i++) {
2093                     if (weapons[i].owner == -1)
2094                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2095                             if (distsq(&coords, &weapons[i].position) >= 1) {
2096                                 if (weapons[i].getType() != staff) {
2097                                     emit_sound_at(knifedrawsound, coords, 128.);
2098                                 }
2099
2100                                 takeWeapon(i);
2101                             }
2102                         }
2103                 }
2104             }
2105
2106             if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2107                 for (unsigned i = 0; i < weapons.size(); i++) {
2108                     bool willwork = true;
2109                     if (weapons[i].owner != -1)
2110                         if (Person::players[weapons[i].owner]->weaponstuck != -1)
2111                             if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2112                                 if (Person::players[weapons[i].owner]->num_weapons > 1)
2113                                     willwork = 0;
2114                     if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2115                         if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2116                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2117                                 bool fleshstuck = false;
2118                                 if (weapons[i].owner != -1)
2119                                     if (victim->weaponstuck != -1) {
2120                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
2121                                             fleshstuck = true;
2122                                         }
2123                                     }
2124                                 if (fleshstuck) {
2125                                     emit_sound_at(fleshstabremovesound, coords, 128.);
2126                                 } else {
2127                                     if (weapons[i].getType() != staff) {
2128                                         emit_sound_at(knifedrawsound, coords, 128.);
2129                                     }
2130                                 }
2131                                 if (weapons[i].owner != -1) {
2132                                     victim = Person::players[weapons[i].owner];
2133                                     if (victim->num_weapons == 1)
2134                                         victim->num_weapons = 0;
2135                                     else
2136                                         victim->num_weapons = 1;
2137
2138                                     //victim->weaponactive=-1;
2139                                     victim->skeleton.longdead = 0;
2140                                     victim->skeleton.free = 1;
2141                                     victim->skeleton.broken = 0;
2142
2143                                     for (int j = 0; j < victim->skeleton.num_joints; j++) {
2144                                         victim->skeleton.joints[j].velchange = 0;
2145                                         victim->skeleton.joints[j].locked = 0;
2146                                     }
2147
2148                                     XYZ relative;
2149                                     relative = 0;
2150                                     relative.y = 10;
2151                                     Normalise(&relative);
2152                                     XYZ footvel, footpoint;
2153                                     footvel = 0;
2154                                     footpoint = weapons[i].position;
2155                                     if (victim->weaponstuck != -1) {
2156                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
2157                                             if (bloodtoggle)
2158                                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2159                                             weapons[i].bloody = 2;
2160                                             weapons[i].blooddrip = 5;
2161                                             victim->weaponstuck = -1;
2162                                         }
2163                                     }
2164                                     if (victim->num_weapons > 0) {
2165                                         if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2166                                             victim->weaponstuck = 0;
2167                                         if (victim->weaponids[0] == int(i))
2168                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2169                                     }
2170
2171                                     victim->jointVel(abdomen) += relative * 6;
2172                                     victim->jointVel(neck) += relative * 6;
2173                                     victim->jointVel(rightshoulder) += relative * 6;
2174                                     victim->jointVel(leftshoulder) += relative * 6;
2175                                 }
2176                                 takeWeapon(i);
2177                             }
2178                         }
2179                 }
2180             }
2181
2182             if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2183                 if (weaponactive == -1)
2184                     weaponactive = 0;
2185                 else if (weaponactive == 0) {
2186                     weaponactive = -1;
2187                     if (num_weapons == 2) {
2188                         int buffer;
2189                         buffer = weaponids[0];
2190                         weaponids[0] = weaponids[1];
2191                         weaponids[1] = buffer;
2192                     }
2193                 }
2194                 if (weaponactive == -1) {
2195                     emit_sound_at(knifesheathesound, coords, 128.);
2196                 }
2197                 if (weaponactive != -1) {
2198                     emit_sound_at(knifedrawsound, coords, 128.);
2199                 }
2200             }
2201
2202
2203             if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2204                 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2205                 Normalise(&rotatetarget);
2206                 targetyaw = -asin(0 - rotatetarget.x);
2207                 targetyaw *= 360 / 6.28;
2208                 if (rotatetarget.z < 0)
2209                     targetyaw = 180 - targetyaw;
2210
2211                 if (animTarget == walljumprightkickanim)
2212                     targetyaw += 40;
2213                 if (animTarget == walljumpleftkickanim)
2214                     targetyaw -= 40;
2215             }
2216
2217             bool dojumpattack;
2218             dojumpattack = 0;
2219             if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2220                 dojumpattack = 1;
2221             if (hasvictim)
2222                 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2223                     dojumpattack = 1;
2224             if (!hostile)
2225                 dojumpattack = 0;
2226             if (dojumpattack) {
2227                 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2228                     animTarget = rabbittackleanim;
2229                     frameTarget = 0;
2230                     emit_sound_at(jumpsound, coords);
2231                 }
2232
2233                 float closestdist;
2234                 closestdist = 0;
2235                 int closestid;
2236                 closestid = -1;
2237                 XYZ targetloc;
2238                 targetloc = velocity;
2239                 Normalise(&targetloc);
2240                 targetloc += coords;
2241                 for (unsigned i = 0; i < Person::players.size(); i++) {
2242                     if (i != id)
2243                         if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2244                             closestdist = distsq(&targetloc, &Person::players[i]->coords);
2245                             closestid = i;
2246                         }
2247                 }
2248                 if (closestid != -1)
2249                     if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2250                         hasvictim = 1;
2251                         victim = Person::players[closestid];
2252                         coords = victim->coords;
2253                         animCurrent = rabbittacklinganim;
2254                         animTarget = rabbittacklinganim;
2255                         frameCurrent = 0;
2256                         frameTarget = 1;
2257                         XYZ rotatetarget;
2258                         if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2259                             rotatetarget = coords - victim->coords;
2260                             Normalise(&rotatetarget);
2261                             targetyaw = -asin(0 - rotatetarget.x);
2262                             targetyaw *= 360 / 6.28;
2263                             if (rotatetarget.z < 0)
2264                                 targetyaw = 180 - targetyaw;
2265                         }
2266                         if (animTarget != rabbitrunninganim) {
2267                             emit_sound_at(jumpsound, coords, 128.);
2268                         }
2269                     }
2270             }
2271
2272             //Move impacts
2273             float damagemult = 1 * power;
2274             if (creature == wolftype)
2275                 damagemult = 2.5 * power;
2276             if (hasvictim) {
2277                 damagemult /= victim->damagetolerance / 200;
2278             }
2279             if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2280                 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2281                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2282                         escapednum = 0;
2283                         if (id == 0)
2284                             camerashake += .4;
2285                         if (Random() % 2 || creature == wolftype) {
2286                             victim->spurt = 1;
2287                             DoBlood(.2, 250);
2288                             if (creature == wolftype)
2289                                 DoBloodBig(0, 250);
2290                         }
2291                         if (tutoriallevel != 1) {
2292                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
2293                         }
2294                         if (creature == wolftype) {
2295                             emit_sound_at(clawslicesound, victim->coords, 128.);
2296                             victim->spurt = 1;
2297                             victim->DoBloodBig(2 / victim->armorhead, 175);
2298                         }
2299                         victim->RagDoll(0);
2300                         XYZ relative;
2301                         relative = victim->coords - coords;
2302                         relative.y = 0;
2303                         Normalise(&relative);
2304                         relative = DoRotation(relative, 0, -90, 0);
2305                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2306                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2307                         }
2308                         victim->jointVel(head) += relative * damagemult * 200;
2309                         victim->Puff(head);
2310                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
2311
2312                         SolidHitBonus(id);
2313                     }
2314                 }
2315
2316                 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2317                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2318                         escapednum = 0;
2319                         if (id == 0)
2320                             camerashake += .4;
2321                         if (Random() % 2 || creature == wolftype) {
2322                             victim->spurt = 1;
2323                             if (creature == wolftype)
2324                                 DoBloodBig(0, 235);
2325                         }
2326                         emit_sound_at(whooshhitsound, victim->coords);
2327                         if (creature == wolftype) {
2328                             emit_sound_at(clawslicesound, victim->coords, 128.);
2329                             victim->spurt = 1;
2330                             victim->DoBloodBig(2, 175);
2331                         }
2332                         victim->RagDoll(0);
2333                         XYZ relative;
2334                         relative = victim->coords - coords;
2335                         relative.y = 0;
2336                         Normalise(&relative);
2337                         relative.y -= 1;
2338                         Normalise(&relative);
2339                         relative = DoRotation(relative, 0, 90, 0);
2340                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2341                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2342                         }
2343                         victim->jointVel(head) += relative * damagemult * 100;
2344                         victim->Puff(head);
2345                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2346                     }
2347                 }
2348
2349                 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2350                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2351                         escapednum = 0;
2352                         if (id == 0)
2353                             camerashake += .4;
2354                         victim->spurt = 1;
2355                         DoBlood(.2, 250);
2356                         if (tutoriallevel != 1) {
2357                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2358                         }
2359                         if (creature == wolftype) {
2360                             emit_sound_at(clawslicesound, victim->coords, 128.);
2361                             victim->spurt = 1;
2362                             victim->DoBloodBig(2 / victim->armorhead, 175);
2363                         }
2364                         victim->RagDoll(0);
2365                         XYZ relative;
2366                         relative = facing;
2367                         relative.y = 0;
2368                         Normalise(&relative);
2369                         relative = DoRotation(relative, 0, -90, 0);
2370                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2371                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2372                         }
2373                         victim->jointVel(head) += relative * damagemult * 200;
2374                         victim->Puff(head);
2375                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2376
2377                         if (victim->damage > victim->damagetolerance)
2378                             award_bonus(id, style);
2379                         else
2380                             SolidHitBonus(id);
2381                     }
2382                 }
2383
2384                 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2385                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2386                         escapednum = 0;
2387                         if (id == 0)
2388                             camerashake += .4;
2389                         victim->spurt = 1;
2390                         DoBlood(.2, 250);
2391                         if (tutoriallevel != 1) {
2392                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2393                         }
2394                         if (creature == wolftype) {
2395                             emit_sound_at(clawslicesound, victim->coords, 128.);
2396                             victim->spurt = 1;
2397                             victim->DoBloodBig(2 / victim->armorhead, 175);
2398                         }
2399                         victim->RagDoll(0);
2400                         XYZ relative;
2401                         relative = facing;
2402                         relative.y = 0;
2403                         Normalise(&relative);
2404                         relative = DoRotation(relative, 0, 90, 0);
2405                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2406                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2407                         }
2408                         victim->jointVel(head) += relative * damagemult * 200;
2409                         victim->Puff(head);
2410                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2411
2412                         if (victim->damage > victim->damagetolerance)
2413                             award_bonus(id, style);
2414                         else
2415                             SolidHitBonus(id);
2416                     }
2417                 }
2418
2419                 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2420                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2421                         escapednum = 0;
2422                         if (id == 0)
2423                             camerashake += .4;
2424                         if (Random() % 2) {
2425                             victim->spurt = 1;
2426                             DoBlood(.2, 235);
2427                         }
2428                         emit_sound_at(whooshhitsound, victim->coords);
2429                         victim->RagDoll(0);
2430                         XYZ relative;
2431                         relative = victim->coords - coords;
2432                         relative.y = 0;
2433                         Normalise(&relative);
2434                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2435                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2436                         }
2437                         victim->jointVel(head) += relative * damagemult * 100;
2438                         victim->Puff(head);
2439                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2440                     }
2441                 }
2442
2443                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2444                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2445                         escapednum = 0;
2446                         if (id == 0)
2447                             camerashake += .2;
2448                         emit_sound_at(whooshhitsound, victim->coords, 128.);
2449
2450                         victim->skeleton.longdead = 0;
2451                         victim->skeleton.free = 1;
2452                         victim->skeleton.broken = 0;
2453                         victim->skeleton.spinny = 1;
2454
2455                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2456                             victim->skeleton.joints[i].velchange = 0;
2457                             victim->skeleton.joints[i].delay = 0;
2458                             victim->skeleton.joints[i].locked = 0;
2459                             //victim->skeleton.joints[i].velocity=0;
2460                         }
2461
2462                         XYZ relative;
2463                         relative = 0;
2464                         relative.y = 1;
2465                         Normalise(&relative);
2466                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2467                             victim->skeleton.joints[i].velocity.y = relative.y * 10;
2468                             victim->skeleton.joints[i].position.y += relative.y * .3;
2469                             victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2470                             victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2471                         }
2472                         victim->Puff(abdomen);
2473                         victim->jointVel(abdomen).y = relative.y * 400;
2474                     }
2475                 }
2476
2477                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2478                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2479                         escapednum = 0;
2480                         if (id == 0)
2481                             camerashake += .4;
2482                         if (tutoriallevel != 1) {
2483                             emit_sound_at(heavyimpactsound, coords, 128.);
2484                         }
2485                         XYZ relative;
2486                         relative = victim->coords - coords;
2487                         relative.y = 0;
2488                         Normalise(&relative);
2489                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2490                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2491                         }
2492                         victim->Puff(abdomen);
2493                         if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2494                             slomo = 1;
2495                             slomodelay = .2;
2496                         }
2497                         victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2498                         victim->jointVel(abdomen) += relative * damagemult * 300;
2499                     }
2500                 }
2501
2502                 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2503                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2504                         escapednum = 0;
2505                         if (id == 0)
2506                             camerashake += .4;
2507                         if (tutoriallevel != 1) {
2508                             emit_sound_at(thudsound, coords);
2509                         }
2510
2511                         victim->skeleton.longdead = 0;
2512                         victim->skeleton.free = 1;
2513                         victim->skeleton.broken = 0;
2514                         victim->skeleton.spinny = 1;
2515
2516                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2517                             victim->skeleton.joints[i].velchange = 0;
2518                             //victim->skeleton.joints[i].delay=0;
2519                             victim->skeleton.joints[i].locked = 0;
2520                         }
2521                         XYZ relative;
2522                         relative = victim->coords - coords;
2523                         Normalise(&relative);
2524                         relative.y += .3;
2525                         Normalise(&relative);
2526                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2527                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2528                         }
2529                         if (!victim->dead)
2530                             SolidHitBonus(id);
2531
2532                         victim->Puff(abdomen);
2533                         victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2534                         victim->jointVel(abdomen) += relative * damagemult * 200;
2535                         staggerdelay = .5;
2536                         if (!victim->dead)
2537                             staggerdelay = 1.2;
2538
2539
2540                     }
2541                 }
2542
2543                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2544
2545                     if (hasvictim)
2546                         if (!victim->skeleton.free)
2547                             hasvictim = 0;
2548
2549                     if (!hasvictim) {
2550                         terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2551                         emit_sound_at(knifesheathesound, coords, 128.);
2552                     }
2553
2554                     if (victim && hasvictim) {
2555                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2556
2557                             XYZ where, startpoint, endpoint, movepoint, colpoint;
2558                             float rotationpoint;
2559                             int whichtri;
2560                             if (weapons[weaponids[weaponactive]].getType() == knife) {
2561                                 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2562                                 where -= victim->coords;
2563                                 if (!victim->skeleton.free)
2564                                     where = DoRotation(where, 0, -victim->yaw, 0);
2565                                 //where=scale;
2566                                 startpoint = where;
2567                                 startpoint.y += 100;
2568                                 endpoint = where;
2569                                 endpoint.y -= 100;
2570                             }
2571                             if (weapons[weaponids[weaponactive]].getType() == sword) {
2572                                 where = weapons[weaponids[weaponactive]].position;
2573                                 where -= victim->coords;
2574                                 if (!victim->skeleton.free)
2575                                     where = DoRotation(where, 0, -victim->yaw, 0);
2576                                 startpoint = where;
2577                                 where = weapons[weaponids[weaponactive]].tippoint;
2578                                 where -= victim->coords;
2579                                 if (!victim->skeleton.free)
2580                                     where = DoRotation(where, 0, -victim->yaw, 0);
2581                                 endpoint = where;
2582                             }
2583                             if (weapons[weaponids[weaponactive]].getType() == staff) {
2584                                 where = weapons[weaponids[weaponactive]].position;
2585                                 where -= victim->coords;
2586                                 if (!victim->skeleton.free)
2587                                     where = DoRotation(where, 0, -victim->yaw, 0);
2588                                 startpoint = where;
2589                                 where = weapons[weaponids[weaponactive]].tippoint;
2590                                 where -= victim->coords;
2591                                 if (!victim->skeleton.free)
2592                                     where = DoRotation(where, 0, -victim->yaw, 0);
2593                                 endpoint = where;
2594                             }
2595                             movepoint = 0;
2596                             rotationpoint = 0;
2597                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2598
2599                             if (whichtri != -1) {
2600                                 if (victim->dead != 2) {
2601                                     victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2602                                     if (!victim->dead)
2603                                         award_bonus(id, FinishedBonus);
2604                                 }
2605                                 if (bloodtoggle)
2606                                     weapons[weaponids[weaponactive]].bloody = 2;
2607
2608                                 victim->skeleton.longdead = 0;
2609                                 victim->skeleton.free = 1;
2610                                 victim->skeleton.broken = 0;
2611
2612                                 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2613                                     victim->skeleton.joints[i].velchange = 0;
2614                                     victim->skeleton.joints[i].locked = 0;
2615                                     //victim->skeleton.joints[i].velocity=0;
2616                                 }
2617                                 emit_sound_at(fleshstabsound, coords, 128);
2618
2619                             }
2620                             if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2621                                 weapons[weaponids[weaponactive]].blooddrip += 5;
2622                                 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2623                             }
2624                             if (whichtri == -1) {
2625                                 hasvictim = 0;
2626                                 emit_sound_at(knifesheathesound, coords, 128.);
2627                             }
2628                         }
2629                     }
2630                 }
2631
2632                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2633                     if (!hasvictim) {
2634                         emit_sound_at(knifedrawsound, coords, 128);
2635                     }
2636
2637                     if (victim && hasvictim) {
2638                         XYZ footvel, footpoint;
2639
2640                         emit_sound_at(fleshstabremovesound, coords, 128.);
2641
2642                         footvel = 0;
2643                         footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2644
2645                         if (weapons[weaponids[weaponactive]].getType() == sword) {
2646                             XYZ where, startpoint, endpoint, movepoint;
2647                             float rotationpoint;
2648                             int whichtri;
2649
2650                             where = weapons[weaponids[weaponactive]].position;
2651                             where -= victim->coords;
2652                             if (!victim->skeleton.free)
2653                                 where = DoRotation(where, 0, -victim->yaw, 0);
2654                             startpoint = where;
2655                             where = weapons[weaponids[weaponactive]].tippoint;
2656                             where -= victim->coords;
2657                             if (!victim->skeleton.free)
2658                                 where = DoRotation(where, 0, -victim->yaw, 0);
2659                             endpoint = where;
2660
2661                             movepoint = 0;
2662                             rotationpoint = 0;
2663                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2664                             footpoint += victim->coords;
2665
2666                             if (whichtri == -1) {
2667                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2668                             }
2669                         }
2670                         if (weapons[weaponids[weaponactive]].getType() == staff) {
2671                             XYZ where, startpoint, endpoint, movepoint;
2672                             float rotationpoint;
2673                             int whichtri;
2674
2675                             where = weapons[weaponids[weaponactive]].position;
2676                             where -= victim->coords;
2677                             if (!victim->skeleton.free)
2678                                 where = DoRotation(where, 0, -victim->yaw, 0);
2679                             startpoint = where;
2680                             where = weapons[weaponids[weaponactive]].tippoint;
2681                             where -= victim->coords;
2682                             if (!victim->skeleton.free)
2683                                 where = DoRotation(where, 0, -victim->yaw, 0);
2684                             endpoint = where;
2685
2686                             movepoint = 0;
2687                             rotationpoint = 0;
2688                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2689                             footpoint += victim->coords;
2690
2691                             if (whichtri == -1) {
2692                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2693                             }
2694                         }
2695                         hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2696                         if (hasvictim) {
2697                             if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2698                                 victim->skeleton.longdead = 0;
2699                                 victim->skeleton.free = 1;
2700                                 victim->skeleton.broken = 0;
2701
2702                                 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2703                                     victim->skeleton.joints[i].velchange = 0;
2704                                     victim->skeleton.joints[i].locked = 0;
2705                                     //victim->skeleton.joints[i].velocity=0;
2706                                 }
2707
2708                                 XYZ relative;
2709                                 relative = 0;
2710                                 relative.y = 10;
2711                                 Normalise(&relative);
2712                                 //victim->Puff(abdomen);
2713                                 if (bloodtoggle)
2714                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2715
2716                                 if (victim->bloodloss < victim->damagetolerance) {
2717                                     victim->bloodloss += 1000;
2718                                     victim->bled = 0;
2719                                 }
2720
2721                                 victim->jointVel(abdomen) += relative * damagemult * 20;
2722                             }
2723                         }
2724                     }
2725                     if (!hasvictim && onterrain) {
2726                         weapons[weaponids[weaponactive]].bloody = 0;
2727                         weapons[weaponids[weaponactive]].blooddrip = 0;
2728                     }
2729                 }
2730
2731                 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2732                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2733                         escapednum = 0;
2734                         if (id == 0)
2735                             camerashake += .4;
2736                         if (Random() % 2) {
2737                             victim->spurt = 1;
2738                             DoBlood(.2, 235);
2739                         }
2740                         if (tutoriallevel != 1) {
2741                             emit_sound_at(heavyimpactsound, victim->coords, 128);
2742                         }
2743
2744                         victim->RagDoll(0);
2745                         XYZ relative;
2746                         relative = victim->coords - coords;
2747                         relative.y = 0;
2748                         Normalise(&relative);
2749                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2750                             victim->skeleton.joints[i].velocity = relative * 30;
2751                         }
2752                         victim->jointVel(head) += relative * damagemult * 150;
2753
2754                         victim->frameTarget = 0;
2755                         victim->animTarget = staggerbackhardanim;
2756                         victim->targetyaw = targetyaw + 180;
2757                         victim->target = 0;
2758                         victim->stunned = 1;
2759
2760                         victim->Puff(head);
2761                         victim->Puff(abdomen);
2762                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2763
2764                         SolidHitBonus(id);
2765                     }
2766                 }
2767
2768
2769                 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2770                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2771                         escapednum = 0;
2772                         if (id == 0)
2773                             camerashake += .4;
2774                         if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2775                             if (tutoriallevel != 1) {
2776                                 emit_sound_at(thudsound, victim->coords);
2777                             }
2778                         } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2779                             if (tutoriallevel != 1) {
2780                                 emit_sound_at(whooshhitsound, victim->coords);
2781                             }
2782                         } else {
2783                             if (tutoriallevel != 1) {
2784                                 emit_sound_at(heavyimpactsound, victim->coords);
2785                             }
2786                         }
2787
2788                         if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2789                             victim->RagDoll(0);
2790                         XYZ relative;
2791                         relative = victim->coords - coords;
2792                         relative.y = 0;
2793                         Normalise(&relative);
2794                         relative.y = .3;
2795                         Normalise(&relative);
2796                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
2797                             victim->skeleton.joints[i].velocity = relative * 5;
2798                         }
2799                         victim->jointVel(abdomen) += relative * damagemult * 400;
2800
2801                         victim->frameTarget = 0;
2802                         victim->animTarget = staggerbackhardanim;
2803                         victim->targetyaw = targetyaw + 180;
2804                         victim->target = 0;
2805                         victim->stunned = 1;
2806
2807                         victim->Puff(abdomen);
2808                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2809
2810                         SolidHitBonus(id);
2811                     }
2812                 }
2813
2814                 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2815                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2816                         if (victim->id == 0)
2817                             camerashake += .4;
2818                         emit_sound_at(landsound2, victim->coords);
2819
2820                         Puff(righthand);
2821                     }
2822                 }
2823
2824                 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2825                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2826                         if (victim->id == 0)
2827                             camerashake += .4;
2828
2829                         if (weaponactive != -1) {
2830                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2831                                 if (weapons[victim->weaponids[0]].getType() == staff)
2832                                     weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2833                                 if (weapons[weaponids[0]].getType() == staff)
2834                                     weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2835
2836                                 emit_sound_at(swordstaffsound, victim->coords);
2837                             } else {
2838                                 emit_sound_at(metalhitsound, victim->coords);
2839                             }
2840                         }
2841
2842                         //Puff(righthand);
2843                     }
2844                 }
2845
2846                 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2847                     if (weaponactive != -1) {
2848                         escapednum = 0;
2849                         XYZ aim;
2850                         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);
2851                         Normalise(&aim);
2852                         weapons[weaponids[0]].thrown(aim * 50);
2853                         num_weapons--;
2854                         if (num_weapons) {
2855                             weaponids[0] = weaponids[num_weapons];
2856                         }
2857                         weaponactive = -1;
2858                     }
2859                 }
2860
2861                 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2862                     if (hasvictim)
2863                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2864                             escapednum = 0;
2865                             if (tutoriallevel != 1)
2866                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2867
2868                             award_bonus(id, Slicebonus);
2869                             if (tutoriallevel != 1) {
2870                                 emit_sound_at(knifeslicesound, victim->coords);
2871                             }
2872                             //victim->jointVel(abdomen)+=relative*damagemult*200;
2873                             if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2874                                 if (victim->id != 0 || difficulty == 2) {
2875                                     victim->frameTarget = 0;
2876                                     victim->animTarget = staggerbackhardanim;
2877                                     victim->targetyaw = targetyaw + 180;
2878                                     victim->target = 0;
2879                                 }
2880                             }
2881                             victim->lowreversaldelay = 0;
2882                             victim->highreversaldelay = 0;
2883                             if (aitype != playercontrolled)
2884                                 weaponmissdelay = .6;
2885
2886                             if (tutoriallevel != 1)
2887                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2888                                     weapons[weaponids[weaponactive]].bloody = 1;
2889                             if (tutoriallevel != 1)
2890                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2891
2892                             XYZ footvel, footpoint;
2893                             footvel = 0;
2894                             if (skeleton.free) {
2895                                 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2896                             } else {
2897                                 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2898                             }
2899                             if (tutoriallevel != 1) {
2900                                 if (bloodtoggle)
2901                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2902                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2903                                 //footvel.y-=.3;
2904                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2905                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2906                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2907                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2908                             }
2909                             if (tutoriallevel == 1) {
2910                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2911                             }
2912                             victim->DoDamage(damagemult * 0);
2913                         }
2914                 }
2915                 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2916                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2917                         if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2918                             award_bonus(id, Slashbonus);
2919                             escapednum = 0;
2920                             if (tutoriallevel != 1) {
2921                                 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2922                                     victim->DoBloodBig(2 / victim->armorhigh, 190);
2923                                 else
2924                                     victim->DoBloodBig(2 / victim->armorhigh, 185);
2925                                 victim->deathbleeding = 1;
2926                                 emit_sound_at(swordslicesound, victim->coords);
2927                             }
2928                             //victim->jointVel(abdomen)+=relative*damagemult*200;
2929                             if (tutoriallevel != 1) {
2930                                 victim->frameTarget = 0;
2931                                 victim->animTarget = staggerbackhardanim;
2932                                 victim->targetyaw = targetyaw + 180;
2933                                 victim->target = 0;
2934                             }
2935
2936                             if (tutoriallevel != 1) {
2937                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2938                                     weapons[weaponids[weaponactive]].bloody = 1;
2939                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2940
2941                                 float bloodlossamount;
2942                                 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2943                                 victim->bloodloss += bloodlossamount / victim->armorhigh;
2944                                 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2945                                 victim->DoDamage(damagemult * 0);
2946
2947                                 XYZ footvel, footpoint;
2948                                 footvel = 0;
2949                                 if (skeleton.free) {
2950                                     footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2951                                 } else {
2952                                     footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2953                                 }
2954                                 if (bloodtoggle)
2955                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2956                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2957                                 footvel.y -= .3;
2958                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2959                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2960                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2961                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2962                             }
2963                         } else {
2964                             if (victim->weaponactive != -1) {
2965                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2966                                     if (weapons[victim->weaponids[0]].getType() == staff)
2967                                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2968                                     if (weapons[weaponids[0]].getType() == staff)
2969                                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2970
2971                                     emit_sound_at(swordstaffsound, victim->coords);
2972                                 } else {
2973                                     emit_sound_at(metalhitsound, victim->coords);
2974                                 }
2975                             }
2976
2977
2978                             XYZ aim;
2979                             victim->Puff(righthand);
2980                             victim->target = 0;
2981                             victim->frameTarget = 0;
2982                             victim->animTarget = staggerbackhighanim;
2983                             victim->targetyaw = targetyaw + 180;
2984                             victim->target = 0;
2985                             aim = DoRotation(facing, 0, 90, 0) * 21;
2986                             aim.y += 7;
2987                             weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2988                             victim->num_weapons--;
2989                             if (victim->num_weapons) {
2990                                 victim->weaponids[0] = victim->weaponids[num_weapons];
2991                                 if (victim->weaponstuck == victim->num_weapons)
2992                                     victim->weaponstuck = 0;
2993                             }
2994                             victim->weaponactive = -1;
2995                             for (unsigned i = 0; i < Person::players.size(); i++) {
2996                                 Person::players[i]->wentforweapon = 0;
2997                             }
2998
2999                         }
3000                     }
3001                 }
3002
3003                 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3004                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3005                         if (tutoriallevel != 1) {
3006                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3007                             escapednum = 0;
3008                             if (id == 0)
3009                                 camerashake += .4;
3010                             if (Random() % 2 || creature == wolftype) {
3011                                 victim->spurt = 1;
3012                             }
3013                             emit_sound_at(staffheadsound, victim->coords);
3014                         }
3015                         victim->RagDoll(0);
3016                         XYZ relative;
3017                         relative = victim->coords - coords;
3018                         relative.y = 0;
3019                         Normalise(&relative);
3020                         relative = DoRotation(relative, 0, 90, 0);
3021                         relative.y -= 1;
3022                         Normalise(&relative);
3023                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3024                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3025                         }
3026                         victim->jointVel(head) += relative * damagemult * 230;
3027                         victim->jointVel(neck) += relative * damagemult * 230;
3028                         victim->Puff(head);
3029                         if (tutoriallevel != 1) {
3030                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3031
3032                             award_bonus(id, solidhit, 30);
3033                         }
3034                     }
3035                 }
3036
3037                 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3038                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3039                         if (tutoriallevel != 1) {
3040                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3041                             escapednum = 0;
3042                             if (id == 0)
3043                                 camerashake += .4;
3044                             if (Random() % 2 || creature == wolftype) {
3045                                 victim->spurt = 1;
3046                             }
3047                             emit_sound_at(staffheadsound, victim->coords);
3048                         }
3049                         victim->RagDoll(0);
3050                         XYZ relative;
3051                         relative = victim->coords - coords;
3052                         relative.y = 0;
3053                         Normalise(&relative);
3054                         relative = DoRotation(relative, 0, -90, 0);
3055                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3056                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3057                         }
3058                         victim->jointVel(head) += relative * damagemult * 220;
3059                         victim->jointVel(neck) += relative * damagemult * 220;
3060                         victim->Puff(head);
3061                         if (tutoriallevel != 1) {
3062                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
3063
3064                             award_bonus(id, solidhit, 60);
3065                         }
3066                     }
3067                 }
3068
3069                 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3070                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3071                         escapednum = 0;
3072                         if (tutoriallevel != 1) {
3073                             if (!victim->dead)
3074                                 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3075                             if (id == 0)
3076                                 camerashake += .4;
3077                             if (Random() % 2 || creature == wolftype) {
3078                                 victim->spurt = 1;
3079                             }
3080                             emit_sound_at(staffbodysound, victim->coords);
3081                         }
3082                         victim->skeleton.longdead = 0;
3083                         victim->skeleton.free = 1;
3084                         victim->skeleton.broken = 0;
3085
3086                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3087                             victim->skeleton.joints[i].velchange = 0;
3088                             victim->skeleton.joints[i].locked = 0;
3089                             //victim->skeleton.joints[i].velocity=0;
3090                         }
3091
3092                         victim->RagDoll(0);
3093                         XYZ relative;
3094                         relative = 0;
3095                         relative.y = -1;
3096                         Normalise(&relative);
3097                         if (!victim->dead) {
3098                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3099                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3100                             }
3101                             victim->jointVel(abdomen) += relative * damagemult * 40;
3102                         }
3103                         if (victim->dead) {
3104                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3105                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3106                             }
3107                         }
3108                         victim->Puff(abdomen);
3109                         if (tutoriallevel != 1) {
3110                             victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3111
3112                             if (!victim->dead) {
3113                                 award_bonus(id, solidhit, 40);
3114                             }
3115                         }
3116                     }
3117                 }
3118
3119                 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3120                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3121                         escapednum = 0;
3122                         if (id == 0)
3123                             camerashake += .4;
3124                         XYZ relative;
3125                         relative = victim->coords - coords;
3126                         relative.y = 0;
3127                         Normalise(&relative);
3128
3129                         SolidHitBonus(id);
3130
3131                         if (animation[victim->animTarget].height == lowheight) {
3132                             if (Random() % 2) {
3133                                 victim->spurt = 1;
3134                                 DoBlood(.2, 250);
3135                             }
3136                             victim->RagDoll(0);
3137                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3138                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3139                             }
3140                             victim->jointVel(head) += relative * damagemult * 200;
3141                             if (tutoriallevel != 1) {
3142                                 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3143                             }
3144                             victim->Puff(head);
3145                             victim->DoDamage(damagemult * 100 / victim->protectionhead);
3146                             if (victim->howactive == typesleeping)
3147                                 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3148                             if (creature == wolftype) {
3149                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3150                                 victim->spurt = 1;
3151                                 victim->DoBloodBig(2 / victim->armorhead, 175);
3152                             }
3153                         } else {
3154                             if (victim->damage >= victim->damagetolerance)
3155                                 victim->RagDoll(0);
3156                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3157                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3158                             }
3159                             victim->jointVel(abdomen) += relative * damagemult * 200;
3160                             victim->frameTarget = 0;
3161                             victim->animTarget = staggerbackhighanim;
3162                             victim->targetyaw = targetyaw + 180;
3163                             victim->target = 0;
3164                             if (tutoriallevel != 1) {
3165                                 emit_sound_at(landsound2, victim->coords, 128.);
3166                             }
3167                             victim->Puff(abdomen);
3168                             victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3169                             if (creature == wolftype) {
3170                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3171                                 victim->spurt = 1;
3172                                 victim->DoBloodBig(2 / victim->armorhigh, 170);
3173                             }
3174                         }
3175
3176                     }
3177                 }
3178
3179                 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3180                     if ((victim->animTarget != jumpupanim) &&
3181                         (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3182                         (victim != this->shared_from_this())) {
3183                         escapednum = 0;
3184                         if (id == 0)
3185                             camerashake += .2;
3186                         if (tutoriallevel != 1) {
3187                             emit_sound_at(landsound2, victim->coords, 128.);
3188                         }
3189                         XYZ relative;
3190                         relative = victim->coords - coords;
3191                         relative.y = 0;
3192                         Normalise(&relative);
3193
3194                         if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3195                             victim->RagDoll(0);
3196
3197                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3198                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3199                             }
3200                             relative = DoRotation(relative, 0, -90, 0);
3201                             relative.y += .1;
3202                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3203                                 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)
3204                                     victim->skeleton.joints[i].velocity = relative * 80;
3205                             }
3206                             victim->Puff(rightankle);
3207                             victim->Puff(leftankle);
3208                             victim->DoDamage(damagemult * 40 / victim->protectionlow);
3209                         } else {
3210                             if (victim->damage >= victim->damagetolerance)
3211                                 victim->RagDoll(0);
3212                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3213                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3214                             }
3215                             relative = DoRotation(relative, 0, -90, 0);
3216                             for (int i = 0; i < victim->skeleton.num_joints; i++) {
3217                                 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)
3218                                     victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3219                             }
3220                             victim->jointVel(abdomen) += relative * damagemult * 200;
3221                             victim->frameTarget = 0;
3222                             victim->animTarget = staggerbackhighanim;
3223                             victim->targetyaw = targetyaw + 180;
3224                             victim->target = 0;
3225                             if (tutoriallevel != 1) {
3226                                 emit_sound_at(landsound2, victim->coords, 128.);
3227                             }
3228                             victim->Puff(abdomen);
3229                             victim->DoDamage(damagemult * 30 / victim->protectionlow);
3230                         }
3231
3232                         SolidHitBonus(id);
3233
3234                     }
3235                 }
3236             }
3237             if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3238                 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3239                     escapednum = 0;
3240                     if (id == 0)
3241                         camerashake += .4;
3242                     if (Random() % 2) {
3243                         victim->spurt = 1;
3244                         DoBlood(.2, 230);
3245                     }
3246                     if (tutoriallevel != 1) {
3247                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3248                     }
3249                     if (creature == wolftype) {
3250                         emit_sound_at(clawslicesound, victim->coords, 128);
3251                         victim->spurt = 1;
3252                         victim->DoBloodBig(2 / victim->armorhigh, 170);
3253                     }
3254                     victim->RagDoll(0);
3255                     XYZ relative;
3256                     relative = victim->coords - oldcoords;
3257                     relative.y = 0;
3258                     Normalise(&relative);
3259                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3260                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3261                     }
3262                     victim->jointVel(abdomen) += relative * damagemult * 200;
3263                     victim->Puff(abdomen);
3264                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3265
3266                     award_bonus(id, Reversal);
3267                 }
3268
3269                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3270                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3271                         if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3272                             takeWeapon(victim->weaponids[victim->weaponactive]);
3273                             victim->num_weapons--;
3274                             if (victim->num_weapons > 0) {
3275                                 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3276                             }
3277                             victim->weaponactive = -1;
3278                         }
3279                     }
3280                 }
3281
3282                 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3283                     escapednum = 0;
3284                     if (id == 0)
3285                         camerashake += .4;
3286                     if (Random() % 2) {
3287                         victim->spurt = 1;
3288                         DoBlood(.2, 230);
3289                     }
3290                     emit_sound_at(whooshhitsound, victim->coords, 128.);
3291                     victim->RagDoll(0);
3292                     XYZ relative;
3293                     relative = victim->coords - oldcoords;
3294                     relative.y = 0;
3295                     Normalise(&relative);
3296                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3297                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3298                     }
3299                     victim->jointVel(abdomen) += relative * damagemult * 200;
3300                     victim->Puff(head);
3301                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3302                 }
3303
3304                 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3305                     escapednum = 0;
3306                     if (id == 0)
3307                         camerashake += .4;
3308                     if (Random() % 2) {
3309                         victim->spurt = 1;
3310                         DoBlood(.2, 230);
3311                     }
3312
3313                     award_bonus(id, staffreversebonus);
3314
3315                     if (tutoriallevel != 1) {
3316                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3317                     }
3318                     victim->RagDoll(0);
3319                     award_bonus(id, staffreversebonus); // Huh, again?
3320
3321                     XYZ relative;
3322                     relative = victim->coords - oldcoords;
3323                     relative.y = 0;
3324                     Normalise(&relative);
3325                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3326                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3327                     }
3328                     victim->jointVel(abdomen) += relative * damagemult * 200;
3329                     victim->Puff(head);
3330                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3331                 }
3332
3333                 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3334                     escapednum = 0;
3335                     victim->RagDoll(1);
3336                     XYZ relative;
3337                     relative = facing;
3338                     relative.y = 0;
3339                     Normalise(&relative);
3340                     relative.y -= .1;
3341                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3342                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3343                     }
3344                     victim->jointVel(lefthand) *= .1;
3345                     victim->jointVel(leftwrist) *= .2;
3346                     victim->jointVel(leftelbow) *= .5;
3347                     victim->jointVel(leftshoulder) *= .7;
3348                     victim->jointVel(righthand) *= .1;
3349                     victim->jointVel(rightwrist) *= .2;
3350                     victim->jointVel(rightelbow) *= .5;
3351                     victim->jointVel(rightshoulder) *= .7;
3352
3353                     victim->Puff(abdomen);
3354                     victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3355
3356                     award_bonus(id, Reversal);
3357
3358                     bool doslice;
3359                     doslice = 0;
3360                     if (weaponactive != -1 || creature == wolftype)
3361                         doslice = 1;
3362                     if (creature == rabbittype && weaponactive != -1)
3363                         if (weapons[weaponids[0]].getType() == staff)
3364                             doslice = 0;
3365                     if (doslice) {
3366                         if (weaponactive != -1) {
3367                             victim->DoBloodBig(2 / victim->armorhigh, 225);
3368                             emit_sound_at(knifeslicesound, victim->coords);
3369                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3370                                 weapons[weaponids[weaponactive]].bloody = 1;
3371                             weapons[weaponids[weaponactive]].blooddrip += 3;
3372                         }
3373                         if (weaponactive == -1 && creature == wolftype) {
3374                             emit_sound_at(clawslicesound, victim->coords, 128.);
3375                             victim->spurt = 1;
3376                             victim->DoBloodBig(2 / victim->armorhigh, 175);
3377                         }
3378                     }
3379                 }
3380
3381
3382
3383                 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3384                     escapednum = 0;
3385                     victim->RagDoll(1);
3386                     XYZ relative;
3387                     relative = facing;
3388                     relative.y = 0;
3389                     Normalise(&relative);
3390                     relative.y -= .1;
3391                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3392                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3393                     }
3394                     victim->jointVel(lefthand) *= .1 - 1;
3395                     victim->jointVel(leftwrist) *= .2 - 1;
3396                     victim->jointVel(leftelbow) *= .5 - 1;
3397                     victim->jointVel(leftshoulder) *= .7 - 1;
3398                     victim->jointVel(righthand) *= .1 - 1;
3399                     victim->jointVel(rightwrist) *= .2 - 1;
3400                     victim->jointVel(rightelbow) *= .5 - 1;
3401                     victim->jointVel(rightshoulder) *= .7 - 1;
3402
3403                     award_bonus(id, swordreversebonus);
3404                 }
3405
3406                 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3407                     escapednum = 0;
3408                     if (id == 0)
3409                         camerashake += .4;
3410                     if (Random() % 2) {
3411                         victim->spurt = 1;
3412                         DoBlood(.2, 230);
3413                     }
3414                     if (tutoriallevel != 1) {
3415                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3416                     }
3417                     victim->RagDoll(0);
3418                     XYZ relative;
3419                     relative = victim->coords - oldcoords;
3420                     relative.y = 0;
3421                     Normalise(&relative);
3422                     relative = DoRotation(relative, 0, -90, 0);
3423                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3424                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3425                     }
3426                     victim->jointVel(abdomen) += relative * damagemult * 200;
3427                     victim->Puff(abdomen);
3428                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3429
3430                     award_bonus(id, Reversal);
3431                 }
3432
3433                 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3434                     escapednum = 0;
3435                     victim->RagDoll(0);
3436                     victim->skeleton.spinny = 0;
3437                     XYZ relative;
3438                     relative = facing * -1;
3439                     relative.y = -3;
3440                     Normalise(&relative);
3441                     if (victim->id == 0)
3442                         relative /= 30;
3443                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3444                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3445                     }
3446                     victim->damage = victim->damagetolerance;
3447                     victim->permanentdamage = victim->damagetolerance - 1;
3448                     bool doslice;
3449                     doslice = 0;
3450                     if (weaponactive != -1 || creature == wolftype)
3451                         doslice = 1;
3452                     if (creature == rabbittype && weaponactive != -1)
3453                         if (weapons[weaponids[0]].getType() == staff)
3454                             doslice = 0;
3455                     if (doslice) {
3456                         if (weaponactive != -1) {
3457                             victim->DoBloodBig(200, 225);
3458                             emit_sound_at(knifeslicesound, victim->coords);
3459                             if (bloodtoggle)
3460                                 weapons[weaponids[weaponactive]].bloody = 2;
3461                             weapons[weaponids[weaponactive]].blooddrip += 5;
3462                         }
3463
3464                         if (creature == wolftype && weaponactive == -1) {
3465                             emit_sound_at(clawslicesound, victim->coords, 128.);
3466                             victim->spurt = 1;
3467                             victim->DoBloodBig(2, 175);
3468                         }
3469                     }
3470                     award_bonus(id, spinecrusher);
3471                 }
3472
3473                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3474                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3475                         escapednum = 0;
3476                         if (animTarget == knifefollowanim)
3477                             victim->DoBloodBig(200, 210);
3478                         if (animTarget == knifesneakattackanim) {
3479                             XYZ footvel, footpoint;
3480                             footvel = 0;
3481                             footpoint = weapons[weaponids[0]].tippoint;
3482                             if (bloodtoggle)
3483                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3484                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3485                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3486                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3487                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3488                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3489                             victim->DoBloodBig(200, 195);
3490                             award_bonus(id, tracheotomy);
3491                         }
3492                         if (animTarget == knifefollowanim) {
3493                             award_bonus(id, Stabbonus);
3494                             XYZ footvel, footpoint;
3495                             footvel = 0;
3496                             footpoint = weapons[weaponids[0]].tippoint;
3497                             if (bloodtoggle)
3498                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3499                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3500                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3501                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3502                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3503                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3504
3505                         }
3506                         victim->bloodloss += 10000;
3507                         victim->velocity = 0;
3508                         emit_sound_at(fleshstabsound, victim->coords);
3509                         if (bloodtoggle)
3510                             weapons[weaponids[weaponactive]].bloody = 2;
3511                         weapons[weaponids[weaponactive]].blooddrip += 5;
3512                     }
3513                 }
3514
3515                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3516                     escapednum = 0;
3517                     victim->velocity = 0;
3518                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3519                         victim->skeleton.joints[i].velocity = 0;
3520                     }
3521                     if (animTarget == knifefollowanim) {
3522                         victim->RagDoll(0);
3523                         for (int i = 0; i < victim->skeleton.num_joints; i++) {
3524                             victim->skeleton.joints[i].velocity = 0;
3525                         }
3526                     }
3527                     if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3528                         emit_sound_at(fleshstabremovesound, victim->coords);
3529                         if (bloodtoggle)
3530                             weapons[weaponids[weaponactive]].bloody = 2;
3531                         weapons[weaponids[weaponactive]].blooddrip += 5;
3532
3533                         XYZ footvel, footpoint;
3534                         footvel = 0;
3535                         footpoint = weapons[weaponids[0]].tippoint;
3536                         if (bloodtoggle)
3537                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3538                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3539                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3541                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3542                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3543                     }
3544                 }
3545
3546                 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3547                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3548                         award_bonus(id, backstab);
3549
3550                         escapednum = 0;
3551
3552                         XYZ footvel, footpoint;
3553                         footvel = 0;
3554                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3555                         if (bloodtoggle)
3556                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3557                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3558                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3559                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3560                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3561                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3562                         victim->DoBloodBig(200, 180);
3563                         victim->DoBloodBig(200, 215);
3564                         victim->bloodloss += 10000;
3565                         victim->velocity = 0;
3566                         emit_sound_at(fleshstabsound, victim->coords);
3567                         if (bloodtoggle)
3568                             weapons[weaponids[weaponactive]].bloody = 2;
3569                         weapons[weaponids[weaponactive]].blooddrip += 5;
3570                     }
3571                 }
3572
3573                 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3574                     escapednum = 0;
3575                     victim->velocity = 0;
3576                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3577                         victim->skeleton.joints[i].velocity = 0;
3578                     }
3579                     if (weaponactive != -1) {
3580                         emit_sound_at(fleshstabremovesound, victim->coords);
3581                         if (bloodtoggle)
3582                             weapons[weaponids[weaponactive]].bloody = 2;
3583                         weapons[weaponids[weaponactive]].blooddrip += 5;
3584
3585                         XYZ footvel, footpoint;
3586                         footvel = 0;
3587                         footpoint = weapons[weaponids[0]].tippoint;
3588                         if (bloodtoggle)
3589                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3590                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3591                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3592                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3593                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3594                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3595                     }
3596                 }
3597
3598                 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3599                     escapednum = 0;
3600                     if (id == 0)
3601                         camerashake += .4;
3602                     if (Random() % 2) {
3603                         victim->spurt = 1;
3604                         DoBlood(.2, 240);
3605                     }
3606                     if (weaponactive == -1) {
3607                         if (tutoriallevel != 1) {
3608                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
3609                         }
3610                     }
3611                     bool doslice;
3612                     doslice = 0;
3613                     if (weaponactive != -1 || creature == wolftype)
3614                         doslice = 1;
3615                     if (creature == rabbittype && weaponactive != -1)
3616                         if (weapons[weaponids[0]].getType() == staff)
3617                             doslice = 0;
3618                     if (doslice) {
3619                         if (weaponactive != -1) {
3620                             victim->DoBloodBig(2 / victim->armorhead, 225);
3621                             emit_sound_at(knifeslicesound, victim->coords);
3622                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3623                                 weapons[weaponids[weaponactive]].bloody = 1;
3624                             weapons[weaponids[weaponactive]].blooddrip += 3;
3625                         }
3626                         if (weaponactive == -1 && creature == wolftype) {
3627                             emit_sound_at(clawslicesound, victim->coords, 128.);
3628                             victim->spurt = 1;
3629                             victim->DoBloodBig(2 / victim->armorhead, 175);
3630                         }
3631                     }
3632
3633                     award_bonus(id, Reversal);
3634
3635                     victim->Puff(neck);
3636
3637                     XYZ relative;
3638                     relative = facing * -1;
3639                     relative.y = 0;
3640                     Normalise(&relative);
3641                     relative = DoRotation(relative, 0, 90, 0);
3642                     relative.y = .5;
3643                     Normalise(&relative);
3644                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3645                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3646                     }
3647                     victim->jointVel(head) += relative * damagemult * 200;
3648                     if (victim->damage < victim->damagetolerance - 100)
3649                         victim->velocity = relative * 200;
3650                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
3651                     victim->velocity = 0;
3652                 }
3653
3654                 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3655                     escapednum = 0;
3656                     victim->RagDoll(0);
3657                     XYZ relative;
3658                     relative = facing * -1;
3659                     relative.y = 0;
3660                     Normalise(&relative);
3661                     relative = DoRotation(relative, 0, 90, 0);
3662                     relative.y = .5;
3663                     Normalise(&relative);
3664                     for (int i = 0; i < victim->skeleton.num_joints; i++) {
3665                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3666                     }
3667                     victim->jointVel(head) += relative * damagemult * 200;
3668                 }
3669
3670                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3671                     if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3672                         award_bonus(id, reverseko);
3673                     }
3674             }
3675
3676
3677             //Animation end
3678             if (frameTarget > animation[animCurrent].numframes - 1) {
3679                 frameTarget = 0;
3680                 if (wasStop()) {
3681                     animTarget = getIdle();
3682                     FootLand(leftfoot, 1);
3683                     FootLand(rightfoot, 1);
3684                 }
3685                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3686                     animTarget = rollanim;
3687                     frameTarget = 3;
3688                     emit_sound_at(movewhooshsound, coords, 128.);
3689                 }
3690                 if (animCurrent == staggerbackhighanim) {
3691                     animTarget = getIdle();
3692                 }
3693                 if (animCurrent == staggerbackhardanim) {
3694                     animTarget = getIdle();
3695                 }
3696                 if (animCurrent == removeknifeanim) {
3697                     animTarget = getIdle();
3698                 }
3699                 if (animCurrent == crouchremoveknifeanim) {
3700                     animTarget = getCrouch();
3701                 }
3702                 if (animCurrent == backhandspringanim) {
3703                     animTarget = getIdle();
3704                 }
3705                 if (animCurrent == dodgebackanim) {
3706                     animTarget = getIdle();
3707                 }
3708                 if (animCurrent == drawleftanim) {
3709                     animTarget = getIdle();
3710                 }
3711                 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3712                     animTarget = getIdle();
3713                     if (animCurrent == crouchdrawrightanim) {
3714                         animTarget = getCrouch();
3715                     }
3716                     if (weaponactive == -1)
3717                         weaponactive = 0;
3718                     else if (weaponactive == 0) {
3719                         weaponactive = -1;
3720                         if (num_weapons == 2) {
3721                             int buffer;
3722                             buffer = weaponids[0];
3723                             weaponids[0] = weaponids[1];
3724                             weaponids[1] = buffer;
3725                         }
3726                     }
3727
3728                     if (weaponactive == -1) {
3729                         emit_sound_at(knifesheathesound, coords, 128.);
3730                     }
3731                     if (weaponactive != -1) {
3732                         emit_sound_at(knifedrawsound, coords, 128.);
3733                     }
3734                 }
3735                 if (animCurrent == rollanim) {
3736                     animTarget = getCrouch();
3737                     FootLand(leftfoot, 1);
3738                     FootLand(rightfoot, 1);
3739                 }
3740                 if (isFlip()) {
3741                     if (animTarget == walljumprightkickanim) {
3742                         targetrot = -190;
3743                     }
3744                     if (animTarget == walljumpleftkickanim) {
3745                         targetrot = 190;
3746                     }
3747                     animTarget = jumpdownanim;
3748                 }
3749                 if (animCurrent == climbanim) {
3750                     animTarget = getCrouch();
3751                     frameTarget = 1;
3752                     coords += facing * .1;
3753                     if (!isnormal(coords.x))
3754                         coords = oldcoords;
3755                     oldcoords = coords;
3756                     collided = 0;
3757                     targetoffset = 0;
3758                     currentoffset = 0;
3759                     grabdelay = 1;
3760                     velocity = 0;
3761                     collided = 0;
3762                     avoidcollided = 0;
3763                 }
3764                 if (animTarget == rabbitkickreversalanim) {
3765                     animTarget = getCrouch();
3766                     lastfeint = 0;
3767                 }
3768                 if (animTarget == jumpreversalanim) {
3769                     animTarget = getCrouch();
3770                     lastfeint = 0;
3771                 }
3772                 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3773                     if (attackkeydown && animTarget != walljumpfrontanim) {
3774                         int closest = -1;
3775                         float closestdist = -1;
3776                         float distance;
3777                         if (Person::players.size() > 1)
3778                             for (unsigned i = 0; i < Person::players.size(); i++) {
3779                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3780                                     distance = distsq(&Person::players[i]->coords, &coords);
3781                                     if (closestdist == -1 || distance < closestdist) {
3782                                         closestdist = distance;
3783                                         closest = i;
3784                                     }
3785                                 }
3786                             }
3787                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3788                             victim = Person::players[closest];
3789                             animTarget = walljumprightkickanim;
3790                             frameTarget = 0;
3791                             XYZ rotatetarget = victim->coords - coords;
3792                             Normalise(&rotatetarget);
3793                             yaw = -asin(0 - rotatetarget.x);
3794                             yaw *= 360 / 6.28;
3795                             if (rotatetarget.z < 0)
3796                                 yaw = 180 - yaw;
3797                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3798                             velocity = (victim->coords - coords) * 4;
3799                             velocity.y += 2;
3800                             transspeed = 40;
3801                         }
3802                     }
3803                     if (animTarget == walljumpbackanim) {
3804                         animTarget = backflipanim;
3805                         frameTarget = 3;
3806                         velocity = facing * -8;
3807                         velocity.y = 4;
3808                         if (id == 0)
3809                             resume_stream(whooshsound);
3810                     }
3811                     if (animTarget == walljumprightanim) {
3812                         animTarget = rightflipanim;
3813                         frameTarget = 4;
3814                         targetyaw -= 90;
3815                         yaw -= 90;
3816                         velocity = DoRotation(facing, 0, 30, 0) * -8;
3817                         velocity.y = 4;
3818                     }
3819                     if (animTarget == walljumpfrontanim) {
3820                         animTarget = frontflipanim;
3821                         frameTarget = 2;
3822                         //targetyaw-=180;
3823                         ////yaw-=180;
3824                         velocity = facing * 8;
3825                         velocity.y = 4;
3826                     }
3827                     if (id == 0)
3828                         resume_stream(whooshsound);
3829                 }
3830                 if (animTarget == walljumpleftanim) {
3831                     if (attackkeydown) {
3832                         int closest = -1;
3833                         float closestdist = -1;
3834                         float distance;
3835                         if (Person::players.size() > 1)
3836                             for (unsigned i = 0; i < Person::players.size(); i++) {
3837                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3838                                     distance = distsq(&Person::players[i]->coords, &coords);
3839                                     if (closestdist == -1 || distance < closestdist) {
3840                                         closestdist = distance;
3841                                         closest = i;
3842                                     }
3843                                 }
3844                             }
3845                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3846                             victim = Person::players[closest];
3847                             animTarget = walljumpleftkickanim;
3848                             frameTarget = 0;
3849                             XYZ rotatetarget = victim->coords - coords;
3850                             Normalise(&rotatetarget);
3851                             yaw = -asin(0 - rotatetarget.x);
3852                             yaw *= 360 / 6.28;
3853                             if (rotatetarget.z < 0)
3854                                 yaw = 180 - yaw;
3855                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3856                             velocity = (victim->coords - coords) * 4;
3857                             velocity.y += 2;
3858                             transspeed = 40;
3859                         }
3860                     }
3861                     if (animTarget != walljumpleftkickanim) {
3862                         animTarget = leftflipanim;
3863                         frameTarget = 4;
3864                         targetyaw += 90;
3865                         yaw += 90;
3866                         velocity = DoRotation(facing, 0, -30, 0) * -8;
3867                         velocity.y = 4;
3868                     }
3869                     if (id == 0)
3870                         resume_stream(whooshsound);
3871                 }
3872                 if (animTarget == sneakattackanim) {
3873                     animCurrent = getCrouch();
3874                     animTarget = getCrouch();
3875                     frameTarget = 1;
3876                     frameCurrent = 0;
3877                     targetyaw += 180;
3878                     yaw += 180;
3879                     targettilt2 *= -1;
3880                     tilt2 *= -1;
3881                     transspeed = 1000000;
3882                     targetheadyaw += 180;
3883                     coords -= facing * .7;
3884                     if (onterrain)
3885                         coords.y = terrain.getHeight(coords.x, coords.z);
3886
3887                     lastfeint = 0;
3888                 }
3889                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3890                     animTarget = getIdle();
3891                     frameTarget = 0;
3892                     if (onterrain)
3893                         coords.y = terrain.getHeight(coords.x, coords.z);
3894
3895                     lastfeint = 0;
3896                 }
3897                 if (animCurrent == knifefollowanim) {
3898                     animTarget = getIdle();
3899                     lastfeint = 0;
3900                 }
3901                 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3902                     float ycoords = oldcoords.y;
3903                     animTarget = getStop();
3904                     targetyaw += 180;
3905                     yaw += 180;
3906                     targettilt2 *= -1;
3907                     tilt2 *= -1;
3908                     transspeed = 1000000;
3909                     targetheadyaw += 180;
3910                     if (!isnormal(coords.x))
3911                         coords = oldcoords;
3912                     if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3913                         oldcoords = coords + facing * .5;
3914                     else if (animCurrent == sweepreversalanim)
3915                         oldcoords = coords + facing * 1.1;
3916                     else if (animCurrent == upunchreversalanim) {
3917                         oldcoords = coords + facing * 1.5;
3918                         targetyaw += 180;
3919                         yaw += 180;
3920                         targetheadyaw += 180;
3921                         targettilt2 *= -1;
3922                         tilt2 *= -1;
3923                     } else if (animCurrent == knifeslashreversalanim) {
3924                         oldcoords = coords + facing * .5;
3925                         targetyaw += 90;
3926                         yaw += 90;
3927                         targetheadyaw += 90;
3928                         targettilt2 = 0;
3929                         tilt2 = 0;
3930                     } else if (animCurrent == staffspinhitreversalanim) {
3931                         targetyaw += 180;
3932                         yaw += 180;
3933                         targetheadyaw += 180;
3934                         targettilt2 = 0;
3935                         tilt2 = 0;
3936                     }
3937                     if (onterrain)
3938                         oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3939                     else
3940                         oldcoords.y = ycoords;
3941                     currentoffset = coords - oldcoords;
3942                     targetoffset = 0;
3943                     coords = oldcoords;
3944
3945                     lastfeint = 0;
3946                 }
3947                 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3948                     velocity = 0;
3949                     velocity.y = -5;
3950                     RagDoll(0);
3951                 }
3952                 if (animation[animTarget].attack == reversed) {
3953                     escapednum++;
3954                     if (animTarget == sweepreversedanim)
3955                         targetyaw += 90;
3956                     animTarget = backhandspringanim;
3957                     frameTarget = 2;
3958                     emit_sound_at(landsound, coords, 128);
3959
3960                     if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3961                         animTarget = rollanim;
3962                         frameTarget = 5;
3963                         oldcoords = coords;
3964                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3965                         coords.y = oldcoords.y;
3966                     }
3967                     if (animCurrent == knifeslashreversedanim) {
3968                         animTarget = rollanim;
3969                         frameTarget = 0;
3970                         targetyaw += 90;
3971                         yaw += 90;
3972                         oldcoords = coords;
3973                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3974                         coords.y = oldcoords.y;
3975                     }
3976                 }
3977                 if (wasFlip()) {
3978                     animTarget = jumpdownanim;
3979                 }
3980                 if (wasLanding())
3981                     animTarget = getIdle();
3982                 if (wasLandhard())
3983                     animTarget = getIdle();
3984                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3985                     animTarget = getIdle();
3986                     oldcoords = coords;
3987                     coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3988                     coords.y = oldcoords.y;
3989                     //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3990                     targetoffset.y = coords.y;
3991                     if (onterrain)
3992                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
3993                     currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3994                     currentoffset.y -= (coords.y - targetoffset.y);
3995                     coords.y = targetoffset.y;
3996                     targetoffset = 0;
3997                     normalsupdatedelay = 0;
3998                 }
3999                 if (animCurrent == upunchanim) {
4000                     animTarget = getStop();
4001                     normalsupdatedelay = 0;
4002                     lastfeint = 0;
4003                 }
4004                 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4005                     targetyaw = yaw;
4006                     bool hasstaff;
4007                     hasstaff = 0;
4008                     if (num_weapons > 0)
4009                         if (weapons[0].getType() == staff)
4010                             hasstaff = 1;
4011                     if (!hasstaff)
4012                         DoDamage(35);
4013                     RagDoll(0);
4014                     lastfeint = 0;
4015                     rabbitkickragdoll = 1;
4016                 }
4017                 if (animCurrent == rabbitkickreversedanim) {
4018                     if (!feint) {
4019                         velocity = 0;
4020                         velocity.y = -10;
4021                         //DoDamage(100);
4022                         RagDoll(0);
4023                         skeleton.spinny = 0;
4024                         SolidHitBonus(!id); // FIXME: tricky id
4025                     }
4026                     if (feint) {
4027                         escapednum++;
4028                         animTarget = rollanim;
4029                         coords += facing;
4030                         if (id == 0)
4031                             pause_sound(whooshsound);
4032                     }
4033                     lastfeint = 0;
4034                 }
4035                 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4036                     velocity = 0;
4037                     velocity.y = -10;
4038                     RagDoll(0);
4039                     skeleton.spinny = 0;
4040                 }
4041                 if (animCurrent == jumpreversedanim) {
4042                     if (!feint) {
4043                         velocity = 0;
4044                         velocity.y = -10;
4045                         //DoDamage(100);
4046                         RagDoll(0);
4047                         skeleton.spinny = 0;
4048                         SolidHitBonus(!id); // FIXME: tricky id
4049                     }
4050                     if (feint) {
4051                         escapednum++;
4052                         animTarget = rollanim;
4053                         coords += facing * 2;
4054                         if (id == 0)
4055                             pause_sound(whooshsound);
4056                     }
4057                     lastfeint = 0;
4058                 }
4059
4060                 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) {
4061                     animTarget = getupfromfrontanim;
4062                     lastfeint = 0;
4063                 } else if (animation[animCurrent].attack == normalattack) {
4064                     animTarget = getIdle();
4065                     lastfeint = 0;
4066                 }
4067                 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4068                     animTarget = blockhighleftstrikeanim;
4069                 }
4070                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4071                     animTarget = getIdle();
4072                     lastfeint = 0;
4073                 }
4074                 if (animCurrent == spinkickanim && victim->skeleton.free) {
4075                     if (creature == rabbittype)
4076                         animTarget = fightidleanim;
4077                 }
4078             }
4079             target = 0;
4080
4081             if (isIdle() && !wasIdle())
4082                 normalsupdatedelay = 0;
4083
4084             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4085                 animTarget = jumpdownanim;
4086             }
4087         }
4088         if (!skeleton.free) {
4089             oldtarget = target;
4090             if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4091                 if (!isRun() || !wasRun()) {
4092                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4093                         target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4094                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4095                         target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4096                 }
4097                 if (isRun() && wasRun()) {
4098                     float tempspeed;
4099                     tempspeed = velspeed;
4100                     if (tempspeed < 10 * speedmult)
4101                         tempspeed = 10 * speedmult;
4102                     target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4103                 }
4104             } else if (transspeed)
4105                 target += multiplier * transspeed * speed * 2;
4106             else {
4107                 if (!isRun() || !wasRun()) {
4108                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4109                         target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4110                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4111                         target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4112                 }
4113             }
4114
4115             if (animCurrent != animTarget)
4116                 target = (target + oldtarget) / 2;
4117
4118             if (target > 1) {
4119                 frameCurrent = frameTarget;
4120                 target = 1;
4121             }
4122             oldrot = rot;
4123             rot = targetrot * target;
4124             yaw += rot - oldrot;
4125             if (target == 1) {
4126                 rot = 0;
4127                 oldrot = 0;
4128                 targetrot = 0;
4129             }
4130             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4131                 //Old rotates
4132                 for (int i = 0; i < skeleton.num_joints; i++) {
4133                     skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4134                 }
4135
4136                 skeleton.FindForwards();
4137
4138                 for (int i = 0; i < skeleton.num_muscles; i++) {
4139                     if (skeleton.muscles[i].visible) {
4140                         skeleton.FindRotationMuscle(i, animTarget);
4141                     }
4142                 }
4143                 for (int i = 0; i < skeleton.num_muscles; i++) {
4144                     if (skeleton.muscles[i].visible) {
4145                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4146                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4147                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4148                             skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4149                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4150                             skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4151                     }
4152                 }
4153
4154                 //New rotates
4155                 for (int i = 0; i < skeleton.num_joints; i++) {
4156                     skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4157                 }
4158
4159                 skeleton.FindForwards();
4160
4161                 for (int i = 0; i < skeleton.num_muscles; i++) {
4162                     if (skeleton.muscles[i].visible) {
4163                         skeleton.FindRotationMuscle(i, animTarget);
4164                     }
4165                 }
4166                 for (int i = 0; i < skeleton.num_muscles; i++) {
4167                     if (skeleton.muscles[i].visible) {
4168                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4169                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4170                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4171                             skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4172                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4173                             skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4174                         if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4175                         if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4176                         if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4177                         if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4178                         if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4179                         if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4180                     }
4181                 }
4182             }
4183             if (frameCurrent >= animation[animCurrent].numframes)
4184                 frameCurrent = animation[animCurrent].numframes - 1;
4185
4186             oldanimCurrent = animCurrent;
4187             oldanimTarget = animTarget;
4188             oldframeTarget = frameTarget;
4189             oldframeCurrent = frameCurrent;
4190
4191             for (int i = 0; i < skeleton.num_joints; i++) {
4192                 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4193                 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4194             }
4195             offset = currentoffset * (1 - target) + targetoffset * target;
4196             for (int i = 0; i < skeleton.num_muscles; i++) {
4197                 if (skeleton.muscles[i].visible) {
4198                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4199                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4200                     skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4201                 }
4202             }
4203         }
4204
4205         if (isLanding() && landhard) {
4206             if (id == 0)
4207                 camerashake += .4;
4208             animTarget = getLandhard();
4209             frameTarget = 0;
4210             target = 0;
4211             landhard = 0;
4212             transspeed = 15;
4213         }
4214     }
4215 }
4216
4217 /* EFFECT
4218  * MONSTER
4219  * TODO
4220  */
4221 void Person::DoStuff()
4222 {
4223     static XYZ terrainnormal;
4224     static XYZ flatfacing;
4225     static XYZ flatvelocity;
4226     static float flatvelspeed;
4227     static int i, j, l;
4228     static XYZ average;
4229     static int howmany;
4230     static int bloodsize;
4231     static int startx, starty, endx, endy;
4232     static GLubyte color;
4233     static XYZ bloodvel;
4234
4235     onfiredelay -= multiplier;
4236     if (onfiredelay < 0 && onfire) {
4237         if (Random() % 2 == 0) {
4238             crouchkeydown = 1;
4239         }
4240         onfiredelay = 0.3;
4241     }
4242
4243     crouchkeydowntime += multiplier;
4244     if (!crouchkeydown)
4245         crouchkeydowntime = 0;
4246     jumpkeydowntime += multiplier;
4247     if (!jumpkeydown && skeleton.free)
4248         jumpkeydowntime = 0;
4249
4250     if (hostile || damage > 0 || bloodloss > 0)
4251         immobile = 0;
4252
4253     if (isIdle() || isRun())
4254         targetoffset = 0;
4255
4256     if (num_weapons == 1 && weaponactive != -1)
4257         weaponstuck = -1;
4258
4259     if (id == 0)
4260         blooddimamount -= multiplier * .3;
4261     speechdelay -= multiplier;
4262     texupdatedelay -= multiplier;
4263     interestdelay -= multiplier;
4264     flamedelay -= multiplier;
4265     parriedrecently -= multiplier;
4266     if (!victim) {
4267         victim = this->shared_from_this();
4268         hasvictim = 0;
4269     }
4270
4271     if (id == 0)
4272         speed = 1.1 * speedmult;
4273     else
4274         speed = 1.0 * speedmult;
4275     if (!skeleton.free)
4276         rabbitkickragdoll = 0;
4277
4278     speed *= speedmult;
4279
4280     if (id != 0 && (creature == rabbittype || difficulty != 2))
4281         superruntoggle = 0;
4282     if (id != 0 && creature == wolftype && difficulty == 2) {
4283         superruntoggle = 0;
4284         if (aitype != passivetype) {
4285             superruntoggle = 1;
4286             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) {
4287                 superruntoggle = 0;
4288             }
4289         }
4290         if (scale < 0.2)
4291             superruntoggle = 0;
4292         if (animTarget == wolfrunninganim && !superruntoggle) {
4293             animTarget = getRun();
4294             frameTarget = 0;
4295         }
4296     }
4297     if (weaponactive == -1 && num_weapons > 0) {
4298         if (weapons[weaponids[0]].getType() == staff) {
4299             weaponactive = 0;
4300         }
4301     }
4302
4303     if (onfire) {
4304         burnt += multiplier;
4305         deathbleeding = 1;
4306         if (burnt > .6)
4307             burnt = .6;
4308         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4309
4310         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4311             float gLoc[3];
4312             float vel[3];
4313             gLoc[0] = coords.x;
4314             gLoc[1] = coords.y;
4315             gLoc[2] = coords.z;
4316             vel[0] = velocity.x;
4317             vel[1] = velocity.y;
4318             vel[2] = velocity.z;
4319
4320             if (id == 0) {
4321                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4322                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4323             }
4324         }
4325     }
4326     while (flamedelay < 0 && onfire) {
4327         flamedelay += .006;
4328         howmany = abs(Random() % (skeleton.num_joints));
4329         if (skeleton.free) {
4330             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4331             flatfacing = skeleton.joints[howmany].position * scale + coords;
4332         } else {
4333             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4334             flatvelocity = (coords - oldcoords) / multiplier / 2;
4335         }
4336         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4337     }
4338
4339     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4340         flamedelay += .05;
4341         howmany = abs(Random() % (skeleton.num_joints));
4342         if (skeleton.free) {
4343             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4344             flatfacing = skeleton.joints[howmany].position * scale + coords;
4345         } else {
4346             flatvelocity = (coords - oldcoords) / multiplier / 2;
4347             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4348         }
4349         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4350     }
4351
4352     if (bleeding > 0) {
4353         bleeding -= multiplier * .3;
4354         if (bloodtoggle == 2) {
4355             skeleton.drawmodel.textureptr.bind();
4356             if ((bleeding <= 0) && (detail != 2))
4357                 DoMipmaps();
4358         }
4359     }
4360
4361     if (neckspurtamount > 0) {
4362         neckspurtamount -= multiplier;
4363         neckspurtdelay -= multiplier * 3;
4364         neckspurtparticledelay -= multiplier * 3;
4365         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4366             spurt = 0;
4367             bloodvel = 0;
4368             if (skeleton.free) {
4369                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4370                 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4371                 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4372             } else {
4373                 bloodvel.z = 5 * neckspurtamount;
4374                 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4375                 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4376                 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4377             }
4378             neckspurtparticledelay = .05;
4379         }
4380         if (neckspurtdelay < 0) {
4381             neckspurtdelay = 3;
4382         }
4383     }
4384
4385     if (deathbleeding > 0 && dead != 2) {
4386         if (deathbleeding < 5)
4387             bleeddelay -= deathbleeding * multiplier / 4;
4388         else
4389             bleeddelay -= 5 * multiplier / 4;
4390         if (bleeddelay < 0 && bloodtoggle) {
4391             bleeddelay = 1;
4392             XYZ bloodvel;
4393             if (bloodtoggle) {
4394                 bloodvel = 0;
4395                 if (skeleton.free) {
4396                     bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4397                     Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4398                 } else {
4399                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4400                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4401                 }
4402             }
4403         }
4404         bloodloss += deathbleeding * multiplier * 80;
4405         deathbleeding -= multiplier * 1.6;
4406         if (deathbleeding < 0)
4407             deathbleeding = 0;
4408         if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4409             if (weaponactive != -1) {
4410                 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4411                 weapons[weaponids[0]].velocity.x += .01;
4412                 num_weapons--;
4413                 if (num_weapons) {
4414                     weaponids[0] = weaponids[num_weapons];
4415                     if (weaponstuck == num_weapons)
4416                         weaponstuck = 0;
4417                 }
4418                 weaponactive = -1;
4419                 for (unsigned i = 0; i < Person::players.size(); i++) {
4420                     Person::players[i]->wentforweapon = 0;
4421                 }
4422
4423                 if (id == 0) {
4424                     Game::flash(.5, 0);
4425                 }
4426             }
4427
4428             if (!dead && creature == wolftype) {
4429                 award_bonus(0, Wolfbonus);
4430             }
4431             dead = 2;
4432             if (animTarget == knifefollowedanim && !skeleton.free) {
4433                 for (int i = 0; i < skeleton.num_joints; i++) {
4434                     skeleton.joints[i].velocity = 0;
4435                     skeleton.joints[i].velocity.y = -2;
4436                 }
4437             }
4438             if (id != 0 && unconscioustime > .1) {
4439                 numafterkill++;
4440             }
4441
4442             RagDoll(0);
4443         }
4444     }
4445
4446     if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4447         texupdatedelay = .12;
4448
4449         bloodsize = 5 - realtexdetail;
4450
4451         startx = 0;
4452         starty = 0;
4453         startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4454         starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4455         endx = startx + bloodsize;
4456         endy = starty + bloodsize;
4457
4458         if (startx < 0) {
4459             startx = 0;
4460             bleeding = 0;
4461         }
4462         if (starty < 0) {
4463             starty = 0;
4464             bleeding = 0;
4465         }
4466         if (endx > skeleton.skinsize - 1) {
4467             endx = skeleton.skinsize - 1;
4468             bleeding = 0;
4469         }
4470         if (endy > skeleton.skinsize - 1) {
4471             endy = skeleton.skinsize - 1;
4472             bleeding = 0;
4473         }
4474         if (endx < startx)
4475             endx = startx;
4476         if (endy < starty)
4477             endy = starty;
4478
4479         for (i = startx; i < endx; i++) {
4480             for (j = starty; j < endy; j++) {
4481                 if (Random() % 2 == 0) {
4482                     color = Random() % 85 + 170;
4483                     if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4484                         skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4485                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4486                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4487                 }
4488             }
4489         }
4490         if (detail > 1) {
4491             skeleton.drawmodel.textureptr.bind();
4492             DoMipmaps();
4493         }
4494
4495         if (skeleton.free) {
4496             bleedx += 4 * direction / realtexdetail;
4497             if (detail == 2)
4498                 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4499             else
4500                 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4501         } else {
4502             bleedy -= 4 / realtexdetail;
4503             if (detail == 2)
4504                 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4505             else
4506                 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4507         }
4508     }
4509
4510     if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4511         righthandmorphness = targetrighthandmorphness;
4512         righthandmorphstart = righthandmorphend;
4513     } else if (righthandmorphness > targetrighthandmorphness) {
4514         righthandmorphness -= multiplier * 4;
4515     } else if (righthandmorphness < targetrighthandmorphness) {
4516         righthandmorphness += multiplier * 4;
4517     }
4518
4519     if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4520         lefthandmorphness = targetlefthandmorphness;
4521         lefthandmorphstart = lefthandmorphend;
4522     } else if (lefthandmorphness > targetlefthandmorphness) {
4523         lefthandmorphness -= multiplier * 4;
4524     } else if (lefthandmorphness < targetlefthandmorphness) {
4525         lefthandmorphness += multiplier * 4;
4526     }
4527
4528     if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4529         if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4530             tailmorphness = targettailmorphness;
4531             tailmorphstart = tailmorphend;
4532         } else if (tailmorphness > targettailmorphness) {
4533             tailmorphness -= multiplier * 10;
4534         } else if (tailmorphness < targettailmorphness) {
4535             tailmorphness += multiplier * 10;
4536         }
4537     }
4538
4539     if (creature == wolftype) {
4540         if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4541             tailmorphness = targettailmorphness;
4542             tailmorphstart = tailmorphend;
4543         } else if (tailmorphness > targettailmorphness) {
4544             tailmorphness -= multiplier * 2;
4545         } else if (tailmorphness < targettailmorphness) {
4546             tailmorphness += multiplier * 2;
4547         }
4548     }
4549
4550     if (headmorphend == 3 || headmorphstart == 3) {
4551         if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4552             headmorphness = targetheadmorphness;
4553             headmorphstart = headmorphend;
4554         } else if (headmorphness > targetheadmorphness) {
4555             headmorphness -= multiplier * 7;
4556         } else if (headmorphness < targetheadmorphness) {
4557             headmorphness += multiplier * 7;
4558         }
4559     } else if (headmorphend == 5 || headmorphstart == 5) {
4560         if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4561             headmorphness = targetheadmorphness;
4562             headmorphstart = headmorphend;
4563         } else if (headmorphness > targetheadmorphness) {
4564             headmorphness -= multiplier * 10;
4565         } else if (headmorphness < targetheadmorphness) {
4566             headmorphness += multiplier * 10;
4567         }
4568     } else {
4569         if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4570             headmorphness = targetheadmorphness;
4571             headmorphstart = headmorphend;
4572         } else if (headmorphness > targetheadmorphness) {
4573             headmorphness -= multiplier * 4;
4574         } else if (headmorphness < targetheadmorphness) {
4575             headmorphness += multiplier * 4;
4576         }
4577     }
4578
4579     if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4580         chestmorphness = targetchestmorphness;
4581         chestmorphstart = chestmorphend;
4582     } else if (chestmorphness > targetchestmorphness) {
4583         chestmorphness -= multiplier;
4584     } else if (chestmorphness < targetchestmorphness) {
4585         chestmorphness += multiplier;
4586     }
4587
4588     if (dead != 2 && howactive <= typesleeping) {
4589         if (chestmorphstart == 0 && chestmorphend == 0) {
4590             chestmorphness = 0;
4591             targetchestmorphness = 1;
4592             chestmorphend = 3;
4593         }
4594         if (chestmorphstart != 0 && chestmorphend != 0) {
4595             chestmorphness = 0;
4596             targetchestmorphness = 1;
4597             chestmorphend = 0;
4598             if (environment == snowyenvironment) {
4599                 XYZ footpoint;
4600                 XYZ footvel;
4601                 if (skeleton.free) {
4602                     footvel = skeleton.specialforward[0] * -1;
4603                     footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4604                 } else {
4605                     footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4606                     footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4607                 }
4608                 if (animTarget == sleepanim)
4609                     footvel = DoRotation(footvel, 0, 90, 0);
4610                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4611             }
4612         }
4613
4614         if (!dead && howactive < typesleeping) {
4615             blinkdelay -= multiplier * 2;
4616             if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4617                 headmorphness = 0;
4618                 targetheadmorphness = 1;
4619                 headmorphend = 3;
4620                 blinkdelay = (float)(abs(Random() % 40)) / 5;
4621             }
4622             if (headmorphstart == 3 && headmorphend == 3) {
4623                 headmorphness = 0;
4624                 targetheadmorphness = 1;
4625                 headmorphend = 0;
4626             }
4627         }
4628         if (!dead) {
4629             twitchdelay -= multiplier * 1.5;
4630             if (animTarget != hurtidleanim) {
4631                 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4632                     headmorphness = 0;
4633                     targetheadmorphness = 1;
4634                     headmorphend = 5;
4635                     twitchdelay = (float)(abs(Random() % 40)) / 5;
4636                 }
4637                 if (headmorphstart == 5 && headmorphend == 5) {
4638                     headmorphness = 0;
4639                     targetheadmorphness = 1;
4640                     headmorphend = 0;
4641                 }
4642             }
4643             if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4644                 twitchdelay3 -= multiplier * 1;
4645                 if (Random() % 2 == 0) {
4646                     if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4647                         righthandmorphness = 0;
4648                         targetrighthandmorphness = 1;
4649                         righthandmorphend = 1;
4650                         if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4651                     }
4652                     if (righthandmorphstart == 1 && righthandmorphend == 1) {
4653                         righthandmorphness = 0;
4654                         targetrighthandmorphness = 1;
4655                         righthandmorphend = 0;
4656                     }
4657                 }
4658                 if (Random() % 2 == 0) {
4659                     if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4660                         lefthandmorphness = 0;
4661                         targetlefthandmorphness = 1;
4662                         lefthandmorphend = 1;
4663                         twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4664                     }
4665                     if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4666                         lefthandmorphness = 0;
4667                         targetlefthandmorphness = 1;
4668                         lefthandmorphend = 0;
4669                     }
4670                 }
4671             }
4672         }
4673         if (!dead) {
4674             if (creature == rabbittype) {
4675                 if (howactive < typesleeping)
4676                     twitchdelay2 -= multiplier * 1.5;
4677                 else
4678                     twitchdelay2 -= multiplier * 0.5;
4679                 if (howactive <= typesleeping) {
4680                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4681                         tailmorphness = 0;
4682                         targettailmorphness = 1;
4683                         tailmorphend = 1;
4684                         twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4685                     }
4686                     if (tailmorphstart == 1 && tailmorphend == 1) {
4687                         tailmorphness = 0;
4688                         targettailmorphness = 1;
4689                         tailmorphend = 2;
4690                     }
4691                     if (tailmorphstart == 2 && tailmorphend == 2) {
4692                         tailmorphness = 0;
4693                         targettailmorphness = 1;
4694                         tailmorphend = 0;
4695                     }
4696                 }
4697             }
4698         }
4699     }
4700     if (creature == wolftype) {
4701         twitchdelay2 -= multiplier * 1.5;
4702         if (tailmorphend != 0)
4703             if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4704                 tailmorphness = 0;
4705                 targettailmorphness = 1;
4706                 tailmorphend = 0;
4707                 twitchdelay2 = .1;
4708             }
4709         if (tailmorphend != 5)
4710             if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4711                 tailmorphness = 0;
4712                 targettailmorphness = 1;
4713                 tailmorphend = 5;
4714                 twitchdelay2 = .1;
4715             }
4716         if (twitchdelay2 <= 0) {
4717             if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4718                 tailmorphness = 0;
4719                 targettailmorphness = 1;
4720                 tailmorphend = 1;
4721             }
4722             if (tailmorphstart == 1 && tailmorphend == 1) {
4723                 tailmorphness = 0;
4724                 targettailmorphness = 1;
4725                 tailmorphend = 2;
4726             }
4727             if (tailmorphstart == 2 && tailmorphend == 2) {
4728                 tailmorphness = 0;
4729                 targettailmorphness = 1;
4730                 tailmorphend = 3;
4731             }
4732             if (tailmorphstart == 3 && tailmorphend == 3) {
4733                 tailmorphness = 0;
4734                 targettailmorphness = 1;
4735                 tailmorphend = 4;
4736             }
4737             if (tailmorphstart == 4 && tailmorphend == 4) {
4738                 tailmorphness = 0;
4739                 targettailmorphness = 1;
4740                 tailmorphend = 1;
4741             }
4742         }
4743     }
4744
4745     if (dead != 1)
4746         unconscioustime = 0;
4747
4748     if (dead == 1 || howactive == typesleeping) {
4749         unconscioustime += multiplier;
4750         //If unconscious, close eyes and mouth
4751         if (righthandmorphend != 0)
4752             righthandmorphness = 0;
4753         righthandmorphend = 0;
4754         targetrighthandmorphness = 1;
4755
4756         if (lefthandmorphend != 0)
4757             lefthandmorphness = 0;
4758         lefthandmorphend = 0;
4759         targetlefthandmorphness = 1;
4760
4761         if (headmorphend != 3 && headmorphend != 5)
4762             headmorphness = 0;
4763         headmorphend = 3;
4764         targetheadmorphness = 1;
4765     }
4766
4767
4768     if (howactive > typesleeping) {
4769         XYZ headpoint;
4770         headpoint = coords;
4771         if (bloodtoggle && !bled) {
4772             terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4773         }
4774         if (bloodtoggle && !bled)
4775             for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4776                 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4777                 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4778                 float size = .8;
4779                 float opacity = .6;
4780                 float yaw = 0;
4781                 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4782             }
4783         bled = 1;
4784     }
4785
4786     if (dead == 2 || howactive > typesleeping) {
4787         //If dead, open mouth and hands
4788         if (righthandmorphend != 0)
4789             righthandmorphness = 0;
4790         righthandmorphend = 0;
4791         targetrighthandmorphness = 1;
4792
4793         if (lefthandmorphend != 0)
4794             lefthandmorphness = 0;
4795         lefthandmorphend = 0;
4796         targetlefthandmorphness = 1;
4797
4798         if (headmorphend != 2)
4799             headmorphness = 0;
4800         headmorphend = 2;
4801         targetheadmorphness = 1;
4802     }
4803
4804     if (stunned > 0 && !dead && headmorphend != 2) {
4805         if (headmorphend != 4)
4806             headmorphness = 0;
4807         headmorphend = 4;
4808         targetheadmorphness = 1;
4809     }
4810
4811     if (damage > damagetolerance && !dead) {
4812
4813         dead = 1;
4814         unconscioustime = 0;
4815
4816         if (creature == wolftype) {
4817             award_bonus(0, Wolfbonus);
4818         }
4819
4820         RagDoll(0);
4821
4822         if (weaponactive != -1) {
4823             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4824             weapons[weaponids[0]].velocity.x += .01;
4825             num_weapons--;
4826             if (num_weapons) {
4827                 weaponids[0] = weaponids[num_weapons];
4828                 if (weaponstuck == num_weapons)
4829                     weaponstuck = 0;
4830             }
4831             weaponactive = -1;
4832             for (unsigned i = 0; i < Person::players.size(); i++) {
4833                 Person::players[i]->wentforweapon = 0;
4834             }
4835         }
4836
4837
4838
4839         if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4840             slomo = 1;
4841             slomodelay = .2;
4842         }
4843
4844         damage += 20;
4845     }
4846
4847     if (!dead)
4848         damage -= multiplier * 13;
4849     if (!dead)
4850         permanentdamage -= multiplier * 4;
4851     if (isIdle() || isCrouch()) {
4852         if (!dead)
4853             permanentdamage -= multiplier * 4;
4854     }
4855     if (damage < 0)
4856         damage = 0;
4857     if (permanentdamage < 0)
4858         permanentdamage = 0;
4859     if (superpermanentdamage < 0)
4860         superpermanentdamage = 0;
4861     if (permanentdamage < superpermanentdamage) {
4862         permanentdamage = superpermanentdamage;
4863     }
4864     if (damage < permanentdamage) {
4865         damage = permanentdamage;
4866     }
4867     if (dead == 1 && damage < damagetolerance) {
4868         dead = 0;
4869         skeleton.free = 1;
4870         damage -= 20;
4871         for (int i = 0; i < skeleton.num_joints; i++) {
4872             skeleton.joints[i].velocity = 0;
4873         }
4874     }
4875     if (permanentdamage > damagetolerance && dead != 2) {
4876         DoBlood(1, 255);
4877
4878         if (weaponactive != -1) {
4879             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4880             weapons[weaponids[0]].velocity.x += .01;
4881             num_weapons--;
4882             if (num_weapons) {
4883                 weaponids[0] = weaponids[num_weapons];
4884                 if (weaponstuck == num_weapons)
4885                     weaponstuck = 0;
4886             }
4887             weaponactive = -1;
4888             for (unsigned i = 0; i < Person::players.size(); i++) {
4889                 Person::players[i]->wentforweapon = 0;
4890             }
4891         }
4892
4893         bled = 0;
4894
4895         if (!dead && creature == wolftype) {
4896             award_bonus(0, Wolfbonus);
4897         }
4898
4899         if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4900             award_bonus(id, touchofdeath);
4901         if (id != 0 && unconscioustime > .1) {
4902             numafterkill++;
4903         }
4904
4905         dead = 2;
4906
4907         skeleton.free = 1;
4908
4909         emit_sound_at(breaksound, coords);
4910     }
4911
4912     if (skeleton.free == 1) {
4913         if (id == 0)
4914             pause_sound(whooshsound);
4915
4916         if (!dead) {
4917             //If knocked over, open hands and close mouth
4918             if (righthandmorphend != 0)
4919                 righthandmorphness = 0;
4920             righthandmorphend = 0;
4921             targetrighthandmorphness = 1;
4922
4923             if (lefthandmorphend != 0)
4924                 lefthandmorphness = 0;
4925             lefthandmorphend = 0;
4926             targetlefthandmorphness = 1;
4927
4928             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4929                 if (headmorphend != 0)
4930                     headmorphness = 0;
4931                 headmorphend = 0;
4932                 targetheadmorphness = 1;
4933             }
4934         }
4935
4936         skeleton.DoGravity(&scale);
4937         float damageamount;
4938         damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4939         if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4940             award_bonus(id, deepimpact);
4941         DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4942
4943         average = 0;
4944         howmany = 0;
4945         for (j = 0; j < skeleton.num_joints; j++) {
4946             average += skeleton.joints[j].position;
4947             howmany++;
4948         }
4949         average /= howmany;
4950         coords += average * scale;
4951         for (j = 0; j < skeleton.num_joints; j++) {
4952             skeleton.joints[j].position -= average;
4953         }
4954         average /= multiplier;
4955
4956         velocity = 0;
4957         for (int i = 0; i < skeleton.num_joints; i++) {
4958             velocity += skeleton.joints[i].velocity * scale;
4959         }
4960         velocity /= skeleton.num_joints;
4961
4962         if (!isnormal(velocity.x) && velocity.x) {
4963             velocity = 0;
4964         }
4965
4966         if (findLength(&average) < 10 && dead && skeleton.free) {
4967             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4968             if (skeleton.longdead > 2000) {
4969                 if (skeleton.longdead > 6000) {
4970                     if (id == 0)
4971                         pause_sound(whooshsound);
4972                     skeleton.free = 3;
4973                     DrawSkeleton();
4974                     skeleton.free = 2;
4975                 }
4976                 if (dead == 2 && bloodloss < damagetolerance) {
4977                     XYZ headpoint;
4978                     headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4979                     DoBlood(1, 255);
4980                     if (bloodtoggle && !bled) {
4981                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4982                     }
4983                     if (bloodtoggle && !bled)
4984                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4985                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4986                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4987                             float size = .2 * 1.2;
4988                             float opacity = .6;
4989                             float yaw = 0;
4990                             objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4991                         }
4992                     bled = 1;
4993                 }
4994                 if (dead == 2 && bloodloss >= damagetolerance) {
4995                     XYZ headpoint;
4996                     headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4997                     if (bleeding <= 0)
4998                         DoBlood(1, 255);
4999                     if (bloodtoggle && !bled) {
5000                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5001                     }
5002                     if (bloodtoggle && !bled)
5003                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5004                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5005                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5006                             float size = .8;
5007                             float opacity = .6;
5008                             float yaw = 0;
5009                             objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5010                         }
5011                     bled = 1;
5012                 }
5013             }
5014         }
5015
5016         if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5017             bool canrecover = 1;
5018             XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5019             startpoint = coords;
5020             endpoint = coords;
5021             endpoint.y -= .7;
5022             if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5023                 canrecover = 0;
5024             if (velocity.y < -30)
5025                 canrecover = 0;
5026             for (i = 0; i < objects.numobjects; i++) {
5027                 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5028                     colviewer = startpoint;
5029                     coltarget = endpoint;
5030                     if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5031                         canrecover = 0;
5032                 }
5033             }
5034             if (canrecover) {
5035                 skeleton.free = 0;
5036                 XYZ middle;
5037                 middle = 0;
5038
5039                 terrainnormal = jointPos(groin) - jointPos(abdomen);
5040                 if (joint(groin).locked && joint(abdomen).locked) {
5041                     terrainnormal = jointPos(groin) - jointPos(abdomen);
5042                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5043                 }
5044                 if (joint(abdomen).locked && joint(neck).locked) {
5045                     terrainnormal = jointPos(abdomen) - jointPos(neck);
5046                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5047                 }
5048                 if (joint(groin).locked && joint(neck).locked) {
5049                     terrainnormal = jointPos(groin) - jointPos(neck);
5050                     middle = (jointPos(groin) + jointPos(neck)) / 2;
5051                 }
5052                 Normalise(&terrainnormal);
5053
5054                 targetyaw = -asin(0 - terrainnormal.x);
5055                 targetyaw *= 360 / 6.28;
5056                 if (terrainnormal.z < 0)
5057                     targetyaw = 180 - targetyaw;
5058                 yaw = targetyaw;
5059
5060                 frameTarget = 0;
5061                 animTarget = flipanim;
5062                 crouchtogglekeydown = 1;
5063                 target = 0;
5064                 tilt2 = 0;
5065                 targettilt2 = 0;
5066
5067                 animCurrent = tempanim;
5068                 frameCurrent = 0;
5069                 target = 0;
5070
5071                 for (int i = 0; i < skeleton.num_joints; i++) {
5072                     tempanimation.position[i][0] = skeleton.joints[i].position;
5073                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5074                 }
5075             }
5076         }
5077
5078         if (findLength(&average) < 10 && !dead && skeleton.free) {
5079             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5080             if (skeleton.longdead > (damage + 500) * 1.5) {
5081                 if (id == 0)
5082                     pause_sound(whooshsound);
5083                 skeleton.free = 0;
5084                 velocity = 0;
5085                 XYZ middle;
5086                 middle = 0;
5087
5088                 terrainnormal = jointPos(groin) - jointPos(abdomen);
5089                 if (joint(groin).locked && joint(abdomen).locked) {
5090                     terrainnormal = jointPos(groin) - jointPos(abdomen);
5091                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5092                 }
5093                 if (joint(abdomen).locked && joint(neck).locked) {
5094                     terrainnormal = jointPos(abdomen) - jointPos(neck);
5095                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5096                 }
5097                 if (joint(groin).locked && joint(neck).locked) {
5098                     terrainnormal = jointPos(groin) - jointPos(neck);
5099                     middle = (jointPos(groin) + jointPos(neck)) / 2;
5100                 }
5101                 Normalise(&terrainnormal);
5102
5103                 targetyaw = -asin(0 - terrainnormal.x);
5104                 targetyaw *= 360 / 6.28;
5105                 if (terrainnormal.z < 0)
5106                     targetyaw = 180 - targetyaw;
5107                 yaw = targetyaw;
5108
5109                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5110
5111
5112                 if (skeleton.forward.y < 0) {
5113                     animTarget = getupfrombackanim;
5114                     frameTarget = 0;
5115                     targettilt2 = 0;
5116                 }
5117                 if (skeleton.forward.y > -.3) {
5118                     animTarget = getupfromfrontanim;
5119                     yaw += 180;
5120                     targetyaw += 180;
5121                     targettilt2 *= -1;
5122                     frameTarget = 0;
5123                     targettilt2 = 0;
5124                 }
5125
5126                 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5127                     animTarget = rollanim;
5128                     targetyaw = lookyaw;
5129                     if (id == 0) {
5130                         if (rightkeydown) {
5131                             targetyaw -= 90;
5132                             if (forwardkeydown)
5133                                 targetyaw += 45;
5134                             if (backkeydown)
5135                                 targetyaw -= 45;
5136                         }
5137                         if (leftkeydown) {
5138                             targetyaw += 90;
5139                             if (forwardkeydown)
5140                                 targetyaw -= 45;
5141                             if (backkeydown)
5142                                 targetyaw += 45;
5143                         }
5144                         if (backkeydown) {
5145                             if ( !leftkeydown && !rightkeydown)
5146                                 targetyaw += 180;
5147                         }
5148                         targetyaw += 180;
5149                     }
5150                 }
5151
5152                 if (abs(targettilt2) > 50)
5153                     targettilt2 = 0;
5154                 animCurrent = tempanim;
5155                 frameCurrent = 0;
5156                 target = 0;
5157                 tilt2 = targettilt2;
5158
5159                 if (middle.y > 0 && animTarget != rollanim)
5160                     targetoffset.y = middle.y + 1;
5161
5162                 for (int i = 0; i < skeleton.num_joints; i++) {
5163                     tempanimation.position[i][0] = skeleton.joints[i].position;
5164                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5165                 }
5166             }
5167         }
5168
5169         bool hasstaff;
5170         hasstaff = 0;
5171         if (num_weapons > 0)
5172             if (weapons[0].getType() == staff)
5173                 hasstaff = 1;
5174         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5175             if (velocity.y > -30) {
5176                 XYZ tempvelocity;
5177                 tempvelocity = velocity;
5178                 Normalise(&tempvelocity);
5179                 targetyaw = -asin(0 - tempvelocity.x);
5180                 targetyaw *= 360 / 6.28;
5181                 if (velocity.z < 0)
5182                     targetyaw = 180 - targetyaw;
5183                 //targetyaw+=180;
5184
5185                 skeleton.free = 0;
5186                 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5187                     animTarget = rollanim;
5188                     frameTarget = 2;
5189                 } else {
5190                     animTarget = backhandspringanim;
5191                     targetyaw += 180;
5192                     frameTarget = 6;
5193                 }
5194                 target = 0;
5195
5196                 emit_sound_at(movewhooshsound, coords, 128.);
5197
5198                 animCurrent = animTarget;
5199                 frameCurrent = frameTarget - 1;
5200                 target = 0;
5201
5202                 velocity = 0;
5203
5204                 yaw = targetyaw;
5205                 tilt = 0;
5206                 targettilt = 0;
5207                 tilt2 = 0;
5208                 targettilt2 = 0;
5209             }
5210         }
5211         if (skeleton.freefall == 0)
5212             freefall = 0;
5213
5214     }
5215
5216     if (aitype != passivetype || skeleton.free == 1)
5217         if (findLengthfast(&velocity) > .1)
5218             for (i = 0; i < objects.numobjects; i++) {
5219                 if (objects.type[i] == firetype)
5220                     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) {
5221                         if (onfire) {
5222                             if (!objects.onfire[i]) {
5223                                 emit_sound_at(firestartsound, objects.position[i]);
5224                             }
5225                             objects.onfire[i] = 1;
5226                         }
5227                         if (!onfire) {
5228                             if (objects.onfire[i]) {
5229                                 CatchFire();
5230                             }
5231                         }
5232                     }
5233                 if (objects.type[i] == bushtype)
5234                     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) {
5235                         if (onfire) {
5236                             if (!objects.onfire[i]) {
5237                                 emit_sound_at(firestartsound, objects.position[i]);
5238                             }
5239                             objects.onfire[i] = 1;
5240                         }
5241
5242                         if (!onfire) {
5243                             if (objects.onfire[i]) {
5244                                 CatchFire();
5245                             }
5246                         }
5247                         if (objects.messedwith[i] <= 0) {
5248                             XYZ tempvel;
5249                             XYZ pos;
5250
5251                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5252
5253                             if (id == 0) {
5254                                 addEnvSound(coords, 4 * findLength(&velocity));
5255                             }
5256
5257                             int howmany;
5258                             if (environment == grassyenvironment)
5259                                 howmany = findLength(&velocity) * 4;
5260                             if (environment == snowyenvironment)
5261                                 howmany = findLength(&velocity) * 2;
5262                             if (detail == 2)
5263                                 if (environment != desertenvironment)
5264                                     for (j = 0; j < howmany; j++) {
5265                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5266                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5267                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5268                                         pos = coords;
5269                                         pos.y += 1;
5270                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5271                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5272                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5273                                         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);
5274                                         Sprite::setLastSpriteSpecial(1);
5275                                     }
5276                             howmany = findLength(&velocity) * 4;
5277                             if (detail == 2)
5278                                 if (environment == snowyenvironment)
5279                                     for (j = 0; j < howmany; j++) {
5280                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5281                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5282                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5283                                         pos = coords;
5284                                         pos.y += 1;
5285                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5286                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5287                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5288                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5289                                         Sprite::setLastSpriteSpecial(2);
5290                                     }
5291                         }
5292                         objects.rotx[i] += velocity.x * multiplier * 6;
5293                         objects.roty[i] += velocity.z * multiplier * 6;
5294                         objects.messedwith[i] = .5;
5295                     }
5296                 XYZ tempcoord;
5297                 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5298                     if (objects.pitch[i] == 0)
5299                         tempcoord = coords;
5300                     else {
5301                         tempcoord = coords - objects.position[i];
5302                         tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5303                         tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5304                         tempcoord += objects.position[i];
5305                     }
5306                     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]) {
5307                         if (objects.messedwith[i] <= 0) {
5308                             XYZ tempvel;
5309                             XYZ pos;
5310
5311                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5312
5313                             if (id == 0) {
5314                                 addEnvSound(coords, 4 * findLength(&velocity));
5315                             }
5316
5317                             int howmany;
5318                             if (environment == grassyenvironment)
5319                                 howmany = findLength(&velocity) * 4;
5320                             if (environment == snowyenvironment)
5321                                 howmany = findLength(&velocity) * 2;
5322                             if (detail == 2)
5323                                 if (environment != desertenvironment)
5324                                     for (j = 0; j < howmany; j++) {
5325                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5326                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5327                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5328                                         pos = coords;
5329                                         pos += velocity * .1;
5330                                         pos.y += 1;
5331                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5332                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5333                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5334                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .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);
5335                                         Sprite::setLastSpriteSpecial(1);
5336                                     }
5337                             howmany = findLength(&velocity) * 4;
5338                             if (detail == 2)
5339                                 if (environment == snowyenvironment)
5340                                     for (j = 0; j < howmany; j++) {
5341                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5342                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5343                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5344                                         pos = coords;
5345                                         pos += velocity * .1;
5346                                         pos.y += 1;
5347                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5348                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5349                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5350                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5351                                         Sprite::setLastSpriteSpecial(2);
5352                                     }
5353                         }
5354                         objects.messedwith[i] = .5;
5355                     }
5356                 }
5357             }
5358
5359     if (!skeleton.free) {
5360         bool play;
5361         play = 0;
5362         if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5363             play = 1;
5364         if (hasvictim)
5365             if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5366                 play = 1;
5367         if (tutoriallevel == 1 && id != 0)
5368             play = 0;
5369         if (play && aitype != playercontrolled) {
5370             int whichsound = -1;
5371             i = abs(Random() % 4);
5372             if (speechdelay <= 0) {
5373                 if (creature == rabbittype) {
5374                     if (i == 0)
5375                         whichsound = rabbitchitter;
5376                     if (i == 1)
5377                         whichsound = rabbitchitter2;
5378                 }
5379                 if (creature == wolftype) {
5380                     if (i == 0)
5381                         whichsound = growlsound;
5382                     if (i == 1)
5383                         whichsound = growl2sound;
5384                 }
5385             }
5386             speechdelay = .3;
5387
5388             if (whichsound != -1) {
5389                 emit_sound_at(whichsound, coords);
5390             }
5391         }
5392
5393         if (animTarget == staggerbackhighanim)
5394             staggerdelay = 1;
5395         if (animTarget == staggerbackhardanim)
5396             staggerdelay = 1;
5397         staggerdelay -= multiplier;
5398         if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5399             hasvictim = 1;
5400         if (velocity.y < -30 && animTarget == jumpdownanim)
5401             RagDoll(0);
5402         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5403             animTarget = getIdle();
5404             frameTarget = 0;
5405             target = 0;
5406         }
5407         weaponmissdelay -= multiplier;
5408         highreversaldelay -= multiplier;
5409         lowreversaldelay -= multiplier;
5410         lastcollide -= multiplier;
5411         skiddelay -= multiplier;
5412         if (!isnormal(velocity.x) && velocity.x) {
5413             velocity = 0;
5414         }
5415         if (!isnormal(targettilt) && targettilt) {
5416             targettilt = 0;
5417         }
5418         if (!isnormal(targettilt2) && targettilt2) {
5419             targettilt2 = 0;
5420         }
5421         if (!isnormal(targetyaw) && targetyaw) {
5422             targetyaw = 0;
5423         }
5424
5425         if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5426             //open hands and close mouth
5427             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5428                 righthandmorphness = 0;
5429                 righthandmorphend = 0;
5430                 targetrighthandmorphness = 1;
5431             }
5432
5433             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5434                 lefthandmorphness = 0;
5435                 lefthandmorphend = 0;
5436                 targetlefthandmorphness = 1;
5437             }
5438
5439             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5440                 headmorphness = 0;
5441                 headmorphend = 0;
5442                 targetheadmorphness = 1;
5443             }
5444         }
5445
5446         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) {
5447             //open hands and mouth
5448             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5449                 righthandmorphness = 0;
5450                 righthandmorphend = 0;
5451                 targetrighthandmorphness = 1;
5452             }
5453
5454             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5455                 lefthandmorphness = 0;
5456                 lefthandmorphend = 0;
5457                 targetlefthandmorphness = 1;
5458             }
5459
5460             if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5461                 headmorphness = 0;
5462                 headmorphend = 1;
5463                 targetheadmorphness = 1;
5464             }
5465         }
5466
5467         if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5468             //close hands and mouth
5469             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5470                 righthandmorphness = 0;
5471                 righthandmorphend = 1;
5472                 targetrighthandmorphness = 1;
5473             }
5474
5475             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5476                 lefthandmorphness = 0;
5477                 lefthandmorphend = 1;
5478                 targetlefthandmorphness = 1;
5479             }
5480
5481             if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5482                 headmorphness = 0;
5483                 headmorphend = 0;
5484                 targetheadmorphness = 1;
5485             }
5486         }
5487
5488         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) {
5489             //close hands and yell
5490             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5491                 righthandmorphness = 0;
5492                 righthandmorphend = 1;
5493                 targetrighthandmorphness = 1;
5494             }
5495
5496             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5497                 lefthandmorphness = 0;
5498                 lefthandmorphend = 1;
5499                 targetlefthandmorphness = 1;
5500             }
5501
5502             if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5503                 headmorphness = 1;
5504                 headmorphend = 2;
5505                 targetheadmorphness = 1;
5506             }
5507         }
5508
5509         bool behind;
5510         behind = 0;
5511         if (hasvictim) {
5512             if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5513                 (victim->aitype != searchtype) && (aitype != passivetype) &&
5514                 (aitype != searchtype) && (victim->id < Person::players.size())) {
5515                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5516             }
5517         }
5518
5519         if (!dead && animTarget != hurtidleanim)
5520             if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5521                 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5522                     headmorphend = 4;
5523                     //headmorphness=1;
5524                     targetheadmorphness = 1;
5525                 }
5526             }
5527
5528         if (weaponactive != -1) {
5529             if (weapons[weaponids[weaponactive]].getType() != staff) {
5530                 righthandmorphstart = 1;
5531                 righthandmorphend = 1;
5532             }
5533             if (weapons[weaponids[weaponactive]].getType() == staff) {
5534                 righthandmorphstart = 2;
5535                 righthandmorphend = 2;
5536             }
5537             targetrighthandmorphness = 1;
5538         }
5539
5540         terrainnormal = terrain.getNormal(coords.x, coords.z);
5541
5542         if (animation[animTarget].attack != reversal) {
5543             if (!isnormal(coords.x))
5544                 coords = oldcoords;
5545             oldcoords = coords;
5546         }
5547
5548         flatfacing = 0;
5549         flatfacing.z = 1;
5550
5551         flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5552         facing = flatfacing;
5553         ReflectVector(&facing, terrainnormal);
5554         Normalise(&facing);
5555
5556         if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5557             if (onterrain)
5558                 targettilt2 = -facing.y * 20;
5559             else
5560                 targettilt2 = 0;
5561         }
5562         onterrain = 0;
5563         if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5564             targettilt2 = 0;
5565         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5566             flatvelocity = velocity;
5567             flatvelocity.y = 0;
5568             flatvelspeed = findLength(&flatvelocity);
5569             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5570             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5571             if (velocity.y < 0)
5572                 targettilt2 *= -1;
5573             if (velocity.y < 0)
5574                 targettilt *= -1;
5575             if (targettilt > 25)
5576                 targettilt = 25;
5577             if (targettilt < -25)
5578                 targettilt = -25;
5579         }
5580
5581         if (targettilt2 > 45)
5582             targettilt2 = 45;
5583         if (targettilt2 < -45)
5584             targettilt2 = -45;
5585         if (abs(tilt2 - targettilt2) < multiplier * 400)
5586             tilt2 = targettilt2;
5587         else if (tilt2 > targettilt2) {
5588             tilt2 -= multiplier * 400;
5589         } else if (tilt2 < targettilt2) {
5590             tilt2 += multiplier * 400;
5591         }
5592         if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5593             if (tilt2 > 25)
5594                 tilt2 = 25;
5595             if (tilt2 < -25)
5596                 tilt2 = -25;
5597         }
5598
5599         if (!isnormal(targettilt) && targettilt) {
5600             targettilt = 0;
5601         }
5602         if (!isnormal(targettilt2) && targettilt2) {
5603             targettilt2 = 0;
5604         }
5605
5606         //Running velocity
5607         if (animTarget == rabbittackleanim) {
5608             velocity += facing * multiplier * speed * 700 * scale;
5609             velspeed = findLength(&velocity);
5610             if (velspeed > speed * 65 * scale) {
5611                 velocity /= velspeed;
5612                 velspeed = speed * 65 * scale;
5613                 velocity *= velspeed;
5614             }
5615             velocity.y += gravity * multiplier * 20;
5616             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5617             velspeed = findLength(&velocity);
5618             velocity = flatfacing * velspeed;
5619         }
5620         if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5621             if (isRun() || animTarget == rabbitkickanim) {
5622                 velocity += facing * multiplier * speed * 700 * scale;
5623                 velspeed = findLength(&velocity);
5624                 if (velspeed > speed * 45 * scale) {
5625                     velocity /= velspeed;
5626                     velspeed = speed * 45 * scale;
5627                     velocity *= velspeed;
5628                 }
5629                 velocity.y += gravity * multiplier * 20;
5630                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5631                 velspeed = findLength(&velocity);
5632                 if (velspeed < speed * 30 * scale)
5633                     velspeed = speed * 30 * scale;
5634                 velocity = flatfacing * velspeed;
5635             }
5636         } else if (isRun()) {
5637             velocity += facing * multiplier * speed * 700 * scale;
5638             velspeed = findLength(&velocity);
5639             if (creature == rabbittype) {
5640                 if (velspeed > speed * 55 * scale) {
5641                     velocity /= velspeed;
5642                     velspeed = speed * 55 * scale;
5643                     velocity *= velspeed;
5644                 }
5645             }
5646             if (creature == wolftype) {
5647                 if (velspeed > speed * 75 * scale) {
5648                     velocity /= velspeed;
5649                     velspeed = speed * 75 * scale;
5650                     velocity *= velspeed;
5651                 }
5652             }
5653             velocity.y += gravity * multiplier * 20;
5654             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5655             velspeed = findLength(&velocity);
5656             velocity = flatfacing * velspeed;
5657         }
5658
5659         if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5660             velocity += facing * multiplier * speed * 700 * scale;
5661             velspeed = findLength(&velocity);
5662             if (velspeed > speed * 45 * scale) {
5663                 velocity /= velspeed;
5664                 velspeed = speed * 45 * scale;
5665                 velocity *= velspeed;
5666             }
5667             velocity.y += gravity * multiplier * 20;
5668             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5669             velspeed = findLength(&velocity);
5670             velocity = flatfacing * velspeed;
5671         }
5672
5673         if (animTarget == sneakanim || animTarget == walkanim) {
5674             velocity += facing * multiplier * speed * 700 * scale;
5675             velspeed = findLength(&velocity);
5676             if (velspeed > speed * 12 * scale) {
5677                 velocity /= velspeed;
5678                 velspeed = speed * 12 * scale;
5679                 velocity *= velspeed;
5680             }
5681             velocity.y += gravity * multiplier * 20;
5682             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5683             velspeed = findLength(&velocity);
5684             velocity = flatfacing * velspeed;
5685         }
5686
5687         if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5688             velocity += facing * multiplier * speed * 700 * scale;
5689             velspeed = findLength(&velocity);
5690             if (velspeed > speed * 2 * scale) {
5691                 velocity /= velspeed;
5692                 velspeed = speed * 2 * scale;
5693                 velocity *= velspeed;
5694             }
5695             velocity.y += gravity * multiplier * 20;
5696             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5697             velspeed = findLength(&velocity);
5698             velocity = flatfacing * velspeed;
5699         }
5700
5701
5702         if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5703             velocity -= facing * multiplier * speed * 700 * scale;
5704             velspeed = findLength(&velocity);
5705             if (velspeed > speed * 2 * scale) {
5706                 velocity /= velspeed;
5707                 velspeed = speed * 2 * scale;
5708                 velocity *= velspeed;
5709             }
5710             velocity.y += gravity * multiplier * 20;
5711             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5712             velspeed = findLength(&velocity);
5713             velocity = flatfacing * velspeed * -1;
5714         }
5715
5716         if (animTarget == fightsidestep) {
5717             velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5718             velspeed = findLength(&velocity);
5719             if (velspeed > speed * 12 * scale) {
5720                 velocity /= velspeed;
5721                 velspeed = speed * 12 * scale;
5722                 velocity *= velspeed;
5723             }
5724             velocity.y += gravity * multiplier * 20;
5725             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5726             velspeed = findLength(&velocity);
5727             velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5728         }
5729
5730         if (animTarget == staggerbackhighanim) {
5731             coords -= facing * multiplier * speed * 16 * scale;
5732             velocity = 0;
5733         }
5734         if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5735             coords -= facing * multiplier * speed * 20 * scale;
5736             velocity = 0;
5737         }
5738
5739         if (animTarget == backhandspringanim) {
5740             //coords-=facing*multiplier*50*scale;
5741             velocity += facing * multiplier * speed * 700 * scale * -1;
5742             velspeed = findLength(&velocity);
5743             if (velspeed > speed * 50 * scale) {
5744                 velocity /= velspeed;
5745                 velspeed = speed * 50 * scale;
5746                 velocity *= velspeed;
5747             }
5748             velocity.y += gravity * multiplier * 20;
5749             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5750             velspeed = findLength(&velocity);
5751             velocity = flatfacing * velspeed * -1;
5752         }
5753         if (animTarget == dodgebackanim) {
5754             //coords-=facing*multiplier*50*scale;
5755             velocity += facing * multiplier * speed * 700 * scale * -1;
5756             velspeed = findLength(&velocity);
5757             if (velspeed > speed * 60 * scale) {
5758                 velocity /= velspeed;
5759                 velspeed = speed * 60 * scale;
5760                 velocity *= velspeed;
5761             }
5762             velocity.y += gravity * multiplier * 20;
5763             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5764             velspeed = findLength(&velocity);
5765             velocity = flatfacing * velspeed * -1;
5766         }
5767
5768         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5769             velspeed = findLength(&velocity);
5770         }
5771
5772
5773         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5774             velocity.y += gravity * multiplier;
5775         }
5776
5777         if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5778             coords += velocity * multiplier;
5779
5780         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5781             if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5782                 RagDoll(0);
5783
5784             if (animTarget == jumpupanim) {
5785                 jumppower = -4;
5786                 animTarget = getIdle();
5787             }
5788             target = 0;
5789             frameTarget = 0;
5790             onterrain = 1;
5791
5792             if (id == 0) {
5793                 pause_sound(whooshsound);
5794                 OPENAL_SetVolume(channels[whooshsound], 0);
5795             }
5796
5797             if (animTarget == jumpdownanim || isFlip()) {
5798                 if (isFlip())jumppower = -4;
5799                 animTarget = getLanding();
5800                 emit_sound_at(landsound, coords, 128.);
5801
5802                 if (id == 0) {
5803                     addEnvSound(coords);
5804                 }
5805             }
5806         }
5807
5808         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5809             coords.y += gravity * multiplier * 2;
5810         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5811             coords.y = terrain.getHeight(coords.x, coords.z);
5812             onterrain = 1;
5813         }
5814
5815
5816         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)) {
5817             velspeed = findLength(&velocity);
5818             velocity.y = 0;
5819             if (velspeed < multiplier * 300 * scale) {
5820                 velocity = 0;
5821             } else
5822                 velocity -= velocity / velspeed * multiplier * 300 * scale;
5823             if (velspeed > 5 && (isLanding() || isLandhard())) {
5824                 skiddingdelay += multiplier;
5825                 if (skiddelay <= 0) {
5826                     FootLand(leftfoot, .5);
5827                     FootLand(rightfoot, .5);
5828                     skiddelay = .02;
5829                 }
5830             } else
5831                 skiddingdelay = 0;
5832         }
5833
5834         if (isLandhard()) {
5835             velspeed = findLength(&velocity);
5836             velocity.y = 0;
5837             if (velspeed < multiplier * 600 * scale) {
5838                 velocity = 0;
5839             } else
5840                 velocity -= velocity / velspeed * multiplier * 600 * scale;
5841             velocity = 0;
5842             if (velspeed > 5 && (isLanding() || isLandhard())) {
5843                 skiddingdelay += multiplier;
5844                 if (skiddelay <= 0) {
5845                     FootLand(leftfoot, .5);
5846                     FootLand(rightfoot, .5);
5847                     skiddelay = .02;
5848                 }
5849             } else
5850                 skiddingdelay = 0;
5851         }
5852
5853         if (skiddingdelay < 0)
5854             skiddingdelay += multiplier;
5855         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5856             skiddingdelay = -1;
5857             if (!onterrain || environment == grassyenvironment) {
5858                 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5859             } else {
5860                 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5861             }
5862         }
5863
5864         if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5865             terrainnormal = victim->coords - coords;
5866             Normalise(&terrainnormal);
5867             targetyaw = -asin(0 - terrainnormal.x);
5868             targetyaw *= 360 / 6.28;
5869             if (terrainnormal.z < 0)
5870                 targetyaw = 180 - targetyaw;
5871             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5872         }
5873
5874         if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5875             targetyaw = victim->targetyaw;
5876         }
5877         if (animTarget == rabbittacklinganim) {
5878             coords = victim->coords;
5879         }
5880     }
5881     skeleton.oldfree = skeleton.free;
5882
5883     XYZ midterrain;
5884     midterrain = 0;
5885     midterrain.x = terrain.size * terrain.scale / 2;
5886     midterrain.z = terrain.size * terrain.scale / 2;
5887     if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5888         XYZ tempposit;
5889         tempposit = coords - midterrain;
5890         tempposit.y = 0;
5891         Normalise(&tempposit);
5892         tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5893         coords.x = tempposit.x + midterrain.x;
5894         coords.z = tempposit.z + midterrain.z;
5895     }
5896 }
5897
5898
5899 /* EFFECT
5900  * inverse kinematics helper function
5901  */
5902 void IKHelper(Person *p, float interp)
5903 {
5904     XYZ point, change, change2;
5905     float heightleft, heightright;
5906
5907     // TODO: implement localToWorld and worldToLocal
5908     //       but keep in mind it won't be the same math if player is ragdolled or something
5909     //       - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5910     //       then comb through code for places where to use it
5911
5912     // point = localToWorld(jointPos(leftfoot))
5913     point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5914     // adjust height of foot
5915     heightleft = terrain.getHeight(point.x, point.z) + .04;
5916     point.y = heightleft;
5917     change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5918     change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5919     // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5920     p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5921     // move ankle along with foot
5922     p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5923     // average knee pos between old and new pos
5924     p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5925
5926     // do same as above for right leg
5927     point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5928     heightright = terrain.getHeight(point.x, point.z) + .04;
5929     point.y = heightright;
5930     change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5931     change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5932     p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5933     p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5934     p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5935
5936     // fix up skeleton now that we've moved body parts?
5937     p->skeleton.DoConstraints(&p->coords, &p->scale);
5938 }
5939
5940 /* EFFECT
5941  * MONSTER
5942  * TODO: ???
5943  */
5944 int Person::DrawSkeleton()
5945 {
5946     int oldplayerdetail;
5947     if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5948         if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5949             calcrot = 1;
5950         }
5951
5952         if (headless) {
5953             headmorphness = 0;
5954             headmorphstart = 6;
5955             headmorphend = 6;
5956         }
5957
5958         glAlphaFunc(GL_GREATER, 0.0001);
5959         XYZ terrainlight;
5960         float terrainheight;
5961         float distance;
5962         if (!isnormal(yaw))
5963             yaw = 0;
5964         if (!isnormal(tilt))
5965             tilt = 0;
5966         if (!isnormal(tilt2))
5967             tilt2 = 0;
5968         oldplayerdetail = playerdetail;
5969         playerdetail = 0;
5970         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5971             playerdetail = 1;
5972         }
5973         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5974             playerdetail = 1;
5975         }
5976         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5977             playerdetail = 1;
5978         }
5979         if (id == 0)
5980             playerdetail = 1;
5981         if (playerdetail != oldplayerdetail) {
5982             updatedelay = 0;
5983             normalsupdatedelay = 0;
5984         }
5985         static float updatedelaychange;
5986         static float morphness;
5987         static float framemult;
5988         if (calcrot) {
5989             skeleton.FindForwards();
5990             if (howactive == typesittingwall) {
5991                 skeleton.specialforward[1] = 0;
5992                 skeleton.specialforward[1].z = 1;
5993             }
5994         }
5995         static XYZ mid;
5996         static float M[16];
5997         static int i, j, k;
5998         static int weaponattachmuscle;
5999         static int weaponrotatemuscle;
6000         static XYZ weaponpoint;
6001         static int start, endthing;
6002         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6003             if (!isSleeping() && !isSitting()) {
6004                 // TODO: give these meaningful names
6005                 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6006                                     || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6007                 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6008                                     || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6009
6010                 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6011                     IKHelper(this, 1);
6012                     if (creature == wolftype)
6013                         IKHelper(this, 1);
6014                 }
6015
6016                 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6017                     IKHelper(this, target);
6018                     if (creature == wolftype)
6019                         IKHelper(this, target);
6020                 }
6021
6022                 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6023                     IKHelper(this, 1 - target);
6024                     if (creature == wolftype)
6025                         IKHelper(this, 1 - target);
6026                 }
6027             }
6028
6029             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()))
6030                 DoHead();
6031             else {
6032                 targetheadyaw = -targetyaw;
6033                 targetheadpitch = 0;
6034                 if (animation[animTarget].attack == 3)
6035                     targetheadyaw += 180;
6036             }
6037             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6038                 skeleton.drawmodel.vertex[i] = 0;
6039                 skeleton.drawmodel.vertex[i].y = 999;
6040             }
6041             for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6042                 skeleton.drawmodellow.vertex[i] = 0;
6043                 skeleton.drawmodellow.vertex[i].y = 999;
6044             }
6045             for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6046                 skeleton.drawmodelclothes.vertex[i] = 0;
6047                 skeleton.drawmodelclothes.vertex[i].y = 999;
6048             }
6049             for (int i = 0; i < skeleton.num_muscles; i++) {
6050                 // convenience renames
6051                 const int p1 = skeleton.muscles[i].parent1->label;
6052                 const int p2 = skeleton.muscles[i].parent2->label;
6053
6054                 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6055                     morphness = 0;
6056                     start = 0;
6057                     endthing = 0;
6058
6059                     if (p1 == righthand || p2 == righthand) {
6060                         morphness = righthandmorphness;
6061                         start = righthandmorphstart;
6062                         endthing = righthandmorphend;
6063                     }
6064                     if (p1 == lefthand || p2 == lefthand) {
6065                         morphness = lefthandmorphness;
6066                         start = lefthandmorphstart;
6067                         endthing = lefthandmorphend;
6068                     }
6069                     if (p1 == head || p2 == head) {
6070                         morphness = headmorphness;
6071                         start = headmorphstart;
6072                         endthing = headmorphend;
6073                     }
6074                     if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6075                         morphness = chestmorphness;
6076                         start = chestmorphstart;
6077                         endthing = chestmorphend;
6078                     }
6079                     if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6080                         morphness = tailmorphness;
6081                         start = tailmorphstart;
6082                         endthing = tailmorphend;
6083                     }
6084                     if (calcrot)
6085                         skeleton.FindRotationMuscle(i, animTarget);
6086                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6087                     glMatrixMode(GL_MODELVIEW);
6088                     glPushMatrix();
6089                     glLoadIdentity();
6090                     if (!skeleton.free)
6091                         glRotatef(tilt2, 1, 0, 0);
6092                     if (!skeleton.free)
6093                         glRotatef(tilt, 0, 0, 1);
6094
6095
6096                     glTranslatef(mid.x, mid.y, mid.z);
6097
6098                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6099                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6100
6101                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6102                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6103
6104                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6105                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6106
6107                     if (playerdetail || skeleton.free == 3) {
6108                         for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6109                             XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6110                             XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6111                             glMatrixMode(GL_MODELVIEW);
6112                             glPushMatrix();
6113                             if (p1 == abdomen || p2 == abdomen)
6114                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6115                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6116                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6117                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6118                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6119                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6120                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6121                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6122                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6123                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6124                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6125                             if (p1 == head || p2 == head)
6126                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6127                                              (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6128                                              (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6129                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6130                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6131                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6132                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6133                             glPopMatrix();
6134                         }
6135                     }
6136                     if (!playerdetail || skeleton.free == 3) {
6137                         for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6138                             XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6139                             glMatrixMode(GL_MODELVIEW);
6140                             glPushMatrix();
6141                             if (p1 == abdomen || p2 == abdomen)
6142                                 glTranslatef(v0.x * proportionbody.x,
6143                                              v0.y * proportionbody.y,
6144                                              v0.z * proportionbody.z);
6145                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6146                                 glTranslatef(v0.x * proportionarms.x,
6147                                              v0.y * proportionarms.y,
6148                                              v0.z * proportionarms.z);
6149                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6150                                 glTranslatef(v0.x * proportionlegs.x,
6151                                              v0.y * proportionlegs.y,
6152                                              v0.z * proportionlegs.z);
6153                             if (p1 == head || p2 == head)
6154                                 glTranslatef(v0.x * proportionhead.x,
6155                                              v0.y * proportionhead.y,
6156                                              v0.z * proportionhead.z);
6157
6158                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6159                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6160                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6161                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6162                             glPopMatrix();
6163                         }
6164                     }
6165                     glPopMatrix();
6166                 }
6167                 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6168                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6169
6170                     glMatrixMode(GL_MODELVIEW);
6171                     glPushMatrix();
6172                     glLoadIdentity();
6173                     if (!skeleton.free)
6174                         glRotatef(tilt2, 1, 0, 0);
6175                     if (!skeleton.free)
6176                         glRotatef(tilt, 0, 0, 1);
6177                     glTranslatef(mid.x, mid.y, mid.z);
6178                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6179                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6180
6181                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6182                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6183
6184                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6185                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6186
6187                     for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6188                         XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6189                         glMatrixMode(GL_MODELVIEW);
6190                         glPushMatrix();
6191                         if (p1 == abdomen || p2 == abdomen)
6192                             glTranslatef(v0.x * proportionbody.x,
6193                                          v0.y * proportionbody.y,
6194                                          v0.z * proportionbody.z);
6195                         if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6196                             glTranslatef(v0.x * proportionarms.x,
6197                                          v0.y * proportionarms.y,
6198                                          v0.z * proportionarms.z);
6199                         if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6200                             glTranslatef(v0.x * proportionlegs.x,
6201                                          v0.y * proportionlegs.y,
6202                                          v0.z * proportionlegs.z);
6203                         if (p1 == head || p2 == head)
6204                             glTranslatef(v0.x * proportionhead.x,
6205                                          v0.y * proportionhead.y,
6206                                          v0.z * proportionhead.z);
6207                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
6208                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6209                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6210                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6211                         glPopMatrix();
6212                     }
6213                     glPopMatrix();
6214                 }
6215                 updatedelay = 1 + (float)(Random() % 100) / 1000;
6216             }
6217             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6218                 normalsupdatedelay = 1;
6219                 if (playerdetail || skeleton.free == 3)
6220                     skeleton.drawmodel.CalculateNormals(0);
6221                 if (!playerdetail || skeleton.free == 3)
6222                     skeleton.drawmodellow.CalculateNormals(0);
6223                 if (skeleton.clothes)
6224                     skeleton.drawmodelclothes.CalculateNormals(0);
6225             } else {
6226                 if (playerdetail || skeleton.free == 3)
6227                     skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6228                 if (!playerdetail || skeleton.free == 3)
6229                     skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6230                 if (skeleton.clothes) {
6231                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6232                 }
6233             }
6234         }
6235         framemult = .01;
6236         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6237         if (updatedelaychange > -realmultiplier * 30)
6238             updatedelaychange = -realmultiplier * 30;
6239         if (updatedelaychange > -framemult * 4)
6240             updatedelaychange = -framemult * 4;
6241         if (skeleton.free == 1)
6242             updatedelaychange *= 6;
6243         if (id == 0)
6244             updatedelaychange *= 8;
6245         updatedelay += updatedelaychange;
6246
6247         glMatrixMode(GL_MODELVIEW);
6248         glPushMatrix();
6249         glTranslatef(coords.x, coords.y - .02, coords.z);
6250         if (!skeleton.free) {
6251             glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6252             glRotatef(yaw, 0, 1, 0);
6253         }
6254         if (showpoints) {
6255             glPointSize(5);
6256             glColor4f(.4, 1, .4, 1);
6257             glDisable(GL_LIGHTING);
6258             glDisable(GL_TEXTURE_2D);
6259             glBegin(GL_POINTS);
6260             if (playerdetail)
6261                 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6262                     XYZ &v0 = skeleton.drawmodel.vertex[i];
6263                     glVertex3f(v0.x, v0.y, v0.z);
6264                 }
6265             glEnd();
6266             glBegin(GL_LINES);
6267
6268             if (playerdetail)
6269                 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6270                     XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6271                     XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6272                     XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6273                     glVertex3f(v0.x, v0.y, v0.z);
6274                     glVertex3f(v1.x, v1.y, v1.z);
6275                     glVertex3f(v1.x, v1.y, v1.z);
6276                     glVertex3f(v2.x, v2.y, v2.z);
6277                     glVertex3f(v2.x, v2.y, v2.z);
6278                     glVertex3f(v0.x, v0.y, v0.z);
6279                 }
6280
6281             glEnd();
6282         }
6283
6284         terrainlight = terrain.getLighting(coords.x, coords.z);
6285         distance = distsq(&viewer, &coords);
6286         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6287         if (distance > 1)
6288             distance = 1;
6289         if (distance > 0) {
6290             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6291             if (terrainheight < 1)
6292                 terrainheight = 1;
6293             if (terrainheight > 1.7)
6294                 terrainheight = 1.7;
6295
6296             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6297             glDisable(GL_BLEND);
6298             glAlphaFunc(GL_GREATER, 0.0001);
6299             glEnable(GL_TEXTURE_2D);
6300             if (cellophane) {
6301                 glDisable(GL_TEXTURE_2D);
6302                 glColor4f(.7, .35, 0, .5);
6303                 glDepthMask(0);
6304                 glEnable(GL_LIGHTING);
6305                 glEnable(GL_BLEND);
6306             }
6307             if (tutoriallevel && id != 0) {
6308                 glColor4f(.7, .7, .7, 0.6);
6309                 glDepthMask(0);
6310                 glEnable(GL_LIGHTING);
6311                 glEnable(GL_BLEND);
6312                 if (canattack && cananger)
6313                     if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6314                         glDisable(GL_TEXTURE_2D);
6315                         glColor4f(1, 0, 0, 0.8);
6316                     }
6317                 glMatrixMode(GL_TEXTURE);
6318                 glPushMatrix();
6319                 glTranslatef(0, -smoketex, 0);
6320                 glTranslatef(-smoketex, 0, 0);
6321             }
6322             if (playerdetail) {
6323                 if (!showpoints) {
6324                     if ((tutoriallevel && id != 0))
6325                         skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6326                     else
6327                         skeleton.drawmodel.draw();
6328                 }
6329             }
6330             if (!playerdetail) {
6331                 if ((tutoriallevel && id != 0))
6332                     skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6333                 else
6334                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6335             }
6336
6337             if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6338                 if (tutoriallevel && id != 0) {
6339                     glPopMatrix();
6340                     glMatrixMode(GL_MODELVIEW);
6341                     glEnable(GL_TEXTURE_2D);
6342                     glColor4f(.7, .7, .7, 0.6);
6343                     glDepthMask(0);
6344                     glEnable(GL_LIGHTING);
6345                     glEnable(GL_BLEND);
6346                     if (canattack && cananger)
6347                         if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6348                             glDisable(GL_TEXTURE_2D);
6349                             glColor4f(1, 0, 0, 0.8);
6350                         }
6351                     glMatrixMode(GL_TEXTURE);
6352                     glPushMatrix();
6353                     glTranslatef(0, -smoketex * .6, 0);
6354                     glTranslatef(smoketex * .6, 0, 0);
6355                     if (playerdetail) {
6356                         if (!showpoints) {
6357                             if ((tutoriallevel && id != 0))
6358                                 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6359                             else
6360                                 skeleton.drawmodel.draw();
6361                         }
6362                     }
6363                     if (!playerdetail) {
6364                         if ((tutoriallevel && id != 0))
6365                             skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6366                         else
6367                             skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6368                     }
6369                 }
6370
6371
6372             if (tutoriallevel && id != 0) {
6373                 glPopMatrix();
6374                 glMatrixMode(GL_MODELVIEW);
6375                 glEnable(GL_TEXTURE_2D);
6376             }
6377             if (skeleton.clothes) {
6378                 glDepthMask(0);
6379                 glEnable(GL_BLEND);
6380                 if (!immediate)
6381                     skeleton.drawmodelclothes.draw();
6382                 if (immediate)
6383                     skeleton.drawmodelclothes.drawimmediate();
6384                 glDepthMask(1);
6385             }
6386         }
6387         glPopMatrix();
6388
6389         if (num_weapons > 0) {
6390             for (k = 0; k < num_weapons; k++) {
6391                 i = weaponids[k];
6392                 if (weaponactive == k) {
6393                     if (weapons[i].getType() != staff) {
6394                         for (j = 0; j < skeleton.num_muscles; j++) {
6395                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6396                                 weaponattachmuscle = j;
6397                             }
6398                         }
6399                         for (j = 0; j < skeleton.num_muscles; j++) {
6400                             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) {
6401                                 weaponrotatemuscle = j;
6402                             }
6403                         }
6404                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6405                         if (creature == wolftype)
6406                             weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6407                     }
6408                     if (weapons[i].getType() == staff) {
6409                         for (j = 0; j < skeleton.num_muscles; j++) {
6410                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6411                                 weaponattachmuscle = j;
6412                             }
6413                         }
6414                         for (j = 0; j < skeleton.num_muscles; j++) {
6415                             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) {
6416                                 weaponrotatemuscle = j;
6417                             }
6418                         }
6419                         //weaponpoint=jointPos(rightwrist);
6420                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6421                         //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6422                         XYZ tempnormthing, vec1, vec2;
6423                         vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6424                         vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6425                         CrossProduct(&vec1, &vec2, &tempnormthing);
6426                         Normalise(&tempnormthing);
6427                         if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6428                             weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6429                     }
6430                 }
6431                 if (weaponactive != k && weaponstuck != k) {
6432                     if (weapons[i].getType() == knife)
6433                         weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6434                     if (weapons[i].getType() == sword)
6435                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6436                     if (weapons[i].getType() == staff)
6437                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6438                     for (j = 0; j < skeleton.num_muscles; j++) {
6439                         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) {
6440                             weaponrotatemuscle = j;
6441                         }
6442                     }
6443                 }
6444                 if (weaponstuck == k) {
6445                     if (weaponstuckwhere == 0)
6446                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6447                     else
6448                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6449                     for (j = 0; j < skeleton.num_muscles; j++) {
6450                         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) {
6451                             weaponrotatemuscle = j;
6452                         }
6453                     }
6454                 }
6455                 if (skeleton.free) {
6456                     weapons[i].position = weaponpoint * scale + coords;
6457                     weapons[i].bigrotation = 0;
6458                     weapons[i].bigtilt = 0;
6459                     weapons[i].bigtilt2 = 0;
6460                 } else {
6461                     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;
6462                     weapons[i].bigrotation = yaw;
6463                     weapons[i].bigtilt = tilt;
6464                     weapons[i].bigtilt2 = tilt2;
6465                 }
6466                 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6467                 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6468                 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6469                 if (weaponactive == k) {
6470                     if (weapons[i].getType() == knife) {
6471                         weapons[i].smallrotation = 180;
6472                         weapons[i].smallrotation2 = 0;
6473                         if (isCrouch() || wasCrouch()) {
6474                             weapons[i].smallrotation2 = 20;
6475                         }
6476                         if (animTarget == hurtidleanim) {
6477                             weapons[i].smallrotation2 = 50;
6478                         }
6479                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6480                             XYZ temppoint1, temppoint2;
6481                             float distance;
6482
6483                             temppoint1 = jointPos(righthand);
6484                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6485                             distance = findDistance(&temppoint1, &temppoint2);
6486                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6487                             weapons[i].rotation2 *= 360 / 6.28;
6488                             temppoint1.y = 0;
6489                             temppoint2.y = 0;
6490                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6491                             weapons[i].rotation1 *= 360 / 6.28;
6492                             weapons[i].rotation3 = 0;
6493                             weapons[i].smallrotation = -90;
6494                             weapons[i].smallrotation2 = 0;
6495                             if (temppoint1.x > temppoint2.x)
6496                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6497                         }
6498                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6499                             XYZ temppoint1, temppoint2;
6500                             float distance;
6501
6502                             temppoint1 = jointPos(righthand);
6503                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6504                             distance = findDistance(&temppoint1, &temppoint2);
6505                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6506                             weapons[i].rotation2 *= 360 / 6.28;
6507                             temppoint1.y = 0;
6508                             temppoint2.y = 0;
6509                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6510                             weapons[i].rotation1 *= 360 / 6.28;
6511                             weapons[i].rotation3 = 0;
6512                             weapons[i].smallrotation = 90;
6513                             weapons[i].smallrotation2 = 0;
6514                             if (temppoint1.x > temppoint2.x)
6515                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6516                         }
6517                         if (animTarget == knifethrowanim) {
6518                             weapons[i].smallrotation = 90;
6519                             //weapons[i].smallrotation2=-90;
6520                             weapons[i].smallrotation2 = 0;
6521                             weapons[i].rotation1 = 0;
6522                             weapons[i].rotation2 = 0;
6523                             weapons[i].rotation3 = 0;
6524                         }
6525                         if (animTarget == knifesneakattackanim && frameTarget < 5) {
6526                             weapons[i].smallrotation = -90;
6527                             weapons[i].rotation1 = 0;
6528                             weapons[i].rotation2 = 0;
6529                             weapons[i].rotation3 = 0;
6530                         }
6531                     }
6532                     if (weapons[i].getType() == sword) {
6533                         weapons[i].smallrotation = 0;
6534                         weapons[i].smallrotation2 = 0;
6535                         if (animTarget == knifethrowanim) {
6536                             weapons[i].smallrotation = -90;
6537                             weapons[i].smallrotation2 = 0;
6538                             weapons[i].rotation1 = 0;
6539                             weapons[i].rotation2 = 0;
6540                             weapons[i].rotation3 = 0;
6541                         }
6542                         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)) {
6543                             XYZ temppoint1, temppoint2;
6544                             float distance;
6545
6546                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6547                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6548                             distance = findDistance(&temppoint1, &temppoint2);
6549                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6550                             weapons[i].rotation2 *= 360 / 6.28;
6551                             temppoint1.y = 0;
6552                             temppoint2.y = 0;
6553                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6554                             weapons[i].rotation1 *= 360 / 6.28;
6555                             weapons[i].rotation3 = 0;
6556                             weapons[i].smallrotation = 90;
6557                             weapons[i].smallrotation2 = 0;
6558                             if (temppoint1.x > temppoint2.x)
6559                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6560                         }
6561                     }
6562                     if (weapons[i].getType() == staff) {
6563                         weapons[i].smallrotation = 100;
6564                         weapons[i].smallrotation2 = 0;
6565                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6566                             XYZ temppoint1, temppoint2;
6567                             float distance;
6568
6569                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6570                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6571                             distance = findDistance(&temppoint1, &temppoint2);
6572                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6573                             weapons[i].rotation2 *= 360 / 6.28;
6574                             temppoint1.y = 0;
6575                             temppoint2.y = 0;
6576                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6577                             weapons[i].rotation1 *= 360 / 6.28;
6578                             weapons[i].rotation3 = 0;
6579                             weapons[i].smallrotation = 90;
6580                             weapons[i].smallrotation2 = 0;
6581                             if (temppoint1.x > temppoint2.x)
6582                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6583                         }
6584                     }
6585                 }
6586                 if (weaponactive != k && weaponstuck != k) {
6587                     if (weapons[i].getType() == knife) {
6588                         weapons[i].smallrotation = -70;
6589                         weapons[i].smallrotation2 = 10;
6590                     }
6591                     if (weapons[i].getType() == sword) {
6592                         weapons[i].smallrotation = -100;
6593                         weapons[i].smallrotation2 = -8;
6594                     }
6595                     if (weapons[i].getType() == staff) {
6596                         weapons[i].smallrotation = -100;
6597                         weapons[i].smallrotation2 = -8;
6598                     }
6599                 }
6600                 if (weaponstuck == k) {
6601                     if (weaponstuckwhere == 0)
6602                         weapons[i].smallrotation = 180;
6603                     else
6604                         weapons[i].smallrotation = 0;
6605                     weapons[i].smallrotation2 = 10;
6606                 }
6607             }
6608         }
6609     }
6610
6611     calcrot = 0;
6612     if (skeleton.free)
6613         calcrot = 1;
6614     if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6615         calcrot = 1;
6616     if (animCurrent != animTarget)
6617         calcrot = 1;
6618     if (skeleton.free == 2)
6619         calcrot = 0;
6620
6621     return 0;
6622 }
6623
6624
6625 /* FUNCTION?
6626  */
6627 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6628 {
6629     static int i, j;
6630     static float distance;
6631     static float olddistance;
6632     static int intersecting;
6633     static int firstintersecting;
6634     static XYZ point;
6635     static XYZ oldp1;
6636     static XYZ start, end;
6637     static float slopethreshold = -.4;
6638
6639     firstintersecting = -1;
6640
6641     oldp1 = *p1;
6642     *p1 = *p1 - *move;
6643     if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6644         return -1;
6645     if (*rotate)
6646         *p1 = DoRotation(*p1, 0, -*rotate, 0);
6647     for (i = 0; i < 4; i++) {
6648         for (j = 0; j < model->TriangleNum; j++) {
6649             if (model->facenormals[j].y <= slopethreshold) {
6650                 intersecting = 0;
6651                 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)));
6652                 if (distance < radius) {
6653                     point = *p1 - model->facenormals[j] * distance;
6654                     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]]))
6655                         intersecting = 1;
6656                     if (!intersecting)
6657                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6658                                                                 &model->vertex[model->Triangles[j].vertex[1]],
6659                                                                 p1, &radius);
6660                     if (!intersecting)
6661                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6662                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6663                                                                 p1, &radius);
6664                     if (!intersecting)
6665                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6666                                                                 &model->vertex[model->Triangles[j].vertex[2]],
6667                                                                 p1, &radius);
6668                     end = *p1 - point;
6669                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6670                         start = *p1;
6671                         end = *p1;
6672                         end.y -= radius;
6673                         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)) {
6674                             p1->y = point.y + radius;
6675                             if ((animTarget == jumpdownanim || isFlip())) {
6676                                 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6677                                     RagDoll(0);
6678
6679                                 if (animTarget == jumpupanim) {
6680                                     jumppower = -4;
6681                                     animTarget = getIdle();
6682                                 }
6683                                 target = 0;
6684                                 frameTarget = 0;
6685                                 onterrain = 1;
6686
6687                                 if (id == 0) {
6688                                     pause_sound(whooshsound);
6689                                     OPENAL_SetVolume(channels[whooshsound], 0);
6690                                 }
6691
6692                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6693                                     if (isFlip())
6694                                         jumppower = -4;
6695                                     animTarget = getLanding();
6696                                     emit_sound_at(landsound, coords, 128.);
6697
6698                                     if (id == 0) {
6699                                         addEnvSound(coords);
6700                                     }
6701                                 }
6702                             }
6703                         }
6704                     }
6705                 }
6706                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6707                     olddistance = distance;
6708                     firstintersecting = j;
6709                     *p = point;
6710                 }
6711             }
6712         }
6713         for (j = 0; j < model->TriangleNum; j++) {
6714             if (model->facenormals[j].y > slopethreshold) {
6715                 intersecting = 0;
6716                 start = *p1;
6717                 start.y -= radius / 4;
6718                 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6719                 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6720                 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6721                 distance = abs((model->facenormals[j].x * start.x)
6722                                + (model->facenormals[j].y * start.y)
6723                                + (model->facenormals[j].z * start.z)
6724                                - ((model->facenormals[j].x * v0.x)
6725                                   + (model->facenormals[j].y * v0.y)
6726                                   + (model->facenormals[j].z * v0.z)));
6727                 if (distance < radius * .5) {
6728                     point = start - model->facenormals[j] * distance;
6729                     if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6730                         intersecting = 1;
6731                     if (!intersecting)
6732                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6733                     if (!intersecting)
6734                         intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6735                     if (!intersecting)
6736                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6737                     end = *p1 - point;
6738                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6739                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6740                             start = velocity;
6741                             velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6742                             if (findLengthfast(&start) < findLengthfast(&velocity))
6743                                 velocity = start;
6744                         }
6745                         *p1 += model->facenormals[j] * (distance - radius * .5);
6746                     }
6747                 }
6748                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6749                     olddistance = distance;
6750                     firstintersecting = j;
6751                     *p = point;
6752                 }
6753             }
6754         }
6755     }
6756     if (*rotate)
6757         *p = DoRotation(*p, 0, *rotate, 0);
6758     *p = *p + *move;
6759     if (*rotate)
6760         *p1 = DoRotation(*p1, 0, *rotate, 0);
6761     *p1 += *move;
6762     return firstintersecting;
6763 }
6764
6765 void Person::takeWeapon(int weaponId)
6766 {
6767     weaponactive = 0;
6768     weapons[weaponId].owner = id;
6769     if (num_weapons > 0) {
6770         weaponids[num_weapons] = weaponids[0];
6771     }
6772     num_weapons++;
6773     weaponids[0] = weaponId;
6774 }
6775
6776 void Person::addClothes()
6777 {
6778     if (numclothes > 0) {
6779         for (int i = 0; i < numclothes; i++) {
6780             addClothes(i);
6781         }
6782         DoMipmaps();
6783     }
6784 }
6785
6786 bool Person::addClothes(const int& clothesId)
6787 {
6788     LOGFUNC;
6789     const char* fileName = clothes[clothesId];
6790
6791     GLubyte* array = &skeleton.skinText[0];
6792
6793     //Load Image
6794     ImageRec texture;
6795     bool opened = load_image(fileName, texture);
6796
6797     float alphanum;
6798     //Is it valid?
6799     if (opened) {
6800         float tintr = clothestintr[clothesId];
6801         float tintg = clothestintg[clothesId];
6802         float tintb = clothestintb[clothesId];
6803
6804         if (tintr > 1) tintr = 1;
6805         if (tintg > 1) tintg = 1;
6806         if (tintb > 1) tintb = 1;
6807
6808         if (tintr < 0) tintr = 0;
6809         if (tintg < 0) tintg = 0;
6810         if (tintb < 0) tintb = 0;
6811
6812         int bytesPerPixel = texture.bpp / 8;
6813
6814         int tempnum = 0;
6815         alphanum = 255;
6816         for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6817             if (bytesPerPixel == 3)
6818                 alphanum = 255;
6819             else if ((i + 1) % 4 == 0)
6820                 alphanum = texture.data[i];
6821             if ((i + 1) % 4 || bytesPerPixel == 3) {
6822                 if ((i % 4) == 0)
6823                     texture.data[i] *= tintr;
6824                 if ((i % 4) == 1)
6825                     texture.data[i] *= tintg;
6826                 if ((i % 4) == 2)
6827                     texture.data[i] *= tintb;
6828                 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6829                 tempnum++;
6830             }
6831         }
6832         return 1;
6833     } else {
6834         return 0;
6835     }
6836 }