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