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