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