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