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