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