]> git.jsancho.org Git - lugaru.git/blob - Source/Person.cpp
added some comments
[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(skeleton.joints[skeleton.jointlabels[head]].velocity, ((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, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
333                     Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
334                 }
335                 if (!skeleton.free) {
336                     Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
337                     Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 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(skeleton.joints[skeleton.jointlabels[head]].velocity, ((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, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
356                         } else {
357                             Sprite::MakeSprite(splintersprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 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(skeleton.joints[skeleton.jointlabels[head]].velocity, ((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, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
464                     Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
465                 }
466                 if (!skeleton.free) {
467                     Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
468                     Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 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(skeleton.joints[skeleton.jointlabels[head]].velocity, ((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, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
712                         Sprite::MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position * scale + coords, bloodvel, 1, 1, 1, .3, 1);
713                     }
714                     if (!skeleton.free) {
715                         Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
716                         Sprite::MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 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 = skeleton.joints[skeleton.jointlabels[neck]].position;
1390         skeleton.joints[skeleton.jointlabels[head]].position = rotatearound + DoRotation(skeleton.joints[skeleton.jointlabels[head]].position - 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 = skeleton.joints[skeleton.jointlabels[righthand]].velocity * scale * -.3;
1555                 weapons[weaponids[0]].velocity.x += .01;
1556                 weapons[weaponids[0]].tipvelocity = skeleton.joints[skeleton.jointlabels[righthand]].velocity * 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
1594             if (which == 1)
1595                 footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
1605             if (which == 1)
1606                 footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
1621             if (which == 1)
1622                 footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
1633             if (which == 1)
1634                 footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
1649             if (which == 1)
1650                 footpoint = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 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(skeleton.joints[skeleton.jointlabels[whichlabel]].position, 0, yaw, 0) * scale + coords;
1666     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1667 }
1668
1669 /* FUNCTION
1670  * convenience function
1671  */
1672 Joint& Person::getJointFor(int bodypart)
1673 {
1674     return skeleton.joints[skeleton.jointlabels[bodypart]];
1675 }
1676
1677 /* EFFECT
1678  * I think I added this in an attempt to clean up code
1679  */
1680 void Person::setAnimation(int animation)
1681 {
1682     animTarget = animation;
1683     frameTarget = 0;
1684     target = 0;
1685 }
1686
1687 /* EFFECT
1688  * MONSTER
1689  * TODO: ???
1690  */
1691 void Person::DoAnimations()
1692 {
1693     if (!skeleton.free) {
1694         int i = 0;
1695         static float oldtarget;
1696
1697         if (isIdle() && animCurrent != getIdle())
1698             normalsupdatedelay = 0;
1699
1700         if (animTarget == tempanim || animCurrent == tempanim) {
1701             animation[tempanim] = tempanimation;
1702         }
1703         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1704             float gLoc[3];
1705             float vel[3];
1706             gLoc[0] = coords.x;
1707             gLoc[1] = coords.y;
1708             gLoc[2] = coords.z;
1709             vel[0] = velocity.x;
1710             vel[1] = velocity.y;
1711             vel[2] = velocity.z;
1712
1713             if (id == 0) {
1714                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1715                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1716             }
1717             if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1718                 landhard = 1;
1719             if (!crouchkeydown && velocity.y >= -15)
1720                 landhard = 0;
1721         }
1722         if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1723             XYZ targfacing;
1724             targfacing = 0;
1725             targfacing.z = 1;
1726
1727             targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1728
1729             if (normaldotproduct(targfacing, velocity) >= -.3)
1730                 animTarget = flipanim;
1731             else
1732                 animTarget = backflipanim;
1733             crouchtogglekeydown = 1;
1734             frameTarget = 0;
1735             target = 0;
1736
1737             if (id == 0)
1738                 numflipped++;
1739         }
1740
1741         if (animation[animTarget].attack != reversed)
1742             feint = 0;
1743         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1744             crouchtogglekeydown = 0;
1745             if (aitype == playercontrolled)
1746                 feint = 0;
1747         } else {
1748             if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1749                 feint = 1;
1750             if (!isFlip())
1751                 crouchtogglekeydown = 1;
1752         }
1753
1754
1755         if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1756             if (detail)
1757                 normalsupdatedelay = 0;
1758         }
1759
1760         if (target >= 1) {
1761             if (animTarget == rollanim && frameTarget == 3 && onfire) {
1762                 onfire = 0;
1763                 emit_sound_at(fireendsound, coords);
1764                 pause_sound(stream_firesound);
1765                 deathbleeding = 0;
1766             }
1767
1768             if (animTarget == rabbittacklinganim && frameTarget == 1) {
1769                 //if(victim->aitype==attacktypecutoff&&Random()%2==0&&victim->stunned<=0&&animation[victim->animTarget].attack==neutral&&victim->id!=0)Reverse();
1770                 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1771                     Reverse();
1772                 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1773                     if (normaldotproduct(victim->facing, facing) > 0)
1774                         victim->animTarget = rabbittackledbackanim;
1775                     else
1776                         victim->animTarget = rabbittackledfrontanim;
1777                     victim->frameTarget = 2;
1778                     victim->target = 0;
1779                     victim->yaw = yaw;
1780                     victim->targetyaw = yaw;
1781                     if (victim->aitype == gethelptype)
1782                         victim->DoDamage(victim->damagetolerance - victim->damage);
1783                     //victim->DoDamage(30);
1784                     if (creature == wolftype) {
1785                         DoBloodBig(0, 255);
1786                         emit_sound_at(clawslicesound, victim->coords);
1787                         victim->spurt = 1;
1788                         victim->DoBloodBig(1 / victim->armorhead, 210);
1789                     }
1790                     award_bonus(id, TackleBonus,
1791                                 victim->aitype == gethelptype ? 50 : 0);
1792                 }
1793             }
1794
1795             if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1796                 if (weapons[weaponids[0]].getType() == knife) {
1797                     if (weaponactive == -1)
1798                         weaponactive = 0;
1799                     else if (weaponactive == 0)
1800                         weaponactive = -1;
1801
1802                     if (weaponactive == -1) {
1803                         emit_sound_at(knifesheathesound, coords);
1804                     }
1805                     if (weaponactive != -1) {
1806                         emit_sound_at(knifedrawsound, coords, 128);
1807                     }
1808                 }
1809                 drawtogglekeydown = 1;
1810             }
1811             //Footstep sounds
1812             if (tutoriallevel != 1 || id == 0)
1813                 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1814                     int whichsound;
1815                     if (onterrain) {
1816                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
1817                             if (animation[animTarget].label[frameTarget] == 1)
1818                                 whichsound = footstepsound;
1819                             else
1820                                 whichsound = footstepsound2;
1821                             if (animation[animTarget].label[frameTarget] == 1)
1822                                 FootLand(0, 1);
1823                             if (animation[animTarget].label[frameTarget] == 2)
1824                                 FootLand(1, 1);
1825                             if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1826                                 FootLand(1, 1);
1827                                 FootLand(0, 1);
1828                             }
1829
1830                         }
1831                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1832                             if (animation[animTarget].label[frameTarget] == 1)
1833                                 whichsound = footstepsound3;
1834                             else
1835                                 whichsound = footstepsound4;
1836                         }
1837                     }
1838                     if (!onterrain) {
1839                         if (animation[animTarget].label[frameTarget] == 1)
1840                             whichsound = footstepsound3;
1841                         else
1842                             whichsound = footstepsound4;
1843                     }
1844                     if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1845                         if (animation[animTarget].attack != neutral) {
1846                             i = abs(Random() % 3);
1847                             if (i == 0)
1848                                 whichsound = lowwhooshsound;
1849                             if (i == 1)
1850                                 whichsound = midwhooshsound;
1851                             if (i == 2)
1852                                 whichsound = highwhooshsound;
1853                         }
1854                         if (animation[animTarget].attack == neutral)
1855                             whichsound = movewhooshsound;
1856                     } else if (animation[animTarget].label[frameTarget] == 4)
1857                         whichsound = knifeswishsound;
1858                     if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1859                         whichsound = landsound2;
1860
1861                     emit_sound_at(whichsound, coords, 256.);
1862
1863                     if (id == 0)
1864                         if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1865                             envsound[numenvsounds] = coords;
1866                             if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1867                                 envsoundvol[numenvsounds] = 15;
1868                             else
1869                                 envsoundvol[numenvsounds] = 6;
1870                             envsoundlife[numenvsounds] = .4;
1871                             numenvsounds++;
1872                         }
1873
1874                     if (animation[animTarget].label[frameTarget] == 3) {
1875                         whichsound--;
1876                         emit_sound_at(whichsound, coords, 128.);
1877                     }
1878                 }
1879
1880             //Combat sounds
1881             if (tutoriallevel != 1 || id == 0)
1882                 if (speechdelay <= 0)
1883                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1884                         if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1885                             int whichsound = -1;
1886                             if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1887                                 if (animation[animTarget].attack != neutral) {
1888                                     i = abs(Random() % 4);
1889                                     if (creature == rabbittype) {
1890                                         if (i == 0) whichsound = rabbitattacksound;
1891                                         if (i == 1) whichsound = rabbitattack2sound;
1892                                         if (i == 2) whichsound = rabbitattack3sound;
1893                                         if (i == 3) whichsound = rabbitattack4sound;
1894                                     }
1895                                     if (creature == wolftype) {
1896                                         if (i == 0) whichsound = barksound;
1897                                         if (i == 1) whichsound = bark2sound;
1898                                         if (i == 2) whichsound = bark3sound;
1899                                         if (i == 3) whichsound = barkgrowlsound;
1900                                     }
1901                                     speechdelay = .3;
1902                                 }
1903                                 //if(animation[animTarget].attack==neutral)whichsound=movewhooshsound;
1904                             }
1905                             //else if(animation[animTarget].label[frameTarget]==4)whichsound=knifeswishsound;
1906                             //if(animation[animTarget].label[frameTarget]==8)whichsound=landsound2;
1907
1908                             if (whichsound != -1) {
1909                                 emit_sound_at(whichsound, coords);
1910                             }
1911                         }
1912
1913
1914
1915             if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1916                 FootLand(0, 1);
1917                 FootLand(1, 1);
1918             }
1919
1920             transspeed = 0;
1921             currentoffset = targetoffset;
1922             frameTarget = frameCurrent;
1923             animCurrent = animTarget;
1924             frameTarget++;
1925
1926             if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1927                 for (i = 0; i < weapons.size(); i++) {
1928                     if (weapons[i].owner == -1)
1929                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1930                             if (distsq(&coords, &weapons[i].position) >= 1) {
1931                                 if (weapons[i].getType() != staff) {
1932                                     emit_sound_at(knifedrawsound, coords, 128.);
1933                                 }
1934
1935                                 weaponactive = 0;
1936                                 weapons[i].owner = id;
1937                                 if (num_weapons > 0) {
1938                                     weaponids[num_weapons] = weaponids[0];
1939                                 }
1940                                 num_weapons++;
1941                                 weaponids[0] = i;
1942                             }
1943                         }
1944                 }
1945             }
1946
1947             if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1948                 for (i = 0; i < weapons.size(); i++) {
1949                     bool willwork = true;
1950                     if (weapons[i].owner != -1)
1951                         if (player[weapons[i].owner].weaponstuck != -1)
1952                             if (player[weapons[i].owner].weaponids[player[weapons[i].owner].weaponstuck] == i)
1953                                 if (player[weapons[i].owner].num_weapons > 1)
1954                                     willwork = 0;
1955                     if ((weapons[i].owner == -1) || (hasvictim && weapons[i].owner == victim->id && victim->skeleton.free))
1956                         if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1957                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1958                                 bool fleshstuck = false;
1959                                 if (weapons[i].owner != -1)
1960                                     if (victim->weaponstuck != -1) {
1961                                         if (victim->weaponids[victim->weaponstuck] == i) {
1962                                             fleshstuck = true;
1963                                         }
1964                                     }
1965                                 if (fleshstuck) {
1966                                     emit_sound_at(fleshstabremovesound, coords, 128.);
1967                                 } else {
1968                                     if (weapons[i].getType() != staff) {
1969                                         emit_sound_at(knifedrawsound, coords, 128.);
1970                                     }
1971                                 }
1972                                 weaponactive = 0;
1973                                 if (weapons[i].owner != -1) {
1974
1975                                     victim = &player[weapons[i].owner];
1976                                     if (victim->num_weapons == 1)
1977                                         victim->num_weapons = 0;
1978                                     else
1979                                         victim->num_weapons = 1;
1980
1981                                     //victim->weaponactive=-1;
1982                                     victim->skeleton.longdead = 0;
1983                                     victim->skeleton.free = 1;
1984                                     victim->skeleton.broken = 0;
1985
1986                                     for (int j = 0; j < victim->skeleton.num_joints; j++) {
1987                                         victim->skeleton.joints[j].velchange = 0;
1988                                         victim->skeleton.joints[j].locked = 0;
1989                                     }
1990
1991                                     XYZ relative;
1992                                     relative = 0;
1993                                     relative.y = 10;
1994                                     Normalise(&relative);
1995                                     XYZ footvel, footpoint;
1996                                     footvel = 0;
1997                                     footpoint = weapons[i].position;
1998                                     if (victim->weaponstuck != -1) {
1999                                         if (victim->weaponids[victim->weaponstuck] == i) {
2000                                             if (bloodtoggle)
2001                                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2002                                             weapons[i].bloody = 2;
2003                                             weapons[i].blooddrip = 5;
2004                                             victim->weaponstuck = -1;
2005                                         }
2006                                     }
2007                                     if (victim->num_weapons > 0) {
2008                                         if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2009                                             victim->weaponstuck = 0;
2010                                         if (victim->weaponids[0] == i)
2011                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2012                                     }
2013
2014                                     victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * 6;
2015                                     victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * 6;
2016                                     victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity += relative * 6;
2017                                     victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity += relative * 6;
2018                                 }
2019                                 weapons[i].owner = id;
2020                                 if (num_weapons > 0) {
2021                                     weaponids[num_weapons] = weaponids[0];
2022                                 }
2023                                 num_weapons++;
2024                                 weaponids[0] = i;
2025                             }
2026                         }
2027                 }
2028             }
2029
2030             if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2031                 if (weaponactive == -1)
2032                     weaponactive = 0;
2033                 else if (weaponactive == 0) {
2034                     weaponactive = -1;
2035                     if (num_weapons == 2) {
2036                         int buffer;
2037                         buffer = weaponids[0];
2038                         weaponids[0] = weaponids[1];
2039                         weaponids[1] = buffer;
2040                     }
2041                 }
2042                 if (weaponactive == -1) {
2043                     emit_sound_at(knifesheathesound, coords, 128.);
2044                 }
2045                 if (weaponactive != -1) {
2046                     emit_sound_at(knifedrawsound, coords, 128.);
2047                 }
2048             }
2049
2050
2051             if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2052                 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2053                 Normalise(&rotatetarget);
2054                 targetyaw = -asin(0 - rotatetarget.x);
2055                 targetyaw *= 360 / 6.28;
2056                 if (rotatetarget.z < 0)
2057                     targetyaw = 180 - targetyaw;
2058
2059                 if (animTarget == walljumprightkickanim)
2060                     targetyaw += 40;
2061                 if (animTarget == walljumpleftkickanim)
2062                     targetyaw -= 40;
2063             }
2064
2065             bool dojumpattack;
2066             dojumpattack = 0;
2067             if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2068                 dojumpattack = 1;
2069             if (hasvictim)
2070                 if (distsq(&victim->coords, &/*player[i].*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2071                     dojumpattack = 1;
2072             if (!hostile)
2073                 dojumpattack = 0;
2074             if (dojumpattack) {
2075                 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2076                     animTarget = rabbittackleanim;
2077                     frameTarget = 0;
2078                     emit_sound_at(jumpsound, coords);
2079                 }
2080
2081                 float closestdist;
2082                 closestdist = 0;
2083                 int closestid;
2084                 closestid = -1;
2085                 XYZ targetloc;
2086                 targetloc = velocity;
2087                 Normalise(&targetloc);
2088                 targetloc += coords;
2089                 for (i = 0; i < numplayers; i++) {
2090                     if (i != id)
2091                         if (distsq(&targetloc, &player[i].coords) < closestdist || closestdist == 0) {
2092                             closestdist = distsq(&targetloc, &player[i].coords);
2093                             closestid = i;
2094                         }
2095                 }
2096                 if (closestid != -1)
2097                     if (closestdist < 5 && !player[closestid].dead && animation[player[closestid].animTarget].height != lowheight && player[closestid].animTarget != backhandspringanim) {
2098                         hasvictim = 1;
2099                         victim = &player[closestid];
2100                         coords = victim->coords;
2101                         animCurrent = rabbittacklinganim;
2102                         animTarget = rabbittacklinganim;
2103                         frameCurrent = 0;
2104                         frameTarget = 1;
2105                         XYZ rotatetarget;
2106                         if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2107                             rotatetarget = coords - victim->coords;
2108                             Normalise(&rotatetarget);
2109                             targetyaw = -asin(0 - rotatetarget.x);
2110                             targetyaw *= 360 / 6.28;
2111                             if (rotatetarget.z < 0)
2112                                 targetyaw = 180 - targetyaw;
2113                         }
2114                         if (animTarget != rabbitrunninganim) {
2115                             emit_sound_at(jumpsound, coords, 128.);
2116                         }
2117                     }
2118             }
2119
2120             //Move impacts
2121             float damagemult = 1 * power;
2122             if (creature == wolftype)
2123                 damagemult = 2.5 * power;
2124             if (hasvictim) {
2125                 damagemult /= victim->damagetolerance / 200;
2126             }
2127             //if(onfire)damagemult=3;
2128             if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2129                 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2130                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2131                         escapednum = 0;
2132                         if (id == 0)
2133                             camerashake += .4;
2134                         if (Random() % 2 || creature == wolftype) {
2135                             victim->spurt = 1;
2136                             DoBlood(.2, 250);
2137                             if (creature == wolftype)
2138                                 DoBloodBig(0, 250);
2139                         }
2140                         if (tutoriallevel != 1) {
2141                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
2142                         }
2143                         if (creature == wolftype) {
2144                             emit_sound_at(clawslicesound, victim->coords, 128.);
2145                             victim->spurt = 1;
2146                             victim->DoBloodBig(2 / victim->armorhead, 175);
2147                         }
2148                         victim->RagDoll(0);
2149                         XYZ relative;
2150                         relative = victim->coords - coords;
2151                         relative.y = 0;
2152                         Normalise(&relative);
2153                         relative = DoRotation(relative, 0, -90, 0);
2154                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2155                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2156                         }
2157                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
2158                         //FootLand(1,2);
2159                         victim->Puff(head);
2160                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
2161
2162                         SolidHitBonus(id);
2163                     }
2164                 }
2165
2166                 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2167                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2168                         escapednum = 0;
2169                         if (id == 0)
2170                             camerashake += .4;
2171                         if (Random() % 2 || creature == wolftype) {
2172                             victim->spurt = 1;
2173                             if (creature == wolftype)
2174                                 DoBloodBig(0, 235);
2175                         }
2176                         emit_sound_at(whooshhitsound, victim->coords);
2177                         if (creature == wolftype) {
2178                             emit_sound_at(clawslicesound, victim->coords, 128.);
2179                             victim->spurt = 1;
2180                             victim->DoBloodBig(2, 175);
2181                         }
2182                         victim->RagDoll(0);
2183                         XYZ relative;
2184                         relative = victim->coords - coords;
2185                         relative.y = 0;
2186                         Normalise(&relative);
2187                         relative.y -= 1;
2188                         Normalise(&relative);
2189                         relative = DoRotation(relative, 0, 90, 0);
2190                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2191                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2192                         }
2193                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 100;
2194                         //FootLand(1,2);
2195                         victim->Puff(head);
2196                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2197                     }
2198                 }
2199
2200                 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2201                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2202                         escapednum = 0;
2203                         if (id == 0)
2204                             camerashake += .4;
2205                         victim->spurt = 1;
2206                         DoBlood(.2, 250);
2207                         if (tutoriallevel != 1) {
2208                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2209                         }
2210                         if (creature == wolftype) {
2211                             emit_sound_at(clawslicesound, victim->coords, 128.);
2212                             victim->spurt = 1;
2213                             victim->DoBloodBig(2 / victim->armorhead, 175);
2214                         }
2215                         victim->RagDoll(0);
2216                         XYZ relative;
2217                         relative = facing;
2218                         relative.y = 0;
2219                         Normalise(&relative);
2220                         relative = DoRotation(relative, 0, -90, 0);
2221                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2222                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2223                         }
2224                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
2225                         //FootLand(1,2);
2226                         victim->Puff(head);
2227                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2228
2229                         if (victim->damage > victim->damagetolerance)
2230                             award_bonus(id, style);
2231                         else
2232                             SolidHitBonus(id);
2233                     }
2234                 }
2235
2236                 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2237                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2238                         escapednum = 0;
2239                         if (id == 0)
2240                             camerashake += .4;
2241                         victim->spurt = 1;
2242                         DoBlood(.2, 250);
2243                         if (tutoriallevel != 1) {
2244                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2245                         }
2246                         if (creature == wolftype) {
2247                             emit_sound_at(clawslicesound, victim->coords, 128.);
2248                             victim->spurt = 1;
2249                             victim->DoBloodBig(2 / victim->armorhead, 175);
2250                         }
2251                         victim->RagDoll(0);
2252                         XYZ relative;
2253                         relative = facing;
2254                         relative.y = 0;
2255                         Normalise(&relative);
2256                         relative = DoRotation(relative, 0, 90, 0);
2257                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2258                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2259                         }
2260                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
2261                         //FootLand(1,2);
2262                         victim->Puff(head);
2263                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2264
2265                         if (victim->damage > victim->damagetolerance)
2266                             award_bonus(id, style);
2267                         else
2268                             SolidHitBonus(id);
2269                     }
2270                 }
2271
2272                 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2273                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2274                         escapednum = 0;
2275                         if (id == 0)
2276                             camerashake += .4;
2277                         if (Random() % 2) {
2278                             victim->spurt = 1;
2279                             DoBlood(.2, 235);
2280                         }
2281                         emit_sound_at(whooshhitsound, victim->coords);
2282                         victim->RagDoll(0);
2283                         XYZ relative;
2284                         relative = victim->coords - coords;
2285                         relative.y = 0;
2286                         Normalise(&relative);
2287                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2288                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2289                         }
2290                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 100;
2291                         //FootLand(1,2);
2292                         victim->Puff(head);
2293                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2294                     }
2295                 }
2296
2297                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2298                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2299                         escapednum = 0;
2300                         if (id == 0)
2301                             camerashake += .2;
2302                         emit_sound_at(whooshhitsound, victim->coords, 128.);
2303
2304                         victim->skeleton.longdead = 0;
2305                         victim->skeleton.free = 1;
2306                         victim->skeleton.broken = 0;
2307                         victim->skeleton.spinny = 1;
2308
2309                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2310                             victim->skeleton.joints[i].velchange = 0;
2311                             victim->skeleton.joints[i].delay = 0;
2312                             victim->skeleton.joints[i].locked = 0;
2313                             //victim->skeleton.joints[i].velocity=0;
2314                         }
2315
2316                         XYZ relative;
2317                         relative = 0;
2318                         relative.y = 1;
2319                         Normalise(&relative);
2320                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2321                             victim->skeleton.joints[i].velocity.y = relative.y * 10;
2322                             victim->skeleton.joints[i].position.y += relative.y * .3;
2323                             victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2324                             victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2325                         }
2326                         victim->Puff(abdomen);
2327                         victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity.y = relative.y * 400;
2328                     }
2329                 }
2330
2331                 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2332                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2333                         escapednum = 0;
2334                         if (id == 0)
2335                             camerashake += .4;
2336                         if (tutoriallevel != 1) {
2337                             emit_sound_at(heavyimpactsound, coords, 128.);
2338                         }
2339                         XYZ relative;
2340                         relative = victim->coords - coords;
2341                         relative.y = 0;
2342                         Normalise(&relative);
2343                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2344                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2345                         }
2346                         victim->Puff(abdomen);
2347                         if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2348                             slomo = 1;
2349                             slomodelay = .2;
2350                         }
2351                         victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2352                         victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 300;
2353                     }
2354                 }
2355
2356                 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2357                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2358                         escapednum = 0;
2359                         if (id == 0)
2360                             camerashake += .4;
2361                         if (tutoriallevel != 1) {
2362                             emit_sound_at(thudsound, coords);
2363                         }
2364
2365                         victim->skeleton.longdead = 0;
2366                         victim->skeleton.free = 1;
2367                         victim->skeleton.broken = 0;
2368                         victim->skeleton.spinny = 1;
2369
2370                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2371                             victim->skeleton.joints[i].velchange = 0;
2372                             //victim->skeleton.joints[i].delay=0;
2373                             victim->skeleton.joints[i].locked = 0;
2374                         }
2375                         XYZ relative;
2376                         relative = victim->coords - coords;
2377                         Normalise(&relative);
2378                         relative.y += .3;
2379                         Normalise(&relative);
2380                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2381                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2382                         }
2383                         if (!victim->dead)
2384                             SolidHitBonus(id);
2385
2386                         victim->Puff(abdomen);
2387                         victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2388                         victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
2389                         staggerdelay = .5;
2390                         if (!victim->dead)
2391                             staggerdelay = 1.2;
2392
2393
2394                     }
2395                 }
2396
2397                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2398                     //if(id==0)camerashake+=.4;
2399
2400                     if (hasvictim)
2401                         if (!victim->skeleton.free)
2402                             hasvictim = 0;
2403
2404                     if (!hasvictim) {
2405                         terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2406                         emit_sound_at(knifesheathesound, coords, 128.);
2407                     }
2408
2409                     if (victim && hasvictim) {
2410                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2411
2412                             XYZ where, startpoint, endpoint, movepoint, colpoint;
2413                             float rotationpoint;
2414                             int whichtri;
2415                             if (weapons[weaponids[weaponactive]].getType() == knife) {
2416                                 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2417                                 where -= victim->coords;
2418                                 if (!victim->skeleton.free)
2419                                     where = DoRotation(where, 0, -victim->yaw, 0);
2420                                 //where=scale;
2421                                 startpoint = where;
2422                                 startpoint.y += 100;
2423                                 endpoint = where;
2424                                 endpoint.y -= 100;
2425                             }
2426                             if (weapons[weaponids[weaponactive]].getType() == sword) {
2427                                 where = weapons[weaponids[weaponactive]].position;
2428                                 where -= victim->coords;
2429                                 if (!victim->skeleton.free)
2430                                     where = DoRotation(where, 0, -victim->yaw, 0);
2431                                 startpoint = where;
2432                                 where = weapons[weaponids[weaponactive]].tippoint;
2433                                 where -= victim->coords;
2434                                 if (!victim->skeleton.free)
2435                                     where = DoRotation(where, 0, -victim->yaw, 0);
2436                                 endpoint = where;
2437                             }
2438                             if (weapons[weaponids[weaponactive]].getType() == staff) {
2439                                 where = weapons[weaponids[weaponactive]].position;
2440                                 where -= victim->coords;
2441                                 if (!victim->skeleton.free)
2442                                     where = DoRotation(where, 0, -victim->yaw, 0);
2443                                 startpoint = where;
2444                                 where = weapons[weaponids[weaponactive]].tippoint;
2445                                 where -= victim->coords;
2446                                 if (!victim->skeleton.free)
2447                                     where = DoRotation(where, 0, -victim->yaw, 0);
2448                                 endpoint = where;
2449                             }
2450                             movepoint = 0;
2451                             rotationpoint = 0;
2452                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2453
2454                             if (whichtri != -1) {
2455                                 if (victim->dead != 2) {
2456                                     victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2457                                     if (!victim->dead)
2458                                         award_bonus(id, FinishedBonus);
2459                                 }
2460                                 if (bloodtoggle)
2461                                     weapons[weaponids[weaponactive]].bloody = 2;
2462
2463                                 victim->skeleton.longdead = 0;
2464                                 victim->skeleton.free = 1;
2465                                 victim->skeleton.broken = 0;
2466
2467                                 for (i = 0; i < victim->skeleton.num_joints; i++) {
2468                                     victim->skeleton.joints[i].velchange = 0;
2469                                     victim->skeleton.joints[i].locked = 0;
2470                                     //victim->skeleton.joints[i].velocity=0;
2471                                 }
2472                                 emit_sound_at(fleshstabsound, coords, 128);
2473
2474                             }
2475                             if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2476                                 weapons[weaponids[weaponactive]].blooddrip += 5;
2477                                 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2478                             }
2479                             if (whichtri == -1) {
2480                                 hasvictim = 0;
2481                                 emit_sound_at(knifesheathesound, coords, 128.);
2482                             }
2483                         }
2484                     }
2485                 }
2486
2487                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2488                     if (!hasvictim) {
2489                         emit_sound_at(knifedrawsound, coords, 128);
2490                     }
2491
2492                     if (victim && hasvictim) {
2493                         XYZ footvel, footpoint;
2494
2495                         emit_sound_at(fleshstabremovesound, coords, 128.);
2496
2497                         footvel = 0;
2498                         footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2499
2500                         if (weapons[weaponids[weaponactive]].getType() == sword) {
2501                             XYZ where, startpoint, endpoint, movepoint;
2502                             float rotationpoint;
2503                             int whichtri;
2504
2505                             where = weapons[weaponids[weaponactive]].position;
2506                             where -= victim->coords;
2507                             if (!victim->skeleton.free)
2508                                 where = DoRotation(where, 0, -victim->yaw, 0);
2509                             startpoint = where;
2510                             where = weapons[weaponids[weaponactive]].tippoint;
2511                             where -= victim->coords;
2512                             if (!victim->skeleton.free)
2513                                 where = DoRotation(where, 0, -victim->yaw, 0);
2514                             endpoint = where;
2515
2516                             movepoint = 0;
2517                             rotationpoint = 0;
2518                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2519                             footpoint += victim->coords;
2520
2521                             if (whichtri == -1) {
2522                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2523                             }
2524                         }
2525                         if (weapons[weaponids[weaponactive]].getType() == staff) {
2526                             XYZ where, startpoint, endpoint, movepoint;
2527                             float rotationpoint;
2528                             int whichtri;
2529
2530                             where = weapons[weaponids[weaponactive]].position;
2531                             where -= victim->coords;
2532                             if (!victim->skeleton.free)
2533                                 where = DoRotation(where, 0, -victim->yaw, 0);
2534                             startpoint = where;
2535                             where = weapons[weaponids[weaponactive]].tippoint;
2536                             where -= victim->coords;
2537                             if (!victim->skeleton.free)
2538                                 where = DoRotation(where, 0, -victim->yaw, 0);
2539                             endpoint = where;
2540
2541                             movepoint = 0;
2542                             rotationpoint = 0;
2543                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2544                             footpoint += victim->coords;
2545
2546                             if (whichtri == -1) {
2547                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2548                             }
2549                         }
2550                         hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2551                         if (hasvictim) {
2552                             if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2553                                 victim->skeleton.longdead = 0;
2554                                 victim->skeleton.free = 1;
2555                                 victim->skeleton.broken = 0;
2556
2557                                 for (i = 0; i < victim->skeleton.num_joints; i++) {
2558                                     victim->skeleton.joints[i].velchange = 0;
2559                                     victim->skeleton.joints[i].locked = 0;
2560                                     //victim->skeleton.joints[i].velocity=0;
2561                                 }
2562
2563                                 XYZ relative;
2564                                 relative = 0;
2565                                 relative.y = 10;
2566                                 Normalise(&relative);
2567                                 //victim->Puff(abdomen);
2568                                 if (bloodtoggle)
2569                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2570
2571                                 if (victim->bloodloss < victim->damagetolerance) {
2572                                     victim->bloodloss += 1000;
2573                                     victim->bled = 0;
2574                                 }
2575
2576                                 victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 20;
2577                             }
2578                         }
2579                     }
2580                     if (!hasvictim && onterrain) {
2581                         weapons[weaponids[weaponactive]].bloody = 0;
2582                         weapons[weaponids[weaponactive]].blooddrip = 0;
2583                     }
2584                 }
2585
2586                 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2587                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2588                         escapednum = 0;
2589                         if (id == 0)
2590                             camerashake += .4;
2591                         if (Random() % 2) {
2592                             victim->spurt = 1;
2593                             DoBlood(.2, 235);
2594                         }
2595                         if (tutoriallevel != 1) {
2596                             emit_sound_at(heavyimpactsound, victim->coords, 128);
2597                         }
2598
2599                         victim->RagDoll(0);
2600                         XYZ relative;
2601                         relative = victim->coords - coords;
2602                         relative.y = 0;
2603                         Normalise(&relative);
2604                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2605                             victim->skeleton.joints[i].velocity = relative * 30;
2606                         }
2607                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 150;
2608
2609                         victim->frameTarget = 0;
2610                         victim->animTarget = staggerbackhardanim;
2611                         victim->targetyaw = targetyaw + 180;
2612                         victim->target = 0;
2613                         victim->stunned = 1;
2614
2615                         victim->Puff(head);
2616                         victim->Puff(abdomen);
2617                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2618
2619                         SolidHitBonus(id);
2620                     }
2621                 }
2622
2623
2624                 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2625                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2626                         escapednum = 0;
2627                         if (id == 0)
2628                             camerashake += .4;
2629                         if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2630                             if (tutoriallevel != 1) {
2631                                 emit_sound_at(thudsound, victim->coords);
2632                             }
2633                         } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2634                             if (tutoriallevel != 1) {
2635                                 emit_sound_at(whooshhitsound, victim->coords);
2636                             }
2637                         } else {
2638                             if (tutoriallevel != 1) {
2639                                 emit_sound_at(heavyimpactsound, victim->coords);
2640                             }
2641                         }
2642
2643                         if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2644                             victim->RagDoll(0);
2645                         XYZ relative;
2646                         relative = victim->coords - coords;
2647                         relative.y = 0;
2648                         Normalise(&relative);
2649                         relative.y = .3;
2650                         Normalise(&relative);
2651                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2652                             victim->skeleton.joints[i].velocity = relative * 5;
2653                         }
2654                         victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 400;
2655
2656                         victim->frameTarget = 0;
2657                         victim->animTarget = staggerbackhardanim;
2658                         victim->targetyaw = targetyaw + 180;
2659                         victim->target = 0;
2660                         victim->stunned = 1;
2661
2662                         victim->Puff(abdomen);
2663                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2664
2665                         SolidHitBonus(id);
2666                     }
2667                 }
2668
2669                 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2670                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2671                         if (victim->id == 0)
2672                             camerashake += .4;
2673                         emit_sound_at(landsound2, victim->coords);
2674
2675                         Puff(righthand);
2676                     }
2677                 }
2678
2679                 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2680                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2681                         if (victim->id == 0)
2682                             camerashake += .4;
2683
2684                         if (weaponactive != -1) {
2685                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2686                                 if (weapons[victim->weaponids[0]].getType() == staff)
2687                                     weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2688                                 if (weapons[weaponids[0]].getType() == staff)
2689                                     weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2690
2691                                 emit_sound_at(swordstaffsound, victim->coords);
2692                             } else {
2693                                 emit_sound_at(metalhitsound, victim->coords);
2694                             }
2695                         }
2696
2697                         //Puff(righthand);
2698                     }
2699                 }
2700
2701                 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2702                     if (weaponactive != -1) {
2703                         escapednum = 0;
2704                         XYZ aim;
2705                         weapons[weaponids[0]].owner = -1;
2706                         aim = victim->coords + DoRotation(victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position, 0, victim->yaw, 0) * victim->scale + victim->velocity * findDistance(&victim->coords, &coords) / 50 - (coords + DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position, 0, yaw, 0) * scale);
2707                         Normalise(&aim);
2708                         /*if(victim->animTarget==jumpupanim||victim->animTarget==jumpdownanim){
2709                         aim=DoRotation(aim,(float)abs(Random()%15)-7,(float)abs(Random()%15)-7,0);
2710                         }*/
2711                         weapons[weaponids[0]].velocity = aim * 50;
2712                         weapons[weaponids[0]].tipvelocity = aim * 50;
2713                         weapons[weaponids[0]].missed = 0;
2714                         weapons[weaponids[0]].hitsomething = 0;
2715                         weapons[weaponids[0]].freetime = 0;
2716                         weapons[weaponids[0]].firstfree = 1;
2717                         weapons[weaponids[0]].physics = 0;
2718                         num_weapons--;
2719                         if (num_weapons) {
2720                             weaponids[0] = weaponids[num_weapons];
2721                         }
2722                         weaponactive = -1;
2723                     }
2724                 }
2725
2726                 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2727                     if (hasvictim)
2728                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2729                             escapednum = 0;
2730                             if (tutoriallevel != 1)
2731                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2732
2733                             award_bonus(id, Slicebonus);
2734                             if (tutoriallevel != 1) {
2735                                 emit_sound_at(knifeslicesound, victim->coords);
2736                             }
2737                             //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
2738                             if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2739                                 if (victim->id != 0 || difficulty == 2) {
2740                                     victim->frameTarget = 0;
2741                                     victim->animTarget = staggerbackhardanim;
2742                                     victim->targetyaw = targetyaw + 180;
2743                                     victim->target = 0;
2744                                 }
2745                             }
2746                             victim->lowreversaldelay = 0;
2747                             victim->highreversaldelay = 0;
2748                             if (aitype != playercontrolled)
2749                                 weaponmissdelay = .6;
2750
2751                             if (tutoriallevel != 1)
2752                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2753                                     weapons[weaponids[weaponactive]].bloody = 1;
2754                             if (tutoriallevel != 1)
2755                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2756
2757                             XYZ footvel, footpoint;
2758                             footvel = 0;
2759                             if (skeleton.free) {
2760                                 footpoint = (victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2 * victim->scale + victim->coords;
2761                             }
2762                             if (!skeleton.free) {
2763                                 footpoint = DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2764                             }
2765                             if (tutoriallevel != 1) {
2766                                 if (bloodtoggle)
2767                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2768                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2769                                 //footvel.y-=.3;
2770                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2771                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2772                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2773                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2774                             }
2775                             if (tutoriallevel == 1) {
2776                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2777                             }
2778                             victim->DoDamage(damagemult * 0);
2779                         }
2780                 }
2781                 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2782                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2783                         if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2784                             award_bonus(id, Slashbonus);
2785                             escapednum = 0;
2786                             if (tutoriallevel != 1) {
2787                                 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2788                                     victim->DoBloodBig(2 / victim->armorhigh, 190);
2789                                 else
2790                                     victim->DoBloodBig(2 / victim->armorhigh, 185);
2791                                 victim->deathbleeding = 1;
2792                                 emit_sound_at(swordslicesound, victim->coords);
2793                             }
2794                             //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
2795                             if (tutoriallevel != 1) {
2796                                 victim->frameTarget = 0;
2797                                 victim->animTarget = staggerbackhardanim;
2798                                 victim->targetyaw = targetyaw + 180;
2799                                 victim->target = 0;
2800                             }
2801
2802                             if (tutoriallevel != 1) {
2803                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2804                                     weapons[weaponids[weaponactive]].bloody = 1;
2805                                 weapons[weaponids[weaponactive]].blooddrip += 3;
2806
2807                                 float bloodlossamount;
2808                                 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2809                                 victim->bloodloss += bloodlossamount / victim->armorhigh;
2810                                 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2811                                 victim->DoDamage(damagemult * 0);
2812
2813                                 XYZ footvel, footpoint;
2814                                 footvel = 0;
2815                                 if (skeleton.free) {
2816                                     footpoint = (victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2 * victim->scale + victim->coords;
2817                                 }
2818                                 if (!skeleton.free) {
2819                                     footpoint = DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position + victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2820                                 }
2821                                 if (bloodtoggle)
2822                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2823                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
2824                                 footvel.y -= .3;
2825                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2826                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2827                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2828                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2829                             }
2830                         } else {
2831                             if (victim->weaponactive != -1) {
2832                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2833                                     if (weapons[victim->weaponids[0]].getType() == staff)
2834                                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2835                                     if (weapons[weaponids[0]].getType() == staff)
2836                                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2837
2838                                     emit_sound_at(swordstaffsound, victim->coords);
2839                                 } else {
2840                                     emit_sound_at(metalhitsound, victim->coords);
2841                                 }
2842                             }
2843
2844
2845                             XYZ aim;
2846                             victim->Puff(righthand);
2847                             victim->target = 0;
2848                             victim->frameTarget = 0;
2849                             victim->animTarget = staggerbackhighanim;
2850                             victim->targetyaw = targetyaw + 180;
2851                             victim->target = 0;
2852                             weapons[victim->weaponids[0]].owner = -1;
2853                             aim = DoRotation(facing, 0, 90, 0) * 21;
2854                             aim.y += 7;
2855                             weapons[victim->weaponids[0]].velocity = aim * -.2;
2856                             weapons[victim->weaponids[0]].tipvelocity = aim;
2857                             weapons[victim->weaponids[0]].missed = 1;
2858                             weapons[weaponids[0]].hitsomething = 0;
2859                             weapons[victim->weaponids[0]].freetime = 0;
2860                             weapons[victim->weaponids[0]].firstfree = 1;
2861                             weapons[victim->weaponids[0]].physics = 1;
2862                             victim->num_weapons--;
2863                             if (victim->num_weapons) {
2864                                 victim->weaponids[0] = victim->weaponids[num_weapons];
2865                                 if (victim->weaponstuck == victim->num_weapons)
2866                                     victim->weaponstuck = 0;
2867                             }
2868                             victim->weaponactive = -1;
2869                             for (i = 0; i < numplayers; i++) {
2870                                 player[i].wentforweapon = 0;
2871                             }
2872
2873                         }
2874                     }
2875                 }
2876
2877                 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2878                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2879                         if (tutoriallevel != 1) {
2880                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2881                             escapednum = 0;
2882                             if (id == 0)
2883                                 camerashake += .4;
2884                             if (Random() % 2 || creature == wolftype) {
2885                                 victim->spurt = 1;
2886                             }
2887                             emit_sound_at(staffheadsound, victim->coords);
2888                         }
2889                         victim->RagDoll(0);
2890                         XYZ relative;
2891                         relative = victim->coords - coords;
2892                         relative.y = 0;
2893                         Normalise(&relative);
2894                         relative = DoRotation(relative, 0, 90, 0);
2895                         relative.y -= 1;
2896                         Normalise(&relative);
2897                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2898                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2899                         }
2900                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 230;
2901                         victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * damagemult * 230;
2902                         //FootLand(1,2);
2903                         victim->Puff(head);
2904                         if (tutoriallevel != 1) {
2905                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2906
2907                             award_bonus(id, solidhit, 30);
2908                         }
2909                     }
2910                 }
2911
2912                 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2913                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2914                         if (tutoriallevel != 1) {
2915                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2916                             escapednum = 0;
2917                             if (id == 0)
2918                                 camerashake += .4;
2919                             if (Random() % 2 || creature == wolftype) {
2920                                 victim->spurt = 1;
2921                             }
2922                             emit_sound_at(staffheadsound, victim->coords);
2923                         }
2924                         victim->RagDoll(0);
2925                         XYZ relative;
2926                         relative = victim->coords - coords;
2927                         relative.y = 0;
2928                         Normalise(&relative);
2929                         relative = DoRotation(relative, 0, -90, 0);
2930                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2931                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2932                         }
2933                         victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 220;
2934                         victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity += relative * damagemult * 220;
2935                         //FootLand(1,2);
2936                         victim->Puff(head);
2937                         if (tutoriallevel != 1) {
2938                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
2939
2940                             award_bonus(id, solidhit, 60);
2941                         }
2942                     }
2943                 }
2944
2945                 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2946                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2947                         escapednum = 0;
2948                         if (tutoriallevel != 1) {
2949                             if (!victim->dead)
2950                                 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2951                             if (id == 0)
2952                                 camerashake += .4;
2953                             if (Random() % 2 || creature == wolftype) {
2954                                 victim->spurt = 1;
2955                             }
2956                             emit_sound_at(staffbodysound, victim->coords);
2957                         }
2958                         victim->skeleton.longdead = 0;
2959                         victim->skeleton.free = 1;
2960                         victim->skeleton.broken = 0;
2961
2962                         for (i = 0; i < victim->skeleton.num_joints; i++) {
2963                             victim->skeleton.joints[i].velchange = 0;
2964                             victim->skeleton.joints[i].locked = 0;
2965                             //victim->skeleton.joints[i].velocity=0;
2966                         }
2967
2968                         victim->RagDoll(0);
2969                         XYZ relative;
2970                         relative = 0;
2971                         /*relative=victim->coords-coords;
2972                         relative.y=0;
2973                         Normalise(&relative);
2974                         relative=DoRotation(relative,0,90,0);*/
2975                         relative.y = -1;
2976                         Normalise(&relative);
2977                         if (!victim->dead) {
2978                             for (i = 0; i < victim->skeleton.num_joints; i++) {
2979                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2980                             }
2981                             //FootLand(1,2);
2982                             victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 40;
2983                         }
2984                         if (victim->dead) {
2985                             for (i = 0; i < victim->skeleton.num_joints; i++) {
2986                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2987                             }
2988                             //FootLand(1,2);
2989                             //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*20;
2990                         }
2991                         victim->Puff(abdomen);
2992                         if (tutoriallevel != 1) {
2993                             victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2994
2995                             if (!victim->dead) {
2996                                 award_bonus(id, solidhit, 40);
2997                             }
2998                         }
2999                     }
3000                 }
3001
3002                 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3003                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3004                         escapednum = 0;
3005                         if (id == 0)
3006                             camerashake += .4;
3007                         XYZ relative;
3008                         relative = victim->coords - coords;
3009                         relative.y = 0;
3010                         Normalise(&relative);
3011
3012                         SolidHitBonus(id);
3013
3014                         if (animation[victim->animTarget].height == lowheight) {
3015                             if (Random() % 2) {
3016                                 victim->spurt = 1;
3017                                 DoBlood(.2, 250);
3018                             }
3019                             victim->RagDoll(0);
3020                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3021                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3022                             }
3023                             victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
3024                             if (tutoriallevel != 1) {
3025                                 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3026                             }
3027                             victim->Puff(head);
3028                             victim->DoDamage(damagemult * 100 / victim->protectionhead);
3029                             if (victim->howactive == typesleeping)
3030                                 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3031                             if (creature == wolftype) {
3032                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3033                                 victim->spurt = 1;
3034                                 victim->DoBloodBig(2 / victim->armorhead, 175);
3035                             }
3036                         } else {
3037                             if (victim->damage >= victim->damagetolerance)
3038                                 victim->RagDoll(0);
3039                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3040                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3041                             }
3042                             victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3043                             victim->frameTarget = 0;
3044                             victim->animTarget = staggerbackhighanim;
3045                             victim->targetyaw = targetyaw + 180;
3046                             victim->target = 0;
3047                             if (tutoriallevel != 1) {
3048                                 emit_sound_at(landsound2, victim->coords, 128.);
3049                             }
3050                             victim->Puff(abdomen);
3051                             victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3052                             if (creature == wolftype) {
3053                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3054                                 victim->spurt = 1;
3055                                 victim->DoBloodBig(2 / victim->armorhigh, 170);
3056                             }
3057                         }
3058
3059                     }
3060                 }
3061
3062                 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3063                     if (victim->animTarget != jumpupanim && distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim != this) {
3064                         escapednum = 0;
3065                         if (id == 0)
3066                             camerashake += .2;
3067                         if (tutoriallevel != 1) {
3068                             emit_sound_at(landsound2, victim->coords, 128.);
3069                         }
3070                         XYZ relative;
3071                         relative = victim->coords - coords;
3072                         relative.y = 0;
3073                         Normalise(&relative);
3074
3075                         if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3076                             victim->RagDoll(0);
3077
3078                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3079                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3080                             }
3081                             relative = DoRotation(relative, 0, -90, 0);
3082                             relative.y += .1;
3083                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3084                                 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)
3085                                     victim->skeleton.joints[i].velocity = relative * 80;
3086                             }
3087                             victim->Puff(rightankle);
3088                             victim->Puff(leftankle);
3089                             victim->DoDamage(damagemult * 40 / victim->protectionlow);
3090                         } else {
3091                             if (victim->damage >= victim->damagetolerance)
3092                                 victim->RagDoll(0);
3093                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3094                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3095                             }
3096                             relative = DoRotation(relative, 0, -90, 0);
3097                             for (i = 0; i < victim->skeleton.num_joints; i++) {
3098                                 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)
3099                                     victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3100                             }
3101                             victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3102                             victim->frameTarget = 0;
3103                             victim->animTarget = staggerbackhighanim;
3104                             victim->targetyaw = targetyaw + 180;
3105                             victim->target = 0;
3106                             if (tutoriallevel != 1) {
3107                                 emit_sound_at(landsound2, victim->coords, 128.);
3108                             }
3109                             victim->Puff(abdomen);
3110                             victim->DoDamage(damagemult * 30 / victim->protectionlow);
3111                         }
3112
3113                         SolidHitBonus(id);
3114
3115                     }
3116                 }
3117             }
3118             if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3119                 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3120                     escapednum = 0;
3121                     if (id == 0)
3122                         camerashake += .4;
3123                     if (Random() % 2) {
3124                         victim->spurt = 1;
3125                         DoBlood(.2, 230);
3126                     }
3127                     if (tutoriallevel != 1) {
3128                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3129                     }
3130                     if (creature == wolftype) {
3131                         emit_sound_at(clawslicesound, victim->coords, 128);
3132                         victim->spurt = 1;
3133                         victim->DoBloodBig(2 / victim->armorhigh, 170);
3134                     }
3135                     victim->RagDoll(0);
3136                     XYZ relative;
3137                     relative = victim->coords - oldcoords;
3138                     relative.y = 0;
3139                     Normalise(&relative);
3140                     //relative=DoRotation(relative,0,-90,0);
3141                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3142                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3143                     }
3144                     victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3145                     //FootLand(1,2);
3146                     victim->Puff(abdomen);
3147                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3148
3149                     award_bonus(id, Reversal);
3150                 }
3151
3152                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3153                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3154                         if (weapons[victim->weaponids[victim->weaponactive]].owner == victim->id) {
3155                             weapons[victim->weaponids[victim->weaponactive]].owner = id;
3156                             weaponactive = 0;
3157                             if (num_weapons > 0) {
3158                                 weaponids[num_weapons] = weaponids[victim->weaponactive];
3159                             }
3160                             num_weapons++;
3161                             weaponids[0] = victim->weaponids[victim->weaponactive];
3162                             victim->num_weapons--;
3163                             if (victim->num_weapons > 0) {
3164                                 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3165                                 //if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
3166                             }
3167                             victim->weaponactive = -1;
3168                         }
3169                     }
3170                 }
3171
3172                 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3173                     escapednum = 0;
3174                     if (id == 0)
3175                         camerashake += .4;
3176                     if (Random() % 2) {
3177                         victim->spurt = 1;
3178                         DoBlood(.2, 230);
3179                     }
3180                     emit_sound_at(whooshhitsound, victim->coords, 128.);
3181                     victim->RagDoll(0);
3182                     XYZ relative;
3183                     relative = victim->coords - oldcoords;
3184                     relative.y = 0;
3185                     Normalise(&relative);
3186                     //relative=DoRotation(relative,0,-90,0);
3187                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3188                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3189                     }
3190                     victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3191                     //FootLand(1,2);
3192                     victim->Puff(head);
3193                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3194                 }
3195
3196                 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3197                     escapednum = 0;
3198                     if (id == 0)
3199                         camerashake += .4;
3200                     if (Random() % 2) {
3201                         victim->spurt = 1;
3202                         DoBlood(.2, 230);
3203                     }
3204
3205                     award_bonus(id, staffreversebonus);
3206
3207                     if (tutoriallevel != 1) {
3208                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3209                     }
3210                     victim->RagDoll(0);
3211                     award_bonus(id, staffreversebonus); // Huh, again?
3212
3213                     XYZ relative;
3214                     relative = victim->coords - oldcoords;
3215                     relative.y = 0;
3216                     Normalise(&relative);
3217                     //relative=DoRotation(relative,0,-90,0);
3218                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3219                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3220                     }
3221                     victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3222                     //FootLand(1,2);
3223                     victim->Puff(head);
3224                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3225                 }
3226
3227                 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3228                     escapednum = 0;
3229                     victim->RagDoll(1);
3230                     XYZ relative;
3231                     relative = facing;
3232                     relative.y = 0;
3233                     Normalise(&relative);
3234                     //relative*=-1;
3235                     relative.y -= .1;
3236                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3237                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3238                     }
3239                     victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity *= .1;
3240                     victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity *= .2;
3241                     victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity *= .5;
3242                     victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity *= .7;
3243                     victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity *= .1;
3244                     victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity *= .2;
3245                     victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity *= .5;
3246                     victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity *= .7;
3247
3248                     victim->Puff(abdomen);
3249                     victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3250
3251                     award_bonus(id, Reversal);
3252
3253                     bool doslice;
3254                     doslice = 0;
3255                     if (weaponactive != -1 || creature == wolftype)
3256                         doslice = 1;
3257                     if (creature == rabbittype && weaponactive != -1)
3258                         if (weapons[weaponids[0]].getType() == staff)
3259                             doslice = 0;
3260                     if (doslice) {
3261                         if (weaponactive != -1) {
3262                             victim->DoBloodBig(2 / victim->armorhigh, 225);
3263                             emit_sound_at(knifeslicesound, victim->coords);
3264                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3265                                 weapons[weaponids[weaponactive]].bloody = 1;
3266                             weapons[weaponids[weaponactive]].blooddrip += 3;
3267                         }
3268                         if (weaponactive == -1 && creature == wolftype) {
3269                             ;
3270                             emit_sound_at(clawslicesound, victim->coords, 128.);
3271                             victim->spurt = 1;
3272                             victim->DoBloodBig(2 / victim->armorhigh, 175);
3273                         }
3274                     }
3275                 }
3276
3277
3278
3279                 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3280                     escapednum = 0;
3281                     victim->RagDoll(1);
3282                     XYZ relative;
3283                     relative = facing;
3284                     relative.y = 0;
3285                     Normalise(&relative);
3286                     //relative*=-1;
3287                     relative.y -= .1;
3288                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3289                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3290                     }
3291                     victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity *= .1 - 1;
3292                     victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity *= .2 - 1;
3293                     victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity *= .5 - 1;
3294                     victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity *= .7 - 1;
3295                     victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity *= .1 - 1;
3296                     victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity *= .2 - 1;
3297                     victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity *= .5 - 1;
3298                     victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity *= .7 - 1;
3299
3300                     award_bonus(id, swordreversebonus);
3301                 }
3302
3303                 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3304                     escapednum = 0;
3305                     if (id == 0)
3306                         camerashake += .4;
3307                     if (Random() % 2) {
3308                         victim->spurt = 1;
3309                         DoBlood(.2, 230);
3310                     }
3311                     if (tutoriallevel != 1) {
3312                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3313                     }
3314                     victim->RagDoll(0);
3315                     XYZ relative;
3316                     relative = victim->coords - oldcoords;
3317                     relative.y = 0;
3318                     Normalise(&relative);
3319                     relative = DoRotation(relative, 0, -90, 0);
3320                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3321                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3322                     }
3323                     victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity += relative * damagemult * 200;
3324                     //FootLand(1,2);
3325                     victim->Puff(abdomen);
3326                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3327
3328                     award_bonus(id, Reversal);
3329                 }
3330
3331                 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3332                     escapednum = 0;
3333                     victim->RagDoll(0);
3334                     victim->skeleton.spinny = 0;
3335                     XYZ relative;
3336                     relative = facing * -1;
3337                     relative.y = -3;
3338                     Normalise(&relative);
3339                     if (victim->id == 0)
3340                         relative /= 30;
3341                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3342                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3343                     }
3344                     //victim->DoDamage(1000);
3345                     victim->damage = victim->damagetolerance;
3346                     victim->permanentdamage = victim->damagetolerance - 1;
3347                     bool doslice;
3348                     doslice = 0;
3349                     if (weaponactive != -1 || creature == wolftype)
3350                         doslice = 1;
3351                     if (creature == rabbittype && weaponactive != -1)
3352                         if (weapons[weaponids[0]].getType() == staff)
3353                             doslice = 0;
3354                     if (doslice) {
3355                         if (weaponactive != -1) {
3356                             victim->DoBloodBig(200, 225);
3357                             emit_sound_at(knifeslicesound, victim->coords);
3358                             if (bloodtoggle)
3359                                 weapons[weaponids[weaponactive]].bloody = 2;
3360                             weapons[weaponids[weaponactive]].blooddrip += 5;
3361                         }
3362
3363                         if (creature == wolftype && weaponactive == -1) {
3364                             emit_sound_at(clawslicesound, victim->coords, 128.);
3365                             victim->spurt = 1;
3366                             victim->DoBloodBig(2, 175);
3367                         }
3368                     }
3369                     award_bonus(id, spinecrusher);
3370                 }
3371
3372                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3373                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3374                         escapednum = 0;
3375                         if (animTarget == knifefollowanim)
3376                             victim->DoBloodBig(200, 210);
3377                         if (animTarget == knifesneakattackanim) {
3378                             /*victim->DoBloodBig(200,195);
3379                             XYZ bloodvel;
3380                             bloodvel=0;
3381                             bloodvel.z=20;
3382                             bloodvel.y=5;
3383                             bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,yaw+((float)(Random()%100))/4,0)*scale;
3384                             Sprite::MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position,0,yaw,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
3385                             */
3386                             XYZ footvel, footpoint;
3387                             footvel = 0;
3388                             footpoint = weapons[weaponids[0]].tippoint;
3389                             if (bloodtoggle)
3390                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3391                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3392                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3393                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3394                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3395                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3396                             victim->DoBloodBig(200, 195);
3397                             award_bonus(id, tracheotomy);
3398                         }
3399                         if (animTarget == knifefollowanim) {
3400                             award_bonus(id, Stabbonus);
3401                             XYZ footvel, footpoint;
3402                             footvel = 0;
3403                             footpoint = weapons[weaponids[0]].tippoint;
3404                             if (bloodtoggle)
3405                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3406                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3407                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3408                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3409                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3410                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3411
3412                         }
3413                         victim->bloodloss += 10000;
3414                         victim->velocity = 0;
3415                         emit_sound_at(fleshstabsound, victim->coords);
3416                         if (bloodtoggle)
3417                             weapons[weaponids[weaponactive]].bloody = 2;
3418                         weapons[weaponids[weaponactive]].blooddrip += 5;
3419                     }
3420                 }
3421
3422                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3423                     escapednum = 0;
3424                     victim->velocity = 0;
3425                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3426                         victim->skeleton.joints[i].velocity = 0;
3427                     }
3428                     if (animTarget == knifefollowanim) {
3429                         victim->RagDoll(0);
3430                         for (i = 0; i < victim->skeleton.num_joints; i++) {
3431                             victim->skeleton.joints[i].velocity = 0;
3432                         }
3433                     }
3434                     if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3435                         emit_sound_at(fleshstabremovesound, victim->coords);
3436                         if (bloodtoggle)
3437                             weapons[weaponids[weaponactive]].bloody = 2;
3438                         weapons[weaponids[weaponactive]].blooddrip += 5;
3439
3440                         XYZ footvel, footpoint;
3441                         footvel = 0;
3442                         footpoint = weapons[weaponids[0]].tippoint;
3443                         if (bloodtoggle)
3444                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3445                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3446                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3447                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3448                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3449                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3450                     }
3451                 }
3452
3453                 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3454                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3455                         award_bonus(id, backstab);
3456
3457                         escapednum = 0;
3458
3459                         XYZ footvel, footpoint;
3460                         footvel = 0;
3461                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3462                         if (bloodtoggle)
3463                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3464                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3465                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3466                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3467                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3468                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3469                         victim->DoBloodBig(200, 180);
3470                         victim->DoBloodBig(200, 215);
3471                         victim->bloodloss += 10000;
3472                         victim->velocity = 0;
3473                         emit_sound_at(fleshstabsound, victim->coords);
3474                         if (bloodtoggle)
3475                             weapons[weaponids[weaponactive]].bloody = 2;
3476                         weapons[weaponids[weaponactive]].blooddrip += 5;
3477                     }
3478                 }
3479
3480                 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3481                     escapednum = 0;
3482                     victim->velocity = 0;
3483                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3484                         victim->skeleton.joints[i].velocity = 0;
3485                     }
3486                     if (weaponactive != -1) {
3487                         emit_sound_at(fleshstabremovesound, victim->coords);
3488                         if (bloodtoggle)
3489                             weapons[weaponids[weaponactive]].bloody = 2;
3490                         weapons[weaponids[weaponactive]].blooddrip += 5;
3491
3492                         XYZ footvel, footpoint;
3493                         footvel = 0;
3494                         footpoint = weapons[weaponids[0]].tippoint;
3495                         if (bloodtoggle)
3496                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3497                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3498                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3499                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3500                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3501                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3502                     }
3503                 }
3504
3505                 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3506                     escapednum = 0;
3507                     if (id == 0)
3508                         camerashake += .4;
3509                     if (Random() % 2) {
3510                         victim->spurt = 1;
3511                         DoBlood(.2, 240);
3512                     }
3513                     if (weaponactive == -1) {
3514                         if (tutoriallevel != 1) {
3515                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
3516                         }
3517                     }
3518                     bool doslice;
3519                     doslice = 0;
3520                     if (weaponactive != -1 || creature == wolftype)
3521                         doslice = 1;
3522                     if (creature == rabbittype && weaponactive != -1)
3523                         if (weapons[weaponids[0]].getType() == staff)
3524                             doslice = 0;
3525                     if (doslice) {
3526                         if (weaponactive != -1) {
3527                             victim->DoBloodBig(2 / victim->armorhead, 225);
3528                             emit_sound_at(knifeslicesound, victim->coords);
3529                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3530                                 weapons[weaponids[weaponactive]].bloody = 1;
3531                             weapons[weaponids[weaponactive]].blooddrip += 3;
3532                         }
3533                         if (weaponactive == -1 && creature == wolftype) {
3534                             emit_sound_at(clawslicesound, victim->coords, 128.);
3535                             victim->spurt = 1;
3536                             victim->DoBloodBig(2 / victim->armorhead, 175);
3537                         }
3538                     }
3539
3540                     award_bonus(id, Reversal);
3541
3542                     victim->Puff(neck);
3543
3544                     XYZ relative;
3545                     //relative=victim->coords-oldcoords;
3546                     relative = facing * -1;
3547                     relative.y = 0;
3548                     Normalise(&relative);
3549                     relative = DoRotation(relative, 0, 90, 0);
3550                     relative.y = .5;
3551                     Normalise(&relative);
3552                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3553                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3554                     }
3555                     victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
3556                     if (victim->damage < victim->damagetolerance - 100)
3557                         victim->velocity = relative * 200;
3558                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
3559                     victim->velocity = 0;
3560                 }
3561
3562                 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3563                     escapednum = 0;
3564                     victim->RagDoll(0);
3565                     XYZ relative;
3566                     //relative=victim->coords-oldcoords;
3567                     relative = facing * -1;
3568                     relative.y = 0;
3569                     Normalise(&relative);
3570                     relative = DoRotation(relative, 0, 90, 0);
3571                     relative.y = .5;
3572                     Normalise(&relative);
3573                     for (i = 0; i < victim->skeleton.num_joints; i++) {
3574                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3575                     }
3576                     victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity += relative * damagemult * 200;
3577                 }
3578
3579                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3580                     if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3581                         award_bonus(id, reverseko);
3582                     }
3583             }
3584
3585
3586             //Animation end
3587             if (frameTarget > animation[animCurrent].numframes - 1) {
3588                 frameTarget = 0;
3589                 if (wasStop()) {
3590                     animTarget = getIdle();
3591                     FootLand(0, 1);
3592                     FootLand(1, 1);
3593                 }
3594                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3595                     animTarget = rollanim;
3596                     frameTarget = 3;
3597                     emit_sound_at(movewhooshsound, coords, 128.);
3598                 }
3599                 if (animCurrent == staggerbackhighanim) {
3600                     animTarget = getIdle();
3601                 }
3602                 if (animCurrent == staggerbackhardanim) {
3603                     animTarget = getIdle();
3604                 }
3605                 if (animCurrent == removeknifeanim) {
3606                     animTarget = getIdle();
3607                 }
3608                 if (animCurrent == crouchremoveknifeanim) {
3609                     animTarget = getCrouch();
3610                 }
3611                 if (animCurrent == backhandspringanim) {
3612                     animTarget = getIdle();
3613                 }
3614                 if (animCurrent == dodgebackanim) {
3615                     animTarget = getIdle();
3616                 }
3617                 if (animCurrent == drawleftanim) {
3618                     animTarget = getIdle();
3619                 }
3620                 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3621                     animTarget = getIdle();
3622                     if (animCurrent == crouchdrawrightanim) {
3623                         animTarget = getCrouch();
3624                     }
3625                     if (weaponactive == -1)
3626                         weaponactive = 0;
3627                     else if (weaponactive == 0) {
3628                         weaponactive = -1;
3629                         if (num_weapons == 2) {
3630                             int buffer;
3631                             buffer = weaponids[0];
3632                             weaponids[0] = weaponids[1];
3633                             weaponids[1] = buffer;
3634                         }
3635                     }
3636
3637                     if (weaponactive == -1) {
3638                         emit_sound_at(knifesheathesound, coords, 128.);
3639                     }
3640                     if (weaponactive != -1) {
3641                         emit_sound_at(knifedrawsound, coords, 128.);
3642                     }
3643                 }
3644                 if (animCurrent == rollanim) {
3645                     animTarget = getCrouch();
3646                     FootLand(0, 1);
3647                     FootLand(1, 1);
3648                 }
3649                 if (isFlip()) {
3650                     if (animTarget == walljumprightkickanim) {
3651                         targetrot = -190;
3652                     }
3653                     if (animTarget == walljumpleftkickanim) {
3654                         targetrot = 190;
3655                     }
3656                     animTarget = jumpdownanim;
3657                 }
3658                 if (animCurrent == climbanim) {
3659                     animTarget = getCrouch();
3660                     frameTarget = 1;
3661                     coords += facing * .1;
3662                     if (!isnormal(coords.x))
3663                         coords = oldcoords;
3664                     oldcoords = coords;
3665                     collided = 0;
3666                     targetoffset = 0;
3667                     currentoffset = 0;
3668                     grabdelay = 1;
3669                     velocity = 0;
3670                     collided = 0;
3671                     avoidcollided = 0;
3672                 }
3673                 if (animTarget == rabbitkickreversalanim) {
3674                     animTarget = getCrouch();
3675                     lastfeint = 0;
3676                 }
3677                 if (animTarget == jumpreversalanim) {
3678                     animTarget = getCrouch();
3679                     lastfeint = 0;
3680                 }
3681                 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3682                     if (attackkeydown && animTarget != walljumpfrontanim) {
3683                         int closest = -1;
3684                         float closestdist = -1;
3685                         float distance;
3686                         if (numplayers > 1)
3687                             for (i = 0; i < numplayers; i++) {
3688                                 if (id != i && player[i].coords.y < coords.y && !player[i].skeleton.free) {
3689                                     distance = distsq(&player[i].coords, &coords);
3690                                     if (closestdist == -1 || distance < closestdist) {
3691                                         closestdist = distance;
3692                                         closest = i;
3693                                     }
3694                                 }
3695                             }
3696                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3697                             victim = &player[closest];
3698                             animTarget = walljumprightkickanim;
3699                             frameTarget = 0;
3700                             XYZ rotatetarget = victim->coords - coords;
3701                             Normalise(&rotatetarget);
3702                             yaw = -asin(0 - rotatetarget.x);
3703                             yaw *= 360 / 6.28;
3704                             if (rotatetarget.z < 0)
3705                                 yaw = 180 - yaw;
3706                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3707                             velocity = (victim->coords - coords) * 4;
3708                             velocity.y += 2;
3709                             transspeed = 40;
3710                         }
3711                     }
3712                     if (animTarget == walljumpbackanim) {
3713                         animTarget = backflipanim;
3714                         frameTarget = 3;
3715                         velocity = facing * -8;
3716                         velocity.y = 4;
3717                         if (id == 0)
3718                             resume_stream(whooshsound);
3719                     }
3720                     if (animTarget == walljumprightanim) {
3721                         animTarget = rightflipanim;
3722                         frameTarget = 4;
3723                         targetyaw -= 90;
3724                         yaw -= 90;
3725                         velocity = DoRotation(facing, 0, 30, 0) * -8;
3726                         velocity.y = 4;
3727                     }
3728                     if (animTarget == walljumpfrontanim) {
3729                         animTarget = frontflipanim;
3730                         frameTarget = 2;
3731                         //targetyaw-=180;
3732                         ////yaw-=180;
3733                         velocity = facing * 8;
3734                         velocity.y = 4;
3735                     }
3736                     if (id == 0)
3737                         resume_stream(whooshsound);
3738                 }
3739                 if (animTarget == walljumpleftanim) {
3740                     if (attackkeydown) {
3741                         int closest = -1;
3742                         float closestdist = -1;
3743                         float distance;
3744                         if (numplayers > 1)
3745                             for (i = 0; i < numplayers; i++) {
3746                                 if (id != i && player[i].coords.y < coords.y && !player[i].skeleton.free) {
3747                                     distance = distsq(&player[i].coords, &coords);
3748                                     if (closestdist == -1 || distance < closestdist) {
3749                                         closestdist = distance;
3750                                         closest = i;
3751                                     }
3752                                 }
3753                             }
3754                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3755                             victim = &player[closest];
3756                             animTarget = walljumpleftkickanim;
3757                             frameTarget = 0;
3758                             XYZ rotatetarget = victim->coords - coords;
3759                             Normalise(&rotatetarget);
3760                             yaw = -asin(0 - rotatetarget.x);
3761                             yaw *= 360 / 6.28;
3762                             if (rotatetarget.z < 0)
3763                                 yaw = 180 - yaw;
3764                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3765                             velocity = (victim->coords - coords) * 4;
3766                             velocity.y += 2;
3767                             transspeed = 40;
3768                         }
3769                     }
3770                     if (animTarget != walljumpleftkickanim) {
3771                         animTarget = leftflipanim;
3772                         frameTarget = 4;
3773                         targetyaw += 90;
3774                         yaw += 90;
3775                         velocity = DoRotation(facing, 0, -30, 0) * -8;
3776                         velocity.y = 4;
3777                     }
3778                     if (id == 0)
3779                         resume_stream(whooshsound);
3780                 }
3781                 if (animTarget == sneakattackanim) {
3782                     animCurrent = getCrouch();
3783                     animTarget = getCrouch();
3784                     frameTarget = 1;
3785                     frameCurrent = 0;
3786                     targetyaw += 180;
3787                     yaw += 180;
3788                     targettilt2 *= -1;
3789                     tilt2 *= -1;
3790                     transspeed = 1000000;
3791                     targetheadyaw += 180;
3792                     coords -= facing * .7;
3793                     if (onterrain)
3794                         coords.y = terrain.getHeight(coords.x, coords.z);
3795
3796                     lastfeint = 0;
3797                 }
3798                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3799                     animTarget = getIdle();
3800                     frameTarget = 0;
3801                     if (onterrain)
3802                         coords.y = terrain.getHeight(coords.x, coords.z);
3803
3804                     lastfeint = 0;
3805                 }
3806                 if (animCurrent == knifefollowanim) {
3807                     animTarget = getIdle();
3808                     lastfeint = 0;
3809                 }
3810                 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3811                     float ycoords = oldcoords.y;
3812                     animTarget = getStop();
3813                     targetyaw += 180;
3814                     yaw += 180;
3815                     targettilt2 *= -1;
3816                     tilt2 *= -1;
3817                     transspeed = 1000000;
3818                     targetheadyaw += 180;
3819                     if (!isnormal(coords.x))
3820                         coords = oldcoords;
3821                     if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3822                         oldcoords = coords + facing * .5;
3823                     else if (animCurrent == sweepreversalanim)
3824                         oldcoords = coords + facing * 1.1;
3825                     else if (animCurrent == upunchreversalanim) {
3826                         oldcoords = coords + facing * 1.5;
3827                         targetyaw += 180;
3828                         yaw += 180;
3829                         targetheadyaw += 180;
3830                         targettilt2 *= -1;
3831                         tilt2 *= -1;
3832                     } else if (animCurrent == knifeslashreversalanim) {
3833                         oldcoords = coords + facing * .5;
3834                         targetyaw += 90;
3835                         yaw += 90;
3836                         targetheadyaw += 90;
3837                         targettilt2 = 0;
3838                         tilt2 = 0;
3839                     } else if (animCurrent == staffspinhitreversalanim) {
3840                         targetyaw += 180;
3841                         yaw += 180;
3842                         targetheadyaw += 180;
3843                         targettilt2 = 0;
3844                         tilt2 = 0;
3845                     }
3846                     if (onterrain)
3847                         oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3848                     else
3849                         oldcoords.y = ycoords;
3850                     currentoffset = coords - oldcoords;
3851                     targetoffset = 0;
3852                     coords = oldcoords;
3853
3854                     lastfeint = 0;
3855                 }
3856                 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3857                     velocity = 0;
3858                     velocity.y = -5;
3859                     RagDoll(0);
3860                 }
3861                 if (animation[animTarget].attack == reversed) {
3862                     escapednum++;
3863                     if (animTarget == sweepreversedanim)
3864                         targetyaw += 90;
3865                     animTarget = backhandspringanim;
3866                     frameTarget = 2;
3867                     emit_sound_at(landsound, coords, 128);
3868
3869                     if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3870                         animTarget = rollanim;
3871                         frameTarget = 5;
3872                         oldcoords = coords;
3873                         coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
3874                         coords.y = oldcoords.y;
3875                     }
3876                     if (animCurrent == knifeslashreversedanim) {
3877                         animTarget = rollanim;
3878                         frameTarget = 0;
3879                         targetyaw += 90;
3880                         yaw += 90;
3881                         oldcoords = coords;
3882                         coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
3883                         coords.y = oldcoords.y;
3884                     }
3885                 }
3886                 if (wasFlip()) {
3887                     animTarget = jumpdownanim;
3888                 }
3889                 if (wasLanding())
3890                     animTarget = getIdle();
3891                 if (wasLandhard())
3892                     animTarget = getIdle();
3893                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3894                     animTarget = getIdle();
3895                     oldcoords = coords;
3896                     coords += (DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) + DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0)) / 2 * scale;
3897                     coords.y = oldcoords.y;
3898                     //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3899                     targetoffset.y = coords.y;
3900                     if (onterrain)
3901                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
3902                     currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3903                     currentoffset.y -= (coords.y - targetoffset.y);
3904                     coords.y = targetoffset.y;
3905                     targetoffset = 0;
3906                     normalsupdatedelay = 0;
3907                 }
3908                 if (animCurrent == upunchanim) {
3909                     animTarget = getStop();
3910                     normalsupdatedelay = 0;
3911                     lastfeint = 0;
3912                 }
3913                 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3914                     targetyaw = yaw;
3915                     bool hasstaff;
3916                     hasstaff = 0;
3917                     if (num_weapons > 0)
3918                         if (weapons[0].getType() == staff)
3919                             hasstaff = 1;
3920                     if (!hasstaff)
3921                         DoDamage(35);
3922                     RagDoll(0);
3923                     lastfeint = 0;
3924                     rabbitkickragdoll = 1;
3925                 }
3926                 if (animCurrent == rabbitkickreversedanim) {
3927                     if (!feint) {
3928                         velocity = 0;
3929                         velocity.y = -10;
3930                         //DoDamage(100);
3931                         RagDoll(0);
3932                         skeleton.spinny = 0;
3933                         SolidHitBonus(!id); // FIXME: tricky id
3934                     }
3935                     if (feint) {
3936                         escapednum++;
3937                         animTarget = rollanim;
3938                         coords += facing;
3939                         if (id == 0)
3940                             pause_sound(whooshsound);
3941                     }
3942                     lastfeint = 0;
3943                 }
3944                 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3945                     velocity = 0;
3946                     velocity.y = -10;
3947                     RagDoll(0);
3948                     skeleton.spinny = 0;
3949                 }
3950                 if (animCurrent == jumpreversedanim) {
3951                     if (!feint) {
3952                         velocity = 0;
3953                         velocity.y = -10;
3954                         //DoDamage(100);
3955                         RagDoll(0);
3956                         skeleton.spinny = 0;
3957                         SolidHitBonus(!id); // FIXME: tricky id
3958                     }
3959                     if (feint) {
3960                         escapednum++;
3961                         animTarget = rollanim;
3962                         coords += facing * 2;
3963                         if (id == 0)
3964                             pause_sound(whooshsound);
3965                     }
3966                     lastfeint = 0;
3967                 }
3968
3969                 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) {
3970                     animTarget = getupfromfrontanim;
3971                     lastfeint = 0;
3972                 } else if (animation[animCurrent].attack == normalattack) {
3973                     animTarget = getIdle();
3974                     lastfeint = 0;
3975                 }
3976                 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3977                     animTarget = blockhighleftstrikeanim;
3978                 }
3979                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3980                     animTarget = getIdle();
3981                     lastfeint = 0;
3982                 }
3983                 if (animCurrent == spinkickanim && victim->skeleton.free) {
3984                     if (creature == rabbittype)
3985                         animTarget = fightidleanim;
3986                 }
3987             }
3988             target = 0;
3989
3990             if (isIdle() && !wasIdle())
3991                 normalsupdatedelay = 0;
3992
3993             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3994                 animTarget = jumpdownanim;
3995             }
3996         }
3997         if (!skeleton.free) {
3998             oldtarget = target;
3999             if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4000                 if (!isRun() || !wasRun()) {
4001                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4002                         target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4003                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4004                         target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4005                 }
4006                 if (isRun() && wasRun()) {
4007                     float tempspeed;
4008                     tempspeed = velspeed;
4009                     if (tempspeed < 10 * speedmult)
4010                         tempspeed = 10 * speedmult;
4011                     target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4012                 }
4013             } else if (transspeed)
4014                 target += multiplier * transspeed * speed * 2;
4015             else {
4016                 if (!isRun() || !wasRun()) {
4017                     if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4018                         target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4019                     if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4020                         target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4021                 }
4022             }
4023
4024             if (animCurrent != animTarget)
4025                 target = (target + oldtarget) / 2;
4026
4027             if (target > 1) {
4028                 frameCurrent = frameTarget;
4029                 target = 1;
4030             }
4031             oldrot = rot;
4032             rot = targetrot * target;
4033             yaw += rot - oldrot;
4034             if (target == 1) {
4035                 rot = 0;
4036                 oldrot = 0;
4037                 targetrot = 0;
4038             }
4039             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4040                 //Old rotates
4041                 for (i = 0; i < skeleton.num_joints; i++) {
4042                     skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4043                 }
4044
4045                 skeleton.FindForwards();
4046
4047                 for (i = 0; i < skeleton.num_muscles; i++) {
4048                     if (skeleton.muscles[i].visible) {
4049                         skeleton.FindRotationMuscle(i, animTarget);
4050                     }
4051                 }
4052                 for (i = 0; i < skeleton.num_muscles; i++) {
4053                     if (skeleton.muscles[i].visible) {
4054                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4055                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4056                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4057                             skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4058                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4059                             skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4060                     }
4061                 }
4062
4063                 //New rotates
4064                 for (i = 0; i < skeleton.num_joints; i++) {
4065                     skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4066                 }
4067
4068                 skeleton.FindForwards();
4069
4070                 for (i = 0; i < skeleton.num_muscles; i++) {
4071                     if (skeleton.muscles[i].visible) {
4072                         skeleton.FindRotationMuscle(i, animTarget);
4073                     }
4074                 }
4075                 for (i = 0; i < skeleton.num_muscles; i++) {
4076                     if (skeleton.muscles[i].visible) {
4077                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4078                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4079                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4080                             skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4081                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4082                             skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4083                         if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4084                         if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4085                         if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4086                         if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4087                         if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4088                         if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4089                     }
4090                 }
4091             }
4092             if (frameCurrent >= animation[animCurrent].numframes)
4093                 frameCurrent = animation[animCurrent].numframes - 1;
4094
4095             oldanimCurrent = animCurrent;
4096             oldanimTarget = animTarget;
4097             oldframeTarget = frameTarget;
4098             oldframeCurrent = frameCurrent;
4099
4100             for (i = 0; i < skeleton.num_joints; i++) {
4101                 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4102                 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4103             }
4104             offset = currentoffset * (1 - target) + targetoffset * target;
4105             for (i = 0; i < skeleton.num_muscles; i++) {
4106                 if (skeleton.muscles[i].visible) {
4107                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4108                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4109                     skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4110                 }
4111             }
4112         }
4113
4114         if (isLanding() && landhard) {
4115             if (id == 0)
4116                 camerashake += .4;
4117             animTarget = getLandhard();
4118             frameTarget = 0;
4119             target = 0;
4120             landhard = 0;
4121             transspeed = 15;
4122         }
4123     }
4124     //skeleton.DoConstraints();
4125 }
4126
4127 /* EFFECT
4128  * MONSTER
4129  * TODO
4130  */
4131 void Person::DoStuff()
4132 {
4133     static XYZ terrainnormal;
4134     static XYZ flatfacing;
4135     static XYZ flatvelocity;
4136     static float flatvelspeed;
4137     static int i, j, l;
4138     static XYZ average;
4139     static int howmany;
4140     static int bloodsize;
4141     static int startx, starty, endx, endy;
4142     static GLubyte color;
4143     static XYZ bloodvel;
4144
4145     onfiredelay -= multiplier;
4146     if (onfiredelay < 0 && onfire) {
4147         if (Random() % 2 == 0) {
4148             crouchkeydown = 1;
4149         }
4150         onfiredelay = 0.3;
4151     }
4152
4153     crouchkeydowntime += multiplier;
4154     if (!crouchkeydown)
4155         crouchkeydowntime = 0;
4156     jumpkeydowntime += multiplier;
4157     if (!jumpkeydown && skeleton.free)
4158         jumpkeydowntime = 0;
4159
4160     if (hostile || damage > 0 || bloodloss > 0)
4161         immobile = 0;
4162
4163     if (isIdle() || isRun())
4164         targetoffset = 0;
4165
4166     if (num_weapons == 1 && weaponactive != -1)
4167         weaponstuck = -1;
4168
4169     if (id == 0)
4170         blooddimamount -= multiplier * .3;
4171     speechdelay -= multiplier;
4172     texupdatedelay -= multiplier;
4173     interestdelay -= multiplier;
4174     flamedelay -= multiplier;
4175     parriedrecently -= multiplier;
4176     if (!victim) {
4177         victim = this;
4178         hasvictim = 0;
4179     }
4180
4181     if (id == 0)
4182         speed = 1.1 * speedmult;
4183     else
4184         speed = 1.0 * speedmult;
4185     if (!skeleton.free)
4186         rabbitkickragdoll = 0;
4187
4188     speed *= speedmult;
4189
4190     if (id != 0 && (creature == rabbittype || difficulty != 2))
4191         superruntoggle = 0;
4192     if (id != 0 && creature == wolftype && difficulty == 2) {
4193         superruntoggle = 0;
4194         if (aitype != passivetype) {
4195             superruntoggle = 1;
4196             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) {
4197                 superruntoggle = 0;
4198             }
4199         }
4200         if (scale < 0.2)
4201             superruntoggle = 0;
4202         if (animTarget == wolfrunninganim && !superruntoggle) {
4203             animTarget = getRun();
4204             frameTarget = 0;
4205         }
4206     }
4207     if (weaponactive == -1 && num_weapons > 0) {
4208         if (weapons[weaponids[0]].getType() == staff) {
4209             weaponactive = 0;
4210         }
4211     }
4212
4213     if (onfire) {
4214         burnt += multiplier;
4215         /*if(aitype!=playercontrolled)*///deathbleeding=5;
4216         /*if(aitype!=playercontrolled)*/
4217         deathbleeding = 1;
4218         if (burnt > .6)
4219             burnt = .6;
4220         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4221
4222         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4223             float gLoc[3];
4224             float vel[3];
4225             gLoc[0] = coords.x;
4226             gLoc[1] = coords.y;
4227             gLoc[2] = coords.z;
4228             vel[0] = velocity.x;
4229             vel[1] = velocity.y;
4230             vel[2] = velocity.z;
4231
4232             if (id == 0) {
4233                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4234                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4235             }
4236         }
4237     }
4238     while (flamedelay < 0 && onfire) {
4239         flamedelay += .006;
4240         howmany = abs(Random() % (skeleton.num_joints));
4241         if (!skeleton.free)
4242             flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4243         if (skeleton.free)
4244             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4245         if (!skeleton.free)
4246             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4247         if (skeleton.free)
4248             flatfacing = skeleton.joints[howmany].position * scale + coords;
4249         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4250     }
4251
4252     while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4253         flamedelay += .05;
4254         howmany = abs(Random() % (skeleton.num_joints));
4255         if (!skeleton.free)
4256             flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4257         if (skeleton.free)
4258             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4259         if (!skeleton.free)
4260             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4261         if (skeleton.free)
4262             flatfacing = skeleton.joints[howmany].position * scale + coords;
4263         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4264     }
4265
4266     if (bleeding > 0) {
4267         bleeding -= multiplier * .3;
4268         if (bloodtoggle == 2) {
4269             skeleton.drawmodel.textureptr.bind();
4270             if (bleeding <= 0 && (detail != 2 || osx))
4271                 DoMipmaps();
4272         }
4273     }
4274
4275     if (neckspurtamount > 0) {
4276         neckspurtamount -= multiplier;
4277         neckspurtdelay -= multiplier * 3;
4278         neckspurtparticledelay -= multiplier * 3;
4279         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4280             spurt = 0;
4281             bloodvel = 0;
4282             if (!skeleton.free) {
4283                 bloodvel.z = 5 * neckspurtamount;
4284                 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4285             }
4286             if (skeleton.free) {
4287                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4288             }
4289             if (skeleton.free)
4290                 bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4291             if (!skeleton.free)
4292                 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4293             if (skeleton.free)
4294                 Sprite::MakeSprite(bloodsprite, (skeleton.joints[skeleton.jointlabels[neck]].position + (skeleton.joints[skeleton.jointlabels[neck]].position - skeleton.joints[skeleton.jointlabels[head]].position) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4295             if (!skeleton.free)
4296                 Sprite::MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position + (skeleton.joints[skeleton.jointlabels[neck]].position - skeleton.joints[skeleton.jointlabels[head]].position) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4297             neckspurtparticledelay = .05;
4298         }
4299         if (neckspurtdelay < 0) {
4300             neckspurtdelay = 3;
4301         }
4302     }
4303
4304     if (deathbleeding > 0 && dead != 2) {
4305         if (deathbleeding < 5)
4306             bleeddelay -= deathbleeding * multiplier / 4;
4307         else
4308             bleeddelay -= 5 * multiplier / 4;
4309         if (bleeddelay < 0 && bloodtoggle) {
4310             bleeddelay = 1;
4311             XYZ bloodvel;
4312             if (bloodtoggle) {
4313                 bloodvel = 0;
4314                 if (skeleton.free)
4315                     bloodvel += DoRotation(skeleton.joints[skeleton.jointlabels[abdomen]].velocity, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4316                 if (!skeleton.free)
4317                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4318                 if (skeleton.free)
4319                     Sprite::MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[abdomen]].position * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4320                 if (!skeleton.free)
4321                     Sprite::MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[abdomen]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4322             }
4323         }
4324         bloodloss += deathbleeding * multiplier * 80;
4325         deathbleeding -= multiplier * 1.6;
4326         //if(id==0)deathbleeding-=multiplier*.2;
4327         if (deathbleeding < 0)
4328             deathbleeding = 0;
4329         if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4330             if (weaponactive != -1) {
4331                 weapons[weaponids[0]].owner = -1;
4332                 weapons[weaponids[0]].velocity = velocity * scale * -.3;
4333                 weapons[weaponids[0]].velocity.x += .01;
4334                 weapons[weaponids[0]].tipvelocity = velocity * scale;
4335                 weapons[weaponids[0]].missed = 1;
4336                 weapons[weaponids[0]].hitsomething = 0;
4337                 weapons[weaponids[0]].freetime = 0;
4338                 weapons[weaponids[0]].firstfree = 1;
4339                 weapons[weaponids[0]].physics = 1;
4340                 num_weapons--;
4341                 if (num_weapons) {
4342                     weaponids[0] = weaponids[num_weapons];
4343                     if (weaponstuck == num_weapons)
4344                         weaponstuck = 0;
4345                 }
4346                 weaponactive = -1;
4347                 for (i = 0; i < numplayers; i++) {
4348                     player[i].wentforweapon = 0;
4349                 }
4350
4351                 if (id == 0) {
4352                     flashamount = .5;
4353                     flashr = 1;
4354                     flashg = 0;
4355                     flashb = 0;
4356                     flashdelay = 0;
4357                 }
4358             }
4359
4360             if (!dead && creature == wolftype) {
4361                 award_bonus(0, Wolfbonus);
4362             }
4363             dead = 2;
4364             if (animTarget == knifefollowedanim && !skeleton.free) {
4365                 for (i = 0; i < skeleton.num_joints; i++) {
4366                     skeleton.joints[i].velocity = 0;
4367                     skeleton.joints[i].velocity.y = -2;
4368                 }
4369             }
4370             if (id != 0 && unconscioustime > .1) {
4371                 numafterkill++;
4372             }
4373
4374             RagDoll(0);
4375         }
4376     }
4377
4378     if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4379         texupdatedelay = .12;
4380
4381         bloodsize = 5 - realtexdetail;
4382
4383         startx = 0;
4384         starty = 0;
4385         startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4386         starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4387         endx = startx + bloodsize;
4388         endy = starty + bloodsize;
4389
4390         if (startx < 0) {
4391             startx = 0;
4392             bleeding = 0;
4393         }
4394         if (starty < 0) {
4395             starty = 0;
4396             bleeding = 0;
4397         }
4398         if (endx > skeleton.skinsize - 1) {
4399             endx = skeleton.skinsize - 1;
4400             bleeding = 0;
4401         }
4402         if (endy > skeleton.skinsize - 1) {
4403             endy = skeleton.skinsize - 1;
4404             bleeding = 0;
4405         }
4406         if (endx < startx)
4407             endx = startx;
4408         if (endy < starty)
4409             endy = starty;
4410
4411         for (i = startx; i < endx; i++) {
4412             for (j = starty; j < endy; j++) {
4413                 if (Random() % 2 == 0) {
4414                     color = Random() % 85 + 170;
4415                     if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4416                         skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4417                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4418                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4419                 }
4420             }
4421         }
4422         if (!osx && detail > 1) {
4423             skeleton.drawmodel.textureptr.bind();
4424             DoMipmaps();
4425         }
4426
4427         if (!skeleton.free) {
4428             bleedy -= 4 / realtexdetail;
4429             if (detail == 2)
4430                 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4431             else
4432                 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4433         }
4434         if (skeleton.free) {
4435             bleedx += 4 * direction / realtexdetail;
4436             if (detail == 2)
4437                 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4438             else
4439                 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4440         }
4441     }
4442
4443     if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4444         righthandmorphness = targetrighthandmorphness;
4445         righthandmorphstart = righthandmorphend;
4446     } else if (righthandmorphness > targetrighthandmorphness) {
4447         righthandmorphness -= multiplier * 4;
4448     } else if (righthandmorphness < targetrighthandmorphness) {
4449         righthandmorphness += multiplier * 4;
4450     }
4451
4452     if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4453         lefthandmorphness = targetlefthandmorphness;
4454         lefthandmorphstart = lefthandmorphend;
4455     } else if (lefthandmorphness > targetlefthandmorphness) {
4456         lefthandmorphness -= multiplier * 4;
4457     } else if (lefthandmorphness < targetlefthandmorphness) {
4458         lefthandmorphness += multiplier * 4;
4459     }
4460
4461     if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4462         if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4463             tailmorphness = targettailmorphness;
4464             tailmorphstart = tailmorphend;
4465         } else if (tailmorphness > targettailmorphness) {
4466             tailmorphness -= multiplier * 10;
4467         } else if (tailmorphness < targettailmorphness) {
4468             tailmorphness += multiplier * 10;
4469         }
4470     }
4471
4472     if (creature == wolftype) {
4473         if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4474             tailmorphness = targettailmorphness;
4475             tailmorphstart = tailmorphend;
4476         } else if (tailmorphness > targettailmorphness) {
4477             tailmorphness -= multiplier * 2;
4478         } else if (tailmorphness < targettailmorphness) {
4479             tailmorphness += multiplier * 2;
4480         }
4481     }
4482
4483     if (headmorphend == 3 || headmorphstart == 3) {
4484         if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4485             headmorphness = targetheadmorphness;
4486             headmorphstart = headmorphend;
4487         } else if (headmorphness > targetheadmorphness) {
4488             headmorphness -= multiplier * 7;
4489         } else if (headmorphness < targetheadmorphness) {
4490             headmorphness += multiplier * 7;
4491         }
4492     } else if (headmorphend == 5 || headmorphstart == 5) {
4493         if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4494             headmorphness = targetheadmorphness;
4495             headmorphstart = headmorphend;
4496         } else if (headmorphness > targetheadmorphness) {
4497             headmorphness -= multiplier * 10;
4498         } else if (headmorphness < targetheadmorphness) {
4499             headmorphness += multiplier * 10;
4500         }
4501     } else {
4502         if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4503             headmorphness = targetheadmorphness;
4504             headmorphstart = headmorphend;
4505         } else if (headmorphness > targetheadmorphness) {
4506             headmorphness -= multiplier * 4;
4507         } else if (headmorphness < targetheadmorphness) {
4508             headmorphness += multiplier * 4;
4509         }
4510     }
4511
4512     if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4513         chestmorphness = targetchestmorphness;
4514         chestmorphstart = chestmorphend;
4515     } else if (chestmorphness > targetchestmorphness) {
4516         chestmorphness -= multiplier;
4517     } else if (chestmorphness < targetchestmorphness) {
4518         chestmorphness += multiplier;
4519     }
4520
4521     if (dead != 2 && howactive <= typesleeping) {
4522         if (chestmorphstart == 0 && chestmorphend == 0) {
4523             chestmorphness = 0;
4524             targetchestmorphness = 1;
4525             chestmorphend = 3;
4526         }
4527         if (chestmorphstart != 0 && chestmorphend != 0) {
4528             chestmorphness = 0;
4529             targetchestmorphness = 1;
4530             chestmorphend = 0;
4531             if (environment == snowyenvironment) {
4532                 XYZ footpoint;
4533                 XYZ footvel;
4534                 if (!skeleton.free)
4535                     footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4536                 if (skeleton.free)
4537                     footvel = skeleton.specialforward[0] * -1;
4538                 if (!skeleton.free)
4539                     footpoint = DoRotation((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2, 0, yaw, 0) * scale + coords;
4540                 if (skeleton.free)
4541                     footpoint = ((skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2) * scale + coords;
4542                 if (animTarget == sleepanim)
4543                     footvel = DoRotation(footvel, 0, 90, 0);
4544                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4545             }
4546         }
4547
4548         if (!dead && howactive < typesleeping) {
4549             blinkdelay -= multiplier * 2;
4550             if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4551                 headmorphness = 0;
4552                 targetheadmorphness = 1;
4553                 headmorphend = 3;
4554                 blinkdelay = (float)(abs(Random() % 40)) / 5;
4555             }
4556             if (headmorphstart == 3 && headmorphend == 3) {
4557                 headmorphness = 0;
4558                 targetheadmorphness = 1;
4559                 headmorphend = 0;
4560             }
4561         }
4562         if (!dead) {
4563             twitchdelay -= multiplier * 1.5;
4564             if (animTarget != hurtidleanim) {
4565                 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4566                     headmorphness = 0;
4567                     targetheadmorphness = 1;
4568                     headmorphend = 5;
4569                     twitchdelay = (float)(abs(Random() % 40)) / 5;
4570                 }
4571                 if (headmorphstart == 5 && headmorphend == 5) {
4572                     headmorphness = 0;
4573                     targetheadmorphness = 1;
4574                     headmorphend = 0;
4575                 }
4576             }
4577             if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4578                 twitchdelay3 -= multiplier * 1;
4579                 if (Random() % 2 == 0) {
4580                     if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4581                         righthandmorphness = 0;
4582                         targetrighthandmorphness = 1;
4583                         righthandmorphend = 1;
4584                         if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4585                     }
4586                     if (righthandmorphstart == 1 && righthandmorphend == 1) {
4587                         righthandmorphness = 0;
4588                         targetrighthandmorphness = 1;
4589                         righthandmorphend = 0;
4590                     }
4591                 }
4592                 if (Random() % 2 == 0) {
4593                     if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4594                         lefthandmorphness = 0;
4595                         targetlefthandmorphness = 1;
4596                         lefthandmorphend = 1;
4597                         twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4598                     }
4599                     if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4600                         lefthandmorphness = 0;
4601                         targetlefthandmorphness = 1;
4602                         lefthandmorphend = 0;
4603                     }
4604                 }
4605             }
4606         }
4607         if (!dead) {
4608             if (creature == rabbittype) {
4609                 if (howactive < typesleeping)
4610                     twitchdelay2 -= multiplier * 1.5;
4611                 else
4612                     twitchdelay2 -= multiplier * 0.5;
4613                 if (howactive <= typesleeping) {
4614                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4615                         tailmorphness = 0;
4616                         targettailmorphness = 1;
4617                         tailmorphend = 1;
4618                         twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4619                     }
4620                     if (tailmorphstart == 1 && tailmorphend == 1) {
4621                         tailmorphness = 0;
4622                         targettailmorphness = 1;
4623                         tailmorphend = 2;
4624                     }
4625                     if (tailmorphstart == 2 && tailmorphend == 2) {
4626                         tailmorphness = 0;
4627                         targettailmorphness = 1;
4628                         tailmorphend = 0;
4629                     }
4630                 }
4631             }
4632         }
4633     }
4634     if (creature == wolftype) {
4635         twitchdelay2 -= multiplier * 1.5;
4636         if (tailmorphend != 0)
4637             if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4638                 tailmorphness = 0;
4639                 targettailmorphness = 1;
4640                 tailmorphend = 0;
4641                 twitchdelay2 = .1;
4642             }
4643         if (tailmorphend != 5)
4644             if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4645                 tailmorphness = 0;
4646                 targettailmorphness = 1;
4647                 tailmorphend = 5;
4648                 twitchdelay2 = .1;
4649             }
4650         if (twitchdelay2 <= 0) {
4651             if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4652                 tailmorphness = 0;
4653                 targettailmorphness = 1;
4654                 tailmorphend = 1;
4655             }
4656             if (tailmorphstart == 1 && tailmorphend == 1) {
4657                 tailmorphness = 0;
4658                 targettailmorphness = 1;
4659                 tailmorphend = 2;
4660             }
4661             if (tailmorphstart == 2 && tailmorphend == 2) {
4662                 tailmorphness = 0;
4663                 targettailmorphness = 1;
4664                 tailmorphend = 3;
4665             }
4666             if (tailmorphstart == 3 && tailmorphend == 3) {
4667                 tailmorphness = 0;
4668                 targettailmorphness = 1;
4669                 tailmorphend = 4;
4670             }
4671             if (tailmorphstart == 4 && tailmorphend == 4) {
4672                 tailmorphness = 0;
4673                 targettailmorphness = 1;
4674                 tailmorphend = 1;
4675             }
4676         }
4677     }
4678
4679     if (dead != 1)
4680         unconscioustime = 0;
4681
4682     if (dead == 1 || howactive == typesleeping) {
4683         unconscioustime += multiplier;
4684         //If unconscious, close eyes and mouth
4685         if (righthandmorphend != 0)
4686             righthandmorphness = 0;
4687         righthandmorphend = 0;
4688         targetrighthandmorphness = 1;
4689
4690         if (lefthandmorphend != 0)
4691             lefthandmorphness = 0;
4692         lefthandmorphend = 0;
4693         targetlefthandmorphness = 1;
4694
4695         if (headmorphend != 3 && headmorphend != 5)
4696             headmorphness = 0;
4697         headmorphend = 3;
4698         targetheadmorphness = 1;
4699     }
4700
4701
4702     if (howactive > typesleeping) {
4703         XYZ headpoint;
4704         headpoint = coords;
4705         if (bloodtoggle && !bled) {
4706             terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4707         }
4708         if (bloodtoggle && !bled)
4709             for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4710                 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4711                 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4712                 float size = .8;
4713                 float opacity = .6;
4714                 float yaw = 0;
4715                 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4716             }
4717         bled = 1;
4718     }
4719
4720     if (dead == 2 || howactive > typesleeping) {
4721         //If dead, open mouth and hands
4722         if (righthandmorphend != 0)
4723             righthandmorphness = 0;
4724         righthandmorphend = 0;
4725         targetrighthandmorphness = 1;
4726
4727         if (lefthandmorphend != 0)
4728             lefthandmorphness = 0;
4729         lefthandmorphend = 0;
4730         targetlefthandmorphness = 1;
4731
4732         if (headmorphend != 2)
4733             headmorphness = 0;
4734         headmorphend = 2;
4735         targetheadmorphness = 1;
4736     }
4737
4738     if (stunned > 0 && !dead && headmorphend != 2) {
4739         if (headmorphend != 4)
4740             headmorphness = 0;
4741         headmorphend = 4;
4742         targetheadmorphness = 1;
4743     }
4744
4745     if (damage > damagetolerance && !dead) {
4746
4747         dead = 1;
4748         unconscioustime = 0;
4749
4750         if (creature == wolftype) {
4751             award_bonus(0, Wolfbonus);
4752         }
4753
4754         RagDoll(0);
4755
4756         if (weaponactive != -1) {
4757             weapons[weaponids[0]].owner = -1;
4758             weapons[weaponids[0]].velocity = velocity * scale * -.3;
4759             weapons[weaponids[0]].velocity.x += .01;
4760             weapons[weaponids[0]].tipvelocity = velocity * scale;
4761             weapons[weaponids[0]].missed = 1;
4762             weapons[weaponids[0]].hitsomething = 0;
4763             weapons[weaponids[0]].freetime = 0;
4764             weapons[weaponids[0]].firstfree = 1;
4765             weapons[weaponids[0]].physics = 1;
4766             num_weapons--;
4767             if (num_weapons) {
4768                 weaponids[0] = weaponids[num_weapons];
4769                 if (weaponstuck == num_weapons)
4770                     weaponstuck = 0;
4771             }
4772             weaponactive = -1;
4773             for (i = 0; i < numplayers; i++) {
4774                 player[i].wentforweapon = 0;
4775             }
4776         }
4777
4778
4779
4780         if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4781             slomo = 1;
4782             slomodelay = .2;
4783         }
4784
4785         damage += 20;
4786     }
4787
4788     //if(dead)damage-=multiplier/4;
4789     if (!dead)
4790         damage -= multiplier * 13;
4791     //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
4792     if (!dead)
4793         permanentdamage -= multiplier * 4;
4794     if (isIdle() || isCrouch()) {
4795         if (!dead)
4796             permanentdamage -= multiplier * 4;
4797         //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
4798     }
4799     if (damage < 0)
4800         damage = 0;
4801     if (permanentdamage < 0)
4802         permanentdamage = 0;
4803     if (superpermanentdamage < 0)
4804         superpermanentdamage = 0;
4805     if (permanentdamage < superpermanentdamage) {
4806         permanentdamage = superpermanentdamage;
4807     }
4808     if (damage < permanentdamage) {
4809         damage = permanentdamage;
4810     }
4811     if (dead == 1 && damage < damagetolerance) {
4812         dead = 0;
4813         skeleton.free = 1;
4814         damage -= 20;
4815         for (i = 0; i < skeleton.num_joints; i++) {
4816             skeleton.joints[i].velocity = 0;
4817         }
4818     }
4819     if (permanentdamage > damagetolerance && dead != 2) {
4820         DoBlood(1, 255);
4821
4822         if (weaponactive != -1) {
4823             weapons[weaponids[0]].owner = -1;
4824             weapons[weaponids[0]].velocity = velocity * scale * -.3;
4825             weapons[weaponids[0]].velocity.x += .01;
4826             weapons[weaponids[0]].tipvelocity = velocity * scale;
4827             weapons[weaponids[0]].missed = 1;
4828             weapons[weaponids[0]].hitsomething = 0;
4829             weapons[weaponids[0]].freetime = 0;
4830             weapons[weaponids[0]].firstfree = 1;
4831             weapons[weaponids[0]].physics = 1;
4832             num_weapons--;
4833             if (num_weapons) {
4834                 weaponids[0] = weaponids[num_weapons];
4835                 if (weaponstuck == num_weapons)
4836                     weaponstuck = 0;
4837             }
4838             weaponactive = -1;
4839             for (i = 0; i < numplayers; i++) {
4840                 player[i].wentforweapon = 0;
4841             }
4842         }
4843
4844         bled = 0;
4845
4846         if (!dead && creature == wolftype) {
4847             award_bonus(0, Wolfbonus);
4848         }
4849
4850         if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4851             award_bonus(id, touchofdeath);
4852         if (id != 0 && unconscioustime > .1) {
4853             numafterkill++;
4854         }
4855
4856         dead = 2;
4857
4858         skeleton.free = 1;
4859
4860         emit_sound_at(breaksound, coords);
4861     }
4862
4863     if (skeleton.free == 1) {
4864         if (id == 0)
4865             pause_sound(whooshsound);
4866
4867         if (!dead) {
4868             //If knocked over, open hands and close mouth
4869             if (righthandmorphend != 0)
4870                 righthandmorphness = 0;
4871             righthandmorphend = 0;
4872             targetrighthandmorphness = 1;
4873
4874             if (lefthandmorphend != 0)
4875                 lefthandmorphness = 0;
4876             lefthandmorphend = 0;
4877             targetlefthandmorphness = 1;
4878
4879             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4880                 if (headmorphend != 0)
4881                     headmorphness = 0;
4882                 headmorphend = 0;
4883                 targetheadmorphness = 1;
4884             }
4885         }
4886
4887         skeleton.DoGravity(&scale);
4888         float damageamount;
4889         damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4890         if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4891             award_bonus(id, deepimpact);
4892         DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4893
4894         average = 0;
4895         howmany = 0;
4896         for (j = 0; j < skeleton.num_joints; j++) {
4897             average += skeleton.joints[j].position;
4898             howmany++;
4899         }
4900         average /= howmany;
4901         coords += average * scale;
4902         for (j = 0; j < skeleton.num_joints; j++) {
4903             skeleton.joints[j].position -= average;
4904         }
4905         average /= multiplier;
4906
4907         //velocity=skeleton.joints[skeleton.jointlabels[groin]].velocity*scale;
4908         velocity = 0;
4909         for (i = 0; i < skeleton.num_joints; i++) {
4910             velocity += skeleton.joints[i].velocity * scale;
4911         }
4912         velocity /= skeleton.num_joints;
4913
4914         if (!isnormal(velocity.x) && velocity.x) {
4915             velocity = 0;
4916         }
4917
4918         if (findLength(&average) < 10 && dead && skeleton.free) {
4919             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4920             if (skeleton.longdead > 2000) {
4921                 if (skeleton.longdead > 6000) {
4922                     if (id == 0)
4923                         pause_sound(whooshsound);
4924                     skeleton.free = 3;
4925                     DrawSkeleton();
4926                     skeleton.free = 2;
4927                 }
4928                 if (dead == 2 && bloodloss < damagetolerance) {
4929                     XYZ headpoint;
4930                     headpoint = (skeleton.joints[skeleton.jointlabels[head]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2 * scale + coords;
4931                     DoBlood(1, 255);
4932                     if (bloodtoggle && !bled) {
4933                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4934                     }
4935                     if (bloodtoggle && !bled)
4936                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4937                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4938                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4939                             float size = .2 * 1.2;
4940                             float opacity = .6;
4941                             float yaw = 0;
4942                             objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4943                         }
4944                     bled = 1;
4945                 }
4946                 if (dead == 2 && bloodloss >= damagetolerance) {
4947                     XYZ headpoint;
4948                     headpoint = (skeleton.joints[skeleton.jointlabels[abdomen]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2 * scale + coords;
4949                     if (bleeding <= 0)
4950                         DoBlood(1, 255);
4951                     if (bloodtoggle && !bled) {
4952                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4953                     }
4954                     if (bloodtoggle && !bled)
4955                         for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4956                             j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4957                             XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4958                             float size = .8;
4959                             float opacity = .6;
4960                             float yaw = 0;
4961                             objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4962                         }
4963                     bled = 1;
4964                 }
4965             }
4966         }
4967
4968         if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4969             bool canrecover = 1;
4970             XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4971             startpoint = coords;
4972             endpoint = coords;
4973             endpoint.y -= .7;
4974             if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4975                 canrecover = 0;
4976             if (velocity.y < -30)
4977                 canrecover = 0;
4978             for (i = 0; i < objects.numobjects; i++) {
4979                 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4980                     colviewer = startpoint;
4981                     coltarget = endpoint;
4982                     if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4983                         canrecover = 0;
4984                 }
4985             }
4986             if (canrecover) {
4987                 skeleton.free = 0;
4988                 XYZ middle;
4989                 middle = 0;
4990
4991                 terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
4992                 if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[abdomen]].locked) {
4993                     terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
4994                     middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
4995                 }
4996                 if (skeleton.joints[skeleton.jointlabels[abdomen]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
4997                     terrainnormal = skeleton.joints[skeleton.jointlabels[abdomen]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
4998                     middle = (skeleton.joints[skeleton.jointlabels[neck]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
4999                 }
5000                 if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
5001                     terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
5002                     middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2;
5003                 }
5004                 Normalise(&terrainnormal);
5005
5006                 targetyaw = -asin(0 - terrainnormal.x);
5007                 targetyaw *= 360 / 6.28;
5008                 if (terrainnormal.z < 0)
5009                     targetyaw = 180 - targetyaw;
5010                 yaw = targetyaw;
5011
5012                 frameTarget = 0;
5013                 //      frameTarget=2;
5014                 animTarget = flipanim;
5015                 crouchtogglekeydown = 1;
5016                 target = 0;
5017                 tilt2 = 0;
5018                 targettilt2 = 0;
5019
5020                 animCurrent = tempanim;
5021                 frameCurrent = 0;
5022                 target = 0;
5023                 //tilt2=targettilt2;
5024
5025                 //if(middle.y>0)targetoffset.y=middle.y+1;
5026
5027                 for (i = 0; i < skeleton.num_joints; i++) {
5028                     tempanimation.position[i][0] = skeleton.joints[i].position;
5029                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5030                 }
5031             }
5032         }
5033
5034         if (findLength(&average) < 10 && !dead && skeleton.free) {
5035             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5036             if (skeleton.longdead > (damage + 500) * 1.5) {
5037                 if (id == 0)
5038                     pause_sound(whooshsound);
5039                 skeleton.free = 0;
5040                 velocity = 0;
5041                 XYZ middle;
5042                 middle = 0;
5043
5044                 terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
5045                 if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[abdomen]].locked) {
5046                     terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[abdomen]].position;
5047                     middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
5048                 }
5049                 if (skeleton.joints[skeleton.jointlabels[abdomen]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
5050                     terrainnormal = skeleton.joints[skeleton.jointlabels[abdomen]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
5051                     middle = (skeleton.joints[skeleton.jointlabels[neck]].position + skeleton.joints[skeleton.jointlabels[abdomen]].position) / 2;
5052                 }
5053                 if (skeleton.joints[skeleton.jointlabels[groin]].locked && skeleton.joints[skeleton.jointlabels[neck]].locked) {
5054                     terrainnormal = skeleton.joints[skeleton.jointlabels[groin]].position - skeleton.joints[skeleton.jointlabels[neck]].position;
5055                     middle = (skeleton.joints[skeleton.jointlabels[groin]].position + skeleton.joints[skeleton.jointlabels[neck]].position) / 2;
5056                 }
5057                 Normalise(&terrainnormal);
5058
5059                 targetyaw = -asin(0 - terrainnormal.x);
5060                 targetyaw *= 360 / 6.28;
5061                 if (terrainnormal.z < 0)
5062                     targetyaw = 180 - targetyaw;
5063                 yaw = targetyaw;
5064
5065                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5066
5067
5068                 if (skeleton.forward.y < 0) {
5069                     animTarget = getupfrombackanim;
5070                     frameTarget = 0;
5071                     targettilt2 = 0;
5072                 }
5073                 if (skeleton.forward.y > -.3) {
5074                     animTarget = getupfromfrontanim;
5075                     yaw += 180;
5076                     targetyaw += 180;
5077                     targettilt2 *= -1;
5078                     frameTarget = 0;
5079                     targettilt2 = 0;
5080                 }
5081
5082                 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5083                     animTarget = rollanim;
5084                     targetyaw = lookyaw;
5085                     if (id == 0) {
5086                         if (rightkeydown) {
5087                             targetyaw -= 90;
5088                             if (forwardkeydown)
5089                                 targetyaw += 45;
5090                             if (backkeydown)
5091                                 targetyaw -= 45;
5092                         }
5093                         if (leftkeydown) {
5094                             targetyaw += 90;
5095                             if (forwardkeydown)
5096                                 targetyaw -= 45;
5097                             if (backkeydown)
5098                                 targetyaw += 45;
5099                         }
5100                         if (backkeydown) {
5101                             if ( !leftkeydown && !rightkeydown)
5102                                 targetyaw += 180;
5103                         }
5104                         targetyaw += 180;
5105                     }
5106                 }
5107
5108                 if (abs(targettilt2) > 50)
5109                     targettilt2 = 0;
5110                 animCurrent = tempanim;
5111                 frameCurrent = 0;
5112                 target = 0;
5113                 tilt2 = targettilt2;
5114
5115                 if (middle.y > 0 && animTarget != rollanim)
5116                     targetoffset.y = middle.y + 1;
5117
5118                 for (i = 0; i < skeleton.num_joints; i++) {
5119                     tempanimation.position[i][0] = skeleton.joints[i].position;
5120                     tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5121                 }
5122             }
5123         }
5124
5125         bool hasstaff;
5126         hasstaff = 0;
5127         if (num_weapons > 0)
5128             if (weapons[0].getType() == staff)
5129                 hasstaff = 1;
5130         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5131             if (velocity.y > -30) {
5132                 XYZ tempvelocity;
5133                 tempvelocity = velocity;
5134                 Normalise(&tempvelocity);
5135                 targetyaw = -asin(0 - tempvelocity.x);
5136                 targetyaw *= 360 / 6.28;
5137                 if (velocity.z < 0)
5138                     targetyaw = 180 - targetyaw;
5139                 //targetyaw+=180;
5140
5141                 skeleton.free = 0;
5142                 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5143                     animTarget = rollanim;
5144                     frameTarget = 2;
5145                 } else {
5146                     animTarget = backhandspringanim;
5147                     targetyaw += 180;
5148                     frameTarget = 6;
5149                 }
5150                 target = 0;
5151
5152                 emit_sound_at(movewhooshsound, coords, 128.);
5153
5154                 animCurrent = animTarget;
5155                 frameCurrent = frameTarget - 1;
5156                 target = 0;
5157
5158                 velocity = 0;
5159
5160                 yaw = targetyaw;
5161                 tilt = 0;
5162                 targettilt = 0;
5163                 tilt2 = 0;
5164                 targettilt2 = 0;
5165             }
5166         }
5167         if (skeleton.freefall == 0)
5168             freefall = 0;
5169
5170     }
5171
5172     if (aitype != passivetype || skeleton.free == 1)
5173         if (findLengthfast(&velocity) > .1)
5174             for (i = 0; i < objects.numobjects; i++) {
5175                 if (objects.type[i] == firetype)
5176                     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) {
5177                         if (onfire) {
5178                             if (!objects.onfire[i]) {
5179                                 emit_sound_at(firestartsound, objects.position[i]);
5180                             }
5181                             objects.onfire[i] = 1;
5182                         }
5183                         if (!onfire) {
5184                             if (objects.onfire[i]) {
5185                                 CatchFire();
5186                             }
5187                         }
5188                     }
5189                 if (objects.type[i] == bushtype)
5190                     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) {
5191                         if (onfire) {
5192                             if (!objects.onfire[i]) {
5193                                 emit_sound_at(firestartsound, objects.position[i]);
5194                             }
5195                             objects.onfire[i] = 1;
5196                         }
5197
5198                         if (!onfire) {
5199                             if (objects.onfire[i]) {
5200                                 CatchFire();
5201                             }
5202                         }
5203                         if (objects.messedwith[i] <= 0) {
5204                             XYZ tempvel;
5205                             XYZ pos;
5206
5207                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5208
5209                             if (id == 0) {
5210                                 envsound[numenvsounds] = coords;
5211                                 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5212                                 envsoundlife[numenvsounds] = .4;
5213                                 numenvsounds++;
5214                             }
5215
5216                             int howmany;
5217                             if (environment == grassyenvironment)
5218                                 howmany = findLength(&velocity) * 4;
5219                             if (environment == snowyenvironment)
5220                                 howmany = findLength(&velocity) * 2;
5221                             if (detail == 2)
5222                                 if (environment != desertenvironment)
5223                                     for (j = 0; j < howmany; j++) {
5224                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5225                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5226                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5227                                         pos = coords;
5228                                         pos.y += 1;
5229                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5230                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5231                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5232                                         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);
5233                                         Sprite::setLastSpriteSpecial(1);
5234                                     }
5235                             howmany = findLength(&velocity) * 4;
5236                             if (detail == 2)
5237                                 if (environment == snowyenvironment)
5238                                     for (j = 0; j < howmany; j++) {
5239                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5240                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5241                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5242                                         pos = coords;
5243                                         pos.y += 1;
5244                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5245                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5246                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5247                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5248                                         Sprite::setLastSpriteSpecial(2);
5249                                     }
5250                         }
5251                         objects.rotx[i] += velocity.x * multiplier * 6;
5252                         objects.roty[i] += velocity.z * multiplier * 6;
5253                         objects.messedwith[i] = .5;
5254                     }
5255                 XYZ tempcoord;
5256                 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5257                     if (objects.pitch[i] == 0)
5258                         tempcoord = coords;
5259                     else {
5260                         tempcoord = coords - objects.position[i];
5261                         tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5262                         tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5263                         tempcoord += objects.position[i];
5264                     }
5265                     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]) {
5266                         if (objects.messedwith[i] <= 0) {
5267                             XYZ tempvel;
5268                             XYZ pos;
5269
5270                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5271
5272                             if (id == 0) {
5273                                 envsound[numenvsounds] = coords;
5274                                 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5275                                 envsoundlife[numenvsounds] = .4;
5276                                 numenvsounds++;
5277                             }
5278
5279                             int howmany;
5280                             if (environment == grassyenvironment)
5281                                 howmany = findLength(&velocity) * 4;
5282                             if (environment == snowyenvironment)
5283                                 howmany = findLength(&velocity) * 2;
5284                             if (detail == 2)
5285                                 if (environment != desertenvironment)
5286                                     for (j = 0; j < howmany; j++) {
5287                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5288                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5289                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5290                                         pos = coords;
5291                                         pos += velocity * .1;
5292                                         pos.y += 1;
5293                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5294                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5295                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5296                                         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);
5297                                         Sprite::setLastSpriteSpecial(1);
5298                                     }
5299                             howmany = findLength(&velocity) * 4;
5300                             if (detail == 2)
5301                                 if (environment == snowyenvironment)
5302                                     for (j = 0; j < howmany; j++) {
5303                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5304                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5305                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5306                                         pos = coords;
5307                                         pos += velocity * .1;
5308                                         pos.y += 1;
5309                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5310                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5311                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5312                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5313                                         Sprite::setLastSpriteSpecial(2);
5314                                     }
5315                         }
5316                         objects.messedwith[i] = .5;
5317                     }
5318                 }
5319             }
5320
5321     if (!skeleton.free) {
5322         bool play;
5323         play = 0;
5324         if ((stunned > 0 || surprised > 0) && numplayers > 2 && aitype != passivetype)
5325             play = 1;
5326         if (hasvictim)
5327             if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5328                 play = 1;
5329         if (tutoriallevel == 1 && id != 0)
5330             play = 0;
5331         if (play && aitype != playercontrolled) {
5332             int whichsound = -1;
5333             i = abs(Random() % 4);
5334             if (speechdelay <= 0) {
5335                 if (creature == rabbittype) {
5336                     if (i == 0)
5337                         whichsound = rabbitchitter;
5338                     if (i == 1)
5339                         whichsound = rabbitchitter2;
5340                 }
5341                 if (creature == wolftype) {
5342                     if (i == 0)
5343                         whichsound = growlsound;
5344                     if (i == 1)
5345                         whichsound = growl2sound;
5346                 }
5347             }
5348             speechdelay = .3;
5349
5350             if (whichsound != -1) {
5351                 emit_sound_at(whichsound, coords);
5352             }
5353         }
5354
5355         if (animTarget == staggerbackhighanim)
5356             staggerdelay = 1;
5357         if (animTarget == staggerbackhardanim)
5358             staggerdelay = 1;
5359         staggerdelay -= multiplier;
5360         if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5361             hasvictim = 1;
5362         if (velocity.y < -30 && animTarget == jumpdownanim)
5363             RagDoll(0);
5364         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5365             animTarget = getIdle();
5366             frameTarget = 0;
5367             target = 0;
5368         }
5369         weaponmissdelay -= multiplier;
5370         highreversaldelay -= multiplier;
5371         lowreversaldelay -= multiplier;
5372         lastcollide -= multiplier;
5373         skiddelay -= multiplier;
5374         if (!isnormal(velocity.x) && velocity.x) {
5375             velocity = 0;
5376         }
5377         if (!isnormal(targettilt) && targettilt) {
5378             targettilt = 0;
5379         }
5380         if (!isnormal(targettilt2) && targettilt2) {
5381             targettilt2 = 0;
5382         }
5383         if (!isnormal(targetyaw) && targetyaw) {
5384             targetyaw = 0;
5385         }
5386
5387         if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5388             //open hands and close mouth
5389             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5390                 righthandmorphness = 0;
5391                 righthandmorphend = 0;
5392                 targetrighthandmorphness = 1;
5393             }
5394
5395             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5396                 lefthandmorphness = 0;
5397                 lefthandmorphend = 0;
5398                 targetlefthandmorphness = 1;
5399             }
5400
5401             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5402                 headmorphness = 0;
5403                 headmorphend = 0;
5404                 targetheadmorphness = 1;
5405             }
5406         }
5407
5408         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) {
5409             //open hands and mouth
5410             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5411                 righthandmorphness = 0;
5412                 righthandmorphend = 0;
5413                 targetrighthandmorphness = 1;
5414             }
5415
5416             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5417                 lefthandmorphness = 0;
5418                 lefthandmorphend = 0;
5419                 targetlefthandmorphness = 1;
5420             }
5421
5422             if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5423                 headmorphness = 0;
5424                 headmorphend = 1;
5425                 targetheadmorphness = 1;
5426             }
5427         }
5428
5429         if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim || animTarget == blockhighleftanim) {
5430             //close hands and mouth
5431             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5432                 righthandmorphness = 0;
5433                 righthandmorphend = 1;
5434                 targetrighthandmorphness = 1;
5435             }
5436
5437             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5438                 lefthandmorphness = 0;
5439                 lefthandmorphend = 1;
5440                 targetlefthandmorphness = 1;
5441             }
5442
5443             if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5444                 headmorphness = 0;
5445                 headmorphend = 0;
5446                 targetheadmorphness = 1;
5447             }
5448         }
5449
5450         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) {
5451             //close hands and yell
5452             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5453                 righthandmorphness = 0;
5454                 righthandmorphend = 1;
5455                 targetrighthandmorphness = 1;
5456             }
5457
5458             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5459                 lefthandmorphness = 0;
5460                 lefthandmorphend = 1;
5461                 targetlefthandmorphness = 1;
5462             }
5463
5464             if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5465                 headmorphness = 1;
5466                 headmorphend = 2;
5467                 targetheadmorphness = 1;
5468             }
5469         }
5470
5471         bool behind;
5472         behind = 0;
5473         if (hasvictim) {
5474             if (victim != this && !victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < numplayers && aitype != passivetype) {
5475                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5476             }
5477         }
5478
5479         if (!dead && animTarget != hurtidleanim)
5480             if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5481                 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5482                     headmorphend = 4;
5483                     //headmorphness=1;
5484                     targetheadmorphness = 1;
5485                 }
5486             }
5487
5488         if (weaponactive != -1) {
5489             if (weapons[weaponids[weaponactive]].getType() != staff) {
5490                 righthandmorphstart = 1;
5491                 righthandmorphend = 1;
5492             }
5493             if (weapons[weaponids[weaponactive]].getType() == staff) {
5494                 righthandmorphstart = 2;
5495                 righthandmorphend = 2;
5496             }
5497             targetrighthandmorphness = 1;
5498         }
5499
5500         terrainnormal = terrain.getNormal(coords.x, coords.z);
5501
5502         if (animation[animTarget].attack != reversal) {
5503             if (!isnormal(coords.x))
5504                 coords = oldcoords;
5505             oldcoords = coords;
5506         }
5507
5508         flatfacing = 0;
5509         flatfacing.z = 1;
5510
5511         flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5512         facing = flatfacing;
5513         ReflectVector(&facing, terrainnormal);
5514         Normalise(&facing);
5515
5516         if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5517             if (onterrain)
5518                 targettilt2 = -facing.y * 20;
5519             else
5520                 targettilt2 = 0;
5521         }
5522         onterrain = 0;
5523         if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5524             targettilt2 = 0;
5525         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5526             flatvelocity = velocity;
5527             flatvelocity.y = 0;
5528             flatvelspeed = findLength(&flatvelocity);
5529             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5530             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5531             if (velocity.y < 0)
5532                 targettilt2 *= -1;
5533             if (velocity.y < 0)
5534                 targettilt *= -1;
5535             if (targettilt > 25)
5536                 targettilt = 25;
5537             if (targettilt < -25)
5538                 targettilt = -25;
5539         }
5540
5541         if (targettilt2 > 45)
5542             targettilt2 = 45;
5543         if (targettilt2 < -45)
5544             targettilt2 = -45;
5545         if (abs(tilt2 - targettilt2) < multiplier * 400)
5546             tilt2 = targettilt2;
5547         else if (tilt2 > targettilt2) {
5548             tilt2 -= multiplier * 400;
5549         } else if (tilt2 < targettilt2) {
5550             tilt2 += multiplier * 400;
5551         }
5552         if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5553             if (tilt2 > 25)
5554                 tilt2 = 25;
5555             if (tilt2 < -25)
5556                 tilt2 = -25;
5557         }
5558
5559         if (!isnormal(targettilt) && targettilt) {
5560             targettilt = 0;
5561         }
5562         if (!isnormal(targettilt2) && targettilt2) {
5563             targettilt2 = 0;
5564         }
5565
5566         //Running velocity
5567         //if(!creature==wolftype||animTarget==rabbitkickanim)
5568         if (animTarget == rabbittackleanim) {
5569             velocity += facing * multiplier * speed * 700 * scale;
5570             velspeed = findLength(&velocity);
5571             if (velspeed > speed * 65 * scale) {
5572                 velocity /= velspeed;
5573                 velspeed = speed * 65 * scale;
5574                 velocity *= velspeed;
5575             }
5576             velocity.y += gravity * multiplier * 20;
5577             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5578             velspeed = findLength(&velocity);
5579             velocity = flatfacing * velspeed;
5580         }
5581         if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5582             if (isRun() || animTarget == rabbitkickanim) {
5583                 velocity += facing * multiplier * speed * 700 * scale;
5584                 velspeed = findLength(&velocity);
5585                 if (velspeed > speed * 45 * scale) {
5586                     velocity /= velspeed;
5587                     velspeed = speed * 45 * scale;
5588                     velocity *= velspeed;
5589                 }
5590                 velocity.y += gravity * multiplier * 20;
5591                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5592                 velspeed = findLength(&velocity);
5593                 if (velspeed < speed * 30 * scale)
5594                     velspeed = speed * 30 * scale;
5595                 velocity = flatfacing * velspeed;
5596             }
5597         } else if (isRun()) {
5598             velocity += facing * multiplier * speed * 700 * scale;
5599             velspeed = findLength(&velocity);
5600             if (creature == rabbittype) {
5601                 if (velspeed > speed * 55 * scale) {
5602                     velocity /= velspeed;
5603                     velspeed = speed * 55 * scale;
5604                     velocity *= velspeed;
5605                 }
5606             }
5607             if (creature == wolftype) {
5608                 if (velspeed > speed * 75 * scale) {
5609                     velocity /= velspeed;
5610                     velspeed = speed * 75 * scale;
5611                     velocity *= velspeed;
5612                 }
5613             }
5614             velocity.y += gravity * multiplier * 20;
5615             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5616             velspeed = findLength(&velocity);
5617             velocity = flatfacing * velspeed;
5618         }
5619
5620         if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5621             velocity += facing * multiplier * speed * 700 * scale;
5622             velspeed = findLength(&velocity);
5623             if (velspeed > speed * 45 * scale) {
5624                 velocity /= velspeed;
5625                 velspeed = speed * 45 * scale;
5626                 velocity *= velspeed;
5627             }
5628             velocity.y += gravity * multiplier * 20;
5629             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5630             velspeed = findLength(&velocity);
5631             velocity = flatfacing * velspeed;
5632         }
5633
5634
5635         /*if(animCurrent==rollanim&&(isCrouch()||isIdle())){
5636         velocity+=facing*multiplier*speed*700*scale;
5637         velspeed=findLength(&velocity);
5638         if(velspeed>speed*25*scale){
5639         velocity/=velspeed;
5640         velspeed=speed*25*scale;
5641         velocity*=velspeed;
5642         }
5643         velocity.y+=gravity*multiplier*20;
5644         ReflectVector(&velocity,terrain.getNormal(coords.x,coords.z));
5645         velspeed=findLength(&velocity);
5646         velocity=flatfacing*velspeed;
5647         }*/
5648
5649         if (animTarget == sneakanim || animTarget == walkanim) {
5650             velocity += facing * multiplier * speed * 700 * scale;
5651             velspeed = findLength(&velocity);
5652             if (velspeed > speed * 12 * scale) {
5653                 velocity /= velspeed;
5654                 velspeed = speed * 12 * scale;
5655                 velocity *= velspeed;
5656             }
5657             velocity.y += gravity * multiplier * 20;
5658             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5659             velspeed = findLength(&velocity);
5660             velocity = flatfacing * velspeed;
5661         }
5662
5663         if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5664             velocity += facing * multiplier * speed * 700 * scale;
5665             velspeed = findLength(&velocity);
5666             if (velspeed > speed * 2 * scale) {
5667                 velocity /= velspeed;
5668                 velspeed = speed * 2 * scale;
5669                 velocity *= velspeed;
5670             }
5671             velocity.y += gravity * multiplier * 20;
5672             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5673             velspeed = findLength(&velocity);
5674             velocity = flatfacing * velspeed;
5675         }
5676
5677
5678         if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5679             velocity -= facing * multiplier * speed * 700 * scale;
5680             velspeed = findLength(&velocity);
5681             if (velspeed > speed * 2 * scale) {
5682                 velocity /= velspeed;
5683                 velspeed = speed * 2 * scale;
5684                 velocity *= velspeed;
5685             }
5686             velocity.y += gravity * multiplier * 20;
5687             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5688             velspeed = findLength(&velocity);
5689             velocity = flatfacing * velspeed * -1;
5690         }
5691
5692         if (animTarget == fightsidestep) {
5693             velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5694             velspeed = findLength(&velocity);
5695             if (velspeed > speed * 12 * scale) {
5696                 velocity /= velspeed;
5697                 velspeed = speed * 12 * scale;
5698                 velocity *= velspeed;
5699             }
5700             velocity.y += gravity * multiplier * 20;
5701             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5702             velspeed = findLength(&velocity);
5703             velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5704         }
5705
5706         if (animTarget == staggerbackhighanim) {
5707             coords -= facing * multiplier * speed * 16 * scale;
5708             velocity = 0;
5709         }
5710         if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5711             coords -= facing * multiplier * speed * 20 * scale;
5712             velocity = 0;
5713         }
5714
5715         if (animTarget == backhandspringanim) {
5716             //coords-=facing*multiplier*50*scale;
5717             velocity += facing * multiplier * speed * 700 * scale * -1;
5718             velspeed = findLength(&velocity);
5719             if (velspeed > speed * 50 * scale) {
5720                 velocity /= velspeed;
5721                 velspeed = speed * 50 * scale;
5722                 velocity *= velspeed;
5723             }
5724             velocity.y += gravity * multiplier * 20;
5725             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5726             velspeed = findLength(&velocity);
5727             velocity = flatfacing * velspeed * -1;
5728         }
5729         if (animTarget == dodgebackanim) {
5730             //coords-=facing*multiplier*50*scale;
5731             velocity += facing * multiplier * speed * 700 * scale * -1;
5732             velspeed = findLength(&velocity);
5733             if (velspeed > speed * 60 * scale) {
5734                 velocity /= velspeed;
5735                 velspeed = speed * 60 * scale;
5736                 velocity *= velspeed;
5737             }
5738             velocity.y += gravity * multiplier * 20;
5739             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5740             velspeed = findLength(&velocity);
5741             velocity = flatfacing * velspeed * -1;
5742         }
5743
5744         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5745             velspeed = findLength(&velocity);
5746         }
5747
5748
5749         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5750             velocity.y += gravity * multiplier;
5751         }
5752
5753         if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5754             coords += velocity * multiplier;
5755
5756         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5757             if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5758                 RagDoll(0);
5759
5760             if (animTarget == jumpupanim) {
5761                 jumppower = -4;
5762                 animTarget = getIdle();
5763             }
5764             target = 0;
5765             frameTarget = 0;
5766             onterrain = 1;
5767
5768             if (id == 0) {
5769                 pause_sound(whooshsound);
5770                 OPENAL_SetVolume(channels[whooshsound], 0);
5771             }
5772
5773             if (animTarget == jumpdownanim || isFlip()) {
5774                 if (isFlip())jumppower = -4;
5775                 animTarget = getLanding();
5776                 emit_sound_at(landsound, coords, 128.);
5777
5778                 if (id == 0) {
5779                     envsound[numenvsounds] = coords;
5780                     envsoundvol[numenvsounds] = 16;
5781                     envsoundlife[numenvsounds] = .4;
5782                     numenvsounds++;
5783                 }
5784             }
5785         }
5786
5787         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5788             coords.y += gravity * multiplier * 2;
5789         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5790             coords.y = terrain.getHeight(coords.x, coords.z);
5791             onterrain = 1;
5792         }
5793
5794
5795         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)) {
5796             velspeed = findLength(&velocity);
5797             velocity.y = 0;
5798             if (velspeed < multiplier * 300 * scale) {
5799                 velocity = 0;
5800             } else
5801                 velocity -= velocity / velspeed * multiplier * 300 * scale;
5802             if (velspeed > 5 && (isLanding() || isLandhard())) {
5803                 skiddingdelay += multiplier;
5804                 if (skiddelay <= 0) {
5805                     FootLand(0, .5);
5806                     FootLand(1, .5);
5807                     skiddelay = .02;
5808                 }
5809             } else
5810                 skiddingdelay = 0;
5811         }
5812
5813         if (isLandhard()) {
5814             velspeed = findLength(&velocity);
5815             velocity.y = 0;
5816             if (velspeed < multiplier * 600 * scale) {
5817                 velocity = 0;
5818             } else
5819                 velocity -= velocity / velspeed * multiplier * 600 * scale;
5820             velocity = 0;
5821             if (velspeed > 5 && (isLanding() || isLandhard())) {
5822                 skiddingdelay += multiplier;
5823                 if (skiddelay <= 0) {
5824                     FootLand(0, .5);
5825                     FootLand(1, .5);
5826                     skiddelay = .02;
5827                 }
5828             } else
5829                 skiddingdelay = 0;
5830         }
5831
5832         if (skiddingdelay < 0)
5833             skiddingdelay += multiplier;
5834         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5835             skiddingdelay = -1;
5836             if (!onterrain || environment == grassyenvironment) {
5837                 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5838             } else {
5839                 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5840             }
5841         }
5842
5843         if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5844             terrainnormal = victim->coords - coords;
5845             Normalise(&terrainnormal);
5846             targetyaw = -asin(0 - terrainnormal.x);
5847             targetyaw *= 360 / 6.28;
5848             if (terrainnormal.z < 0)
5849                 targetyaw = 180 - targetyaw;
5850             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5851         }
5852
5853         if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5854             targetyaw = victim->targetyaw;
5855         }
5856         if (animTarget == rabbittacklinganim) {
5857             coords = victim->coords;
5858         }
5859     }
5860     skeleton.oldfree = skeleton.free;
5861
5862     XYZ midterrain;
5863     midterrain = 0;
5864     midterrain.x = terrain.size * terrain.scale / 2;
5865     midterrain.z = terrain.size * terrain.scale / 2;
5866     if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5867         XYZ tempposit;
5868         tempposit = coords - midterrain;
5869         tempposit.y = 0;
5870         Normalise(&tempposit);
5871         tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5872         coords.x = tempposit.x + midterrain.x;
5873         coords.z = tempposit.z + midterrain.z;
5874     }
5875 }
5876
5877 /* EFFECT
5878  * MONSTER
5879  * TODO: ???
5880  */
5881 int Person::DrawSkeleton()
5882 {
5883     int oldplayerdetail;
5884     if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5885         if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5886             calcrot = 1;
5887         }
5888
5889         if (headless) {
5890             headmorphness = 0;
5891             headmorphstart = 6;
5892             headmorphend = 6;
5893         }
5894
5895         glAlphaFunc(GL_GREATER, 0.0001);
5896         XYZ terrainlight;
5897         float terrainheight;
5898         float distance;
5899         if (!isnormal(yaw))
5900             yaw = 0;
5901         if (!isnormal(tilt))
5902             tilt = 0;
5903         if (!isnormal(tilt2))
5904             tilt2 = 0;
5905         oldplayerdetail = playerdetail;
5906         playerdetail = 0;
5907         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5908             playerdetail = 1;
5909         }
5910         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5911             playerdetail = 1;
5912         }
5913         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5914             playerdetail = 1;
5915         }
5916         if (id == 0)
5917             playerdetail = 1;
5918         if (playerdetail != oldplayerdetail) {
5919             updatedelay = 0;
5920             normalsupdatedelay = 0;
5921         }
5922         static float updatedelaychange;
5923         static float morphness;
5924         static float framemult;
5925         if (calcrot) {
5926             skeleton.FindForwards();
5927             if (howactive == typesittingwall) {
5928                 skeleton.specialforward[1] = 0;
5929                 skeleton.specialforward[1].z = 1;
5930             }
5931         }
5932         static XYZ mid;
5933         static float M[16];
5934         static int i, j, k;
5935         static int weaponattachmuscle;
5936         static int weaponrotatemuscle;
5937         static XYZ weaponpoint;
5938         static int start, endthing;
5939         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5940             if (!isSleeping() && !isSitting()) {
5941                 if (onterrain && ((isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
5942                     XYZ point, newpoint, change, change2;
5943                     point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
5944                     heightleft = terrain.getHeight(point.x, point.z) + .04;
5945                     point.y = heightleft;
5946                     change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5947                     change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5948                     skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
5949                     skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
5950                     skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
5951
5952                     point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
5953                     heightright = terrain.getHeight(point.x, point.z) + .04;
5954                     point.y = heightright;
5955                     change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5956                     change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5957                     skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
5958                     skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
5959                     skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
5960                     skeleton.DoConstraints(&coords, &scale);
5961
5962                     if (creature == wolftype) {
5963                         point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
5964                         heightleft = terrain.getHeight(point.x, point.z) + .04;
5965                         point.y = heightleft;
5966                         change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5967                         change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5968                         skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
5969                         skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
5970                         skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
5971
5972                         point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
5973                         heightright = terrain.getHeight(point.x, point.z) + .04;
5974                         point.y = heightright;
5975                         change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5976                         change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5977                         skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0);
5978                         skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
5979                         skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
5980                         skeleton.DoConstraints(&coords, &scale);
5981                     }
5982                 }
5983                 if (onterrain && ((isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && !(wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
5984                     XYZ point, newpoint, change, change2;
5985                     point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
5986                     heightleft = terrain.getHeight(point.x, point.z) + .04;
5987                     point.y = heightleft;
5988                     change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5989                     change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
5990                     skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[leftfoot]].position * (1 - target);
5991                     skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
5992                     skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
5993
5994                     point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
5995                     heightright = terrain.getHeight(point.x, point.z) + .04;
5996                     point.y = heightright;
5997                     change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5998                     change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
5999                     skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[rightfoot]].position * (1 - target);
6000                     skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
6001                     skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
6002                     skeleton.DoConstraints(&coords, &scale);
6003
6004                     if (creature == wolftype) {
6005                         point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
6006                         heightleft = terrain.getHeight(point.x, point.z) + .04;
6007                         point.y = heightleft;
6008                         change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6009                         change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6010                         skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[leftfoot]].position * (1 - target);
6011                         skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
6012                         skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
6013
6014                         point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
6015                         heightright = terrain.getHeight(point.x, point.z) + .04;
6016                         point.y = heightright;
6017                         change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6018                         change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6019                         skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * target + skeleton.joints[skeleton.jointlabels[rightfoot]].position * (1 - target);
6020                         skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
6021                         skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
6022                         skeleton.DoConstraints(&coords, &scale);
6023                     }
6024                 }
6025
6026                 if (onterrain && (!(isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim) && (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim)) && !skeleton.free) {
6027                     XYZ point, newpoint, change, change2;
6028                     point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
6029                     heightleft = terrain.getHeight(point.x, point.z) + .04;
6030                     point.y = heightleft;
6031                     change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6032                     change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6033                     skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[leftfoot]].position * target;
6034                     skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
6035                     skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
6036
6037                     point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
6038                     heightright = terrain.getHeight(point.x, point.z) + .04;
6039                     point.y = heightright;
6040                     change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6041                     change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6042                     skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[rightfoot]].position * target;
6043                     skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
6044                     skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
6045                     skeleton.DoConstraints(&coords, &scale);
6046
6047                     if (creature == wolftype) {
6048                         point = DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position, 0, yaw, 0) * scale + coords;
6049                         heightleft = terrain.getHeight(point.x, point.z) + .04;
6050                         point.y = heightleft;
6051                         change = skeleton.joints[skeleton.jointlabels[leftankle]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6052                         change2 = skeleton.joints[skeleton.jointlabels[leftknee]].position - skeleton.joints[skeleton.jointlabels[leftfoot]].position;
6053                         skeleton.joints[skeleton.jointlabels[leftfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[leftfoot]].position * target;
6054                         skeleton.joints[skeleton.jointlabels[leftankle]].position = skeleton.joints[skeleton.jointlabels[leftfoot]].position + change;
6055                         skeleton.joints[skeleton.jointlabels[leftknee]].position = (skeleton.joints[skeleton.jointlabels[leftfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[leftknee]].position) / 2;
6056
6057                         point = DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position, 0, yaw, 0) * scale + coords;
6058                         heightright = terrain.getHeight(point.x, point.z) + .04;
6059                         point.y = heightright;
6060                         change = skeleton.joints[skeleton.jointlabels[rightankle]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6061                         change2 = skeleton.joints[skeleton.jointlabels[rightknee]].position - skeleton.joints[skeleton.jointlabels[rightfoot]].position;
6062                         skeleton.joints[skeleton.jointlabels[rightfoot]].position = DoRotation((point - coords) / scale, 0, -yaw, 0) * (1 - target) + skeleton.joints[skeleton.jointlabels[rightfoot]].position * target;
6063                         skeleton.joints[skeleton.jointlabels[rightankle]].position = skeleton.joints[skeleton.jointlabels[rightfoot]].position + change;
6064                         skeleton.joints[skeleton.jointlabels[rightknee]].position = (skeleton.joints[skeleton.jointlabels[rightfoot]].position + change2) / 2 + (skeleton.joints[skeleton.jointlabels[rightknee]].position) / 2;
6065                         skeleton.DoConstraints(&coords, &scale);
6066                     }
6067                 }
6068             }
6069             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()))
6070                 DoHead();
6071             else {
6072                 targetheadyaw = -targetyaw;
6073                 targetheadpitch = 0;
6074                 if (animation[animTarget].attack == 3)
6075                     targetheadyaw += 180;
6076             }
6077             for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6078                 skeleton.drawmodel.vertex[i] = 0;
6079                 skeleton.drawmodel.vertex[i].y = 999;
6080             }
6081             for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6082                 skeleton.drawmodellow.vertex[i] = 0;
6083                 skeleton.drawmodellow.vertex[i].y = 999;
6084             }
6085             for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6086                 skeleton.drawmodelclothes.vertex[i] = 0;
6087                 skeleton.drawmodelclothes.vertex[i].y = 999;
6088             }
6089             for (i = 0; i < skeleton.num_muscles; i++) {
6090                 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6091                     morphness = 0;
6092                     start = 0;
6093                     endthing = 0;
6094                     if (skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent2->label == righthand) {
6095                         morphness = righthandmorphness;
6096                         start = righthandmorphstart;
6097                         endthing = righthandmorphend;
6098                     }
6099                     if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent2->label == lefthand) {
6100                         morphness = lefthandmorphness;
6101                         start = lefthandmorphstart;
6102                         endthing = lefthandmorphend;
6103                     }
6104                     if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head) {
6105                         morphness = headmorphness;
6106                         start = headmorphstart;
6107                         endthing = headmorphend;
6108                     }
6109                     if ((skeleton.muscles[i].parent1->label == neck && skeleton.muscles[i].parent2->label == abdomen) || (skeleton.muscles[i].parent2->label == neck && skeleton.muscles[i].parent1->label == abdomen)) {
6110                         morphness = chestmorphness;
6111                         start = chestmorphstart;
6112                         endthing = chestmorphend;
6113                     }
6114                     if ((skeleton.muscles[i].parent1->label == groin && skeleton.muscles[i].parent2->label == abdomen) || (skeleton.muscles[i].parent2->label == groin && skeleton.muscles[i].parent1->label == abdomen)) {
6115                         morphness = tailmorphness;
6116                         start = tailmorphstart;
6117                         endthing = tailmorphend;
6118                     }
6119                     if (calcrot)
6120                         skeleton.FindRotationMuscle(i, animTarget);
6121                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6122                     glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
6123                     glPushMatrix();
6124                     glLoadIdentity();
6125                     if (!skeleton.free)
6126                         glRotatef(tilt2, 1, 0, 0);
6127                     if (!skeleton.free)
6128                         glRotatef(tilt, 0, 0, 1);
6129
6130
6131                     glTranslatef(mid.x, mid.y, mid.z);
6132
6133                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6134                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6135
6136                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6137                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6138
6139                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6140                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6141
6142                     if (playerdetail || skeleton.free == 3) {
6143                         for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6144                             glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
6145                             glPushMatrix();
6146                             if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
6147                                 glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionbody.x,
6148                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionbody.y,
6149                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionbody.z);
6150                             if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
6151                                 glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionarms.x,
6152                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionarms.y,
6153                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionarms.z);
6154                             if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
6155                                 glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionlegs.x,
6156                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionlegs.y,
6157                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionlegs.z);
6158                             if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
6159                                 glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x * morphness)*proportionhead.x,
6160                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y * morphness)*proportionhead.y,
6161                                              (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z * (1 - morphness) + skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z * morphness)*proportionhead.z);
6162                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6163                             //if(!isnormal(M[12])||!isnormal(M[13])||!isnormal(M[14]))test=0;
6164                             //if(!isnormal(scale))test=1;
6165                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6166                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6167                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6168                             //test=2;
6169                             glPopMatrix();
6170                         }
6171                     }
6172                     if (!playerdetail || skeleton.free == 3) {
6173                         for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6174                             glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
6175                             glPushMatrix();
6176                             if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
6177                                 glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionbody.x,
6178                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionbody.y,
6179                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionbody.z);
6180                             if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
6181                                 glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionarms.x,
6182                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionarms.y,
6183                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionarms.z);
6184                             if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
6185                                 glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionlegs.x,
6186                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionlegs.y,
6187                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionlegs.z);
6188                             if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
6189                                 glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionhead.x,
6190                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionhead.y,
6191                                              (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionhead.z);
6192
6193                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6194                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6195                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6196                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6197                             glPopMatrix();
6198                         }
6199                     }
6200                     glPopMatrix();
6201                 }
6202                 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6203                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6204
6205                     glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
6206                     glPushMatrix();
6207                     glLoadIdentity();
6208                     if (!skeleton.free)
6209                         glRotatef(tilt2, 1, 0, 0);
6210                     if (!skeleton.free)
6211                         glRotatef(tilt, 0, 0, 1);
6212                     glTranslatef(mid.x, mid.y, mid.z);
6213                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6214                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6215
6216                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6217                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6218
6219                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6220                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6221
6222                     for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6223                         glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
6224                         glPushMatrix();
6225                         if (skeleton.muscles[i].parent1->label == abdomen || skeleton.muscles[i].parent2->label == abdomen)
6226                             glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionbody.x,
6227                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionbody.y,
6228                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionbody.z);
6229                         if (skeleton.muscles[i].parent1->label == lefthand || skeleton.muscles[i].parent1->label == righthand || skeleton.muscles[i].parent1->label == leftwrist || skeleton.muscles[i].parent1->label == rightwrist || skeleton.muscles[i].parent1->label == leftelbow || skeleton.muscles[i].parent1->label == rightelbow || skeleton.muscles[i].parent2->label == leftelbow || skeleton.muscles[i].parent2->label == rightelbow)
6230                             glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionarms.x,
6231                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionarms.y,
6232                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionarms.z);
6233                         if (skeleton.muscles[i].parent1->label == leftfoot || skeleton.muscles[i].parent1->label == rightfoot || skeleton.muscles[i].parent1->label == leftankle || skeleton.muscles[i].parent1->label == rightankle || skeleton.muscles[i].parent1->label == leftknee || skeleton.muscles[i].parent1->label == rightknee || skeleton.muscles[i].parent2->label == leftknee || skeleton.muscles[i].parent2->label == rightknee)
6234                             glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionlegs.x,
6235                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionlegs.y,
6236                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionlegs.z);
6237                         if (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)
6238                             glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionhead.x,
6239                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionhead.y,
6240                                          (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionhead.z);
6241                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
6242                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6243                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6244                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6245                         glPopMatrix();
6246                     }
6247                     glPopMatrix();
6248                 }
6249                 updatedelay = 1 + (float)(Random() % 100) / 1000;
6250             }
6251             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6252                 normalsupdatedelay = 1;
6253                 if (playerdetail || skeleton.free == 3)
6254                     skeleton.drawmodel.CalculateNormals(0);
6255                 if (!playerdetail || skeleton.free == 3)
6256                     skeleton.drawmodellow.CalculateNormals(0);
6257                 if (skeleton.clothes)
6258                     skeleton.drawmodelclothes.CalculateNormals(0);
6259             } else {
6260                 if (playerdetail || skeleton.free == 3)
6261                     skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6262                 if (!playerdetail || skeleton.free == 3)
6263                     skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6264                 if (skeleton.clothes) {
6265                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6266                 }
6267             }
6268         }
6269         framemult = .01;
6270         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6271         if (updatedelaychange > -realmultiplier * 30)
6272             updatedelaychange = -realmultiplier * 30;
6273         if (updatedelaychange > -framemult * 4)
6274             updatedelaychange = -framemult * 4;
6275         if (skeleton.free == 1)
6276             updatedelaychange *= 6;
6277         if (id == 0)
6278             updatedelaychange *= 8;
6279         updatedelay += updatedelaychange;
6280
6281         glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
6282         glPushMatrix();
6283         if (!skeleton.free)
6284             glTranslatef(coords.x, coords.y - .02, coords.z);
6285         if (skeleton.free)
6286             glTranslatef(coords.x, coords.y - .02, coords.z);
6287         if (!skeleton.free)
6288             glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6289         if (!skeleton.free)
6290             glRotatef(yaw, 0, 1, 0);
6291         if (showpoints) {
6292             glPointSize(5);
6293             glColor4f(.4, 1, .4, 1);
6294             glDisable(GL_LIGHTING);
6295             glDisable(GL_TEXTURE_2D);
6296             glBegin(GL_POINTS);
6297             if (playerdetail)
6298                 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6299                     glVertex3f(skeleton.drawmodel.vertex[i].x, skeleton.drawmodel.vertex[i].y, skeleton.drawmodel.vertex[i].z);
6300                 }
6301             glEnd();
6302             glBegin(GL_LINES);
6303
6304             if (playerdetail)
6305                 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6306                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
6307                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
6308                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
6309                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
6310                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
6311                     glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y, skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
6312                 }
6313
6314             glEnd();
6315         }
6316
6317         terrainlight = terrain.getLighting(coords.x, coords.z);
6318         distance = distsq(&viewer, &coords);
6319         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6320         if (distance > 1)
6321             distance = 1;
6322         if (distance > 0) {
6323             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6324             if (terrainheight < 1)
6325                 terrainheight = 1;
6326             if (terrainheight > 1.7)
6327                 terrainheight = 1.7;
6328
6329             //burnt=0;
6330             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6331             glDisable(GL_BLEND);
6332             glAlphaFunc(GL_GREATER, 0.0001);
6333             glEnable(GL_TEXTURE_2D);
6334             if (cellophane) {
6335                 glDisable(GL_TEXTURE_2D);
6336                 glColor4f(.7, .35, 0, .5);
6337                 glDepthMask(0);
6338                 glEnable(GL_LIGHTING);
6339                 glEnable(GL_BLEND);
6340             }
6341             if (tutoriallevel && id != 0) {
6342                 //glDisable(GL_TEXTURE_2D);
6343                 glColor4f(.7, .7, .7, 0.6);
6344                 glDepthMask(0);
6345                 glEnable(GL_LIGHTING);
6346                 glEnable(GL_BLEND);
6347                 if (canattack && cananger)
6348                     if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6349                         glDisable(GL_TEXTURE_2D);
6350                         glColor4f(1, 0, 0, 0.8);
6351                     }
6352                 glMatrixMode(GL_TEXTURE);
6353                 glPushMatrix();
6354                 glTranslatef(0, -smoketex, 0);
6355                 glTranslatef(-smoketex, 0, 0);
6356             }
6357             if (playerdetail) {
6358                 if (!showpoints) {
6359                     if ((tutoriallevel && id != 0))
6360                         skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6361                     else
6362                         skeleton.drawmodel.draw();
6363                 }
6364             }
6365             if (!playerdetail) {
6366                 if ((tutoriallevel && id != 0))
6367                     skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6368                 else
6369                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6370             }
6371
6372             if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6373                 if (tutoriallevel && id != 0) {
6374                     glPopMatrix();
6375                     glMatrixMode(GL_MODELVIEW);
6376                     glEnable(GL_TEXTURE_2D);
6377                     glColor4f(.7, .7, .7, 0.6);
6378                     glDepthMask(0);
6379                     glEnable(GL_LIGHTING);
6380                     glEnable(GL_BLEND);
6381                     if (canattack && cananger)
6382                         if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6383                             glDisable(GL_TEXTURE_2D);
6384                             glColor4f(1, 0, 0, 0.8);
6385                         }
6386                     glMatrixMode(GL_TEXTURE);
6387                     glPushMatrix();
6388                     glTranslatef(0, -smoketex * .6, 0);
6389                     glTranslatef(smoketex * .6, 0, 0);
6390                     if (playerdetail) {
6391                         if (!showpoints) {
6392                             if ((tutoriallevel && id != 0))
6393                                 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6394                             else
6395                                 skeleton.drawmodel.draw();
6396                         }
6397                     }
6398                     if (!playerdetail) {
6399                         if ((tutoriallevel && id != 0))
6400                             skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6401                         else
6402                             skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6403                     }
6404                 }
6405
6406
6407             if (tutoriallevel && id != 0) {
6408                 glPopMatrix();
6409                 glMatrixMode(GL_MODELVIEW);
6410                 glEnable(GL_TEXTURE_2D);
6411             }
6412             if (skeleton.clothes) {
6413                 glDepthMask(0);
6414                 glEnable(GL_BLEND);
6415                 if (!immediate)
6416                     skeleton.drawmodelclothes.draw();
6417                 if (immediate)
6418                     skeleton.drawmodelclothes.drawimmediate();
6419                 glDepthMask(1);
6420             }
6421         }
6422         glPopMatrix();
6423
6424         if (num_weapons > 0) {
6425             for (k = 0; k < num_weapons; k++) {
6426                 i = weaponids[k];
6427                 if (weaponactive == k) {
6428                     if (weapons[i].getType() != staff) {
6429                         for (j = 0; j < skeleton.num_muscles; j++) {
6430                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6431                                 weaponattachmuscle = j;
6432                             }
6433                         }
6434                         for (j = 0; j < skeleton.num_muscles; j++) {
6435                             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) {
6436                                 weaponrotatemuscle = j;
6437                             }
6438                         }
6439                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6440                         if (creature == wolftype)
6441                             weaponpoint = (skeleton.joints[skeleton.jointlabels[rightwrist]].position * .7 + skeleton.joints[skeleton.jointlabels[righthand]].position * .3);
6442                     }
6443                     if (weapons[i].getType() == staff) {
6444                         for (j = 0; j < skeleton.num_muscles; j++) {
6445                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6446                                 weaponattachmuscle = j;
6447                             }
6448                         }
6449                         for (j = 0; j < skeleton.num_muscles; j++) {
6450                             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) {
6451                                 weaponrotatemuscle = j;
6452                             }
6453                         }
6454                         //weaponpoint=skeleton.joints[skeleton.jointlabels[rightwrist]].position;
6455                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6456                         //weaponpoint+=skeleton.specialforward[1]*.1+(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightelbow]].position);
6457                         XYZ tempnormthing, vec1, vec2;
6458                         vec1 = (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightelbow]].position);
6459                         vec2 = (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position);
6460                         CrossProduct(&vec1, &vec2, &tempnormthing);
6461                         Normalise(&tempnormthing);
6462                         if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6463                             weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (skeleton.joints[skeleton.jointlabels[rightwrist]].position - skeleton.joints[skeleton.jointlabels[rightelbow]].position);
6464                     }
6465                 }
6466                 if (weaponactive != k && weaponstuck != k) {
6467                     if (weapons[i].getType() == knife)
6468                         weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[righthip]].position - skeleton.joints[skeleton.jointlabels[lefthip]].position) * .1 + (skeleton.joints[skeleton.jointlabels[rightshoulder]].position - skeleton.joints[skeleton.jointlabels[leftshoulder]].position) * .35;
6469                     if (weapons[i].getType() == sword)
6470                         weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[lefthip]].position - skeleton.joints[skeleton.jointlabels[righthip]].position) * .09 + (skeleton.joints[skeleton.jointlabels[leftshoulder]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position) * .33;
6471                     if (weapons[i].getType() == staff)
6472                         weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position + (skeleton.joints[skeleton.jointlabels[lefthip]].position - skeleton.joints[skeleton.jointlabels[righthip]].position) * .09 + (skeleton.joints[skeleton.jointlabels[leftshoulder]].position - skeleton.joints[skeleton.jointlabels[rightshoulder]].position) * .33;
6473                     for (j = 0; j < skeleton.num_muscles; j++) {
6474                         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) {
6475                             weaponrotatemuscle = j;
6476                         }
6477                     }
6478                 }
6479                 if (weaponstuck == k) {
6480                     if (weaponstuckwhere == 0)
6481                         weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position * .5 + skeleton.joints[skeleton.jointlabels[neck]].position * .5 - skeleton.forward * .8;
6482                     else
6483                         weaponpoint = skeleton.joints[skeleton.jointlabels[abdomen]].position * .5 + skeleton.joints[skeleton.jointlabels[neck]].position * .5 + skeleton.forward * .8;
6484                     for (j = 0; j < skeleton.num_muscles; j++) {
6485                         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) {
6486                             weaponrotatemuscle = j;
6487                         }
6488                     }
6489                 }
6490                 if (skeleton.free) {
6491                     weapons[i].position = weaponpoint * scale + coords;
6492                     weapons[i].bigrotation = 0;
6493                     weapons[i].bigtilt = 0;
6494                     weapons[i].bigtilt2 = 0;
6495                 } else {
6496                     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;
6497                     weapons[i].bigrotation = yaw;
6498                     weapons[i].bigtilt = tilt;
6499                     weapons[i].bigtilt2 = tilt2;
6500                 }
6501                 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6502                 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6503                 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6504                 if (weaponactive == k) {
6505                     if (weapons[i].getType() == knife) {
6506                         weapons[i].smallrotation = 180;
6507                         weapons[i].smallrotation2 = 0;
6508                         if (isCrouch() || wasCrouch()) {
6509                             weapons[i].smallrotation2 = 20;
6510                         }
6511                         if (animTarget == hurtidleanim) {
6512                             weapons[i].smallrotation2 = 50;
6513                         }
6514                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6515                             XYZ temppoint1, temppoint2, tempforward;
6516                             float distance;
6517
6518                             temppoint1 = skeleton.joints[skeleton.jointlabels[righthand]].position;
6519                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6520                             distance = findDistance(&temppoint1, &temppoint2);
6521                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6522                             weapons[i].rotation2 *= 360 / 6.28;
6523                             temppoint1.y = 0;
6524                             temppoint2.y = 0;
6525                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6526                             weapons[i].rotation1 *= 360 / 6.28;
6527                             weapons[i].rotation3 = 0;
6528                             weapons[i].smallrotation = -90;
6529                             weapons[i].smallrotation2 = 0;
6530                             if (temppoint1.x > temppoint2.x)
6531                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6532                         }
6533                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6534                             XYZ temppoint1, temppoint2, tempforward;
6535                             float distance;
6536
6537                             temppoint1 = skeleton.joints[skeleton.jointlabels[righthand]].position;
6538                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6539                             distance = findDistance(&temppoint1, &temppoint2);
6540                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6541                             weapons[i].rotation2 *= 360 / 6.28;
6542                             temppoint1.y = 0;
6543                             temppoint2.y = 0;
6544                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6545                             weapons[i].rotation1 *= 360 / 6.28;
6546                             weapons[i].rotation3 = 0;
6547                             weapons[i].smallrotation = 90;
6548                             weapons[i].smallrotation2 = 0;
6549                             if (temppoint1.x > temppoint2.x)
6550                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6551                         }
6552                         if (animTarget == knifethrowanim) {
6553                             weapons[i].smallrotation = 90;
6554                             //weapons[i].smallrotation2=-90;
6555                             weapons[i].smallrotation2 = 0;
6556                             weapons[i].rotation1 = 0;
6557                             weapons[i].rotation2 = 0;
6558                             weapons[i].rotation3 = 0;
6559                         }
6560                         if (animTarget == knifesneakattackanim && frameTarget < 5) {
6561                             weapons[i].smallrotation = -90;
6562                             weapons[i].rotation1 = 0;
6563                             weapons[i].rotation2 = 0;
6564                             weapons[i].rotation3 = 0;
6565                         }
6566                     }
6567                     if (weapons[i].getType() == sword) {
6568                         weapons[i].smallrotation = 0;
6569                         weapons[i].smallrotation2 = 0;
6570                         if (animTarget == knifethrowanim) {
6571                             weapons[i].smallrotation = -90;
6572                             weapons[i].smallrotation2 = 0;
6573                             weapons[i].rotation1 = 0;
6574                             weapons[i].rotation2 = 0;
6575                             weapons[i].rotation3 = 0;
6576                         }
6577                         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)) {
6578                             XYZ temppoint1, temppoint2, tempforward;
6579                             float distance;
6580
6581                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
6582                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6583                             distance = findDistance(&temppoint1, &temppoint2);
6584                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6585                             weapons[i].rotation2 *= 360 / 6.28;
6586                             temppoint1.y = 0;
6587                             temppoint2.y = 0;
6588                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6589                             weapons[i].rotation1 *= 360 / 6.28;
6590                             weapons[i].rotation3 = 0;
6591                             weapons[i].smallrotation = 90;
6592                             weapons[i].smallrotation2 = 0;
6593                             if (temppoint1.x > temppoint2.x)
6594                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6595                         }
6596                     }
6597                     if (weapons[i].getType() == staff) {
6598                         weapons[i].smallrotation = 100;
6599                         weapons[i].smallrotation2 = 0;
6600                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6601                             XYZ temppoint1, temppoint2, tempforward;
6602                             float distance;
6603
6604                             temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
6605                             temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6606                             distance = findDistance(&temppoint1, &temppoint2);
6607                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6608                             weapons[i].rotation2 *= 360 / 6.28;
6609                             temppoint1.y = 0;
6610                             temppoint2.y = 0;
6611                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6612                             weapons[i].rotation1 *= 360 / 6.28;
6613                             weapons[i].rotation3 = 0;
6614                             weapons[i].smallrotation = 90;
6615                             weapons[i].smallrotation2 = 0;
6616                             if (temppoint1.x > temppoint2.x)
6617                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6618                         }
6619                     }
6620                 }
6621                 if (weaponactive != k && weaponstuck != k) {
6622                     if (weapons[i].getType() == knife) {
6623                         weapons[i].smallrotation = -70;
6624                         weapons[i].smallrotation2 = 10;
6625                     }
6626                     if (weapons[i].getType() == sword) {
6627                         weapons[i].smallrotation = -100;
6628                         weapons[i].smallrotation2 = -8;
6629                     }
6630                     if (weapons[i].getType() == staff) {
6631                         weapons[i].smallrotation = -100;
6632                         weapons[i].smallrotation2 = -8;
6633                     }
6634                 }
6635                 if (weaponstuck == k) {
6636                     if (weaponstuckwhere == 0)
6637                         weapons[i].smallrotation = 180;
6638                     else
6639                         weapons[i].smallrotation = 0;
6640                     weapons[i].smallrotation2 = 10;
6641                 }
6642             }
6643         }
6644     }
6645
6646     calcrot = 0;
6647     if (skeleton.free)
6648         calcrot = 1;
6649     if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isFlip() || isWallJump())
6650         calcrot = 1;
6651     if (animCurrent != animTarget)
6652         calcrot = 1;
6653     //if(id==0)calcrot=1;
6654     if (skeleton.free == 2)
6655         calcrot = 0;
6656
6657     return 0;
6658 }
6659
6660
6661 /* FUNCTION?
6662  */
6663 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6664 {
6665     static int i, j;
6666     static float distance;
6667     static float olddistance;
6668     static int intersecting;
6669     static int firstintersecting;
6670     static XYZ point;
6671     static XYZ oldp1;
6672     static XYZ start, end;
6673     static float slopethreshold = -.4;
6674
6675     firstintersecting = -1;
6676
6677     oldp1 = *p1;
6678     *p1 = *p1 - *move;
6679     if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6680         return -1;
6681     if (*rotate)
6682         *p1 = DoRotation(*p1, 0, -*rotate, 0);
6683     for (i = 0; i < 4; i++) {
6684         for (j = 0; j < model->TriangleNum; j++) {
6685             if (model->facenormals[j].y <= slopethreshold) {
6686                 intersecting = 0;
6687                 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)));
6688                 if (distance < radius) {
6689                     point = *p1 - model->facenormals[j] * distance;
6690                     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]]))
6691                         intersecting = 1;
6692                     if (!intersecting)
6693                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6694                                                          &model->vertex[model->Triangles[j].vertex[1]],
6695                                                          p1, &radius);
6696                     if (!intersecting)
6697                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6698                                                          &model->vertex[model->Triangles[j].vertex[2]],
6699                                                          p1, &radius);
6700                     if (!intersecting)
6701                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6702                                                          &model->vertex[model->Triangles[j].vertex[2]],
6703                                                          p1, &radius);
6704                     end = *p1 - point;
6705                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6706                         start = *p1;
6707                         end = *p1;
6708                         end.y -= radius;
6709                         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)) {
6710                             p1->y = point.y + radius;
6711                             if ((animTarget == jumpdownanim || isFlip())) {
6712                                 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6713                                     RagDoll(0);
6714
6715                                 if (animTarget == jumpupanim) {
6716                                     jumppower = -4;
6717                                     animTarget = getIdle();
6718                                 }
6719                                 target = 0;
6720                                 frameTarget = 0;
6721                                 onterrain = 1;
6722
6723                                 if (id == 0) {
6724                                     pause_sound(whooshsound);
6725                                     OPENAL_SetVolume(channels[whooshsound], 0);
6726                                 }
6727
6728                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6729                                     if (isFlip())
6730                                         jumppower = -4;
6731                                     animTarget = getLanding();
6732                                     emit_sound_at(landsound, coords, 128.);
6733
6734                                     if (id == 0) {
6735                                         envsound[numenvsounds] = coords;
6736                                         envsoundvol[numenvsounds] = 16;
6737                                         envsoundlife[numenvsounds] = .4;
6738                                         numenvsounds++;
6739                                     }
6740                                 }
6741                             }
6742                         }
6743                     }
6744                 }
6745                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6746                     olddistance = distance;
6747                     firstintersecting = j;
6748                     *p = point;
6749                 }
6750             }
6751         }
6752         for (j = 0; j < model->TriangleNum; j++) {
6753             if (model->facenormals[j].y > slopethreshold) {
6754                 intersecting = 0;
6755                 start = *p1;
6756                 start.y -= radius / 4;
6757                 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6758                 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6759                 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6760                 distance = abs((model->facenormals[j].x * start.x)
6761                         + (model->facenormals[j].y * start.y)
6762                         + (model->facenormals[j].z * start.z)
6763                         - ((model->facenormals[j].x * v0.x)
6764                             + (model->facenormals[j].y * v0.y)
6765                             + (model->facenormals[j].z * v0.z)));
6766                 if (distance < radius * .5) {
6767                     point = start - model->facenormals[j] * distance;
6768                     if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6769                         intersecting = 1;
6770                     if (!intersecting)
6771                         intersecting = sphere_line_intersection(v0.x,v0.y,v0.z, v1.x,v1.y,v1.z, p1->x, p1->y, p1->z, radius / 2);
6772                     if (!intersecting)
6773                         intersecting = sphere_line_intersection(v1.x,v1.y,v1.z, v2.x,v2.y,v2.z, p1->x, p1->y, p1->z, radius / 2);
6774                     if (!intersecting)
6775                         intersecting = sphere_line_intersection(v0.x,v0.y,v0.z, v2.x,v2.y,v2.z, p1->x, p1->y, p1->z, radius / 2);
6776                     end = *p1 - point;
6777                     if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6778                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6779                             start = velocity;
6780                             velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6781                             if (findLengthfast(&start) < findLengthfast(&velocity))
6782                                 velocity = start;
6783                         }
6784                         *p1 += model->facenormals[j] * (distance - radius * .5);
6785                     }
6786                 }
6787                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6788                     olddistance = distance;
6789                     firstintersecting = j;
6790                     *p = point;
6791                 }
6792             }
6793         }
6794     }
6795     if (*rotate)
6796         *p = DoRotation(*p, 0, *rotate, 0);
6797     *p = *p + *move;
6798     if (*rotate)
6799         *p1 = DoRotation(*p1, 0, *rotate, 0);
6800     *p1 += *move;
6801     return firstintersecting;
6802 }
6803