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