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