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