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