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