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