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