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