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