]> git.jsancho.org Git - lugaru.git/blob - Source/Objects/Person.cpp
6c4bbbbb42df9559c0f09b4a03af5e5230f1c0fb
[lugaru.git] / Source / Objects / Person.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Objects/Person.hpp"
22
23 #include "Animation/Animation.hpp"
24 #include "Audio/Sounds.hpp"
25 #include "Audio/openal_wrapper.hpp"
26 #include "Game.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Tutorial.hpp"
30 #include "Utils/Folders.hpp"
31
32 extern float multiplier;
33 extern Terrain terrain;
34 extern float gravity;
35 extern int environment;
36 extern int detail;
37 extern FRUSTUM frustum;
38 extern XYZ viewer;
39 extern float realmultiplier;
40 extern int slomo;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
50 extern float woozy;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
54 extern bool decalstoggle;
55 extern float fadestart;
56 extern bool freeze;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
63 extern bool cananger;
64 extern float damagedealt;
65 extern int hostile;
66 extern float hostiletime;
67
68 extern bool gamestarted;
69
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
74
75 extern XYZ windvector;
76
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
78 std::vector<PersonType> PersonType::types;
79
80 void PersonType::Load()
81 {
82     types.resize(2);
83
84     /* Wolf */
85     types[wolftype].proportions[0] = 1.1;
86     types[wolftype].proportions[1] = 1.1;
87     types[wolftype].proportions[2] = 1.1;
88     types[wolftype].proportions[3] = 1.1;
89
90     types[wolftype].animRun = wolfrunanim;
91     types[wolftype].animRunning = wolfrunninganim;
92     types[wolftype].animCrouch = wolfcrouchanim;
93     types[wolftype].animStop = wolfstopanim;
94     types[wolftype].animLanding = wolflandanim;
95     types[wolftype].animLandingHard = wolflandhardanim;
96
97     types[wolftype].soundsAttack[0] = barksound;
98     types[wolftype].soundsAttack[1] = bark2sound;
99     types[wolftype].soundsAttack[2] = bark3sound;
100     types[wolftype].soundsAttack[3] = barkgrowlsound;
101     types[wolftype].soundsTalk[0] = growlsound;
102     types[wolftype].soundsTalk[1] = growl2sound;
103
104     types[wolftype].figureFileName = "Skeleton/BasicFigureWolf";
105     types[wolftype].lowFigureFileName = "Skeleton/BasicFigureWolfLow";
106     types[wolftype].clothesFileName = "Skeleton/RabbitBelt";
107     types[wolftype].modelFileNames[0] = "Models/Wolf.solid";
108     types[wolftype].modelFileNames[1] = "Models/Wolf2.solid";
109     types[wolftype].modelFileNames[2] = "Models/Wolf3.solid";
110     types[wolftype].modelFileNames[3] = "Models/Wolf4.solid";
111     types[wolftype].modelFileNames[4] = "Models/Wolf5.solid";
112     types[wolftype].modelFileNames[5] = "Models/Wolf6.solid";
113     types[wolftype].modelFileNames[6] = "Models/Wolf7.solid";
114     types[wolftype].lowModelFileName = "Models/WolfLow.solid";
115     types[wolftype].modelClothesFileName = "Models/Belt.solid";
116
117     types[wolftype].skins.resize(3);
118     types[wolftype].skins[0] = "Textures/Wolf.jpg";
119     types[wolftype].skins[1] = "Textures/DarkWolf.jpg";
120     types[wolftype].skins[2] = "Textures/SnowWolf.jpg";
121
122     /* Rabbit */
123     types[rabbittype].proportions[0] = 1.2;
124     types[rabbittype].proportions[1] = 1.05;
125     types[rabbittype].proportions[2] = 1;
126     types[rabbittype].proportions[3] = 1.1;
127     types[rabbittype].proportions[3].y = 1.05;
128
129     types[rabbittype].animRun = runanim;
130     types[rabbittype].animRunning = rabbitrunninganim;
131     types[rabbittype].animCrouch = crouchanim;
132     types[rabbittype].animStop = stopanim;
133     types[rabbittype].animLanding = landanim;
134     types[rabbittype].animLandingHard = landhardanim;
135
136     types[rabbittype].soundsAttack[0] = rabbitattacksound;
137     types[rabbittype].soundsAttack[1] = rabbitattack2sound;
138     types[rabbittype].soundsAttack[2] = rabbitattack3sound;
139     types[rabbittype].soundsAttack[3] = rabbitattack4sound;
140     types[rabbittype].soundsTalk[0] = rabbitchitter;
141     types[rabbittype].soundsTalk[1] = rabbitchitter2;
142
143     types[rabbittype].figureFileName = "Skeleton/BasicFigure";
144     types[rabbittype].lowFigureFileName = "Skeleton/BasicFigureLow";
145     types[rabbittype].clothesFileName = "Skeleton/RabbitBelt";
146     types[rabbittype].modelFileNames[0] = "Models/Body.solid";
147     types[rabbittype].modelFileNames[1] = "Models/Body2.solid";
148     types[rabbittype].modelFileNames[2] = "Models/Body3.solid";
149     types[rabbittype].modelFileNames[3] = "Models/Body4.solid";
150     types[rabbittype].modelFileNames[4] = "Models/Body5.solid";
151     types[rabbittype].modelFileNames[5] = "Models/Body6.solid";
152     types[rabbittype].modelFileNames[6] = "Models/Body7.solid";
153     types[rabbittype].lowModelFileName = "Models/BodyLow.solid";
154     types[rabbittype].modelClothesFileName = "Models/Belt.solid";
155
156     types[rabbittype].skins.resize(10);
157     types[rabbittype].skins[0] = "Textures/Fur3.jpg";
158     types[rabbittype].skins[1] = "Textures/Fur.jpg";
159     types[rabbittype].skins[2] = "Textures/Fur2.jpg";
160     types[rabbittype].skins[3] = "Textures/Lynx.jpg";
161     types[rabbittype].skins[4] = "Textures/Otter.jpg";
162     types[rabbittype].skins[5] = "Textures/Opal.jpg";
163     types[rabbittype].skins[6] = "Textures/Sable.jpg";
164     types[rabbittype].skins[7] = "Textures/Chocolate.jpg";
165     types[rabbittype].skins[8] = "Textures/BW2.jpg";
166     types[rabbittype].skins[9] = "Textures/WB2.jpg";
167 }
168
169 Person::Person()
170     : whichpatchx(0)
171     , whichpatchz(0)
172     , animCurrent(bounceidleanim)
173     , animTarget(bounceidleanim)
174     , frameCurrent(0)
175     , frameTarget(1)
176     , oldanimCurrent(0)
177     , oldanimTarget(0)
178     , oldframeCurrent(0)
179     , oldframeTarget(0)
180     , howactive(typeactive)
181     , parriedrecently(0)
182     , superruntoggle(false)
183     , lastattack(0)
184     , lastattack2(0)
185     , lastattack3(0)
186     , currentoffset()
187     , targetoffset()
188     , offset()
189     , target(0)
190     , transspeed(0)
191     ,
192
193     realoldcoords()
194     , oldcoords()
195     , coords()
196     , velocity()
197
198     , unconscioustime(0)
199
200     , immobile(false)
201
202     , velspeed(0)
203     , targetyaw(0)
204     , targetrot(0)
205     , rot(0)
206     , oldrot(0)
207     , lookyaw(0)
208     , lookpitch(0)
209     , yaw(0)
210     , pitch(0)
211     , lowyaw(0)
212     , tilt(0)
213     , targettilt(0)
214     , tilt2(0)
215     , targettilt2(0)
216     , rabbitkickenabled(false)
217     ,
218
219     bloodloss(0)
220     , bleeddelay(0)
221     , skiddelay(0)
222     , skiddingdelay(0)
223     , deathbleeding(0)
224     , tempdeltav(0)
225     ,
226
227     damagetolerance(200)
228     , damage(0)
229     , permanentdamage(0)
230     , superpermanentdamage(0)
231     , lastcollide(0)
232     , dead(0)
233     ,
234
235     jumppower(5)
236     , onground(false)
237     ,
238
239     wentforweapon(0)
240     ,
241
242     calcrot(false)
243     ,
244
245     facing()
246     ,
247
248     bleeding(0)
249     , bleedx(0)
250     , bleedy(0)
251     , direction(0)
252     , texupdatedelay(0)
253     ,
254
255     headyaw(0)
256     , headpitch(0)
257     , targetheadyaw(0)
258     , targetheadpitch(0)
259     ,
260
261     onterrain(false)
262     , pause(false)
263     ,
264
265     grabdelay(0)
266     ,
267
268     victim(nullptr)
269     , hasvictim(false)
270     ,
271
272     updatedelay(0)
273     , normalsupdatedelay(0)
274     ,
275
276     jumpstart(false)
277     , forwardkeydown(false)
278     , forwardstogglekeydown(false)
279     , rightkeydown(false)
280     , leftkeydown(false)
281     , backkeydown(false)
282     , jumpkeydown(false)
283     , jumptogglekeydown(false)
284     , crouchkeydown(false)
285     , crouchtogglekeydown(false)
286     , drawkeydown(false)
287     , drawtogglekeydown(false)
288     , throwkeydown(false)
289     , throwtogglekeydown(false)
290     , attackkeydown(false)
291     , feint(false)
292     , lastfeint(false)
293     , headless(false)
294     ,
295
296     crouchkeydowntime(0)
297     , jumpkeydowntime(0)
298     , freefall(false)
299     ,
300
301     turnspeed(0)
302     ,
303
304     aitype(passivetype)
305     , aiupdatedelay(0)
306     , losupdatedelay(0)
307     , ally(0)
308     , collide(0)
309     , collided(-10)
310     , avoidcollided(0)
311     , loaded(false)
312     , whichdirection(false)
313     , whichdirectiondelay(0)
314     , avoidsomething(false)
315     , avoidwhere()
316     , blooddimamount(0)
317     ,
318
319     staggerdelay(0)
320     , blinkdelay(0)
321     , twitchdelay(0)
322     , twitchdelay2(0)
323     , twitchdelay3(0)
324     , lefthandmorphness(0)
325     , righthandmorphness(0)
326     , headmorphness(0)
327     , chestmorphness(0)
328     , tailmorphness(0)
329     , targetlefthandmorphness(0)
330     , targetrighthandmorphness(0)
331     , targetheadmorphness(1)
332     , targetchestmorphness(0)
333     , targettailmorphness(0)
334     , lefthandmorphstart(0)
335     , lefthandmorphend(0)
336     , righthandmorphstart(0)
337     , righthandmorphend(0)
338     , headmorphstart(0)
339     , headmorphend(0)
340     , chestmorphstart(0)
341     , chestmorphend(0)
342     , tailmorphstart(0)
343     , tailmorphend(0)
344     ,
345
346     weaponmissdelay(0)
347     , highreversaldelay(0)
348     , lowreversaldelay(0)
349     ,
350
351     creature(rabbittype)
352     ,
353
354     id(0)
355     ,
356
357     skeleton()
358     ,
359
360     speed(0)
361     , scale(-1)
362     , power(0)
363     , speedmult(0)
364     ,
365
366     protectionhead(0)
367     , protectionhigh(0)
368     , protectionlow(0)
369     , armorhead(0)
370     , armorhigh(0)
371     , armorlow(0)
372     , metalhead(false)
373     , metalhigh(false)
374     , metallow(false)
375     ,
376
377     numclothes(0)
378     ,
379
380     landhard(false)
381     , bled(false)
382     , spurt(false)
383     , onfire(false)
384     , onfiredelay(0)
385     , burnt(0)
386     ,
387
388     flamedelay(0)
389     ,
390
391     playerdetail(0)
392     ,
393
394     num_weapons(0)
395     , weaponactive(-1)
396     , weaponstuck(-1)
397     , weaponstuckwhere(0)
398     ,
399
400     numwaypoints(0)
401     , pausetime(0)
402     ,
403
404     headtarget()
405     , interestdelay(0)
406     ,
407
408     finalfinaltarget()
409     , finaltarget()
410     , finalpathfindpoint(0)
411     , targetpathfindpoint(0)
412     , lastpathfindpoint(0)
413     , lastpathfindpoint2(0)
414     , lastpathfindpoint3(0)
415     , lastpathfindpoint4(0)
416     ,
417
418     waypoint(0)
419     ,
420
421     lastseen()
422     , lastseentime(0)
423     , lastchecktime(0)
424     , stunned(0)
425     , surprised(0)
426     , runninghowlong(0)
427     , occluded(0)
428     , lastoccluded(0)
429     , laststanding(0)
430     , escapednum(0)
431     ,
432
433     speechdelay(0)
434     , neckspurtdelay(0)
435     , neckspurtparticledelay(0)
436     , neckspurtamount(0)
437     ,
438
439     whichskin(0)
440     , rabbitkickragdoll(false)
441     ,
442
443     tempanimation()
444     ,
445
446     jumpclimb(false)
447 {
448     setProportions(1, 1, 1, 1);
449 }
450
451 /* Read a person in tfile. Throws an error if it’s not valid */
452 Person::Person(FILE* tfile, int mapvers, unsigned i)
453     : Person()
454 {
455     id = i;
456     funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
457     if (mapvers >= 5) {
458         funpackf(tfile, "Bi", &howactive);
459     } else {
460         howactive = typeactive;
461     }
462     if (mapvers >= 3) {
463         funpackf(tfile, "Bf", &scale);
464     } else {
465         scale = -1;
466     }
467     if (mapvers >= 11) {
468         funpackf(tfile, "Bb", &immobile);
469     } else {
470         immobile = 0;
471     }
472     if (mapvers >= 12) {
473         funpackf(tfile, "Bf", &yaw);
474     } else {
475         yaw = 0;
476     }
477     targetyaw = yaw;
478     if (num_weapons < 0 || num_weapons > 5) {
479         throw InvalidPersonException();
480     }
481     if (num_weapons > 0 && num_weapons < 5) {
482         for (int j = 0; j < num_weapons; j++) {
483             weaponids[j] = weapons.size();
484             int type;
485             funpackf(tfile, "Bi", &type);
486             weapons.push_back(Weapon(type, id));
487         }
488     }
489     funpackf(tfile, "Bi", &numwaypoints);
490     for (int j = 0; j < numwaypoints; j++) {
491         funpackf(tfile, "Bf", &waypoints[j].x);
492         funpackf(tfile, "Bf", &waypoints[j].y);
493         funpackf(tfile, "Bf", &waypoints[j].z);
494         if (mapvers >= 5) {
495             funpackf(tfile, "Bi", &waypointtype[j]);
496         } else {
497             waypointtype[j] = wpkeepwalking;
498         }
499     }
500
501     funpackf(tfile, "Bi", &waypoint);
502     if (waypoint > (numwaypoints - 1)) {
503         waypoint = 0;
504     }
505
506     funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
507     funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
508     funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
509     funpackf(tfile, "Bf Bf", &power, &speedmult);
510
511     if (mapvers >= 4) {
512         funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]);
513     } else {
514         setProportions(1, 1, 1, 1);
515     }
516
517     funpackf(tfile, "Bi", &numclothes);
518     for (int k = 0; k < numclothes; k++) {
519         int templength;
520         funpackf(tfile, "Bi", &templength);
521         for (int l = 0; l < templength; l++) {
522             funpackf(tfile, "Bb", &clothes[k][l]);
523         }
524         clothes[k][templength] = '\0';
525         funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
526     }
527
528     loaded = true;
529
530     if (scale < 0) {
531         if (creature == wolftype) {
532             scale = .23;
533             damagetolerance = 300;
534         } else {
535             scale = .2;
536         }
537     }
538
539     oldcoords = coords;
540     realoldcoords = coords;
541 }
542
543 void Person::skeletonLoad(bool clothes)
544 {
545     skeleton.id = id;
546     skeleton.Load(
547         PersonType::types[creature].figureFileName,
548         PersonType::types[creature].lowFigureFileName,
549         PersonType::types[creature].clothesFileName,
550         PersonType::types[creature].modelFileNames[0],
551         PersonType::types[creature].modelFileNames[1],
552         PersonType::types[creature].modelFileNames[2],
553         PersonType::types[creature].modelFileNames[3],
554         PersonType::types[creature].modelFileNames[4],
555         PersonType::types[creature].modelFileNames[5],
556         PersonType::types[creature].modelFileNames[6],
557         PersonType::types[creature].lowModelFileName,
558         PersonType::types[creature].modelClothesFileName,
559         clothes);
560
561     skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
562 }
563
564 void Person::setProportions(float head, float body, float arms, float legs)
565 {
566     proportions[0] = head;
567     proportions[1] = body;
568     proportions[2] = arms;
569     proportions[3] = legs;
570 }
571
572 XYZ Person::getProportion(int part) const
573 {
574     XYZ prop = PersonType::types[creature].proportions[part] * proportions[part];
575     if (cellophane) {
576         prop.z = 0;
577     }
578     return prop;
579 }
580
581 /* EFFECT
582  *
583  * USES:
584  * GameTick/doPlayerCollisions
585  */
586 void Person::CheckKick()
587 {
588     if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) {
589         return;
590     }
591
592     if (Animation::animations[victim->animTarget].height != lowheight) {
593         float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
594         XYZ relative = velocity;
595         relative.y = 0;
596         Normalise(&relative);
597
598         victim->spurt = 1;
599         DoBlood(.2, 250);
600         if (!Tutorial::active) {
601             emit_sound_at(heavyimpactsound, victim->coords);
602         }
603         victim->RagDoll(0);
604         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
605             victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
606         }
607         victim->Puff(neck);
608         victim->DoDamage(100 * damagemult / victim->protectionhigh);
609         if (id == 0) {
610             camerashake += .4;
611         }
612
613         target = 0;
614         frameCurrent = 3;
615         animTarget = backflipanim;
616         frameTarget = 4;
617         velocity = facing * -10;
618         velocity.y = 5;
619         skeleton.free = 0;
620         if (id == 0) {
621             resume_stream(whooshsound);
622         }
623
624         award_bonus(id, cannon);
625     } else if (victim->isCrouch()) {
626         animTarget = rabbitkickreversedanim;
627         animCurrent = rabbitkickreversedanim;
628         victim->animCurrent = rabbitkickreversalanim;
629         victim->animTarget = rabbitkickreversalanim;
630         targettilt2 = 0;
631         frameCurrent = 0;
632         frameTarget = 1;
633         target = 0;
634         velocity = 0;
635         victim->oldcoords = victim->coords;
636         coords = victim->coords;
637         victim->targetyaw = targetyaw;
638         victim->victim = this->shared_from_this();
639     }
640 }
641
642 /* EFFECT
643  *
644  * USES:
645  * GameTick::doPlayerCollisions - spread fire between players
646  * GameTick::ProcessDevKeys - press f to ignite
647  * Person::DoStuff - spread fire from lit campfires and bushes
648  */
649 void Person::CatchFire()
650 {
651     XYZ flatfacing, flatvelocity;
652     int howmany;
653     for (int i = 0; i < 10; i++) {
654         howmany = fabs(Random() % (skeleton.joints.size()));
655         if (skeleton.free) {
656             flatvelocity = skeleton.joints[howmany].velocity;
657             flatfacing = skeleton.joints[howmany].position * scale + coords;
658         } else {
659             flatvelocity = velocity;
660             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
661         }
662         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
663     }
664
665     onfiredelay = 0.5;
666
667     emit_sound_at(firestartsound, coords);
668
669     emit_stream_at(stream_firesound, coords);
670
671     flamedelay = 0;
672
673     onfire = 1;
674 }
675
676 /* FUNCTION
677  * idle animation for this creature (depending on status)
678  */
679 int Person::getIdle()
680 {
681     if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype)) {
682         return talkidleanim;
683     }
684     if (hasvictim && (victim != this->shared_from_this())) {
685         if ((!victim->dead && victim->aitype != passivetype &&
686              victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
687              victim->id < Person::players.size())) {
688             if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
689                 if (creature == rabbittype) {
690                     return fightidleanim;
691                 }
692                 if (creature == wolftype) {
693                     return wolfidle;
694                 }
695             }
696             if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
697                 if (weapons[weaponids[weaponactive]].getType() == knife) {
698                     return knifefightidleanim;
699                 }
700                 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1) {
701                     return swordfightidlebothanim;
702                 }
703                 if (weapons[weaponids[weaponactive]].getType() == sword) {
704                     return swordfightidleanim;
705                 }
706                 if (weapons[weaponids[weaponactive]].getType() == staff) {
707                     return swordfightidleanim;
708                 }
709             }
710             if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause) {
711                 return fightsidestep;
712             }
713         }
714     }
715     if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype) {
716         return hurtidleanim;
717     }
718     if (howactive == typesitting) {
719         return sitanim;
720     }
721     if (howactive == typesittingwall) {
722         return sitwallanim;
723     }
724     if (howactive == typesleeping) {
725         return sleepanim;
726     }
727     if (howactive == typedead1) {
728         return dead1anim;
729     }
730     if (howactive == typedead2) {
731         return dead2anim;
732     }
733     if (howactive == typedead3) {
734         return dead3anim;
735     }
736     if (howactive == typedead4) {
737         return dead4anim;
738     }
739     if (creature == rabbittype) {
740         return bounceidleanim;
741     }
742     if (creature == wolftype) {
743         return wolfidle;
744     }
745     return 0;
746 }
747
748 /* FUNCTION
749  * crouch animation for this creature
750  */
751 int Person::getCrouch()
752 {
753     return PersonType::types[creature].animCrouch;
754 }
755
756 /* FUNCTION
757  * running animation for this creature (can be upright or all fours)
758  */
759 int Person::getRun()
760 {
761     if (superruntoggle && (weaponactive == -1)) {
762         return PersonType::types[creature].animRunning;
763     } else {
764         return PersonType::types[creature].animRun;
765     }
766 }
767
768 /* FUNCTION
769  */
770 int Person::getStop()
771 {
772     return PersonType::types[creature].animStop;
773 }
774
775 /* FUNCTION
776  */
777 int Person::getLanding()
778 {
779     return PersonType::types[creature].animLanding;
780 }
781
782 /* FUNCTION
783  */
784 int Person::getLandhard()
785 {
786     return PersonType::types[creature].animLandingHard;
787 }
788
789 /* EFFECT
790  *
791  * USES:
792  * Person::DoAnimations
793  */
794 static void
795 SolidHitBonus(int playerid)
796 {
797     if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) {
798         award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
799     } else {
800         award_bonus(playerid, solidhit);
801     }
802 }
803
804 /* EFFECT
805  * spawns blood effects
806  */
807 void Person::DoBlood(float howmuch, int which)
808 {
809     // FIXME: should abstract out inputs
810     static int bleedxint, bleedyint;
811     static XYZ bloodvel;
812     if (bloodtoggle && !Tutorial::active) {
813         if (bleeding <= 0 && spurt) {
814             spurt = 0;
815             for (int i = 0; i < 3; i++) {
816                 // emit blood particles
817                 bloodvel = 0;
818                 if (skeleton.free) {
819                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
820                     bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
821                     Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
822                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
823                 } else {
824                     bloodvel.z = 10;
825                     bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
826                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
827                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
828                     Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
829                 }
830             }
831             if (Random() % 2 == 0) { // 50% chance
832                 for (int i = 0; i < 3; i++) {
833                     if (Random() % 2 != 0) {
834                         // emit teeth particles
835                         bloodvel = 0;
836                         if (skeleton.free) {
837                             bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
838                             bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
839                         } else {
840                             bloodvel.z = 10;
841                             bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
842                             bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
843                         }
844                         bloodvel *= .2;
845                         if (skeleton.free) {
846                             Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
847                         } else {
848                             Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
849                         }
850                         Sprite::setLastSpriteSpecial(3); // sets it to teeth
851                     }
852                 }
853             }
854         }
855         if (decalstoggle) {
856             // FIXME: manipulating attributes
857             bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
858             bleedxint = 0;
859             bleedyint = 0;
860             if (creature == rabbittype) {
861                 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) {
862                     bleedxint = abs(Random() % 512);
863                     bleedyint = abs(Random() % 512);
864                 }
865             }
866             if (creature == wolftype) {
867                 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) {
868                     bleedxint = abs(Random() % 512);
869                     bleedyint = abs(Random() % 512);
870                 }
871             }
872             bleedy = bleedxint;
873             bleedx = bleedyint;
874             bleedy /= realtexdetail;
875             bleedx /= realtexdetail;
876             direction = abs(Random() % 2) * 2 - 1;
877         }
878     }
879     if (bleeding > 2) {
880         bleeding = 2;
881     }
882 }
883
884 /* EFFECT
885  * spawns big blood effects and ???
886  * modifies character's skin texture
887  */
888 void Person::DoBloodBig(float howmuch, int which)
889 {
890     static int bleedxint, bleedyint, i, j;
891     static XYZ bloodvel;
892     if (howmuch && id == 0) {
893         blooddimamount = 1;
894     }
895
896     if (!Tutorial::active || id == 0) {
897         if (aitype != playercontrolled && howmuch > 0) {
898             // play pain sounds
899             int whichsound = -1;
900
901             if (creature == wolftype) {
902                 int i = abs(Random() % 2);
903                 if (i == 0) {
904                     whichsound = snarlsound;
905                 }
906                 if (i == 1) {
907                     whichsound = snarl2sound;
908                 }
909             }
910             if (creature == rabbittype) {
911                 int i = abs(Random() % 2);
912                 if (i == 0) {
913                     whichsound = rabbitpainsound;
914                 }
915                 if (i == 1 && howmuch >= 2) {
916                     whichsound = rabbitpain1sound;
917                 }
918             }
919
920             if (whichsound != -1) {
921                 emit_sound_at(whichsound, coords);
922                 addEnvSound(coords);
923             }
924         }
925     }
926
927     if (id == 0 && howmuch > 0) {
928         Game::flash(.5, 0);
929     }
930
931     if (bloodtoggle && decalstoggle && !Tutorial::active) {
932         if (bleeding <= 0 && spurt) {
933             spurt = 0;
934             for (int i = 0; i < 3; i++) {
935                 // emit blood particles
936                 // FIXME: copypaste from above
937                 bloodvel = 0;
938                 if (skeleton.free) {
939                     bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
940                     bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
941                     Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
942                     Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
943                 } else {
944                     bloodvel.z = 10;
945                     bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
946                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
947                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
948                     Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
949                 }
950             }
951         }
952
953         // weird texture manipulation code follows.
954         // looks like this is painting blood onto the character's skin texture
955         // FIXME: surely there's a better way
956
957         int offsetx = 0, offsety = 0;
958         if (which == 225) {
959             offsety = Random() % 40;
960             offsetx = abs(Random() % 60);
961         }
962         if (which == 190 || which == 185) {
963             offsety = Random() % 40;
964             offsetx = abs(Random() % 100) - 20;
965         }
966         if (which == 175) {
967             offsety = Random() % 10;
968             offsetx = Random() % 10;
969         }
970         if (which == 170) {
971             offsety = Random() % 20;
972             offsetx = Random() % 20;
973         }
974         if (which == 220 || which == 215) {
975             offsetx = 20;
976         }
977
978         int startx = 512;
979         int starty = 512;
980         int endx = 0;
981         int endy = 0;
982         GLubyte color;
983         if (creature == rabbittype) {
984             for (i = 0; i < 512; i++) {
985                 for (j = 0; j < 512; j++) {
986                     if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
987                         if (i < startx) {
988                             startx = i;
989                         }
990                         if (j < starty) {
991                             starty = j;
992                         }
993                         if (i > endx) {
994                             endx = i;
995                         }
996                         if (j > endy) {
997                             endy = j;
998                         }
999                     }
1000                 }
1001             }
1002         }
1003         if (creature == wolftype) {
1004             for (i = 0; i < 512; i++) {
1005                 for (j = 0; j < 512; j++) {
1006                     if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1007                         if (i < startx) {
1008                             startx = i;
1009                         }
1010                         if (j < starty) {
1011                             starty = j;
1012                         }
1013                         if (i > endx) {
1014                             endx = i;
1015                         }
1016                         if (j > endy) {
1017                             endy = j;
1018                         }
1019                     }
1020                 }
1021             }
1022         }
1023
1024         startx += offsetx;
1025         endx += offsetx;
1026         starty += offsety;
1027         endy += offsety;
1028
1029         if (startx < 0) {
1030             startx = 0;
1031         }
1032         if (starty < 0) {
1033             starty = 0;
1034         }
1035         if (endx > 512 - 1) {
1036             endx = 512 - 1;
1037         }
1038         if (endy > 512 - 1) {
1039             endy = 512 - 1;
1040         }
1041         if (endx < startx) {
1042             endx = startx;
1043         }
1044         if (endy < starty) {
1045             endy = starty;
1046         }
1047
1048         startx /= realtexdetail;
1049         starty /= realtexdetail;
1050         endx /= realtexdetail;
1051         endy /= realtexdetail;
1052
1053         int texdetailint = realtexdetail;
1054         int where;
1055         if (creature == rabbittype) {
1056             for (i = startx; i < endx; i++) {
1057                 for (j = starty; j < endy; j++) {
1058                     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) {
1059                         color = Random() % 85 + 170;
1060                         where = i * skeleton.skinsize * 3 + j * 3;
1061                         if (skeleton.skinText[where + 0] > color / 2) {
1062                             skeleton.skinText[where + 0] = color / 2;
1063                         }
1064                         skeleton.skinText[where + 1] = 0;
1065                         skeleton.skinText[where + 2] = 0;
1066                     }
1067                 }
1068             }
1069         }
1070         if (creature == wolftype) {
1071             for (i = startx; i < endx; i++) {
1072                 for (j = starty; j < endy; j++) {
1073                     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) {
1074                         color = Random() % 85 + 170;
1075                         where = i * skeleton.skinsize * 3 + j * 3;
1076                         if (skeleton.skinText[where + 0] > color / 2) {
1077                             skeleton.skinText[where + 0] = color / 2;
1078                         }
1079                         skeleton.skinText[where + 1] = 0;
1080                         skeleton.skinText[where + 2] = 0;
1081                     }
1082                 }
1083             }
1084         }
1085         skeleton.drawmodel.textureptr.bind();
1086         DoMipmaps();
1087
1088         bleedxint = 0;
1089         bleedyint = 0;
1090         if (creature == rabbittype) {
1091             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) {
1092                 bleedxint = abs(Random() % 512);
1093                 bleedyint = abs(Random() % 512);
1094             }
1095         }
1096         if (creature == wolftype) {
1097             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) {
1098                 bleedxint = abs(Random() % 512);
1099                 bleedyint = abs(Random() % 512);
1100             }
1101         }
1102         bleedy = bleedxint + offsetx;
1103         bleedx = bleedyint + offsety;
1104         bleedy /= realtexdetail;
1105         bleedx /= realtexdetail;
1106         if (bleedx < 0) {
1107             bleedx = 0;
1108         }
1109         if (bleedy < 0) {
1110             bleedy = 0;
1111         }
1112         if (bleedx > skeleton.skinsize - 1) {
1113             bleedx = skeleton.skinsize - 1;
1114         }
1115         if (bleedy > skeleton.skinsize - 1) {
1116             bleedy = skeleton.skinsize - 1;
1117         }
1118         direction = abs(Random() % 2) * 2 - 1;
1119     }
1120     bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1121     deathbleeding += bleeding;
1122     bloodloss += bleeding * 3;
1123
1124     if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1125         if (abs(Random() % 2) == 0) {
1126             aitype = gethelptype;
1127             lastseentime = 12;
1128         } else {
1129             aitype = attacktypecutoff;
1130         }
1131         ally = 0;
1132     }
1133     if (bleeding > 2) {
1134         bleeding = 2;
1135     }
1136 }
1137
1138 /* EFFECT
1139  * similar to DoBloodBig
1140  */
1141 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
1142 {
1143     static int i, j;
1144     static XYZ bloodvel;
1145     static XYZ startpoint, endpoint, colpoint, movepoint;
1146     static float rotationpoint;
1147     static int whichtri;
1148     static XYZ p1, p2, p3, p0;
1149     XYZ bary;
1150     XYZ gxx, gyy;
1151     float coordsx, coordsy;
1152     float total;
1153
1154     if (bloodtoggle && decalstoggle && !Tutorial::active) {
1155         where -= coords;
1156         if (!skeleton.free) {
1157             where = DoRotation(where, 0, -yaw, 0);
1158         }
1159         //where=scale;
1160         startpoint = where;
1161         startpoint.y += 100;
1162         endpoint = where;
1163         endpoint.y -= 100;
1164         movepoint = 0;
1165         rotationpoint = 0;
1166         // ray testing for a tri in the character model
1167         whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
1168         if (whichtri != -1) {
1169             // low level geometry math
1170             p0 = colpoint;
1171             p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0);
1172             p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1);
1173             p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2);
1174
1175             bary.x = distsq(&p0, &p1);
1176             bary.y = distsq(&p0, &p2);
1177             bary.z = distsq(&p0, &p3);
1178
1179             total = bary.x + bary.y + bary.z;
1180             bary.x /= total;
1181             bary.y /= total;
1182             bary.z /= total;
1183
1184             bary.x = 1 - bary.x;
1185             bary.y = 1 - bary.y;
1186             bary.z = 1 - bary.z;
1187
1188             total = bary.x + bary.y + bary.z;
1189             bary.x /= total;
1190             bary.y /= total;
1191             bary.z /= total;
1192
1193             gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1194             gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1195             gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1196             gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1197             gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1198             gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1199             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;
1200             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;
1201
1202             if (bleeding <= 0 && spurt) {
1203                 spurt = 0;
1204                 for (int i = 0; i < 3; i++) {
1205                     // emit blood particles
1206                     // FIXME: more copypaste code
1207                     bloodvel = 0;
1208                     if (skeleton.free) {
1209                         bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1210                         bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1211                         Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1212                         Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1213                     } else {
1214                         bloodvel.z = 10;
1215                         bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1216                         bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1217                         Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1218                         Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1219                     }
1220                 }
1221             }
1222
1223             // texture manipulation follows
1224
1225             int offsetx = 0, offsety = 0;
1226             offsetx = (1 + coordsy) * 512 - 291;
1227             offsety = coordsx * 512 - 437;
1228
1229             int startx = 512;
1230             int starty = 512;
1231             int endx = 0;
1232             int endy = 0;
1233             GLubyte color;
1234             if (creature == rabbittype) {
1235                 for (i = 0; i < 512; i++) {
1236                     for (j = 0; j < 512; j++) {
1237                         if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1238                             if (i < startx) {
1239                                 startx = i;
1240                             }
1241                             if (j < starty) {
1242                                 starty = j;
1243                             }
1244                             if (i > endx) {
1245                                 endx = i;
1246                             }
1247                             if (j > endy) {
1248                                 endy = j;
1249                             }
1250                         }
1251                     }
1252                 }
1253             }
1254             if (creature == wolftype) {
1255                 for (i = 0; i < 512; i++) {
1256                     for (j = 0; j < 512; j++) {
1257                         if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1258                             if (i < startx) {
1259                                 startx = i;
1260                             }
1261                             if (j < starty) {
1262                                 starty = j;
1263                             }
1264                             if (i > endx) {
1265                                 endx = i;
1266                             }
1267                             if (j > endy) {
1268                                 endy = j;
1269                             }
1270                         }
1271                     }
1272                 }
1273             }
1274             startx += offsetx;
1275             endx += offsetx;
1276             starty += offsety;
1277             endy += offsety;
1278
1279             if (startx < 0) {
1280                 startx = 0;
1281             }
1282             if (starty < 0) {
1283                 starty = 0;
1284             }
1285             if (endx > 512 - 1) {
1286                 endx = 512 - 1;
1287             }
1288             if (endy > 512 - 1) {
1289                 endy = 512 - 1;
1290             }
1291             if (endx < startx) {
1292                 endx = startx;
1293             }
1294             if (endy < starty) {
1295                 endy = starty;
1296             }
1297
1298             startx /= realtexdetail;
1299             starty /= realtexdetail;
1300             endx /= realtexdetail;
1301             endy /= realtexdetail;
1302
1303             int texdetailint = realtexdetail;
1304             int where;
1305             if (creature == rabbittype) {
1306                 for (i = startx; i < endx; i++) {
1307                     for (j = starty; j < endy; j++) {
1308                         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) {
1309                             color = Random() % 85 + 170;
1310                             where = i * skeleton.skinsize * 3 + j * 3;
1311                             if (skeleton.skinText[where + 0] > color / 2) {
1312                                 skeleton.skinText[where + 0] = color / 2;
1313                             }
1314                             skeleton.skinText[where + 1] = 0;
1315                             skeleton.skinText[where + 2] = 0;
1316                         } 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) {
1317                             color = Random() % 85 + 170;
1318                             where = i * skeleton.skinsize * 3 + j * 3;
1319                             if (skeleton.skinText[where + 0] > color / 2) {
1320                                 skeleton.skinText[where + 0] = color / 2;
1321                             }
1322                             skeleton.skinText[where + 1] = 0;
1323                             skeleton.skinText[where + 2] = 0;
1324                         }
1325                     }
1326                 }
1327             }
1328             if (creature == wolftype) {
1329                 for (i = startx; i < endx; i++) {
1330                     for (j = starty; j < endy; j++) {
1331                         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) {
1332                             color = Random() % 85 + 170;
1333                             where = i * skeleton.skinsize * 3 + j * 3;
1334                             if (skeleton.skinText[where + 0] > color / 2) {
1335                                 skeleton.skinText[where + 0] = color / 2;
1336                             }
1337                             skeleton.skinText[where + 1] = 0;
1338                             skeleton.skinText[where + 2] = 0;
1339                         } 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) {
1340                             color = Random() % 85 + 170;
1341                             where = i * skeleton.skinsize * 3 + j * 3;
1342                             if (skeleton.skinText[where + 0] > color / 2) {
1343                                 skeleton.skinText[where + 0] = color / 2;
1344                             }
1345                             skeleton.skinText[where + 1] = 0;
1346                             skeleton.skinText[where + 2] = 0;
1347                         }
1348                     }
1349                 }
1350             }
1351             skeleton.drawmodel.textureptr.bind();
1352             DoMipmaps();
1353
1354             bleedy = (1 + coordsy) * 512;
1355             bleedx = coordsx * 512;
1356             bleedy /= realtexdetail;
1357             bleedx /= realtexdetail;
1358             if (bleedx < 0) {
1359                 bleedx = 0;
1360             }
1361             if (bleedy < 0) {
1362                 bleedy = 0;
1363             }
1364             if (bleedx > skeleton.skinsize - 1) {
1365                 bleedx = skeleton.skinsize - 1;
1366             }
1367             if (bleedy > skeleton.skinsize - 1) {
1368                 bleedy = skeleton.skinsize - 1;
1369             }
1370             direction = abs(Random() % 2) * 2 - 1;
1371         }
1372         if (whichtri == -1) {
1373             return 0;
1374         }
1375     }
1376     bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1377     deathbleeding += bleeding;
1378     bloodloss += bleeding * 3;
1379
1380     if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1381         if (abs(Random() % 2) == 0) {
1382             aitype = gethelptype;
1383             lastseentime = 12;
1384         } else {
1385             aitype = attacktypecutoff;
1386         }
1387         ally = 0;
1388     }
1389     if (bleeding > 2) {
1390         bleeding = 2;
1391     }
1392     return 1;
1393 }
1394
1395 /* EFFECT
1396  * guessing this performs a reversal
1397  */
1398 void Person::Reverse()
1399 {
1400     if (!((victim->aitype == playercontrolled || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) {
1401         return;
1402     }
1403
1404     if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) {
1405         return;
1406     }
1407
1408     if (animTarget == sweepanim) {
1409         animTarget = sweepreversedanim;
1410         animCurrent = sweepreversedanim;
1411         victim->animCurrent = sweepreversalanim;
1412         victim->animTarget = sweepreversalanim;
1413     }
1414     if (animTarget == spinkickanim) {
1415         animTarget = spinkickreversedanim;
1416         animCurrent = spinkickreversedanim;
1417         victim->animCurrent = spinkickreversalanim;
1418         victim->animTarget = spinkickreversalanim;
1419     }
1420     if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1421         if (animTarget == rabbittacklinganim) {
1422             frameCurrent = 6;
1423             frameTarget = 7;
1424             victim->frameCurrent = 6;
1425             victim->frameTarget = 7;
1426         }
1427         animTarget = upunchreversedanim;
1428         animCurrent = upunchreversedanim;
1429         victim->animCurrent = upunchreversalanim;
1430         victim->animTarget = upunchreversalanim;
1431     }
1432     if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1433         if (victim->weaponactive != -1) {
1434             victim->throwtogglekeydown = 1;
1435             XYZ tempVelocity = victim->velocity * .2;
1436             if (tempVelocity.x == 0) {
1437                 tempVelocity.x = .1;
1438             }
1439             weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1440             victim->num_weapons--;
1441             if (victim->num_weapons) {
1442                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1443                 if (victim->weaponstuck == victim->num_weapons) {
1444                     victim->weaponstuck = 0;
1445                 }
1446             }
1447
1448             victim->weaponactive = -1;
1449             for (unsigned j = 0; j < Person::players.size(); j++) {
1450                 Person::players[j]->wentforweapon = 0;
1451             }
1452         }
1453
1454         animTarget = staffhitreversedanim;
1455         animCurrent = staffhitreversedanim;
1456         victim->animCurrent = staffhitreversalanim;
1457         victim->animTarget = staffhitreversalanim;
1458     }
1459     if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1460         if (victim->weaponactive != -1) {
1461             victim->throwtogglekeydown = 1;
1462             XYZ tempVelocity = victim->velocity * .2;
1463             if (tempVelocity.x == 0) {
1464                 tempVelocity.x = .1;
1465             }
1466             weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1467             victim->num_weapons--;
1468             if (victim->num_weapons) {
1469                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1470                 if (victim->weaponstuck == victim->num_weapons) {
1471                     victim->weaponstuck = 0;
1472                 }
1473             }
1474
1475             victim->weaponactive = -1;
1476             for (unsigned j = 0; j < Person::players.size(); j++) {
1477                 Person::players[j]->wentforweapon = 0;
1478             }
1479         }
1480         animTarget = staffspinhitreversedanim;
1481         animCurrent = staffspinhitreversedanim;
1482         victim->animCurrent = staffspinhitreversalanim;
1483         victim->animTarget = staffspinhitreversalanim;
1484     }
1485     if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1486         if (victim->weaponactive != -1) {
1487             victim->throwtogglekeydown = 1;
1488             XYZ tempVelocity = victim->velocity * .2;
1489             if (tempVelocity.x == 0) {
1490                 tempVelocity.x = .1;
1491             }
1492             weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1493             victim->num_weapons--;
1494             if (victim->num_weapons) {
1495                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1496                 if (victim->weaponstuck == victim->num_weapons) {
1497                     victim->weaponstuck = 0;
1498                 }
1499             }
1500
1501             victim->weaponactive = -1;
1502             for (unsigned j = 0; j < Person::players.size(); j++) {
1503                 Person::players[j]->wentforweapon = 0;
1504             }
1505         }
1506         animTarget = swordslashreversedanim;
1507         animCurrent = swordslashreversedanim;
1508         victim->animCurrent = swordslashreversalanim;
1509         victim->animTarget = swordslashreversalanim;
1510     }
1511     if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1512         if (victim->weaponactive != -1) {
1513             victim->throwtogglekeydown = 1;
1514             XYZ tempVelocity = victim->velocity * .2;
1515             if (tempVelocity.x == 0) {
1516                 tempVelocity.x = .1;
1517             }
1518             weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1519             victim->num_weapons--;
1520             if (victim->num_weapons) {
1521                 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1522                 if (victim->weaponstuck == victim->num_weapons) {
1523                     victim->weaponstuck = 0;
1524                 }
1525             }
1526
1527             victim->weaponactive = -1;
1528             for (unsigned j = 0; j < Person::players.size(); j++) {
1529                 Person::players[j]->wentforweapon = 0;
1530             }
1531         }
1532         animTarget = knifeslashreversedanim;
1533         animCurrent = knifeslashreversedanim;
1534         victim->animCurrent = knifeslashreversalanim;
1535         victim->animTarget = knifeslashreversalanim;
1536     }
1537     if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1538         victim->targettilt2 = targettilt2;
1539         victim->frameCurrent = frameCurrent;
1540         victim->frameTarget = frameTarget;
1541         victim->target = target;
1542         victim->velocity = 0;
1543         victim->oldcoords = victim->coords;
1544         victim->coords = coords;
1545         victim->targetyaw = targetyaw;
1546         victim->yaw = targetyaw;
1547         victim->victim = this->shared_from_this();
1548     }
1549     if (animTarget == winduppunchanim) {
1550         animTarget = winduppunchblockedanim;
1551         victim->animTarget = blockhighleftanim;
1552         victim->frameTarget = 1;
1553         victim->target = .5;
1554         victim->victim = this->shared_from_this();
1555         victim->targetyaw = targetyaw + 180;
1556     }
1557     if (animTarget == wolfslapanim) {
1558         animTarget = winduppunchblockedanim;
1559         victim->animTarget = blockhighleftanim;
1560         victim->frameTarget = 1;
1561         victim->target = .5;
1562         victim->victim = this->shared_from_this();
1563         victim->targetyaw = targetyaw + 180;
1564     }
1565     if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1566         animTarget = swordslashparriedanim;
1567         parriedrecently = .4;
1568         victim->parriedrecently = 0;
1569         victim->animTarget = swordslashparryanim;
1570         victim->frameTarget = 1;
1571         victim->target = .5;
1572         victim->victim = this->shared_from_this();
1573         victim->targetyaw = targetyaw + 180;
1574
1575         if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1576             if (victim->weaponactive != -1) {
1577                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1578                     if (weapons[victim->weaponids[0]].getType() == staff) {
1579                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1580                     }
1581                     if (weapons[weaponids[0]].getType() == staff) {
1582                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1583                     }
1584                     emit_sound_at(swordstaffsound, victim->coords);
1585                 } else {
1586                     emit_sound_at(metalhitsound, victim->coords);
1587                 }
1588             }
1589             XYZ aim;
1590             victim->Puff(righthand);
1591             victim->target = 0;
1592             victim->frameTarget = 0;
1593             victim->animTarget = staggerbackhighanim;
1594             victim->targetyaw = targetyaw + 180;
1595             victim->target = 0;
1596             aim = DoRotation(facing, 0, 90, 0) * 21;
1597             aim.y += 7;
1598             weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1599             victim->num_weapons--;
1600             if (victim->num_weapons) {
1601                 victim->weaponids[0] = victim->weaponids[num_weapons];
1602                 if (victim->weaponstuck == victim->num_weapons) {
1603                     victim->weaponstuck = 0;
1604                 }
1605             }
1606             victim->weaponactive = -1;
1607             for (unsigned i = 0; i < Person::players.size(); i++) {
1608                 Person::players[i]->wentforweapon = 0;
1609             }
1610         }
1611
1612         if (abs(Random() % 20) == 0) {
1613             if (weaponactive != -1) {
1614                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1615                     if (weapons[victim->weaponids[0]].getType() == staff) {
1616                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1617                     }
1618                     if (weapons[weaponids[0]].getType() == staff) {
1619                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1620                     }
1621
1622                     emit_sound_at(swordstaffsound, coords);
1623                 } else {
1624                     emit_sound_at(metalhitsound, coords);
1625                 }
1626             }
1627
1628             XYZ aim;
1629             Puff(righthand);
1630             target = 0;
1631             frameTarget = 0;
1632             animTarget = staggerbackhighanim;
1633             targetyaw = targetyaw + 180;
1634             target = 0;
1635             aim = DoRotation(facing, 0, 90, 0) * 21;
1636             aim.y += 7;
1637             weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1638             num_weapons--;
1639             if (num_weapons) {
1640                 weaponids[0] = weaponids[num_weapons];
1641                 if (weaponstuck == num_weapons) {
1642                     weaponstuck = 0;
1643                 }
1644             }
1645             weaponactive = -1;
1646             for (unsigned i = 0; i < Person::players.size(); i++) {
1647                 Person::players[i]->wentforweapon = 0;
1648             }
1649         }
1650     }
1651     if (hasvictim) {
1652         if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1653             if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1654                 victim->animTarget = dodgebackanim;
1655                 victim->frameTarget = 0;
1656                 victim->target = 0;
1657
1658                 XYZ rotatetarget;
1659                 rotatetarget = coords - victim->coords;
1660                 Normalise(&rotatetarget);
1661                 victim->targetyaw = -asin(0 - rotatetarget.x);
1662                 victim->targetyaw *= 360 / 6.28;
1663                 if (rotatetarget.z < 0) {
1664                     victim->targetyaw = 180 - victim->targetyaw;
1665                 }
1666
1667                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1668
1669                 victim->lastattack3 = victim->lastattack2;
1670                 victim->lastattack2 = victim->lastattack;
1671                 victim->lastattack = victim->animTarget;
1672             } else {
1673                 victim->animTarget = sweepanim;
1674                 victim->frameTarget = 0;
1675                 victim->target = 0;
1676
1677                 XYZ rotatetarget;
1678                 rotatetarget = coords - victim->coords;
1679                 Normalise(&rotatetarget);
1680                 victim->targetyaw = -asin(0 - rotatetarget.x);
1681                 victim->targetyaw *= 360 / 6.28;
1682                 if (rotatetarget.z < 0) {
1683                     victim->targetyaw = 180 - victim->targetyaw;
1684                 }
1685
1686                 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1687
1688                 victim->lastattack3 = victim->lastattack2;
1689                 victim->lastattack2 = victim->lastattack;
1690                 victim->lastattack = victim->animTarget;
1691             }
1692         }
1693     }
1694
1695     velocity = 0;
1696     victim->velocity = 0;
1697
1698     if (aitype != playercontrolled) {
1699         feint = 0;
1700         if (escapednum < 2) {
1701             int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1702             if ((Random() % chances) == 0) {
1703                 feint = 1;
1704             }
1705         }
1706     }
1707
1708     if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) {
1709         numreversals++;
1710     }
1711 }
1712
1713 /* EFFECT
1714  * get hurt
1715  */
1716 void Person::DoDamage(float howmuch)
1717 {
1718     // stats?
1719     if (id == 0) {
1720         damagetaken += howmuch / power;
1721     } else {
1722         damagedealt += howmuch / power;
1723     }
1724
1725     // reset bonuses
1726     if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1727         bonus = 0;
1728     }
1729
1730     // subtract health
1731     if (!Tutorial::active) {
1732         damage += howmuch / power;
1733         permanentdamage += howmuch / 2 / power;
1734         superpermanentdamage += howmuch / 4 / power;
1735     }
1736     // visual effects
1737     if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) {
1738         DoBlood(1, 255);
1739     }
1740     if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) {
1741         DoBlood(1, 255);
1742     }
1743     spurt = 0;
1744     if (id == 0) {
1745         camerashake += howmuch / 100;
1746         if ((howmuch > 50 && damage > damagetolerance / 2)) {
1747             blackout = damage / damagetolerance;
1748             if (blackout > 1) {
1749                 blackout = 1;
1750             }
1751         }
1752     }
1753
1754     // cancel attack?
1755     if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) {
1756         aitype = attacktypecutoff;
1757     }
1758     if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1759         if (abs(Random() % 2) == 0) {
1760             aitype = gethelptype;
1761             lastseentime = 12;
1762         } else {
1763             aitype = attacktypecutoff;
1764         }
1765         ally = 0;
1766     }
1767
1768     if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1769         XYZ flatvelocity2;
1770         XYZ flatfacing2;
1771         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1772             if (skeleton.free) {
1773                 flatvelocity2 = skeleton.joints[i].velocity;
1774                 flatfacing2 = skeleton.joints[i].position * scale + coords;
1775             } else {
1776                 flatvelocity2 = velocity;
1777                 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1778             }
1779             flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1780             flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1781             flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1782             Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1783             Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1784             Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1785         }
1786
1787         emit_sound_at(splattersound, coords);
1788
1789         skeleton.free = 2;
1790         DoDamage(10000);
1791         RagDoll(0);
1792         if (!dead && creature == wolftype) {
1793             award_bonus(0, Wolfbonus);
1794         }
1795         dead = 2;
1796         coords = 20;
1797     }
1798
1799     // play sounds
1800     if (!Tutorial::active || id == 0) {
1801         if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1802             int whichsound = -1;
1803
1804             if (creature == wolftype) {
1805                 int i = abs(Random() % 2);
1806                 if (i == 0) {
1807                     whichsound = snarlsound;
1808                 }
1809                 if (i == 1) {
1810                     whichsound = snarl2sound;
1811                 }
1812             }
1813             if (creature == rabbittype) {
1814                 int i = abs(Random() % 2);
1815                 if (i == 0) {
1816                     whichsound = rabbitpainsound;
1817                 }
1818                 if (i == 1 && damage > damagetolerance) {
1819                     whichsound = rabbitpain1sound;
1820                 }
1821             }
1822
1823             if (whichsound != -1) {
1824                 emit_sound_at(whichsound, coords);
1825                 addEnvSound(coords);
1826             }
1827         }
1828     }
1829     speechdelay = .3;
1830 }
1831
1832 /* EFFECT
1833  * calculate/animate head facing direction?
1834  */
1835 void Person::DoHead()
1836 {
1837     static XYZ rotatearound;
1838     static XYZ facing;
1839     static float lookspeed = 500;
1840
1841     if (!freeze && !winfreeze) {
1842
1843         //head facing
1844         targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1845         targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1846
1847         while (targetheadyaw > 180) {
1848             targetheadyaw -= 360;
1849         }
1850         while (targetheadyaw < -180) {
1851             targetheadyaw += 360;
1852         }
1853
1854         if (targetheadyaw > 160) {
1855             targetheadpitch = targetheadpitch * -1;
1856         }
1857         if (targetheadyaw < -160) {
1858             targetheadpitch = targetheadpitch * -1;
1859         }
1860         if (targetheadyaw > 160) {
1861             targetheadyaw = targetheadyaw - 180;
1862         }
1863         if (targetheadyaw < -160) {
1864             targetheadyaw = targetheadyaw + 180;
1865         }
1866
1867         if (targetheadpitch > 120) {
1868             targetheadpitch = 120;
1869         }
1870         if (targetheadpitch < -120) {
1871             targetheadpitch = -120;
1872         }
1873         if (targetheadyaw > 120) {
1874             targetheadyaw = 120;
1875         }
1876         if (targetheadyaw < -120) {
1877             targetheadyaw = -120;
1878         }
1879
1880         if (!isIdle()) {
1881             targetheadpitch = 0;
1882         }
1883         if (isIdle()) {
1884             if (targetheadyaw > 80) {
1885                 targetheadyaw = 80;
1886             }
1887             if (targetheadyaw < -80) {
1888                 targetheadyaw = -80;
1889             }
1890             if (targetheadpitch > 50) {
1891                 targetheadpitch = 50;
1892             }
1893             if (targetheadpitch < -50) {
1894                 targetheadpitch = -50;
1895             }
1896         }
1897
1898         if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) {
1899             headyaw = targetheadyaw;
1900         } else if (headyaw > targetheadyaw) {
1901             headyaw -= multiplier * lookspeed;
1902         } else if (headyaw < targetheadyaw) {
1903             headyaw += multiplier * lookspeed;
1904         }
1905
1906         if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) {
1907             headpitch = targetheadpitch;
1908         } else if (headpitch > targetheadpitch) {
1909             headpitch -= multiplier * lookspeed / 2;
1910         } else if (headpitch < targetheadpitch) {
1911             headpitch += multiplier * lookspeed / 2;
1912         }
1913
1914         rotatearound = jointPos(neck);
1915         jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1916
1917         facing = 0;
1918         facing.z = -1;
1919         if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1920             facing = DoRotation(facing, headpitch * .4, 0, 0);
1921             facing = DoRotation(facing, 0, headyaw * .4, 0);
1922         }
1923
1924         if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1925             facing = DoRotation(facing, headpitch * .8, 0, 0);
1926             facing = DoRotation(facing, 0, headyaw * .8, 0);
1927         }
1928
1929         if (animTarget == walkanim) {
1930             facing = DoRotation(facing, headpitch * .6, 0, 0);
1931             facing = DoRotation(facing, 0, headyaw * .6, 0);
1932         }
1933
1934         skeleton.specialforward[0] = facing;
1935         //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1936         for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1937             if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1938                 skeleton.FindRotationMuscle(i, animTarget);
1939             }
1940         }
1941     }
1942 }
1943
1944 /* EFFECT
1945  * ragdolls character?
1946  */
1947 void Person::RagDoll(bool checkcollision)
1948 {
1949     static XYZ change;
1950     static int i;
1951     static float speed;
1952     if (!skeleton.free) {
1953         if (id == 0) {
1954             numfalls++;
1955         }
1956         if (id == 0 && isFlip()) {
1957             numflipfail++;
1958         }
1959
1960         escapednum = 0;
1961
1962         facing = 0;
1963         facing.z = 1;
1964         facing = DoRotation(facing, 0, yaw, 0);
1965
1966         skeleton.freetime = 0;
1967
1968         skeleton.longdead = 0;
1969
1970         skeleton.free = 1;
1971         skeleton.broken = 0;
1972         skeleton.spinny = 1;
1973         freefall = 1;
1974         skeleton.freefall = 1;
1975
1976         if (!isnormal(velocity.x)) {
1977             velocity.x = 0;
1978         }
1979         if (!isnormal(velocity.y)) {
1980             velocity.y = 0;
1981         }
1982         if (!isnormal(velocity.z)) {
1983             velocity.z = 0;
1984         }
1985         if (!isnormal(yaw)) {
1986             yaw = 0;
1987         }
1988         if (!isnormal(coords.x)) {
1989             coords = 0;
1990         }
1991         if (!isnormal(tilt)) {
1992             tilt = 0;
1993         }
1994         if (!isnormal(tilt2)) {
1995             tilt2 = 0;
1996         }
1997
1998         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1999             skeleton.joints[i].delay = 0;
2000             skeleton.joints[i].locked = 0;
2001             skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
2002             if (!isnormal(skeleton.joints[i].position.x)) {
2003                 skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
2004             }
2005             if (!isnormal(skeleton.joints[i].position.x)) {
2006                 skeleton.joints[i].position = coords;
2007             }
2008             skeleton.joints[i].position.y += .1;
2009             skeleton.joints[i].oldposition = skeleton.joints[i].position;
2010             skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
2011         }
2012
2013         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2014             skeleton.joints[i].velocity = 0;
2015             skeleton.joints[i].velchange = 0;
2016         }
2017         skeleton.DoConstraints(&coords, &scale);
2018         if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
2019             skeleton.DoConstraints(&coords, &scale);
2020             skeleton.DoConstraints(&coords, &scale);
2021             skeleton.DoConstraints(&coords, &scale);
2022             skeleton.DoConstraints(&coords, &scale);
2023         }
2024
2025         speed = targetFrame().speed * 2;
2026         if (currentFrame().speed > targetFrame().speed) {
2027             speed = currentFrame().speed * 2;
2028         }
2029         if (transspeed) {
2030             speed = transspeed * 2;
2031         }
2032
2033         speed *= speedmult;
2034
2035         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2036             if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) {
2037                 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
2038             } else {
2039                 skeleton.joints[i].velocity = velocity / scale + facing * 5;
2040             }
2041             change.x = (float)(Random() % 100) / 100;
2042             change.y = (float)(Random() % 100) / 100;
2043             change.z = (float)(Random() % 100) / 100;
2044             skeleton.joints[i].velocity += change;
2045             skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
2046
2047             change.x = (float)(Random() % 100) / 100;
2048             change.y = (float)(Random() % 100) / 100;
2049             change.z = (float)(Random() % 100) / 100;
2050             skeleton.joints[i].velchange += change;
2051             skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
2052         }
2053
2054         if (checkcollision) {
2055             XYZ lowpoint;
2056             XYZ colpoint;
2057             if (!skeleton.joints.empty()) {
2058                 XYZ average;
2059                 average = 0;
2060                 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2061                     average += skeleton.joints[j].position;
2062                 }
2063                 average /= skeleton.joints.size();
2064                 coords += average * scale;
2065                 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
2066                     skeleton.joints[j].position -= average;
2067                 }
2068             }
2069
2070             whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
2071             whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
2072             for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
2073                 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
2074                 lowpoint = coords;
2075                 lowpoint.y += 1;
2076                 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
2077                     coords.x = lowpoint.x;
2078                     coords.z = lowpoint.z;
2079                 }
2080             }
2081         }
2082
2083         yaw = 0;
2084         updatedelay = 0;
2085
2086         velocity = 0;
2087         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
2088             velocity += skeleton.joints[i].velocity * scale;
2089         }
2090         velocity /= skeleton.joints.size();
2091
2092         // drop weapon
2093         if (Random() % 2 == 0) {
2094             if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
2095                 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
2096                 weapons[weaponids[0]].velocity.x += .01;
2097                 num_weapons--;
2098                 if (num_weapons) {
2099                     weaponids[0] = weaponids[num_weapons];
2100                     if (weaponstuck == num_weapons) {
2101                         weaponstuck = 0;
2102                     }
2103                 }
2104                 weaponactive = -1;
2105                 for (unsigned i = 0; i < Person::players.size(); i++) {
2106                     Person::players[i]->wentforweapon = 0;
2107                 }
2108             }
2109         }
2110
2111         animTarget = bounceidleanim;
2112         animCurrent = bounceidleanim;
2113         frameTarget = 0;
2114         frameCurrent = 0;
2115     }
2116 }
2117
2118 /* EFFECT
2119  */
2120 void Person::FootLand(bodypart whichfoot, float opacity)
2121 {
2122     if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
2123         cerr << "FootLand called on wrong bodypart" << endl;
2124         return;
2125     }
2126     static XYZ terrainlight;
2127     static XYZ footvel, footpoint;
2128     if (opacity >= 1 || skiddelay <= 0) {
2129         if (opacity > 1) {
2130             footvel = 0;
2131             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2132             if (distsq(&footpoint, &viewer)) {
2133                 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
2134             }
2135         } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
2136             footvel = velocity / 5;
2137             if (footvel.y < .8) {
2138                 footvel.y = .8;
2139             }
2140             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2141             footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
2142             terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
2143             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2144                 if (environment == snowyenvironment) {
2145                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
2146                     if (detail == 2) {
2147                         terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
2148                     }
2149                 } else if (environment == grassyenvironment) {
2150                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
2151                 } else if (environment == desertenvironment) {
2152                     Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
2153                     if (detail == 2) {
2154                         terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
2155                     }
2156                 }
2157             }
2158         } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
2159             footvel = velocity / 5;
2160             if (footvel.y < .8) {
2161                 footvel.y = .8;
2162             }
2163             footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
2164             if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
2165                 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
2166             }
2167         }
2168     }
2169 }
2170
2171 /* EFFECT
2172  * make a puff effect at a body part (dust effect?)
2173  */
2174 void Person::Puff(int whichlabel)
2175 {
2176     static XYZ footvel, footpoint;
2177
2178     footvel = 0;
2179     footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
2180     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
2181 }
2182
2183 /* EFFECT
2184  * I think I added this in an attempt to clean up code
2185  */
2186 void Person::setTargetAnimation(int animation)
2187 {
2188     animTarget = animation;
2189     frameTarget = 0;
2190     target = 0;
2191 }
2192
2193 /* EFFECT
2194  * MONSTER
2195  * TODO: ???
2196  */
2197 void Person::DoAnimations()
2198 {
2199     if (!skeleton.free) {
2200         static float oldtarget;
2201
2202         if (isIdle() && animCurrent != getIdle()) {
2203             normalsupdatedelay = 0;
2204         }
2205
2206         if (animTarget == tempanim || animCurrent == tempanim) {
2207             Animation::animations[tempanim] = tempanimation;
2208         }
2209         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
2210             float gLoc[3];
2211             gLoc[0] = coords.x;
2212             gLoc[1] = coords.y;
2213             gLoc[2] = coords.z;
2214
2215             if (id == 0) {
2216                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
2217                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
2218             }
2219             if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) {
2220                 landhard = 1;
2221             }
2222             if (!crouchkeydown && velocity.y >= -15) {
2223                 landhard = 0;
2224             }
2225         }
2226         if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
2227             XYZ targfacing;
2228             targfacing = 0;
2229             targfacing.z = 1;
2230
2231             targfacing = DoRotation(targfacing, 0, targetyaw, 0);
2232
2233             if (normaldotproduct(targfacing, velocity) >= -.3) {
2234                 animTarget = flipanim;
2235             } else {
2236                 animTarget = backflipanim;
2237             }
2238             crouchtogglekeydown = 1;
2239             frameTarget = 0;
2240             target = 0;
2241
2242             if (id == 0) {
2243                 numflipped++;
2244             }
2245         }
2246
2247         if (Animation::animations[animTarget].attack != reversed) {
2248             feint = 0;
2249         }
2250         if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
2251             crouchtogglekeydown = 0;
2252             if (aitype == playercontrolled) {
2253                 feint = 0;
2254             }
2255         } else {
2256             if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain)) {
2257                 feint = 1;
2258             }
2259             if (!isFlip()) {
2260                 crouchtogglekeydown = 1;
2261             }
2262         }
2263
2264         if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
2265             if (detail) {
2266                 normalsupdatedelay = 0;
2267             }
2268         }
2269
2270         if (target >= 1) {
2271             if (animTarget == rollanim && frameTarget == 3 && onfire) {
2272                 onfire = 0;
2273                 emit_sound_at(fireendsound, coords);
2274                 pause_sound(stream_firesound);
2275                 deathbleeding = 0;
2276             }
2277
2278             if (animTarget == rabbittacklinganim && frameTarget == 1) {
2279                 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) {
2280                     Reverse();
2281                 }
2282                 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2283                     if (normaldotproduct(victim->facing, facing) > 0) {
2284                         victim->animTarget = rabbittackledbackanim;
2285                     } else {
2286                         victim->animTarget = rabbittackledfrontanim;
2287                     }
2288                     victim->frameTarget = 2;
2289                     victim->target = 0;
2290                     victim->yaw = yaw;
2291                     victim->targetyaw = yaw;
2292                     if (victim->aitype == gethelptype) {
2293                         victim->DoDamage(victim->damagetolerance - victim->damage);
2294                     }
2295                     //victim->DoDamage(30);
2296                     if (creature == wolftype) {
2297                         DoBloodBig(0, 255);
2298                         emit_sound_at(clawslicesound, victim->coords);
2299                         victim->spurt = 1;
2300                         victim->DoBloodBig(1 / victim->armorhead, 210);
2301                     }
2302                     award_bonus(id, TackleBonus,
2303                                 victim->aitype == gethelptype ? 50 : 0);
2304                 }
2305             }
2306
2307             if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2308                 if (weapons[weaponids[0]].getType() == knife) {
2309                     if (weaponactive == -1) {
2310                         weaponactive = 0;
2311                     } else if (weaponactive == 0) {
2312                         weaponactive = -1;
2313                     }
2314
2315                     if (weaponactive == -1) {
2316                         emit_sound_at(knifesheathesound, coords);
2317                     }
2318                     if (weaponactive != -1) {
2319                         emit_sound_at(knifedrawsound, coords, 128);
2320                     }
2321                 }
2322                 drawtogglekeydown = 1;
2323             }
2324             //Footstep sounds
2325             if (!Tutorial::active || id == 0) {
2326                 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2327                     int whichsound = -1;
2328                     if (onterrain) {
2329                         if (terrain.getOpacity(coords.x, coords.z) < .2) {
2330                             if (targetFrame().label == 1) {
2331                                 whichsound = footstepsound;
2332                             } else {
2333                                 whichsound = footstepsound2;
2334                             }
2335                             if (targetFrame().label == 1) {
2336                                 FootLand(leftfoot, 1);
2337                             }
2338                             if (targetFrame().label == 2) {
2339                                 FootLand(rightfoot, 1);
2340                             }
2341                             if (targetFrame().label == 3 && isRun()) {
2342                                 FootLand(rightfoot, 1);
2343                                 FootLand(leftfoot, 1);
2344                             }
2345                         }
2346                         if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2347                             if (targetFrame().label == 1) {
2348                                 whichsound = footstepsound3;
2349                             } else {
2350                                 whichsound = footstepsound4;
2351                             }
2352                         }
2353                     }
2354                     if (!onterrain) {
2355                         if (targetFrame().label == 1) {
2356                             whichsound = footstepsound3;
2357                         } else {
2358                             whichsound = footstepsound4;
2359                         }
2360                     }
2361                     if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2362                         if (Animation::animations[animTarget].attack != neutral) {
2363                             unsigned r = abs(Random() % 3);
2364                             if (r == 0) {
2365                                 whichsound = lowwhooshsound;
2366                             }
2367                             if (r == 1) {
2368                                 whichsound = midwhooshsound;
2369                             }
2370                             if (r == 2) {
2371                                 whichsound = highwhooshsound;
2372                             }
2373                         }
2374                         if (Animation::animations[animTarget].attack == neutral) {
2375                             whichsound = movewhooshsound;
2376                         }
2377                     } else if (targetFrame().label == 4) {
2378                         whichsound = knifeswishsound;
2379                     }
2380                     if (targetFrame().label == 8 && !Tutorial::active) {
2381                         whichsound = landsound2;
2382                     }
2383
2384                     if (whichsound != -1) {
2385                         emit_sound_at(whichsound, coords, 256.);
2386
2387                         if (id == 0) {
2388                             if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2389                                 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2390                                     addEnvSound(coords, 15);
2391                                 } else {
2392                                     addEnvSound(coords, 6);
2393                                 }
2394                             }
2395                         }
2396
2397                         if (targetFrame().label == 3) {
2398                             whichsound--;
2399                             emit_sound_at(whichsound, coords, 128.);
2400                         }
2401                     }
2402                 }
2403             }
2404
2405             //Combat sounds
2406             if (!Tutorial::active || id == 0) {
2407                 if (speechdelay <= 0) {
2408                     if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
2409                         if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2410                             int whichsound = -1;
2411                             if (targetFrame().label == 4 && aitype != playercontrolled) {
2412                                 if (Animation::animations[animTarget].attack != neutral) {
2413                                     unsigned r = abs(Random() % 4);
2414                                     whichsound = PersonType::types[creature].soundsAttack[r];
2415                                     speechdelay = .3;
2416                                 }
2417                             }
2418
2419                             if (whichsound != -1) {
2420                                 emit_sound_at(whichsound, coords);
2421                             }
2422                         }
2423                     }
2424                 }
2425             }
2426
2427             if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2428                 FootLand(leftfoot, 1);
2429                 FootLand(rightfoot, 1);
2430             }
2431
2432             transspeed = 0;
2433             currentoffset = targetoffset;
2434             frameTarget = frameCurrent;
2435             animCurrent = animTarget;
2436             frameTarget++;
2437
2438             if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2439                 for (unsigned i = 0; i < weapons.size(); i++) {
2440                     if (weapons[i].owner == -1) {
2441                         if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2442                             if (distsq(&coords, &weapons[i].position) >= 1) {
2443                                 if (weapons[i].getType() != staff) {
2444                                     emit_sound_at(knifedrawsound, coords, 128.);
2445                                 }
2446
2447                                 takeWeapon(i);
2448                             }
2449                         }
2450                     }
2451                 }
2452             }
2453
2454             if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2455                 for (unsigned i = 0; i < weapons.size(); i++) {
2456                     bool willwork = true;
2457                     if (weapons[i].owner != -1) {
2458                         if (Person::players[weapons[i].owner]->weaponstuck != -1) {
2459                             if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) {
2460                                 if (Person::players[weapons[i].owner]->num_weapons > 1) {
2461                                     willwork = 0;
2462                                 }
2463                             }
2464                         }
2465                     }
2466                     if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) {
2467                         if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2468                             if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2469                                 bool fleshstuck = false;
2470                                 if (weapons[i].owner != -1) {
2471                                     if (victim->weaponstuck != -1) {
2472                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
2473                                             fleshstuck = true;
2474                                         }
2475                                     }
2476                                 }
2477                                 if (fleshstuck) {
2478                                     emit_sound_at(fleshstabremovesound, coords, 128.);
2479                                 } else {
2480                                     if (weapons[i].getType() != staff) {
2481                                         emit_sound_at(knifedrawsound, coords, 128.);
2482                                     }
2483                                 }
2484                                 if (weapons[i].owner != -1) {
2485                                     victim = Person::players[weapons[i].owner];
2486                                     if (victim->num_weapons == 1) {
2487                                         victim->num_weapons = 0;
2488                                     } else {
2489                                         victim->num_weapons = 1;
2490                                     }
2491
2492                                     //victim->weaponactive=-1;
2493                                     victim->skeleton.longdead = 0;
2494                                     victim->skeleton.free = 1;
2495                                     victim->skeleton.broken = 0;
2496
2497                                     for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2498                                         victim->skeleton.joints[j].velchange = 0;
2499                                         victim->skeleton.joints[j].locked = 0;
2500                                     }
2501
2502                                     XYZ relative;
2503                                     relative = 0;
2504                                     relative.y = 10;
2505                                     Normalise(&relative);
2506                                     XYZ footvel, footpoint;
2507                                     footvel = 0;
2508                                     footpoint = weapons[i].position;
2509                                     if (victim->weaponstuck != -1) {
2510                                         if (victim->weaponids[victim->weaponstuck] == int(i)) {
2511                                             if (bloodtoggle) {
2512                                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2513                                             }
2514                                             weapons[i].bloody = 2;
2515                                             weapons[i].blooddrip = 5;
2516                                             victim->weaponstuck = -1;
2517                                         }
2518                                     }
2519                                     if (victim->num_weapons > 0) {
2520                                         if (victim->weaponstuck != 0 && victim->weaponstuck != -1) {
2521                                             victim->weaponstuck = 0;
2522                                         }
2523                                         if (victim->weaponids[0] == int(i)) {
2524                                             victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2525                                         }
2526                                     }
2527
2528                                     victim->jointVel(abdomen) += relative * 6;
2529                                     victim->jointVel(neck) += relative * 6;
2530                                     victim->jointVel(rightshoulder) += relative * 6;
2531                                     victim->jointVel(leftshoulder) += relative * 6;
2532                                 }
2533                                 takeWeapon(i);
2534                             }
2535                         }
2536                     }
2537                 }
2538             }
2539
2540             if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2541                 if (weaponactive == -1) {
2542                     weaponactive = 0;
2543                 } else if (weaponactive == 0) {
2544                     weaponactive = -1;
2545                     if (num_weapons == 2) {
2546                         int buffer;
2547                         buffer = weaponids[0];
2548                         weaponids[0] = weaponids[1];
2549                         weaponids[1] = buffer;
2550                     }
2551                 }
2552                 if (weaponactive == -1) {
2553                     emit_sound_at(knifesheathesound, coords, 128.);
2554                 }
2555                 if (weaponactive != -1) {
2556                     emit_sound_at(knifedrawsound, coords, 128.);
2557                 }
2558             }
2559
2560             if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2561                 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2562                 Normalise(&rotatetarget);
2563                 targetyaw = -asin(0 - rotatetarget.x);
2564                 targetyaw *= 360 / 6.28;
2565                 if (rotatetarget.z < 0) {
2566                     targetyaw = 180 - targetyaw;
2567                 }
2568
2569                 if (animTarget == walljumprightkickanim) {
2570                     targetyaw += 40;
2571                 }
2572                 if (animTarget == walljumpleftkickanim) {
2573                     targetyaw -= 40;
2574                 }
2575             }
2576
2577             bool dojumpattack;
2578             dojumpattack = 0;
2579             if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) {
2580                 dojumpattack = 1;
2581             }
2582             if (hasvictim) {
2583                 if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) {
2584                     dojumpattack = 1;
2585                 }
2586             }
2587             if (!hostile) {
2588                 dojumpattack = 0;
2589             }
2590             if (dojumpattack) {
2591                 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2592                     animTarget = rabbittackleanim;
2593                     frameTarget = 0;
2594                     emit_sound_at(jumpsound, coords);
2595                 }
2596
2597                 float closestdist;
2598                 closestdist = 0;
2599                 int closestid;
2600                 closestid = -1;
2601                 XYZ targetloc;
2602                 targetloc = velocity;
2603                 Normalise(&targetloc);
2604                 targetloc += coords;
2605                 for (unsigned i = 0; i < Person::players.size(); i++) {
2606                     if (i != id) {
2607                         if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2608                             closestdist = distsq(&targetloc, &Person::players[i]->coords);
2609                             closestid = i;
2610                         }
2611                     }
2612                 }
2613                 if (closestid != -1) {
2614                     if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2615                         hasvictim = 1;
2616                         victim = Person::players[closestid];
2617                         coords = victim->coords;
2618                         animCurrent = rabbittacklinganim;
2619                         animTarget = rabbittacklinganim;
2620                         frameCurrent = 0;
2621                         frameTarget = 1;
2622                         XYZ rotatetarget;
2623                         if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2624                             rotatetarget = coords - victim->coords;
2625                             Normalise(&rotatetarget);
2626                             targetyaw = -asin(0 - rotatetarget.x);
2627                             targetyaw *= 360 / 6.28;
2628                             if (rotatetarget.z < 0) {
2629                                 targetyaw = 180 - targetyaw;
2630                             }
2631                         }
2632                         if (animTarget != rabbitrunninganim) {
2633                             emit_sound_at(jumpsound, coords, 128.);
2634                         }
2635                     }
2636                 }
2637             }
2638
2639             //Move impacts
2640             float damagemult = 1 * power;
2641             if (creature == wolftype) {
2642                 damagemult = 2.5 * power;
2643             }
2644             if (hasvictim) {
2645                 damagemult /= victim->damagetolerance / 200;
2646             }
2647             if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2648                 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2649                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2650                         escapednum = 0;
2651                         if (id == 0) {
2652                             camerashake += .4;
2653                         }
2654                         if (Random() % 2 || creature == wolftype) {
2655                             victim->spurt = 1;
2656                             DoBlood(.2, 250);
2657                             if (creature == wolftype) {
2658                                 DoBloodBig(0, 250);
2659                             }
2660                         }
2661                         if (!Tutorial::active) {
2662                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
2663                         }
2664                         if (creature == wolftype) {
2665                             emit_sound_at(clawslicesound, victim->coords, 128.);
2666                             victim->spurt = 1;
2667                             victim->DoBloodBig(2 / victim->armorhead, 175);
2668                         }
2669                         victim->RagDoll(0);
2670                         XYZ relative;
2671                         relative = victim->coords - coords;
2672                         relative.y = 0;
2673                         Normalise(&relative);
2674                         relative = DoRotation(relative, 0, -90, 0);
2675                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2676                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2677                         }
2678                         victim->jointVel(head) += relative * damagemult * 200;
2679                         victim->Puff(head);
2680                         victim->DoDamage(damagemult * 100 / victim->protectionhead);
2681
2682                         SolidHitBonus(id);
2683                     }
2684                 }
2685
2686                 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2687                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2688                         escapednum = 0;
2689                         if (id == 0) {
2690                             camerashake += .4;
2691                         }
2692                         if (Random() % 2 || creature == wolftype) {
2693                             victim->spurt = 1;
2694                             if (creature == wolftype) {
2695                                 DoBloodBig(0, 235);
2696                             }
2697                         }
2698                         emit_sound_at(whooshhitsound, victim->coords);
2699                         if (creature == wolftype) {
2700                             emit_sound_at(clawslicesound, victim->coords, 128.);
2701                             victim->spurt = 1;
2702                             victim->DoBloodBig(2, 175);
2703                         }
2704                         victim->RagDoll(0);
2705                         XYZ relative;
2706                         relative = victim->coords - coords;
2707                         relative.y = 0;
2708                         Normalise(&relative);
2709                         relative.y -= 1;
2710                         Normalise(&relative);
2711                         relative = DoRotation(relative, 0, 90, 0);
2712                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2713                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2714                         }
2715                         victim->jointVel(head) += relative * damagemult * 100;
2716                         victim->Puff(head);
2717                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2718                     }
2719                 }
2720
2721                 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2722                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2723                         escapednum = 0;
2724                         if (id == 0) {
2725                             camerashake += .4;
2726                         }
2727                         victim->spurt = 1;
2728                         DoBlood(.2, 250);
2729                         if (!Tutorial::active) {
2730                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2731                         }
2732                         if (creature == wolftype) {
2733                             emit_sound_at(clawslicesound, victim->coords, 128.);
2734                             victim->spurt = 1;
2735                             victim->DoBloodBig(2 / victim->armorhead, 175);
2736                         }
2737                         victim->RagDoll(0);
2738                         XYZ relative;
2739                         relative = facing;
2740                         relative.y = 0;
2741                         Normalise(&relative);
2742                         relative = DoRotation(relative, 0, -90, 0);
2743                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2744                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2745                         }
2746                         victim->jointVel(head) += relative * damagemult * 200;
2747                         victim->Puff(head);
2748                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2749
2750                         if (victim->damage > victim->damagetolerance) {
2751                             award_bonus(id, style);
2752                         } else {
2753                             SolidHitBonus(id);
2754                         }
2755                     }
2756                 }
2757
2758                 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2759                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2760                         escapednum = 0;
2761                         if (id == 0) {
2762                             camerashake += .4;
2763                         }
2764                         victim->spurt = 1;
2765                         DoBlood(.2, 250);
2766                         if (!Tutorial::active) {
2767                             emit_sound_at(heavyimpactsound, victim->coords, 160.);
2768                         }
2769                         if (creature == wolftype) {
2770                             emit_sound_at(clawslicesound, victim->coords, 128.);
2771                             victim->spurt = 1;
2772                             victim->DoBloodBig(2 / victim->armorhead, 175);
2773                         }
2774                         victim->RagDoll(0);
2775                         XYZ relative;
2776                         relative = facing;
2777                         relative.y = 0;
2778                         Normalise(&relative);
2779                         relative = DoRotation(relative, 0, 90, 0);
2780                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2781                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2782                         }
2783                         victim->jointVel(head) += relative * damagemult * 200;
2784                         victim->Puff(head);
2785                         victim->DoDamage(damagemult * 150 / victim->protectionhead);
2786
2787                         if (victim->damage > victim->damagetolerance) {
2788                             award_bonus(id, style);
2789                         } else {
2790                             SolidHitBonus(id);
2791                         }
2792                     }
2793                 }
2794
2795                 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2796                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2797                         escapednum = 0;
2798                         if (id == 0) {
2799                             camerashake += .4;
2800                         }
2801                         if (Random() % 2) {
2802                             victim->spurt = 1;
2803                             DoBlood(.2, 235);
2804                         }
2805                         emit_sound_at(whooshhitsound, victim->coords);
2806                         victim->RagDoll(0);
2807                         XYZ relative;
2808                         relative = victim->coords - coords;
2809                         relative.y = 0;
2810                         Normalise(&relative);
2811                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2812                             victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2813                         }
2814                         victim->jointVel(head) += relative * damagemult * 100;
2815                         victim->Puff(head);
2816                         victim->DoDamage(damagemult * 50 / victim->protectionhead);
2817                     }
2818                 }
2819
2820                 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2821                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2822                         escapednum = 0;
2823                         if (id == 0) {
2824                             camerashake += .2;
2825                         }
2826                         emit_sound_at(whooshhitsound, victim->coords, 128.);
2827
2828                         victim->skeleton.longdead = 0;
2829                         victim->skeleton.free = 1;
2830                         victim->skeleton.broken = 0;
2831                         victim->skeleton.spinny = 1;
2832
2833                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2834                             victim->skeleton.joints[i].velchange = 0;
2835                             victim->skeleton.joints[i].delay = 0;
2836                             victim->skeleton.joints[i].locked = 0;
2837                             //victim->skeleton.joints[i].velocity=0;
2838                         }
2839
2840                         XYZ relative;
2841                         relative = 0;
2842                         relative.y = 1;
2843                         Normalise(&relative);
2844                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2845                             victim->skeleton.joints[i].velocity.y = relative.y * 10;
2846                             victim->skeleton.joints[i].position.y += relative.y * .3;
2847                             victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2848                             victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2849                         }
2850                         victim->Puff(abdomen);
2851                         victim->jointVel(abdomen).y = relative.y * 400;
2852                     }
2853                 }
2854
2855                 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2856                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2857                         escapednum = 0;
2858                         if (id == 0) {
2859                             camerashake += .4;
2860                         }
2861                         if (!Tutorial::active) {
2862                             emit_sound_at(heavyimpactsound, coords, 128.);
2863                         }
2864                         XYZ relative;
2865                         relative = victim->coords - coords;
2866                         relative.y = 0;
2867                         Normalise(&relative);
2868                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2869                             victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2870                         }
2871                         victim->Puff(abdomen);
2872                         if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2873                             slomo = 1;
2874                             slomodelay = .2;
2875                         }
2876                         victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2877                         victim->jointVel(abdomen) += relative * damagemult * 300;
2878                     }
2879                 }
2880
2881                 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2882                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2883                         escapednum = 0;
2884                         if (id == 0) {
2885                             camerashake += .4;
2886                         }
2887                         if (!Tutorial::active) {
2888                             emit_sound_at(thudsound, coords);
2889                         }
2890
2891                         victim->skeleton.longdead = 0;
2892                         victim->skeleton.free = 1;
2893                         victim->skeleton.broken = 0;
2894                         victim->skeleton.spinny = 1;
2895
2896                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2897                             victim->skeleton.joints[i].velchange = 0;
2898                             //victim->skeleton.joints[i].delay=0;
2899                             victim->skeleton.joints[i].locked = 0;
2900                         }
2901                         XYZ relative;
2902                         relative = victim->coords - coords;
2903                         Normalise(&relative);
2904                         relative.y += .3;
2905                         Normalise(&relative);
2906                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2907                             victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2908                         }
2909                         if (!victim->dead) {
2910                             SolidHitBonus(id);
2911                         }
2912
2913                         victim->Puff(abdomen);
2914                         victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2915                         victim->jointVel(abdomen) += relative * damagemult * 200;
2916                         staggerdelay = .5;
2917                         if (!victim->dead) {
2918                             staggerdelay = 1.2;
2919                         }
2920                     }
2921                 }
2922
2923                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2924
2925                     if (hasvictim) {
2926                         if (!victim->skeleton.free) {
2927                             hasvictim = 0;
2928                         }
2929                     }
2930
2931                     if (!hasvictim) {
2932                         terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2933                         emit_sound_at(knifesheathesound, coords, 128.);
2934                     }
2935
2936                     if (victim && hasvictim) {
2937                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2938
2939                             XYZ where, startpoint, endpoint, movepoint, colpoint;
2940                             float rotationpoint;
2941                             int whichtri;
2942                             if (weapons[weaponids[weaponactive]].getType() == knife) {
2943                                 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2944                                 where -= victim->coords;
2945                                 if (!victim->skeleton.free) {
2946                                     where = DoRotation(where, 0, -victim->yaw, 0);
2947                                 }
2948                                 //where=scale;
2949                                 startpoint = where;
2950                                 startpoint.y += 100;
2951                                 endpoint = where;
2952                                 endpoint.y -= 100;
2953                             }
2954                             if (weapons[weaponids[weaponactive]].getType() == sword) {
2955                                 where = weapons[weaponids[weaponactive]].position;
2956                                 where -= victim->coords;
2957                                 if (!victim->skeleton.free) {
2958                                     where = DoRotation(where, 0, -victim->yaw, 0);
2959                                 }
2960                                 startpoint = where;
2961                                 where = weapons[weaponids[weaponactive]].tippoint;
2962                                 where -= victim->coords;
2963                                 if (!victim->skeleton.free) {
2964                                     where = DoRotation(where, 0, -victim->yaw, 0);
2965                                 }
2966                                 endpoint = where;
2967                             }
2968                             if (weapons[weaponids[weaponactive]].getType() == staff) {
2969                                 where = weapons[weaponids[weaponactive]].position;
2970                                 where -= victim->coords;
2971                                 if (!victim->skeleton.free) {
2972                                     where = DoRotation(where, 0, -victim->yaw, 0);
2973                                 }
2974                                 startpoint = where;
2975                                 where = weapons[weaponids[weaponactive]].tippoint;
2976                                 where -= victim->coords;
2977                                 if (!victim->skeleton.free) {
2978                                     where = DoRotation(where, 0, -victim->yaw, 0);
2979                                 }
2980                                 endpoint = where;
2981                             }
2982                             movepoint = 0;
2983                             rotationpoint = 0;
2984                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2985
2986                             if (whichtri != -1) {
2987                                 if (victim->dead != 2) {
2988                                     victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2989                                     if (!victim->dead) {
2990                                         award_bonus(id, FinishedBonus);
2991                                     }
2992                                 }
2993                                 if (bloodtoggle) {
2994                                     weapons[weaponids[weaponactive]].bloody = 2;
2995                                 }
2996
2997                                 victim->skeleton.longdead = 0;
2998                                 victim->skeleton.free = 1;
2999                                 victim->skeleton.broken = 0;
3000
3001                                 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3002                                     victim->skeleton.joints[i].velchange = 0;
3003                                     victim->skeleton.joints[i].locked = 0;
3004                                     //victim->skeleton.joints[i].velocity=0;
3005                                 }
3006                                 emit_sound_at(fleshstabsound, coords, 128);
3007                             }
3008                             if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
3009                                 weapons[weaponids[weaponactive]].blooddrip += 5;
3010                                 weapons[weaponids[weaponactive]].blooddripdelay = 0;
3011                             }
3012                             if (whichtri == -1) {
3013                                 hasvictim = 0;
3014                                 emit_sound_at(knifesheathesound, coords, 128.);
3015                             }
3016                         }
3017                     }
3018                 }
3019
3020                 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3021                     if (!hasvictim) {
3022                         emit_sound_at(knifedrawsound, coords, 128);
3023                     }
3024
3025                     if (victim && hasvictim) {
3026                         XYZ footvel, footpoint;
3027
3028                         emit_sound_at(fleshstabremovesound, coords, 128.);
3029
3030                         footvel = 0;
3031                         footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3032
3033                         if (weapons[weaponids[weaponactive]].getType() == sword) {
3034                             XYZ where, startpoint, endpoint, movepoint;
3035                             float rotationpoint;
3036                             int whichtri;
3037
3038                             where = weapons[weaponids[weaponactive]].position;
3039                             where -= victim->coords;
3040                             if (!victim->skeleton.free) {
3041                                 where = DoRotation(where, 0, -victim->yaw, 0);
3042                             }
3043                             startpoint = where;
3044                             where = weapons[weaponids[weaponactive]].tippoint;
3045                             where -= victim->coords;
3046                             if (!victim->skeleton.free) {
3047                                 where = DoRotation(where, 0, -victim->yaw, 0);
3048                             }
3049                             endpoint = where;
3050
3051                             movepoint = 0;
3052                             rotationpoint = 0;
3053                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3054                             footpoint += victim->coords;
3055
3056                             if (whichtri == -1) {
3057                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3058                             }
3059                         }
3060                         if (weapons[weaponids[weaponactive]].getType() == staff) {
3061                             XYZ where, startpoint, endpoint, movepoint;
3062                             float rotationpoint;
3063                             int whichtri;
3064
3065                             where = weapons[weaponids[weaponactive]].position;
3066                             where -= victim->coords;
3067                             if (!victim->skeleton.free) {
3068                                 where = DoRotation(where, 0, -victim->yaw, 0);
3069                             }
3070                             startpoint = where;
3071                             where = weapons[weaponids[weaponactive]].tippoint;
3072                             where -= victim->coords;
3073                             if (!victim->skeleton.free) {
3074                                 where = DoRotation(where, 0, -victim->yaw, 0);
3075                             }
3076                             endpoint = where;
3077
3078                             movepoint = 0;
3079                             rotationpoint = 0;
3080                             whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
3081                             footpoint += victim->coords;
3082
3083                             if (whichtri == -1) {
3084                                 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
3085                             }
3086                         }
3087                         hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
3088                         if (hasvictim) {
3089                             if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3090                                 victim->skeleton.longdead = 0;
3091                                 victim->skeleton.free = 1;
3092                                 victim->skeleton.broken = 0;
3093
3094                                 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3095                                     victim->skeleton.joints[i].velchange = 0;
3096                                     victim->skeleton.joints[i].locked = 0;
3097                                     //victim->skeleton.joints[i].velocity=0;
3098                                 }
3099
3100                                 XYZ relative;
3101                                 relative = 0;
3102                                 relative.y = 10;
3103                                 Normalise(&relative);
3104                                 //victim->Puff(abdomen);
3105                                 if (bloodtoggle) {
3106                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
3107                                 }
3108
3109                                 if (victim->bloodloss < victim->damagetolerance) {
3110                                     victim->bloodloss += 1000;
3111                                     victim->bled = 0;
3112                                 }
3113
3114                                 victim->jointVel(abdomen) += relative * damagemult * 20;
3115                             }
3116                         }
3117                     }
3118                     if (!hasvictim && onterrain) {
3119                         weapons[weaponids[weaponactive]].bloody = 0;
3120                         weapons[weaponids[weaponactive]].blooddrip = 0;
3121                     }
3122                 }
3123
3124                 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3125                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
3126                         escapednum = 0;
3127                         if (id == 0) {
3128                             camerashake += .4;
3129                         }
3130                         if (Random() % 2) {
3131                             victim->spurt = 1;
3132                             DoBlood(.2, 235);
3133                         }
3134                         if (!Tutorial::active) {
3135                             emit_sound_at(heavyimpactsound, victim->coords, 128);
3136                         }
3137
3138                         victim->RagDoll(0);
3139                         XYZ relative;
3140                         relative = victim->coords - coords;
3141                         relative.y = 0;
3142                         Normalise(&relative);
3143                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3144                             victim->skeleton.joints[i].velocity = relative * 30;
3145                         }
3146                         victim->jointVel(head) += relative * damagemult * 150;
3147
3148                         victim->frameTarget = 0;
3149                         victim->animTarget = staggerbackhardanim;
3150                         victim->targetyaw = targetyaw + 180;
3151                         victim->target = 0;
3152                         victim->stunned = 1;
3153
3154                         victim->Puff(head);
3155                         victim->Puff(abdomen);
3156                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3157
3158                         SolidHitBonus(id);
3159                     }
3160                 }
3161
3162                 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3163                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
3164                         escapednum = 0;
3165                         if (id == 0) {
3166                             camerashake += .4;
3167                         }
3168                         if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
3169                             if (!Tutorial::active) {
3170                                 emit_sound_at(thudsound, victim->coords);
3171                             }
3172                         } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
3173                             if (!Tutorial::active) {
3174                                 emit_sound_at(whooshhitsound, victim->coords);
3175                             }
3176                         } else {
3177                             if (!Tutorial::active) {
3178                                 emit_sound_at(heavyimpactsound, victim->coords);
3179                             }
3180                         }
3181
3182                         if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) {
3183                             victim->RagDoll(0);
3184                         }
3185                         XYZ relative;
3186                         relative = victim->coords - coords;
3187                         relative.y = 0;
3188                         Normalise(&relative);
3189                         relative.y = .3;
3190                         Normalise(&relative);
3191                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3192                             victim->skeleton.joints[i].velocity = relative * 5;
3193                         }
3194                         victim->jointVel(abdomen) += relative * damagemult * 400;
3195
3196                         victim->frameTarget = 0;
3197                         victim->animTarget = staggerbackhardanim;
3198                         victim->targetyaw = targetyaw + 180;
3199                         victim->target = 0;
3200                         victim->stunned = 1;
3201
3202                         victim->Puff(abdomen);
3203                         victim->DoDamage(damagemult * 60 / victim->protectionhigh);
3204
3205                         SolidHitBonus(id);
3206                     }
3207                 }
3208
3209                 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3210                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3211                         if (victim->id == 0) {
3212                             camerashake += .4;
3213                         }
3214                         emit_sound_at(landsound2, victim->coords);
3215
3216                         Puff(righthand);
3217                     }
3218                 }
3219
3220                 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3221                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
3222                         if (victim->id == 0) {
3223                             camerashake += .4;
3224                         }
3225
3226                         if (weaponactive != -1) {
3227                             if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3228                                 if (weapons[victim->weaponids[0]].getType() == staff) {
3229                                     weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3230                                 }
3231                                 if (weapons[weaponids[0]].getType() == staff) {
3232                                     weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3233                                 }
3234
3235                                 emit_sound_at(swordstaffsound, victim->coords);
3236                             } else {
3237                                 emit_sound_at(metalhitsound, victim->coords);
3238                             }
3239                         }
3240
3241                         //Puff(righthand);
3242                     }
3243                 }
3244
3245                 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3246                     if (weaponactive != -1) {
3247                         escapednum = 0;
3248                         XYZ aim;
3249                         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);
3250                         Normalise(&aim);
3251                         weapons[weaponids[0]].thrown(aim * 50);
3252                         num_weapons--;
3253                         if (num_weapons) {
3254                             weaponids[0] = weaponids[num_weapons];
3255                         }
3256                         weaponactive = -1;
3257                     }
3258                 }
3259
3260                 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3261                     if (hasvictim) {
3262                         if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && /*Animation::animations[victim->animTarget].height!=lowheight&&*/ victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
3263                             escapednum = 0;
3264                             if (!Tutorial::active) {
3265                                 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
3266                             }
3267
3268                             award_bonus(id, Slicebonus);
3269                             if (!Tutorial::active) {
3270                                 emit_sound_at(knifeslicesound, victim->coords);
3271                             }
3272                             //victim->jointVel(abdomen)+=relative*damagemult*200;
3273                             if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
3274                                 if (victim->id != 0 || difficulty == 2) {
3275                                     victim->frameTarget = 0;
3276                                     victim->animTarget = staggerbackhardanim;
3277                                     victim->targetyaw = targetyaw + 180;
3278                                     victim->target = 0;
3279                                 }
3280                             }
3281                             victim->lowreversaldelay = 0;
3282                             victim->highreversaldelay = 0;
3283                             if (aitype != playercontrolled) {
3284                                 weaponmissdelay = .6;
3285                             }
3286
3287                             if (!Tutorial::active) {
3288                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3289                                     weapons[weaponids[weaponactive]].bloody = 1;
3290                                 }
3291                                 weapons[weaponids[weaponactive]].blooddrip += 3;
3292                             }
3293
3294                             XYZ footvel, footpoint;
3295                             footvel = 0;
3296                             if (skeleton.free) {
3297                                 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3298                             } else {
3299                                 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3300                             }
3301                             if (Tutorial::active) {
3302                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
3303                             } else {
3304                                 if (bloodtoggle) {
3305                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
3306                                 }
3307                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
3308                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3309                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3310                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3311                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3312                             }
3313                             victim->DoDamage(damagemult * 0);
3314                         }
3315                     }
3316                 }
3317                 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3318                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
3319                         if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
3320                             award_bonus(id, Slashbonus);
3321                             escapednum = 0;
3322                             if (!Tutorial::active) {
3323                                 if (normaldotproduct(victim->facing, victim->coords - coords) < 0) {
3324                                     victim->DoBloodBig(2 / victim->armorhigh, 190);
3325                                 } else {
3326                                     victim->DoBloodBig(2 / victim->armorhigh, 185);
3327                                 }
3328                                 victim->deathbleeding = 1;
3329                                 emit_sound_at(swordslicesound, victim->coords);
3330                                 victim->frameTarget = 0;
3331                                 victim->animTarget = staggerbackhardanim;
3332                                 victim->targetyaw = targetyaw + 180;
3333                                 victim->target = 0;
3334                                 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3335                                     weapons[weaponids[weaponactive]].bloody = 1;
3336                                 }
3337                                 weapons[weaponids[weaponactive]].blooddrip += 3;
3338
3339                                 float bloodlossamount;
3340                                 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3341                                 victim->bloodloss += bloodlossamount / victim->armorhigh;
3342                                 victim->DoDamage(damagemult * 0);
3343
3344                                 XYZ footvel, footpoint;
3345                                 footvel = 0;
3346                                 if (skeleton.free) {
3347                                     footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3348                                 } else {
3349                                     footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3350                                 }
3351                                 if (bloodtoggle) {
3352                                     Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3353                                 }
3354                                 footvel = DoRotation(facing, 0, 90, 0) * .8;
3355                                 footvel.y -= .3;
3356                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3357                                 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3358                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3359                                 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3360                             }
3361                         } else {
3362                             if (victim->weaponactive != -1) {
3363                                 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3364                                     if (weapons[victim->weaponids[0]].getType() == staff) {
3365                                         weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3366                                     }
3367                                     if (weapons[weaponids[0]].getType() == staff) {
3368                                         weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3369                                     }
3370
3371                                     emit_sound_at(swordstaffsound, victim->coords);
3372                                 } else {
3373                                     emit_sound_at(metalhitsound, victim->coords);
3374                                 }
3375                             }
3376
3377                             XYZ aim;
3378                             victim->Puff(righthand);
3379                             victim->target = 0;
3380                             victim->frameTarget = 0;
3381                             victim->animTarget = staggerbackhighanim;
3382                             victim->targetyaw = targetyaw + 180;
3383                             victim->target = 0;
3384                             aim = DoRotation(facing, 0, 90, 0) * 21;
3385                             aim.y += 7;
3386                             weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3387                             victim->num_weapons--;
3388                             if (victim->num_weapons) {
3389                                 victim->weaponids[0] = victim->weaponids[num_weapons];
3390                                 if (victim->weaponstuck == victim->num_weapons) {
3391                                     victim->weaponstuck = 0;
3392                                 }
3393                             }
3394                             victim->weaponactive = -1;
3395                             for (unsigned i = 0; i < Person::players.size(); i++) {
3396                                 Person::players[i]->wentforweapon = 0;
3397                             }
3398                         }
3399                     }
3400                 }
3401
3402                 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3403                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3404                         if (!Tutorial::active) {
3405                             weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3406                             escapednum = 0;
3407                             if (id == 0) {
3408                                 camerashake += .4;
3409                             }
3410                             if (Random() % 2 || creature == wolftype) {
3411                                 victim->spurt = 1;
3412                             }
3413                             emit_sound_at(staffheadsound, victim->coords);
3414                         }
3415                         victim->RagDoll(0);
3416                         XYZ relative;
3417                         relative = victim->coords - coords;
3418                         relative.y = 0;
3419                         Normalise(&relative);
3420                         relative = DoRotation(relative, 0, 90, 0);
3421                         relative.y -= 1;
3422                         Normalise(&relative);
3423                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3424                             victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3425                         }
3426                         victim->jointVel(head) += relative * damagemult * 230;
3427                         victim->jointVel(neck) += relative * damagemult * 230;
3428                         victim->Puff(head);
3429                         if (!Tutorial::active) {
3430                             victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3431
3432                             award_bonus(id, solidhit, 30);
3433                         }
3434                     }
3435                 }
3436
3437                 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3438                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3439                         if (!Tutorial::active) {
3440                             weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3441                             escapednum = 0;
3442                             if (id == 0) {
3443                                 camerashake += .4;
3444                             }
3445                             if (Random() % 2 || creature == wolftype) {
3446                                 victim->spurt = 1;
3447                             }
3448                             emit_sound_at(staffheadsound, victim->coords);
3449                         }
3450                         victim->RagDoll(0);
3451                         XYZ relative;
3452                         relative = victim->coords - coords;
3453                         relative.y = 0;
3454                         Normalise(&relative);
3455                         relative = DoRotation(relative, 0, -90, 0);
3456                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3457                             victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3458                         }
3459                         victim->jointVel(head) += relative * damagemult * 220;
3460                         victim->jointVel(neck) += relative * damagemult * 220;
3461                         victim->Puff(head);
3462                         if (!Tutorial::active) {
3463                             victim->DoDamage(damagemult * 350 / victim->protectionhead);
3464
3465                             award_bonus(id, solidhit, 60);
3466                         }
3467                     }
3468                 }
3469
3470                 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3471                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3472                         escapednum = 0;
3473                         if (!Tutorial::active) {
3474                             if (!victim->dead) {
3475                                 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3476                             }
3477                             if (id == 0) {
3478                                 camerashake += .4;
3479                             }
3480                             if (Random() % 2 || creature == wolftype) {
3481                                 victim->spurt = 1;
3482                             }
3483                             emit_sound_at(staffbodysound, victim->coords);
3484                         }
3485                         victim->skeleton.longdead = 0;
3486                         victim->skeleton.free = 1;
3487                         victim->skeleton.broken = 0;
3488
3489                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3490                             victim->skeleton.joints[i].velchange = 0;
3491                             victim->skeleton.joints[i].locked = 0;
3492                             //victim->skeleton.joints[i].velocity=0;
3493                         }
3494
3495                         victim->RagDoll(0);
3496                         XYZ relative;
3497                         relative = 0;
3498                         relative.y = -1;
3499                         Normalise(&relative);
3500                         if (!victim->dead) {
3501                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3502                                 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3503                             }
3504                             victim->jointVel(abdomen) += relative * damagemult * 40;
3505                         }
3506                         if (victim->dead) {
3507                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3508                                 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3509                             }
3510                         }
3511                         victim->Puff(abdomen);
3512                         if (!Tutorial::active) {
3513                             victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3514
3515                             if (!victim->dead) {
3516                                 award_bonus(id, solidhit, 40);
3517                             }
3518                         }
3519                     }
3520                 }
3521
3522                 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3523                     if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3524                         escapednum = 0;
3525                         if (id == 0) {
3526                             camerashake += .4;
3527                         }
3528                         XYZ relative;
3529                         relative = victim->coords - coords;
3530                         relative.y = 0;
3531                         Normalise(&relative);
3532
3533                         SolidHitBonus(id);
3534
3535                         if (Animation::animations[victim->animTarget].height == lowheight) {
3536                             if (Random() % 2) {
3537                                 victim->spurt = 1;
3538                                 DoBlood(.2, 250);
3539                             }
3540                             victim->RagDoll(0);
3541                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3542                                 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3543                             }
3544                             victim->jointVel(head) += relative * damagemult * 200;
3545                             if (!Tutorial::active) {
3546                                 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3547                             }
3548                             victim->Puff(head);
3549                             victim->DoDamage(damagemult * 100 / victim->protectionhead);
3550                             if (victim->howactive == typesleeping) {
3551                                 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3552                             }
3553                             if (creature == wolftype) {
3554                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3555                                 victim->spurt = 1;
3556                                 victim->DoBloodBig(2 / victim->armorhead, 175);
3557                             }
3558                         } else {
3559                             if (victim->damage >= victim->damagetolerance) {
3560                                 victim->RagDoll(0);
3561                             }
3562                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3563                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3564                             }
3565                             victim->jointVel(abdomen) += relative * damagemult * 200;
3566                             victim->frameTarget = 0;
3567                             victim->animTarget = staggerbackhighanim;
3568                             victim->targetyaw = targetyaw + 180;
3569                             victim->target = 0;
3570                             if (!Tutorial::active) {
3571                                 emit_sound_at(landsound2, victim->coords, 128.);
3572                             }
3573                             victim->Puff(abdomen);
3574                             victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3575                             if (creature == wolftype) {
3576                                 emit_sound_at(clawslicesound, victim->coords, 128.);
3577                                 victim->spurt = 1;
3578                                 victim->DoBloodBig(2 / victim->armorhigh, 170);
3579                             }
3580                         }
3581                     }
3582                 }
3583
3584                 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3585                     if ((victim->animTarget != jumpupanim) &&
3586                         (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3587                         (victim != this->shared_from_this())) {
3588                         escapednum = 0;
3589                         if (id == 0) {
3590                             camerashake += .2;
3591                         }
3592                         if (!Tutorial::active) {
3593                             emit_sound_at(landsound2, victim->coords, 128.);
3594                         }
3595                         XYZ relative;
3596                         relative = victim->coords - coords;
3597                         relative.y = 0;
3598                         Normalise(&relative);
3599
3600                         if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3601                             victim->RagDoll(0);
3602
3603                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3604                                 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3605                             }
3606                             relative = DoRotation(relative, 0, -90, 0);
3607                             relative.y += .1;
3608                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3609                                 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) {
3610                                     victim->skeleton.joints[i].velocity = relative * 80;
3611                                 }
3612                             }
3613                             victim->Puff(rightankle);
3614                             victim->Puff(leftankle);
3615                             victim->DoDamage(damagemult * 40 / victim->protectionlow);
3616                         } else {
3617                             if (victim->damage >= victim->damagetolerance) {
3618                                 victim->RagDoll(0);
3619                             }
3620                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3621                                 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3622                             }
3623                             relative = DoRotation(relative, 0, -90, 0);
3624                             for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3625                                 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) {
3626                                     victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3627                                 }
3628                             }
3629                             victim->jointVel(abdomen) += relative * damagemult * 200;
3630                             victim->frameTarget = 0;
3631                             victim->animTarget = staggerbackhighanim;
3632                             victim->targetyaw = targetyaw + 180;
3633                             victim->target = 0;
3634                             if (!Tutorial::active) {
3635                                 emit_sound_at(landsound2, victim->coords, 128.);
3636                             }
3637                             victim->Puff(abdomen);
3638                             victim->DoDamage(damagemult * 30 / victim->protectionlow);
3639                         }
3640
3641                         SolidHitBonus(id);
3642                     }
3643                 }
3644             }
3645             if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3646                 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3647                     escapednum = 0;
3648                     if (id == 0) {
3649                         camerashake += .4;
3650                     }
3651                     if (Random() % 2) {
3652                         victim->spurt = 1;
3653                         DoBlood(.2, 230);
3654                     }
3655                     if (!Tutorial::active) {
3656                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3657                     }
3658                     if (creature == wolftype) {
3659                         emit_sound_at(clawslicesound, victim->coords, 128);
3660                         victim->spurt = 1;
3661                         victim->DoBloodBig(2 / victim->armorhigh, 170);
3662                     }
3663                     victim->RagDoll(0);
3664                     XYZ relative;
3665                     relative = victim->coords - oldcoords;
3666                     relative.y = 0;
3667                     Normalise(&relative);
3668                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3669                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3670                     }
3671                     victim->jointVel(abdomen) += relative * damagemult * 200;
3672                     victim->Puff(abdomen);
3673                     victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3674
3675                     award_bonus(id, Reversal);
3676                 }
3677
3678                 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3679                     if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3680                         if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3681                             takeWeapon(victim->weaponids[victim->weaponactive]);
3682                             victim->num_weapons--;
3683                             if (victim->num_weapons > 0) {
3684                                 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3685                             }
3686                             victim->weaponactive = -1;
3687                         }
3688                     }
3689                 }
3690
3691                 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3692                     escapednum = 0;
3693                     if (id == 0) {
3694                         camerashake += .4;
3695                     }
3696                     if (Random() % 2) {
3697                         victim->spurt = 1;
3698                         DoBlood(.2, 230);
3699                     }
3700                     emit_sound_at(whooshhitsound, victim->coords, 128.);
3701                     victim->RagDoll(0);
3702                     XYZ relative;
3703                     relative = victim->coords - oldcoords;
3704                     relative.y = 0;
3705                     Normalise(&relative);
3706                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3707                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3708                     }
3709                     victim->jointVel(abdomen) += relative * damagemult * 200;
3710                     victim->Puff(head);
3711                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3712                 }
3713
3714                 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3715                     escapednum = 0;
3716                     if (id == 0) {
3717                         camerashake += .4;
3718                     }
3719                     if (Random() % 2) {
3720                         victim->spurt = 1;
3721                         DoBlood(.2, 230);
3722                     }
3723
3724                     award_bonus(id, staffreversebonus);
3725
3726                     if (!Tutorial::active) {
3727                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3728                     }
3729                     victim->RagDoll(0);
3730                     award_bonus(id, staffreversebonus); // Huh, again?
3731
3732                     XYZ relative;
3733                     relative = victim->coords - oldcoords;
3734                     relative.y = 0;
3735                     Normalise(&relative);
3736                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3737                         victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3738                     }
3739                     victim->jointVel(abdomen) += relative * damagemult * 200;
3740                     victim->Puff(head);
3741                     victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3742                 }
3743
3744                 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3745                     escapednum = 0;
3746                     victim->RagDoll(1);
3747                     XYZ relative;
3748                     relative = facing;
3749                     relative.y = 0;
3750                     Normalise(&relative);
3751                     relative.y -= .1;
3752                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3753                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3754                     }
3755                     victim->jointVel(lefthand) *= .1;
3756                     victim->jointVel(leftwrist) *= .2;
3757                     victim->jointVel(leftelbow) *= .5;
3758                     victim->jointVel(leftshoulder) *= .7;
3759                     victim->jointVel(righthand) *= .1;
3760                     victim->jointVel(rightwrist) *= .2;
3761                     victim->jointVel(rightelbow) *= .5;
3762                     victim->jointVel(rightshoulder) *= .7;
3763
3764                     victim->Puff(abdomen);
3765                     victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3766
3767                     award_bonus(id, Reversal);
3768
3769                     bool doslice;
3770                     doslice = 0;
3771                     if (weaponactive != -1 || creature == wolftype) {
3772                         doslice = 1;
3773                     }
3774                     if (creature == rabbittype && weaponactive != -1) {
3775                         if (weapons[weaponids[0]].getType() == staff) {
3776                             doslice = 0;
3777                         }
3778                     }
3779                     if (doslice) {
3780                         if (weaponactive != -1) {
3781                             victim->DoBloodBig(2 / victim->armorhigh, 225);
3782                             emit_sound_at(knifeslicesound, victim->coords);
3783                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3784                                 weapons[weaponids[weaponactive]].bloody = 1;
3785                             }
3786                             weapons[weaponids[weaponactive]].blooddrip += 3;
3787                         }
3788                         if (weaponactive == -1 && creature == wolftype) {
3789                             emit_sound_at(clawslicesound, victim->coords, 128.);
3790                             victim->spurt = 1;
3791                             victim->DoBloodBig(2 / victim->armorhigh, 175);
3792                         }
3793                     }
3794                 }
3795
3796                 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3797                     escapednum = 0;
3798                     victim->RagDoll(1);
3799                     XYZ relative;
3800                     relative = facing;
3801                     relative.y = 0;
3802                     Normalise(&relative);
3803                     relative.y -= .1;
3804                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3805                         victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3806                     }
3807                     victim->jointVel(lefthand) *= .1 - 1;
3808                     victim->jointVel(leftwrist) *= .2 - 1;
3809                     victim->jointVel(leftelbow) *= .5 - 1;
3810                     victim->jointVel(leftshoulder) *= .7 - 1;
3811                     victim->jointVel(righthand) *= .1 - 1;
3812                     victim->jointVel(rightwrist) *= .2 - 1;
3813                     victim->jointVel(rightelbow) *= .5 - 1;
3814                     victim->jointVel(rightshoulder) *= .7 - 1;
3815
3816                     award_bonus(id, swordreversebonus);
3817                 }
3818
3819                 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3820                     escapednum = 0;
3821                     if (id == 0) {
3822                         camerashake += .4;
3823                     }
3824                     if (Random() % 2) {
3825                         victim->spurt = 1;
3826                         DoBlood(.2, 230);
3827                     }
3828                     if (!Tutorial::active) {
3829                         emit_sound_at(heavyimpactsound, victim->coords, 128.);
3830                     }
3831                     victim->RagDoll(0);
3832                     XYZ relative;
3833                     relative = victim->coords - oldcoords;
3834                     relative.y = 0;
3835                     Normalise(&relative);
3836                     relative = DoRotation(relative, 0, -90, 0);
3837                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3838                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3839                     }
3840                     victim->jointVel(abdomen) += relative * damagemult * 200;
3841                     victim->Puff(abdomen);
3842                     victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3843
3844                     award_bonus(id, Reversal);
3845                 }
3846
3847                 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3848                     escapednum = 0;
3849                     victim->RagDoll(0);
3850                     victim->skeleton.spinny = 0;
3851                     XYZ relative;
3852                     relative = facing * -1;
3853                     relative.y = -3;
3854                     Normalise(&relative);
3855                     if (victim->id == 0) {
3856                         relative /= 30;
3857                     }
3858                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3859                         victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3860                     }
3861                     victim->damage = victim->damagetolerance;
3862                     victim->permanentdamage = victim->damagetolerance - 1;
3863                     bool doslice;
3864                     doslice = 0;
3865                     if (weaponactive != -1 || creature == wolftype) {
3866                         doslice = 1;
3867                     }
3868                     if (creature == rabbittype && weaponactive != -1) {
3869                         if (weapons[weaponids[0]].getType() == staff) {
3870                             doslice = 0;
3871                         }
3872                     }
3873                     if (doslice) {
3874                         if (weaponactive != -1) {
3875                             victim->DoBloodBig(200, 225);
3876                             emit_sound_at(knifeslicesound, victim->coords);
3877                             if (bloodtoggle) {
3878                                 weapons[weaponids[weaponactive]].bloody = 2;
3879                             }
3880                             weapons[weaponids[weaponactive]].blooddrip += 5;
3881                         }
3882
3883                         if (creature == wolftype && weaponactive == -1) {
3884                             emit_sound_at(clawslicesound, victim->coords, 128.);
3885                             victim->spurt = 1;
3886                             victim->DoBloodBig(2, 175);
3887                         }
3888                     }
3889                     award_bonus(id, spinecrusher);
3890                 }
3891
3892                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3893                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3894                         escapednum = 0;
3895                         if (animTarget == knifefollowanim) {
3896                             victim->DoBloodBig(200, 210);
3897                         }
3898                         if (animTarget == knifesneakattackanim) {
3899                             XYZ footvel, footpoint;
3900                             footvel = 0;
3901                             footpoint = weapons[weaponids[0]].tippoint;
3902                             if (bloodtoggle) {
3903                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3904                             }
3905                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3906                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3907                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3908                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3909                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3910                             victim->DoBloodBig(200, 195);
3911                             award_bonus(id, tracheotomy);
3912                         }
3913                         if (animTarget == knifefollowanim) {
3914                             award_bonus(id, Stabbonus);
3915                             XYZ footvel, footpoint;
3916                             footvel = 0;
3917                             footpoint = weapons[weaponids[0]].tippoint;
3918                             if (bloodtoggle) {
3919                                 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3920                             }
3921                             footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3922                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3923                             Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3924                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3925                             Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3926                         }
3927                         victim->bloodloss += 10000;
3928                         victim->velocity = 0;
3929                         emit_sound_at(fleshstabsound, victim->coords);
3930                         if (bloodtoggle) {
3931                             weapons[weaponids[weaponactive]].bloody = 2;
3932                         }
3933                         weapons[weaponids[weaponactive]].blooddrip += 5;
3934                     }
3935                 }
3936
3937                 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3938                     escapednum = 0;
3939                     victim->velocity = 0;
3940                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3941                         victim->skeleton.joints[i].velocity = 0;
3942                     }
3943                     if (animTarget == knifefollowanim) {
3944                         victim->RagDoll(0);
3945                         for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3946                             victim->skeleton.joints[i].velocity = 0;
3947                         }
3948                     }
3949                     if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3950                         emit_sound_at(fleshstabremovesound, victim->coords);
3951                         if (bloodtoggle) {
3952                             weapons[weaponids[weaponactive]].bloody = 2;
3953                         }
3954                         weapons[weaponids[weaponactive]].blooddrip += 5;
3955
3956                         XYZ footvel, footpoint;
3957                         footvel = 0;
3958                         footpoint = weapons[weaponids[0]].tippoint;
3959                         if (bloodtoggle) {
3960                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3961                         }
3962                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3963                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3964                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3965                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3966                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3967                     }
3968                 }
3969
3970                 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3971                     if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3972                         award_bonus(id, backstab);
3973
3974                         escapednum = 0;
3975
3976                         XYZ footvel, footpoint;
3977                         footvel = 0;
3978                         footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3979                         if (bloodtoggle) {
3980                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3981                         }
3982                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3983                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3984                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3985                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3986                         Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3987                         victim->DoBloodBig(200, 180);
3988                         victim->DoBloodBig(200, 215);
3989                         victim->bloodloss += 10000;
3990                         victim->velocity = 0;
3991                         emit_sound_at(fleshstabsound, victim->coords);
3992                         if (bloodtoggle) {
3993                             weapons[weaponids[weaponactive]].bloody = 2;
3994                         }
3995                         weapons[weaponids[weaponactive]].blooddrip += 5;
3996                     }
3997                 }
3998
3999                 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
4000                     escapednum = 0;
4001                     victim->velocity = 0;
4002                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4003                         victim->skeleton.joints[i].velocity = 0;
4004                     }
4005                     if (weaponactive != -1) {
4006                         emit_sound_at(fleshstabremovesound, victim->coords);
4007                         if (bloodtoggle) {
4008                             weapons[weaponids[weaponactive]].bloody = 2;
4009                         }
4010                         weapons[weaponids[weaponactive]].blooddrip += 5;
4011
4012                         XYZ footvel, footpoint;
4013                         footvel = 0;
4014                         footpoint = weapons[weaponids[0]].tippoint;
4015                         if (bloodtoggle) {
4016                             Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
4017                         }
4018                         footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
4019                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4020                         Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
4021                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
4022                         Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
4023                     }
4024                 }
4025
4026                 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
4027                     escapednum = 0;
4028                     if (id == 0) {
4029                         camerashake += .4;
4030                     }
4031                     if (Random() % 2) {
4032                         victim->spurt = 1;
4033                         DoBlood(.2, 240);
4034                     }
4035                     if (weaponactive == -1) {
4036                         if (!Tutorial::active) {
4037                             emit_sound_at(heavyimpactsound, victim->coords, 128.);
4038                         }
4039                     }
4040                     bool doslice;
4041                     doslice = 0;
4042                     if (weaponactive != -1 || creature == wolftype) {
4043                         doslice = 1;
4044                     }
4045                     if (creature == rabbittype && weaponactive != -1) {
4046                         if (weapons[weaponids[0]].getType() == staff) {
4047                             doslice = 0;
4048                         }
4049                     }
4050                     if (doslice) {
4051                         if (weaponactive != -1) {
4052                             victim->DoBloodBig(2 / victim->armorhead, 225);
4053                             emit_sound_at(knifeslicesound, victim->coords);
4054                             if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
4055                                 weapons[weaponids[weaponactive]].bloody = 1;
4056                             }
4057                             weapons[weaponids[weaponactive]].blooddrip += 3;
4058                         }
4059                         if (weaponactive == -1 && creature == wolftype) {
4060                             emit_sound_at(clawslicesound, victim->coords, 128.);
4061                             victim->spurt = 1;
4062                             victim->DoBloodBig(2 / victim->armorhead, 175);
4063                         }
4064                     }
4065
4066                     award_bonus(id, Reversal);
4067
4068                     victim->Puff(neck);
4069
4070                     XYZ relative;
4071                     relative = facing * -1;
4072                     relative.y = 0;
4073                     Normalise(&relative);
4074                     relative = DoRotation(relative, 0, 90, 0);
4075                     relative.y = .5;
4076                     Normalise(&relative);
4077                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4078                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4079                     }
4080                     victim->jointVel(head) += relative * damagemult * 200;
4081                     if (victim->damage < victim->damagetolerance - 100) {
4082                         victim->velocity = relative * 200;
4083                     }
4084                     victim->DoDamage(damagemult * 100 / victim->protectionhead);
4085                     victim->velocity = 0;
4086                 }
4087
4088                 if (animTarget == sweepreversalanim && ((Animation::animations[animTarget].frames[frameCurrent].label == 9 && victim->damage < victim->damagetolerance) || (Animation::animations[animTarget].frames[frameCurrent].label == 7 && victim->damage > victim->damagetolerance))) {
4089                     escapednum = 0;
4090                     victim->RagDoll(0);
4091                     XYZ relative;
4092                     relative = facing * -1;
4093                     relative.y = 0;
4094                     Normalise(&relative);
4095                     relative = DoRotation(relative, 0, 90, 0);
4096                     relative.y = .5;
4097                     Normalise(&relative);
4098                     for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
4099                         victim->skeleton.joints[i].velocity += relative * damagemult * 20;
4100                     }
4101                     victim->jointVel(head) += relative * damagemult * 200;
4102                 }
4103
4104                 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) {
4105                     if (victim->damage > victim->damagetolerance && bonus != reverseko) {
4106                         award_bonus(id, reverseko);
4107                     }
4108                 }
4109             }
4110
4111             //Animation end
4112             if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
4113                 frameTarget = 0;
4114                 if (wasStop()) {
4115                     animTarget = getIdle();
4116                     FootLand(leftfoot, 1);
4117                     FootLand(rightfoot, 1);
4118                 }
4119                 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
4120                     animTarget = rollanim;
4121                     frameTarget = 3;
4122                     emit_sound_at(movewhooshsound, coords, 128.);
4123                 }
4124                 if (animCurrent == staggerbackhighanim) {
4125                     animTarget = getIdle();
4126                 }
4127                 if (animCurrent == staggerbackhardanim) {
4128                     animTarget = getIdle();
4129                 }
4130                 if (animCurrent == removeknifeanim) {
4131                     animTarget = getIdle();
4132                 }
4133                 if (animCurrent == crouchremoveknifeanim) {
4134                     animTarget = getCrouch();
4135                 }
4136                 if (animCurrent == backhandspringanim) {
4137                     animTarget = getIdle();
4138                 }
4139                 if (animCurrent == dodgebackanim) {
4140                     animTarget = getIdle();
4141                 }
4142                 if (animCurrent == drawleftanim) {
4143                     animTarget = getIdle();
4144                 }
4145                 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
4146                     animTarget = getIdle();
4147                     if (animCurrent == crouchdrawrightanim) {
4148                         animTarget = getCrouch();
4149                     }
4150                     if (weaponactive == -1) {
4151                         weaponactive = 0;
4152                     } else if (weaponactive == 0) {
4153                         weaponactive = -1;
4154                         if (num_weapons == 2) {
4155                             int buffer;
4156                             buffer = weaponids[0];
4157                             weaponids[0] = weaponids[1];
4158                             weaponids[1] = buffer;
4159                         }
4160                     }
4161
4162                     if (weaponactive == -1) {
4163                         emit_sound_at(knifesheathesound, coords, 128.);
4164                     }
4165                     if (weaponactive != -1) {
4166                         emit_sound_at(knifedrawsound, coords, 128.);
4167                     }
4168                 }
4169                 if (animCurrent == rollanim) {
4170                     animTarget = getCrouch();
4171                     FootLand(leftfoot, 1);
4172                     FootLand(rightfoot, 1);
4173                 }
4174                 if (isFlip()) {
4175                     if (animTarget == walljumprightkickanim) {
4176                         targetrot = -190;
4177                     }
4178                     if (animTarget == walljumpleftkickanim) {
4179                         targetrot = 190;
4180                     }
4181                     animTarget = jumpdownanim;
4182                 }
4183                 if (animCurrent == climbanim) {
4184                     animTarget = getCrouch();
4185                     frameTarget = 1;
4186                     coords += facing * .1;
4187                     if (!isnormal(coords.x)) {
4188                         coords = oldcoords;
4189                     }
4190                     oldcoords = coords;
4191                     targetoffset = 0;
4192                     currentoffset = 0;
4193                     grabdelay = 1;
4194                     velocity = 0;
4195                     collided = 0;
4196                     avoidcollided = 0;
4197                 }
4198                 if (animTarget == rabbitkickreversalanim) {
4199                     animTarget = getCrouch();
4200                     lastfeint = 0;
4201                 }
4202                 if (animTarget == jumpreversalanim) {
4203                     animTarget = getCrouch();
4204                     lastfeint = 0;
4205                 }
4206                 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
4207                     if (attackkeydown && animTarget != walljumpfrontanim) {
4208                         int closest = -1;
4209                         float closestdist = -1;
4210                         float distance;
4211                         if (Person::players.size() > 1) {
4212                             for (unsigned i = 0; i < Person::players.size(); i++) {
4213                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4214                                     distance = distsq(&Person::players[i]->coords, &coords);
4215                                     if (closestdist == -1 || distance < closestdist) {
4216                                         closestdist = distance;
4217                                         closest = i;
4218                                     }
4219                                 }
4220                             }
4221                         }
4222                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4223                             victim = Person::players[closest];
4224                             animTarget = walljumprightkickanim;
4225                             frameTarget = 0;
4226                             XYZ rotatetarget = victim->coords - coords;
4227                             Normalise(&rotatetarget);
4228                             yaw = -asin(0 - rotatetarget.x);
4229                             yaw *= 360 / 6.28;
4230                             if (rotatetarget.z < 0) {
4231                                 yaw = 180 - yaw;
4232                             }
4233                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4234                             velocity = (victim->coords - coords) * 4;
4235                             velocity.y += 2;
4236                             transspeed = 40;
4237                         }
4238                     }
4239                     if (animTarget == walljumpbackanim) {
4240                         animTarget = backflipanim;
4241                         frameTarget = 3;
4242                         velocity = facing * -8;
4243                         velocity.y = 4;
4244                         if (id == 0) {
4245                             resume_stream(whooshsound);
4246                         }
4247                     }
4248                     if (animTarget == walljumprightanim) {
4249                         animTarget = rightflipanim;
4250                         frameTarget = 4;
4251                         targetyaw -= 90;
4252                         yaw -= 90;
4253                         velocity = DoRotation(facing, 0, 30, 0) * -8;
4254                         velocity.y = 4;
4255                     }
4256                     if (animTarget == walljumpfrontanim) {
4257                         animTarget = frontflipanim;
4258                         frameTarget = 2;
4259                         //targetyaw-=180;
4260                         ////yaw-=180;
4261                         velocity = facing * 8;
4262                         velocity.y = 4;
4263                     }
4264                     if (id == 0) {
4265                         resume_stream(whooshsound);
4266                     }
4267                 }
4268                 if (animTarget == walljumpleftanim) {
4269                     if (attackkeydown) {
4270                         int closest = -1;
4271                         float closestdist = -1;
4272                         float distance;
4273                         if (Person::players.size() > 1) {
4274                             for (unsigned i = 0; i < Person::players.size(); i++) {
4275                                 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
4276                                     distance = distsq(&Person::players[i]->coords, &coords);
4277                                     if (closestdist == -1 || distance < closestdist) {
4278                                         closestdist = distance;
4279                                         closest = i;
4280                                     }
4281                                 }
4282                             }
4283                         }
4284                         if (closestdist > 0 && closest >= 0 && closestdist < 16) {
4285                             victim = Person::players[closest];
4286                             animTarget = walljumpleftkickanim;
4287                             frameTarget = 0;
4288                             XYZ rotatetarget = victim->coords - coords;
4289                             Normalise(&rotatetarget);
4290                             yaw = -asin(0 - rotatetarget.x);
4291                             yaw *= 360 / 6.28;
4292                             if (rotatetarget.z < 0) {
4293                                 yaw = 180 - yaw;
4294                             }
4295                             targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
4296                             velocity = (victim->coords - coords) * 4;
4297                             velocity.y += 2;
4298                             transspeed = 40;
4299                         }
4300                     }
4301                     if (animTarget != walljumpleftkickanim) {
4302                         animTarget = leftflipanim;
4303                         frameTarget = 4;
4304                         targetyaw += 90;
4305                         yaw += 90;
4306                         velocity = DoRotation(facing, 0, -30, 0) * -8;
4307                         velocity.y = 4;
4308                     }
4309                     if (id == 0) {
4310                         resume_stream(whooshsound);
4311                     }
4312                 }
4313                 if (animTarget == sneakattackanim) {
4314                     animCurrent = getCrouch();
4315                     animTarget = getCrouch();
4316                     frameTarget = 1;
4317                     frameCurrent = 0;
4318                     targetyaw += 180;
4319                     yaw += 180;
4320                     targettilt2 *= -1;
4321                     tilt2 *= -1;
4322                     transspeed = 1000000;
4323                     targetheadyaw += 180;
4324                     coords -= facing * .7;
4325                     if (onterrain) {
4326                         coords.y = terrain.getHeight(coords.x, coords.z);
4327                     }
4328
4329                     lastfeint = 0;
4330                 }
4331                 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
4332                     animTarget = getIdle();
4333                     frameTarget = 0;
4334                     if (onterrain) {
4335                         coords.y = terrain.getHeight(coords.x, coords.z);
4336                     }
4337
4338                     lastfeint = 0;
4339                 }
4340                 if (animCurrent == knifefollowanim) {
4341                     animTarget = getIdle();
4342                     lastfeint = 0;
4343                 }
4344                 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
4345                     float ycoords = oldcoords.y;
4346                     animTarget = getStop();
4347                     targetyaw += 180;
4348                     yaw += 180;
4349                     targettilt2 *= -1;
4350                     tilt2 *= -1;
4351                     transspeed = 1000000;
4352                     targetheadyaw += 180;
4353                     if (!isnormal(coords.x)) {
4354                         coords = oldcoords;
4355                     }
4356                     if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) {
4357                         oldcoords = coords + facing * .5;
4358                     } else if (animCurrent == sweepreversalanim) {
4359                         oldcoords = coords + facing * 1.1;
4360                     } else if (animCurrent == upunchreversalanim) {
4361                         oldcoords = coords + facing * 1.5;
4362                         targetyaw += 180;
4363                         yaw += 180;
4364                         targetheadyaw += 180;
4365                         targettilt2 *= -1;
4366                         tilt2 *= -1;
4367                     } else if (animCurrent == knifeslashreversalanim) {
4368                         oldcoords = coords + facing * .5;
4369                         targetyaw += 90;
4370                         yaw += 90;
4371                         targetheadyaw += 90;
4372                         targettilt2 = 0;
4373                         tilt2 = 0;
4374                     } else if (animCurrent == staffspinhitreversalanim) {
4375                         targetyaw += 180;
4376                         yaw += 180;
4377                         targetheadyaw += 180;
4378                         targettilt2 = 0;
4379                         tilt2 = 0;
4380                     }
4381                     if (onterrain) {
4382                         oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4383                     } else {
4384                         oldcoords.y = ycoords;
4385                     }
4386                     currentoffset = coords - oldcoords;
4387                     targetoffset = 0;
4388                     coords = oldcoords;
4389
4390                     lastfeint = 0;
4391                 }
4392                 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4393                     velocity = 0;
4394                     velocity.y = -5;
4395                     RagDoll(0);
4396                 }
4397                 if (Animation::animations[animTarget].attack == reversed) {
4398                     escapednum++;
4399                     if (animTarget == sweepreversedanim) {
4400                         targetyaw += 90;
4401                     }
4402                     animTarget = backhandspringanim;
4403                     frameTarget = 2;
4404                     emit_sound_at(landsound, coords, 128);
4405
4406                     if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4407                         animTarget = rollanim;
4408                         frameTarget = 5;
4409                         oldcoords = coords;
4410                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4411                         coords.y = oldcoords.y;
4412                     }
4413                     if (animCurrent == knifeslashreversedanim) {
4414                         animTarget = rollanim;
4415                         frameTarget = 0;
4416                         targetyaw += 90;
4417                         yaw += 90;
4418                         oldcoords = coords;
4419                         coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4420                         coords.y = oldcoords.y;
4421                     }
4422                 }
4423                 if (wasFlip()) {
4424                     animTarget = jumpdownanim;
4425                 }
4426                 if (wasLanding()) {
4427                     animTarget = getIdle();
4428                 }
4429                 if (wasLandhard()) {
4430                     animTarget = getIdle();
4431                 }
4432                 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4433                     animTarget = getIdle();
4434                     oldcoords = coords;
4435                     coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4436                     coords.y = oldcoords.y;
4437                     //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4438                     targetoffset.y = coords.y;
4439                     if (onterrain) {
4440                         targetoffset.y = terrain.getHeight(coords.x, coords.z);
4441                     }
4442                     currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4443                     currentoffset.y -= (coords.y - targetoffset.y);
4444                     coords.y = targetoffset.y;
4445                     targetoffset = 0;
4446                     normalsupdatedelay = 0;
4447                 }
4448                 if (animCurrent == upunchanim) {
4449                     animTarget = getStop();
4450                     normalsupdatedelay = 0;
4451                     lastfeint = 0;
4452                 }
4453                 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4454                     targetyaw = yaw;
4455                     bool hasstaff;
4456                     hasstaff = 0;
4457                     if (num_weapons > 0) {
4458                         if (weapons[0].getType() == staff) {
4459                             hasstaff = 1;
4460                         }
4461                     }
4462                     if (!hasstaff) {
4463                         DoDamage(35);
4464                     }
4465                     RagDoll(0);
4466                     lastfeint = 0;
4467                     rabbitkickragdoll = 1;
4468                 }
4469                 if (animCurrent == rabbitkickreversedanim) {
4470                     if (!feint) {
4471                         velocity = 0;
4472                         velocity.y = -10;
4473                         //DoDamage(100);
4474                         RagDoll(0);
4475                         skeleton.spinny = 0;
4476                         SolidHitBonus(!id); // FIXME: tricky id
4477                     }
4478                     if (feint) {
4479                         escapednum++;
4480                         animTarget = rollanim;
4481                         coords += facing;
4482                         if (id == 0) {
4483                             pause_sound(whooshsound);
4484                         }
4485                     }
4486                     lastfeint = 0;
4487                 }
4488                 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4489                     velocity = 0;
4490                     velocity.y = -10;
4491                     RagDoll(0);
4492                     skeleton.spinny = 0;
4493                 }
4494                 if (animCurrent == jumpreversedanim) {
4495                     if (!feint) {
4496                         velocity = 0;
4497                         velocity.y = -10;
4498                         //DoDamage(100);
4499                         RagDoll(0);
4500                         skeleton.spinny = 0;
4501                         SolidHitBonus(!id); // FIXME: tricky id
4502                     }
4503                     if (feint) {
4504                         escapednum++;
4505                         animTarget = rollanim;
4506                         coords += facing * 2;
4507                         if (id == 0) {
4508                             pause_sound(whooshsound);
4509                         }
4510                     }
4511                     lastfeint = 0;
4512                 }
4513
4514                 if (Animation::animations[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
4515                     animTarget = getupfromfrontanim;
4516                     lastfeint = 0;
4517                 } else if (Animation::animations[animCurrent].attack == normalattack) {
4518                     animTarget = getIdle();
4519                     lastfeint = 0;
4520                 }
4521                 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4522                     animTarget = blockhighleftstrikeanim;
4523                 }
4524                 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4525                     animTarget = getIdle();
4526                     lastfeint = 0;
4527                 }
4528                 if (animCurrent == spinkickanim && victim->skeleton.free) {
4529                     if (creature == rabbittype) {
4530                         animTarget = fightidleanim;
4531                     }
4532                 }
4533             }
4534             target = 0;
4535
4536             if (isIdle() && !wasIdle()) {
4537                 normalsupdatedelay = 0;
4538             }
4539
4540             if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4541                 animTarget = jumpdownanim;
4542             }
4543         }
4544         if (!skeleton.free) {
4545             oldtarget = target;
4546             if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4547                 if (!isRun() || !wasRun()) {
4548                     if (targetFrame().speed > currentFrame().speed) {
4549                         target += multiplier * targetFrame().speed * speed * 2;
4550                     }
4551                     if (targetFrame().speed <= currentFrame().speed) {
4552                         target += multiplier * currentFrame().speed * speed * 2;
4553                     }
4554                 }
4555                 if (isRun() && wasRun()) {
4556                     float tempspeed;
4557                     tempspeed = velspeed;
4558                     if (tempspeed < 10 * speedmult) {
4559                         tempspeed = 10 * speedmult;
4560                     }
4561                     /* FIXME - mixed of target and current here, is that intended? */
4562                     target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4563                 }
4564             } else if (transspeed) {
4565                 target += multiplier * transspeed * speed * 2;
4566             } else {
4567                 if (!isRun() || !wasRun()) {
4568                     if (targetFrame().speed > currentFrame().speed) {
4569                         target += multiplier * targetFrame().speed * 2;
4570                     }
4571                     if (targetFrame().speed <= currentFrame().speed) {
4572                         target += multiplier * currentFrame().speed * 2;
4573                     }
4574                 }
4575             }
4576
4577             if (animCurrent != animTarget) {
4578                 target = (target + oldtarget) / 2;
4579             }
4580
4581             if (target > 1) {
4582                 frameCurrent = frameTarget;
4583                 target = 1;
4584             }
4585             oldrot = rot;
4586             rot = targetrot * target;
4587             yaw += rot - oldrot;
4588             if (target == 1) {
4589                 rot = 0;
4590                 oldrot = 0;
4591                 targetrot = 0;
4592             }
4593             if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4594                 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4595             }
4596             if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4597                 //Old rotates
4598                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4599                     skeleton.joints[i].position = currentFrame().joints[i].position;
4600                 }
4601
4602                 skeleton.FindForwards();
4603
4604                 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4605                     if (skeleton.muscles[i].visible) {
4606                         skeleton.FindRotationMuscle(i, animTarget);
4607                     }
4608                 }
4609                 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4610                     if (skeleton.muscles[i].visible) {
4611                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4612                             skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4613                         }
4614                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4615                             skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4616                         }
4617                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4618                             skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4619                         }
4620                     }
4621                 }
4622
4623                 //New rotates
4624                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4625                     skeleton.joints[i].position = targetFrame().joints[i].position;
4626                 }
4627
4628                 skeleton.FindForwards();
4629
4630                 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4631                     if (skeleton.muscles[i].visible) {
4632                         skeleton.FindRotationMuscle(i, animTarget);
4633                     }
4634                 }
4635                 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4636                     if (skeleton.muscles[i].visible) {
4637                         if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) {
4638                             skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4639                         }
4640                         if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) {
4641                             skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4642                         }
4643                         if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) {
4644                             skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4645                         }
4646                         if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) {
4647                             skeleton.muscles[i].newrotate3 -= 360;
4648                         }
4649                         if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) {
4650                             skeleton.muscles[i].newrotate3 += 360;
4651                         }
4652                         if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) {
4653                             skeleton.muscles[i].newrotate2 -= 360;
4654                         }
4655                         if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) {
4656                             skeleton.muscles[i].newrotate2 += 360;
4657                         }
4658                         if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) {
4659                             skeleton.muscles[i].newrotate1 -= 360;
4660                         }
4661                         if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) {
4662                             skeleton.muscles[i].newrotate1 += 360;
4663                         }
4664                     }
4665                 }
4666             }
4667
4668             oldanimCurrent = animCurrent;
4669             oldanimTarget = animTarget;
4670             oldframeTarget = frameTarget;
4671             oldframeCurrent = frameCurrent;
4672
4673             for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4674                 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier;
4675                 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target;
4676             }
4677             offset = currentoffset * (1 - target) + targetoffset * target;
4678             for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4679                 if (skeleton.muscles[i].visible) {
4680                     skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target;
4681                     skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target;
4682                     skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target;
4683                 }
4684             }
4685         }
4686
4687         if (isLanding() && landhard) {
4688             if (id == 0) {
4689                 camerashake += .4;
4690             }
4691             animTarget = getLandhard();
4692             frameTarget = 0;
4693             target = 0;
4694             landhard = 0;
4695             transspeed = 15;
4696         }
4697     }
4698 }
4699
4700 /* EFFECT
4701  * MONSTER
4702  * TODO
4703  */
4704 void Person::DoStuff()
4705 {
4706     static XYZ terrainnormal;
4707     static XYZ flatfacing;
4708     static XYZ flatvelocity;
4709     static float flatvelspeed;
4710     static int bloodsize;
4711     static int startx, starty, endx, endy;
4712     static GLubyte color;
4713     static XYZ bloodvel;
4714
4715     onfiredelay -= multiplier;
4716     if (onfiredelay < 0 && onfire) {
4717         if (Random() % 2 == 0) {
4718             crouchkeydown = 1;
4719         }
4720         onfiredelay = 0.3;
4721     }
4722
4723     crouchkeydowntime += multiplier;
4724     if (!crouchkeydown) {
4725         crouchkeydowntime = 0;
4726     }
4727     jumpkeydowntime += multiplier;
4728     if (!jumpkeydown && skeleton.free) {
4729         jumpkeydowntime = 0;
4730     }
4731
4732     if (hostile || damage > 0 || bloodloss > 0) {
4733         immobile = 0;
4734     }
4735
4736     if (isIdle() || isRun()) {
4737         targetoffset = 0;
4738     }
4739
4740     if (num_weapons == 1 && weaponactive != -1) {
4741         weaponstuck = -1;
4742     }
4743
4744     if (id == 0) {
4745         blooddimamount -= multiplier * .3;
4746     }
4747     speechdelay -= multiplier;
4748     texupdatedelay -= multiplier;
4749     interestdelay -= multiplier;
4750     flamedelay -= multiplier;
4751     parriedrecently -= multiplier;
4752     if (!victim) {
4753         victim = this->shared_from_this();
4754         hasvictim = 0;
4755     }
4756
4757     if (id == 0) {
4758         speed = 1.1 * speedmult;
4759     } else {
4760         speed = 1.0 * speedmult;
4761     }
4762     if (!skeleton.free) {
4763         rabbitkickragdoll = 0;
4764     }
4765
4766     speed *= speedmult;
4767
4768     if (id != 0 && (creature == rabbittype || difficulty != 2)) {
4769         superruntoggle = 0;
4770     }
4771     if (id != 0 && creature == wolftype && difficulty == 2) {
4772         superruntoggle = 0;
4773         if (aitype != passivetype) {
4774             superruntoggle = 1;
4775             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) {
4776                 superruntoggle = 0;
4777             }
4778         }
4779         if (scale < 0.2) {
4780             superruntoggle = 0;
4781         }
4782         if (animTarget == wolfrunninganim && !superruntoggle) {
4783             animTarget = getRun();
4784             frameTarget = 0;
4785         }
4786     }
4787     if (weaponactive == -1 && num_weapons > 0) {
4788         if (weapons[weaponids[0]].getType() == staff) {
4789             weaponactive = 0;
4790         }
4791     }
4792
4793     if (onfire) {
4794         burnt += multiplier;
4795         deathbleeding = 1;
4796         if (burnt > .6) {
4797             burnt = .6;
4798         }
4799         OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4800
4801         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4802             float gLoc[3];
4803             gLoc[0] = coords.x;
4804             gLoc[1] = coords.y;
4805             gLoc[2] = coords.z;
4806
4807             if (id == 0) {
4808                 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc);
4809                 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4810             }
4811         }
4812     }
4813     while (flamedelay < 0 && onfire) {
4814         flamedelay += .006;
4815         int howmany = fabs(Random() % (skeleton.joints.size()));
4816         if (skeleton.free) {
4817             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4818             flatfacing = skeleton.joints[howmany].position * scale + coords;
4819         } else {
4820             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4821             flatvelocity = (coords - oldcoords) / multiplier / 2;
4822         }
4823         Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4824     }
4825
4826     while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4827         flamedelay += .05;
4828         int howmany = fabs(Random() % (skeleton.joints.size()));
4829         if (skeleton.free) {
4830             flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4831             flatfacing = skeleton.joints[howmany].position * scale + coords;
4832         } else {
4833             flatvelocity = (coords - oldcoords) / multiplier / 2;
4834             flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4835         }
4836         Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4837     }
4838
4839     if (bleeding > 0) {
4840         bleeding -= multiplier * .3;
4841         if (bloodtoggle == 2) {
4842             skeleton.drawmodel.textureptr.bind();
4843             if ((bleeding <= 0) && (detail != 2)) {
4844                 DoMipmaps();
4845             }
4846         }
4847     }
4848
4849     if (neckspurtamount > 0) {
4850         neckspurtamount -= multiplier;
4851         neckspurtdelay -= multiplier * 3;
4852         neckspurtparticledelay -= multiplier * 3;
4853         if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4854             spurt = 0;
4855             bloodvel = 0;
4856             if (skeleton.free) {
4857                 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4858                 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4859                 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4860             } else {
4861                 bloodvel.z = 5 * neckspurtamount;
4862                 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4863                 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4864                 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9);
4865             }
4866             neckspurtparticledelay = .05;
4867         }
4868         if (neckspurtdelay < 0) {
4869             neckspurtdelay = 3;
4870         }
4871     }
4872
4873     if (deathbleeding > 0 && dead != 2) {
4874         if (deathbleeding < 5) {
4875             bleeddelay -= deathbleeding * multiplier / 4;
4876         } else {
4877             bleeddelay -= 5 * multiplier / 4;
4878         }
4879         if (bleeddelay < 0 && bloodtoggle) {
4880             bleeddelay = 1;
4881             XYZ bloodvel;
4882             if (bloodtoggle) {
4883                 bloodvel = 0;
4884                 if (skeleton.free) {
4885                     bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4886                     Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4887                 } else {
4888                     bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4889                     Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4890                 }
4891             }
4892         }
4893         bloodloss += deathbleeding * multiplier * 80;
4894         deathbleeding -= multiplier * 1.6;
4895         if (deathbleeding < 0) {
4896             deathbleeding = 0;
4897         }
4898         if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4899             if (weaponactive != -1) {
4900                 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4901                 weapons[weaponids[0]].velocity.x += .01;
4902                 num_weapons--;
4903                 if (num_weapons) {
4904                     weaponids[0] = weaponids[num_weapons];
4905                     if (weaponstuck == num_weapons) {
4906                         weaponstuck = 0;
4907                     }
4908                 }
4909                 weaponactive = -1;
4910                 for (unsigned i = 0; i < Person::players.size(); i++) {
4911                     Person::players[i]->wentforweapon = 0;
4912                 }
4913
4914                 if (id == 0) {
4915                     Game::flash(.5, 0);
4916                 }
4917             }
4918
4919             if (!dead && creature == wolftype) {
4920                 award_bonus(0, Wolfbonus);
4921             }
4922             dead = 2;
4923             if (animTarget == knifefollowedanim && !skeleton.free) {
4924                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4925                     skeleton.joints[i].velocity = 0;
4926                     skeleton.joints[i].velocity.y = -2;
4927                 }
4928             }
4929             if (id != 0 && unconscioustime > .1) {
4930                 numafterkill++;
4931             }
4932
4933             RagDoll(0);
4934         }
4935     }
4936
4937     if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4938         texupdatedelay = .12;
4939
4940         bloodsize = 5 - realtexdetail;
4941
4942         startx = 0;
4943         starty = 0;
4944         startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4945         starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4946         endx = startx + bloodsize;
4947         endy = starty + bloodsize;
4948
4949         if (startx < 0) {
4950             startx = 0;
4951             bleeding = 0;
4952         }
4953         if (starty < 0) {
4954             starty = 0;
4955             bleeding = 0;
4956         }
4957         if (endx > skeleton.skinsize - 1) {
4958             endx = skeleton.skinsize - 1;
4959             bleeding = 0;
4960         }
4961         if (endy > skeleton.skinsize - 1) {
4962             endy = skeleton.skinsize - 1;
4963             bleeding = 0;
4964         }
4965         if (endx < startx) {
4966             endx = startx;
4967         }
4968         if (endy < starty) {
4969             endy = starty;
4970         }
4971
4972         for (int i = startx; i < endx; i++) {
4973             for (int j = starty; j < endy; j++) {
4974                 if (Random() % 2 == 0) {
4975                     color = Random() % 85 + 170;
4976                     if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) {
4977                         skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4978                     }
4979                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4980                     skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4981                 }
4982             }
4983         }
4984         if (detail > 1) {
4985             skeleton.drawmodel.textureptr.bind();
4986             DoMipmaps();
4987         }
4988
4989         if (skeleton.free) {
4990             bleedx += 4 * direction / realtexdetail;
4991             if (detail == 2) {
4992                 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4993             } else {
4994                 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4995             }
4996         } else {
4997             bleedy -= 4 / realtexdetail;
4998             if (detail == 2) {
4999                 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
5000             } else {
5001                 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
5002             }
5003         }
5004     }
5005
5006     if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
5007         righthandmorphness = targetrighthandmorphness;
5008         righthandmorphstart = righthandmorphend;
5009     } else if (righthandmorphness > targetrighthandmorphness) {
5010         righthandmorphness -= multiplier * 4;
5011     } else if (righthandmorphness < targetrighthandmorphness) {
5012         righthandmorphness += multiplier * 4;
5013     }
5014
5015     if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
5016         lefthandmorphness = targetlefthandmorphness;
5017         lefthandmorphstart = lefthandmorphend;
5018     } else if (lefthandmorphness > targetlefthandmorphness) {
5019         lefthandmorphness -= multiplier * 4;
5020     } else if (lefthandmorphness < targetlefthandmorphness) {
5021         lefthandmorphness += multiplier * 4;
5022     }
5023
5024     if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
5025         if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
5026             tailmorphness = targettailmorphness;
5027             tailmorphstart = tailmorphend;
5028         } else if (tailmorphness > targettailmorphness) {
5029             tailmorphness -= multiplier * 10;
5030         } else if (tailmorphness < targettailmorphness) {
5031             tailmorphness += multiplier * 10;
5032         }
5033     }
5034
5035     if (creature == wolftype) {
5036         if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
5037             tailmorphness = targettailmorphness;
5038             tailmorphstart = tailmorphend;
5039         } else if (tailmorphness > targettailmorphness) {
5040             tailmorphness -= multiplier * 2;
5041         } else if (tailmorphness < targettailmorphness) {
5042             tailmorphness += multiplier * 2;
5043         }
5044     }
5045
5046     if (headmorphend == 3 || headmorphstart == 3) {
5047         if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
5048             headmorphness = targetheadmorphness;
5049             headmorphstart = headmorphend;
5050         } else if (headmorphness > targetheadmorphness) {
5051             headmorphness -= multiplier * 7;
5052         } else if (headmorphness < targetheadmorphness) {
5053             headmorphness += multiplier * 7;
5054         }
5055     } else if (headmorphend == 5 || headmorphstart == 5) {
5056         if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
5057             headmorphness = targetheadmorphness;
5058             headmorphstart = headmorphend;
5059         } else if (headmorphness > targetheadmorphness) {
5060             headmorphness -= multiplier * 10;
5061         } else if (headmorphness < targetheadmorphness) {
5062             headmorphness += multiplier * 10;
5063         }
5064     } else {
5065         if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
5066             headmorphness = targetheadmorphness;
5067             headmorphstart = headmorphend;
5068         } else if (headmorphness > targetheadmorphness) {
5069             headmorphness -= multiplier * 4;
5070         } else if (headmorphness < targetheadmorphness) {
5071             headmorphness += multiplier * 4;
5072         }
5073     }
5074
5075     if (abs(chestmorphness - targetchestmorphness) < multiplier) {
5076         chestmorphness = targetchestmorphness;
5077         chestmorphstart = chestmorphend;
5078     } else if (chestmorphness > targetchestmorphness) {
5079         chestmorphness -= multiplier;
5080     } else if (chestmorphness < targetchestmorphness) {
5081         chestmorphness += multiplier;
5082     }
5083
5084     if (dead != 2 && howactive <= typesleeping) {
5085         if (chestmorphstart == 0 && chestmorphend == 0) {
5086             chestmorphness = 0;
5087             targetchestmorphness = 1;
5088             chestmorphend = 3;
5089         }
5090         if (chestmorphstart != 0 && chestmorphend != 0) {
5091             chestmorphness = 0;
5092             targetchestmorphness = 1;
5093             chestmorphend = 0;
5094             if (environment == snowyenvironment) {
5095                 XYZ footpoint;
5096                 XYZ footvel;
5097                 if (skeleton.free) {
5098                     footvel = skeleton.specialforward[0] * -1;
5099                     footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
5100                 } else {
5101                     footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
5102                     footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
5103                 }
5104                 if (animTarget == sleepanim) {
5105                     footvel = DoRotation(footvel, 0, 90, 0);
5106                 }
5107                 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
5108             }
5109         }
5110
5111         if (!dead && howactive < typesleeping) {
5112             blinkdelay -= multiplier * 2;
5113             if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
5114                 headmorphness = 0;
5115                 targetheadmorphness = 1;
5116                 headmorphend = 3;
5117                 blinkdelay = (float)(abs(Random() % 40)) / 5;
5118             }
5119             if (headmorphstart == 3 && headmorphend == 3) {
5120                 headmorphness = 0;
5121                 targetheadmorphness = 1;
5122                 headmorphend = 0;
5123             }
5124         }
5125         if (!dead) {
5126             twitchdelay -= multiplier * 1.5;
5127             if (animTarget != hurtidleanim) {
5128                 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
5129                     headmorphness = 0;
5130                     targetheadmorphness = 1;
5131                     headmorphend = 5;
5132                     twitchdelay = (float)(abs(Random() % 40)) / 5;
5133                 }
5134                 if (headmorphstart == 5 && headmorphend == 5) {
5135                     headmorphness = 0;
5136                     targetheadmorphness = 1;
5137                     headmorphend = 0;
5138                 }
5139             }
5140             if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
5141                 twitchdelay3 -= multiplier * 1;
5142                 if (Random() % 2 == 0) {
5143                     if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
5144                         righthandmorphness = 0;
5145                         targetrighthandmorphness = 1;
5146                         righthandmorphend = 1;
5147                         if (Random() % 2 == 0) {
5148                             twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5149                         }
5150                     }
5151                     if (righthandmorphstart == 1 && righthandmorphend == 1) {
5152                         righthandmorphness = 0;
5153                         targetrighthandmorphness = 1;
5154                         righthandmorphend = 0;
5155                     }
5156                 }
5157                 if (Random() % 2 == 0) {
5158                     if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
5159                         lefthandmorphness = 0;
5160                         targetlefthandmorphness = 1;
5161                         lefthandmorphend = 1;
5162                         twitchdelay3 = (float)(abs(Random() % 40)) / 5;
5163                     }
5164                     if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
5165                         lefthandmorphness = 0;
5166                         targetlefthandmorphness = 1;
5167                         lefthandmorphend = 0;
5168                     }
5169                 }
5170             }
5171         }
5172         if (!dead) {
5173             if (creature == rabbittype) {
5174                 if (howactive < typesleeping) {
5175                     twitchdelay2 -= multiplier * 1.5;
5176                 } else {
5177                     twitchdelay2 -= multiplier * 0.5;
5178                 }
5179                 if (howactive <= typesleeping) {
5180                     if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
5181                         tailmorphness = 0;
5182                         targettailmorphness = 1;
5183                         tailmorphend = 1;
5184                         twitchdelay2 = (float)(abs(Random() % 40)) / 5;
5185                     }
5186                     if (tailmorphstart == 1 && tailmorphend == 1) {
5187                         tailmorphness = 0;
5188                         targettailmorphness = 1;
5189                         tailmorphend = 2;
5190                     }
5191                     if (tailmorphstart == 2 && tailmorphend == 2) {
5192                         tailmorphness = 0;
5193                         targettailmorphness = 1;
5194                         tailmorphend = 0;
5195                     }
5196                 }
5197             }
5198         }
5199     }
5200     if (creature == wolftype) {
5201         twitchdelay2 -= multiplier * 1.5;
5202         if (tailmorphend != 0) {
5203             if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
5204                 tailmorphness = 0;
5205                 targettailmorphness = 1;
5206                 tailmorphend = 0;
5207                 twitchdelay2 = .1;
5208             }
5209         }
5210         if (tailmorphend != 5) {
5211             if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
5212                 tailmorphness = 0;
5213                 targettailmorphness = 1;
5214                 tailmorphend = 5;
5215                 twitchdelay2 = .1;
5216             }
5217         }
5218         if (twitchdelay2 <= 0) {
5219             if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
5220                 tailmorphness = 0;
5221                 targettailmorphness = 1;
5222                 tailmorphend = 1;
5223             }
5224             if (tailmorphstart == 1 && tailmorphend == 1) {
5225                 tailmorphness = 0;
5226                 targettailmorphness = 1;
5227                 tailmorphend = 2;
5228             }
5229             if (tailmorphstart == 2 && tailmorphend == 2) {
5230                 tailmorphness = 0;
5231                 targettailmorphness = 1;
5232                 tailmorphend = 3;
5233             }
5234             if (tailmorphstart == 3 && tailmorphend == 3) {
5235                 tailmorphness = 0;
5236                 targettailmorphness = 1;
5237                 tailmorphend = 4;
5238             }
5239             if (tailmorphstart == 4 && tailmorphend == 4) {
5240                 tailmorphness = 0;
5241                 targettailmorphness = 1;
5242                 tailmorphend = 1;
5243             }
5244         }
5245     }
5246
5247     if (dead != 1) {
5248         unconscioustime = 0;
5249     }
5250
5251     if (dead == 1 || howactive == typesleeping) {
5252         unconscioustime += multiplier;
5253         //If unconscious, close eyes and mouth
5254         if (righthandmorphend != 0) {
5255             righthandmorphness = 0;
5256         }
5257         righthandmorphend = 0;
5258         targetrighthandmorphness = 1;
5259
5260         if (lefthandmorphend != 0) {
5261             lefthandmorphness = 0;
5262         }
5263         lefthandmorphend = 0;
5264         targetlefthandmorphness = 1;
5265
5266         if (headmorphend != 3 && headmorphend != 5) {
5267             headmorphness = 0;
5268         }
5269         headmorphend = 3;
5270         targetheadmorphness = 1;
5271     }
5272
5273     if (howactive > typesleeping) {
5274         XYZ headpoint;
5275         headpoint = coords;
5276         if (bloodtoggle && !bled) {
5277             terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5278             for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5279                 unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5280                 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5281                 float size = .8;
5282                 float opacity = .6;
5283                 float yaw = 0;
5284                 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5285             }
5286         }
5287         bled = 1;
5288     }
5289
5290     if (dead == 2 || howactive > typesleeping) {
5291         //If dead, open mouth and hands
5292         if (righthandmorphend != 0) {
5293             righthandmorphness = 0;
5294         }
5295         righthandmorphend = 0;
5296         targetrighthandmorphness = 1;
5297
5298         if (lefthandmorphend != 0) {
5299             lefthandmorphness = 0;
5300         }
5301         lefthandmorphend = 0;
5302         targetlefthandmorphness = 1;
5303
5304         if (headmorphend != 2) {
5305             headmorphness = 0;
5306         }
5307         headmorphend = 2;
5308         targetheadmorphness = 1;
5309     }
5310
5311     if (stunned > 0 && !dead && headmorphend != 2) {
5312         if (headmorphend != 4) {
5313             headmorphness = 0;
5314         }
5315         headmorphend = 4;
5316         targetheadmorphness = 1;
5317     }
5318
5319     if (damage > damagetolerance && !dead) {
5320
5321         dead = 1;
5322         unconscioustime = 0;
5323
5324         if (creature == wolftype) {
5325             award_bonus(0, Wolfbonus);
5326         }
5327
5328         RagDoll(0);
5329
5330         if (weaponactive != -1) {
5331             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5332             weapons[weaponids[0]].velocity.x += .01;
5333             num_weapons--;
5334             if (num_weapons) {
5335                 weaponids[0] = weaponids[num_weapons];
5336                 if (weaponstuck == num_weapons) {
5337                     weaponstuck = 0;
5338                 }
5339             }
5340             weaponactive = -1;
5341             for (unsigned i = 0; i < Person::players.size(); i++) {
5342                 Person::players[i]->wentforweapon = 0;
5343             }
5344         }
5345
5346         if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
5347             slomo = 1;
5348             slomodelay = .2;
5349         }
5350
5351         damage += 20;
5352     }
5353
5354     if (!dead) {
5355         damage -= multiplier * 13;
5356         permanentdamage -= multiplier * 4;
5357         if (isIdle() || isCrouch()) {
5358             permanentdamage -= multiplier * 4;
5359         }
5360     }
5361     if (damage < 0) {
5362         damage = 0;
5363     }
5364     if (permanentdamage < 0) {
5365         permanentdamage = 0;
5366     }
5367     if (superpermanentdamage < 0) {
5368         superpermanentdamage = 0;
5369     }
5370     if (permanentdamage < superpermanentdamage) {
5371         permanentdamage = superpermanentdamage;
5372     }
5373     if (damage < permanentdamage) {
5374         damage = permanentdamage;
5375     }
5376     if (dead == 1 && damage < damagetolerance) {
5377         dead = 0;
5378         skeleton.free = 1;
5379         damage -= 20;
5380         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5381             skeleton.joints[i].velocity = 0;
5382         }
5383     }
5384     if (permanentdamage > damagetolerance && dead != 2) {
5385         DoBlood(1, 255);
5386
5387         if (weaponactive != -1) {
5388             weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
5389             weapons[weaponids[0]].velocity.x += .01;
5390             num_weapons--;
5391             if (num_weapons) {
5392                 weaponids[0] = weaponids[num_weapons];
5393                 if (weaponstuck == num_weapons) {
5394                     weaponstuck = 0;
5395                 }
5396             }
5397             weaponactive = -1;
5398             for (unsigned i = 0; i < Person::players.size(); i++) {
5399                 Person::players[i]->wentforweapon = 0;
5400             }
5401         }
5402
5403         bled = 0;
5404
5405         if (!dead && creature == wolftype) {
5406             award_bonus(0, Wolfbonus);
5407         }
5408
5409         if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) {
5410             award_bonus(id, touchofdeath);
5411         }
5412         if (id != 0 && unconscioustime > .1) {
5413             numafterkill++;
5414         }
5415
5416         dead = 2;
5417
5418         skeleton.free = 1;
5419
5420         emit_sound_at(breaksound, coords);
5421     }
5422
5423     if (skeleton.free == 1) {
5424         if (id == 0) {
5425             pause_sound(whooshsound);
5426         }
5427
5428         if (!dead) {
5429             //If knocked over, open hands and close mouth
5430             if (righthandmorphend != 0) {
5431                 righthandmorphness = 0;
5432             }
5433             righthandmorphend = 0;
5434             targetrighthandmorphness = 1;
5435
5436             if (lefthandmorphend != 0) {
5437                 lefthandmorphness = 0;
5438             }
5439             lefthandmorphend = 0;
5440             targetlefthandmorphness = 1;
5441
5442             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
5443                 if (headmorphend != 0) {
5444                     headmorphness = 0;
5445                 }
5446                 headmorphend = 0;
5447                 targetheadmorphness = 1;
5448             }
5449         }
5450
5451         skeleton.DoGravity(&scale);
5452         float damageamount;
5453         damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5454         if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) {
5455             award_bonus(id, deepimpact);
5456         }
5457         DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5458
5459         XYZ average;
5460         average = 0;
5461         if (!skeleton.joints.empty()) {
5462             for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5463                 average += skeleton.joints[j].position;
5464             }
5465             average /= skeleton.joints.size();
5466             coords += average * scale;
5467             for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5468                 skeleton.joints[j].position -= average;
5469             }
5470             average /= multiplier;
5471         }
5472
5473         velocity = 0;
5474         for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5475             velocity += skeleton.joints[i].velocity * scale;
5476         }
5477         velocity /= skeleton.joints.size();
5478
5479         if (!isnormal(velocity.x) && velocity.x) {
5480             velocity = 0;
5481         }
5482
5483         if (findLength(&average) < 10 && dead && skeleton.free) {
5484             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5485             if (skeleton.longdead > 2000) {
5486                 if (skeleton.longdead > 6000) {
5487                     if (id == 0) {
5488                         pause_sound(whooshsound);
5489                     }
5490                     skeleton.free = 3;
5491                     DrawSkeleton();
5492                     skeleton.free = 2;
5493                 }
5494                 if (dead == 2 && bloodloss < damagetolerance) {
5495                     XYZ headpoint;
5496                     headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5497                     DoBlood(1, 255);
5498                     if (bloodtoggle && !bled) {
5499                         terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5500                         for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5501                             unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5502                             XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5503                             float size = .2 * 1.2;
5504                             float opacity = .6;
5505                             float yaw = 0;
5506                             Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5507                         }
5508                     }
5509                     bled = 1;
5510                 }
5511                 if (dead == 2 && bloodloss >= damagetolerance) {
5512                     XYZ headpoint;
5513                     headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5514                     if (bleeding <= 0) {
5515                         DoBlood(1, 255);
5516                     }
5517                     if (bloodtoggle && !bled) {
5518                         terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5519                         for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) {
5520                             unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5521                             XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5522                             float size = .8;
5523                             float opacity = .6;
5524                             float yaw = 0;
5525                             Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5526                         }
5527                     }
5528                     bled = 1;
5529                 }
5530             }
5531         }
5532
5533         if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5534             bool canrecover = 1;
5535             XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5536             startpoint = coords;
5537             endpoint = coords;
5538             endpoint.y -= .7;
5539             if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) {
5540                 canrecover = 0;
5541             }
5542             if (velocity.y < -30) {
5543                 canrecover = 0;
5544             }
5545             for (unsigned int i = 0; i < Object::objects.size(); i++) {
5546                 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5547                     colviewer = startpoint;
5548                     coltarget = endpoint;
5549                     if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) {
5550                         canrecover = 0;
5551                     }
5552                 }
5553             }
5554             if (canrecover) {
5555                 skeleton.free = 0;
5556                 XYZ middle;
5557                 middle = 0;
5558
5559                 terrainnormal = jointPos(groin) - jointPos(abdomen);
5560                 if (joint(groin).locked && joint(abdomen).locked) {
5561                     terrainnormal = jointPos(groin) - jointPos(abdomen);
5562                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5563                 }
5564                 if (joint(abdomen).locked && joint(neck).locked) {
5565                     terrainnormal = jointPos(abdomen) - jointPos(neck);
5566                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5567                 }
5568                 if (joint(groin).locked && joint(neck).locked) {
5569                     terrainnormal = jointPos(groin) - jointPos(neck);
5570                     middle = (jointPos(groin) + jointPos(neck)) / 2;
5571                 }
5572                 Normalise(&terrainnormal);
5573
5574                 targetyaw = -asin(0 - terrainnormal.x);
5575                 targetyaw *= 360 / 6.28;
5576                 if (terrainnormal.z < 0) {
5577                     targetyaw = 180 - targetyaw;
5578                 }
5579                 yaw = targetyaw;
5580
5581                 frameTarget = 0;
5582                 animTarget = flipanim;
5583                 crouchtogglekeydown = 1;
5584                 target = 0;
5585                 tilt2 = 0;
5586                 targettilt2 = 0;
5587
5588                 animCurrent = tempanim;
5589                 frameCurrent = 0;
5590                 target = 0;
5591
5592                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5593                     tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5594                     tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5595                 }
5596             }
5597         }
5598
5599         if (findLength(&average) < 10 && !dead && skeleton.free) {
5600             skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5601             if (skeleton.longdead > (damage + 500) * 1.5) {
5602                 if (id == 0) {
5603                     pause_sound(whooshsound);
5604                 }
5605                 skeleton.free = 0;
5606                 velocity = 0;
5607                 XYZ middle;
5608                 middle = 0;
5609
5610                 terrainnormal = jointPos(groin) - jointPos(abdomen);
5611                 if (joint(groin).locked && joint(abdomen).locked) {
5612                     terrainnormal = jointPos(groin) - jointPos(abdomen);
5613                     middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5614                 }
5615                 if (joint(abdomen).locked && joint(neck).locked) {
5616                     terrainnormal = jointPos(abdomen) - jointPos(neck);
5617                     middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5618                 }
5619                 if (joint(groin).locked && joint(neck).locked) {
5620                     terrainnormal = jointPos(groin) - jointPos(neck);
5621                     middle = (jointPos(groin) + jointPos(neck)) / 2;
5622                 }
5623                 Normalise(&terrainnormal);
5624
5625                 targetyaw = -asin(0 - terrainnormal.x);
5626                 targetyaw *= 360 / 6.28;
5627                 if (terrainnormal.z < 0) {
5628                     targetyaw = 180 - targetyaw;
5629                 }
5630                 yaw = targetyaw;
5631
5632                 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5633
5634                 if (skeleton.forward.y < 0) {
5635                     animTarget = getupfrombackanim;
5636                     frameTarget = 0;
5637                     targettilt2 = 0;
5638                 }
5639                 if (skeleton.forward.y > -.3) {
5640                     animTarget = getupfromfrontanim;
5641                     yaw += 180;
5642                     targetyaw += 180;
5643                     targettilt2 *= -1;
5644                     frameTarget = 0;
5645                     targettilt2 = 0;
5646                 }
5647
5648                 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5649                     animTarget = rollanim;
5650                     targetyaw = lookyaw;
5651                     if (id == 0) {
5652                         if (rightkeydown) {
5653                             targetyaw -= 90;
5654                             if (forwardkeydown) {
5655                                 targetyaw += 45;
5656                             }
5657                             if (backkeydown) {
5658                                 targetyaw -= 45;
5659                             }
5660                         }
5661                         if (leftkeydown) {
5662                             targetyaw += 90;
5663                             if (forwardkeydown) {
5664                                 targetyaw -= 45;
5665                             }
5666                             if (backkeydown) {
5667                                 targetyaw += 45;
5668                             }
5669                         }
5670                         if (backkeydown) {
5671                             if (!leftkeydown && !rightkeydown) {
5672                                 targetyaw += 180;
5673                             }
5674                         }
5675                         targetyaw += 180;
5676                     }
5677                 }
5678
5679                 if (abs(targettilt2) > 50) {
5680                     targettilt2 = 0;
5681                 }
5682                 animCurrent = tempanim;
5683                 frameCurrent = 0;
5684                 target = 0;
5685                 tilt2 = targettilt2;
5686
5687                 if (middle.y > 0 && animTarget != rollanim) {
5688                     targetoffset.y = middle.y + 1;
5689                 }
5690
5691                 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5692                     tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5693                     tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5694                 }
5695             }
5696         }
5697
5698         bool hasstaff;
5699         hasstaff = 0;
5700         if (num_weapons > 0) {
5701             if (weapons[0].getType() == staff) {
5702                 hasstaff = 1;
5703             }
5704         }
5705         if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5706             if (velocity.y > -30) {
5707                 XYZ tempvelocity;
5708                 tempvelocity = velocity;
5709                 Normalise(&tempvelocity);
5710                 targetyaw = -asin(0 - tempvelocity.x);
5711                 targetyaw *= 360 / 6.28;
5712                 if (velocity.z < 0) {
5713                     targetyaw = 180 - targetyaw;
5714                 }
5715                 //targetyaw+=180;
5716
5717                 skeleton.free = 0;
5718                 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5719                     animTarget = rollanim;
5720                     frameTarget = 2;
5721                 } else {
5722                     animTarget = backhandspringanim;
5723                     targetyaw += 180;
5724                     frameTarget = 6;
5725                 }
5726                 target = 0;
5727
5728                 emit_sound_at(movewhooshsound, coords, 128.);
5729
5730                 animCurrent = animTarget;
5731                 frameCurrent = frameTarget - 1;
5732                 target = 0;
5733
5734                 velocity = 0;
5735
5736                 yaw = targetyaw;
5737                 tilt = 0;
5738                 targettilt = 0;
5739                 tilt2 = 0;
5740                 targettilt2 = 0;
5741             }
5742         }
5743         if (skeleton.freefall == 0) {
5744             freefall = 0;
5745         }
5746     }
5747
5748     if (aitype != passivetype || skeleton.free == 1) {
5749         if (findLengthfast(&velocity) > .1) {
5750             for (unsigned int i = 0; i < Object::objects.size(); i++) {
5751                 if (Object::objects[i]->type == firetype) {
5752                     if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) {
5753                         if (onfire) {
5754                             if (!Object::objects[i]->onfire) {
5755                                 emit_sound_at(firestartsound, Object::objects[i]->position);
5756                             }
5757                             Object::objects[i]->onfire = 1;
5758                         }
5759                         if (!onfire) {
5760                             if (Object::objects[i]->onfire) {
5761                                 CatchFire();
5762                             }
5763                         }
5764                     }
5765                 }
5766                 if (Object::objects[i]->type == bushtype) {
5767                     if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) {
5768                         if (onfire) {
5769                             if (!Object::objects[i]->onfire) {
5770                                 emit_sound_at(firestartsound, Object::objects[i]->position);
5771                             }
5772                             Object::objects[i]->onfire = 1;
5773                         }
5774
5775                         if (!onfire) {
5776                             if (Object::objects[i]->onfire) {
5777                                 CatchFire();
5778                             }
5779                         }
5780                         if (Object::objects[i]->messedwith <= 0) {
5781                             XYZ tempvel;
5782                             XYZ pos;
5783
5784                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5785
5786                             if (id == 0) {
5787                                 addEnvSound(coords, 4 * findLength(&velocity));
5788                             }
5789
5790                             int howmany = 0;
5791                             if (environment == grassyenvironment) {
5792                                 howmany = findLength(&velocity) * 4;
5793                             }
5794                             if (environment == snowyenvironment) {
5795                                 howmany = findLength(&velocity) * 2;
5796                             }
5797                             if (detail == 2) {
5798                                 if (environment != desertenvironment) {
5799                                     for (int j = 0; j < howmany; j++) {
5800                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5801                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5802                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5803                                         pos = coords;
5804                                         pos.y += 1;
5805                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5806                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5807                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5808                                         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);
5809                                         Sprite::setLastSpriteSpecial(1);
5810                                     }
5811                                 }
5812                             }
5813                             howmany = findLength(&velocity) * 4;
5814                             if (detail == 2) {
5815                                 if (environment == snowyenvironment) {
5816                                     for (int j = 0; j < howmany; j++) {
5817                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5818                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5819                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5820                                         pos = coords;
5821                                         pos.y += 1;
5822                                         pos.x += float(abs(Random() % 100) - 50) / 200;
5823                                         pos.y += float(abs(Random() % 100) - 50) / 200;
5824                                         pos.z += float(abs(Random() % 100) - 50) / 200;
5825                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5826                                         Sprite::setLastSpriteSpecial(2);
5827                                     }
5828                                 }
5829                             }
5830                         }
5831                         Object::objects[i]->rotx += velocity.x * multiplier * 6;
5832                         Object::objects[i]->roty += velocity.z * multiplier * 6;
5833                         Object::objects[i]->messedwith = .5;
5834                     }
5835                 }
5836                 XYZ tempcoord;
5837                 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5838                     if (Object::objects[i]->pitch == 0) {
5839                         tempcoord = coords;
5840                     } else {
5841                         tempcoord = coords - Object::objects[i]->position;
5842                         tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5843                         tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5844                         tempcoord += Object::objects[i]->position;
5845                     }
5846                     if (distsqflat(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 8 && distsq(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 300 && tempcoord.y > Object::objects[i]->position.y + 3 * Object::objects[i]->scale) {
5847                         if (Object::objects[i]->messedwith <= 0) {
5848                             XYZ tempvel;
5849                             XYZ pos;
5850
5851                             emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5852
5853                             if (id == 0) {
5854                                 addEnvSound(coords, 4 * findLength(&velocity));
5855                             }
5856
5857                             int howmany = 0;
5858                             if (environment == grassyenvironment) {
5859                                 howmany = findLength(&velocity) * 4;
5860                             }
5861                             if (environment == snowyenvironment) {
5862                                 howmany = findLength(&velocity) * 2;
5863                             }
5864                             if (detail == 2) {
5865                                 if (environment != desertenvironment) {
5866                                     for (int j = 0; j < howmany; j++) {
5867                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5868                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5869                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5870                                         pos = coords;
5871                                         pos += velocity * .1;
5872                                         pos.y += 1;
5873                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5874                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5875                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5876                                         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);
5877                                         Sprite::setLastSpriteSpecial(1);
5878                                     }
5879                                 }
5880                             }
5881                             howmany = findLength(&velocity) * 4;
5882                             if (detail == 2) {
5883                                 if (environment == snowyenvironment) {
5884                                     for (int j = 0; j < howmany; j++) {
5885                                         tempvel.x = float(abs(Random() % 100) - 50) / 20;
5886                                         tempvel.y = float(abs(Random() % 100) - 50) / 20;
5887                                         tempvel.z = float(abs(Random() % 100) - 50) / 20;
5888                                         pos = coords;
5889                                         pos += velocity * .1;
5890                                         pos.y += 1;
5891                                         pos.x += float(abs(Random() % 100) - 50) / 150;
5892                                         pos.y += float(abs(Random() % 100) - 50) / 150;
5893                                         pos.z += float(abs(Random() % 100) - 50) / 150;
5894                                         Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5895                                         Sprite::setLastSpriteSpecial(2);
5896                                     }
5897                                 }
5898                             }
5899                         }
5900                         Object::objects[i]->messedwith = .5;
5901                     }
5902                 }
5903             }
5904         }
5905     }
5906
5907     if (!skeleton.free) {
5908         bool play;
5909         play = 0;
5910         if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) {
5911             play = 1;
5912         }
5913         if (hasvictim) {
5914             if (aitype != passivetype && victim->skeleton.free && !victim->dead) {
5915                 play = 1;
5916             }
5917         }
5918         if (Tutorial::active && id != 0) {
5919             play = 0;
5920         }
5921         if (play && aitype != playercontrolled) {
5922             int whichsound = -1;
5923             if (speechdelay <= 0) {
5924                 unsigned int i = abs(Random() % 4);
5925                 if (i < 2) {
5926                     whichsound = PersonType::types[creature].soundsTalk[i];
5927                 }
5928             }
5929             speechdelay = .3;
5930
5931             if (whichsound != -1) {
5932                 emit_sound_at(whichsound, coords);
5933             }
5934         }
5935
5936         if (animTarget == staggerbackhighanim) {
5937             staggerdelay = 1;
5938         }
5939         if (animTarget == staggerbackhardanim) {
5940             staggerdelay = 1;
5941         }
5942         staggerdelay -= multiplier;
5943         if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) {
5944             hasvictim = 1;
5945         }
5946         if (velocity.y < -30 && animTarget == jumpdownanim) {
5947             RagDoll(0);
5948         }
5949         if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5950             animTarget = getIdle();
5951             frameTarget = 0;
5952             target = 0;
5953         }
5954         weaponmissdelay -= multiplier;
5955         highreversaldelay -= multiplier;
5956         lowreversaldelay -= multiplier;
5957         lastcollide -= multiplier;
5958         skiddelay -= multiplier;
5959         if (!isnormal(velocity.x) && velocity.x) {
5960             velocity = 0;
5961         }
5962         if (!isnormal(targettilt) && targettilt) {
5963             targettilt = 0;
5964         }
5965         if (!isnormal(targettilt2) && targettilt2) {
5966             targettilt2 = 0;
5967         }
5968         if (!isnormal(targetyaw) && targetyaw) {
5969             targetyaw = 0;
5970         }
5971
5972         if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5973             //open hands and close mouth
5974             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5975                 righthandmorphness = 0;
5976                 righthandmorphend = 0;
5977                 targetrighthandmorphness = 1;
5978             }
5979
5980             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5981                 lefthandmorphness = 0;
5982                 lefthandmorphend = 0;
5983                 targetlefthandmorphness = 1;
5984             }
5985
5986             if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5987                 headmorphness = 0;
5988                 headmorphend = 0;
5989                 targetheadmorphness = 1;
5990             }
5991         }
5992
5993         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) {
5994             //open hands and mouth
5995             if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5996                 righthandmorphness = 0;
5997                 righthandmorphend = 0;
5998                 targetrighthandmorphness = 1;
5999             }
6000
6001             if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
6002                 lefthandmorphness = 0;
6003                 lefthandmorphend = 0;
6004                 targetlefthandmorphness = 1;
6005             }
6006
6007             if (headmorphend != 1 && headmorphness == targetheadmorphness) {
6008                 headmorphness = 0;
6009                 headmorphend = 1;
6010                 targetheadmorphness = 1;
6011             }
6012         }
6013
6014         if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
6015             //close hands and mouth
6016             if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
6017                 righthandmorphness = 0;
6018                 righthandmorphend = 1;
6019                 targetrighthandmorphness = 1;
6020             }
6021
6022             if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
6023                 lefthandmorphness = 0;
6024                 lefthandmorphend = 1;
6025                 targetlefthandmorphness = 1;
6026             }
6027
6028             if (headmorphend != 0 && headmorphness == targetheadmorphness) {
6029                 headmorphness = 0;
6030                 headmorphend = 0;
6031                 targetheadmorphness = 1;
6032             }
6033         }
6034
6035         if (animTarget == spinkickanim ||
6036             animTarget == staffspinhitreversalanim ||
6037             animTarget == staffspinhitreversedanim ||
6038             animTarget == staffhitreversalanim ||
6039             animTarget == staffhitreversedanim ||
6040             animTarget == hurtidleanim ||
6041             animTarget == winduppunchanim ||
6042             animTarget == swordslashreversalanim ||
6043             animTarget == swordslashreversedanim ||
6044             animTarget == knifeslashreversalanim ||
6045             animTarget == knifeslashreversedanim ||
6046             animTarget == knifethrowanim ||
6047             animTarget == knifefollowanim ||
6048             animTarget == knifefollowedanim ||
6049             animTarget == killanim ||
6050             animTarget == dropkickanim ||
6051             animTarget == upunchanim ||
6052             animTarget == knifeslashstartanim ||
6053             animTarget == swordslashanim ||
6054             animTarget == staffhitanim ||
6055             animTarget == staffspinhitanim ||
6056             animTarget == staffgroundsmashanim ||
6057             animTarget == spinkickreversalanim ||
6058             animTarget == sweepreversalanim ||
6059             animTarget == lowkickanim ||
6060             animTarget == sweepreversedanim ||
6061             animTarget == rabbitkickreversalanim ||
6062             animTarget == rabbitkickreversedanim ||
6063             animTarget == jumpreversalanim ||
6064             animTarget == jumpreversedanim) {
6065             //close hands and yell
6066             if (righthandmorphend != 1 &&
6067                 righthandmorphness == targetrighthandmorphness) {
6068                 righthandmorphness = 0;
6069                 righthandmorphend = 1;
6070                 targetrighthandmorphness = 1;
6071             }
6072
6073             if (lefthandmorphend != 1 &&
6074                 lefthandmorphness == targetlefthandmorphness) {
6075                 lefthandmorphness = 0;
6076                 lefthandmorphend = 1;
6077                 targetlefthandmorphness = 1;
6078             }
6079
6080             if (headmorphend != 2 && headmorphness == targetheadmorphness) {
6081                 headmorphness = 1;
6082                 headmorphend = 2;
6083                 targetheadmorphness = 1;
6084             }
6085         }
6086
6087         bool behind;
6088         behind = 0;
6089         if (hasvictim) {
6090             if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
6091                 (victim->aitype != searchtype) && (aitype != passivetype) &&
6092                 (aitype != searchtype) && (victim->id < Person::players.size())) {
6093                 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
6094             }
6095         }
6096
6097         if (!dead && animTarget != hurtidleanim) {
6098             if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
6099                 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
6100                     headmorphend = 4;
6101                     //headmorphness=1;
6102                     targetheadmorphness = 1;
6103                 }
6104             }
6105         }
6106
6107         if (weaponactive != -1) {
6108             if (weapons[weaponids[weaponactive]].getType() != staff) {
6109                 righthandmorphstart = 1;
6110                 righthandmorphend = 1;
6111             }
6112             if (weapons[weaponids[weaponactive]].getType() == staff) {
6113                 righthandmorphstart = 2;
6114                 righthandmorphend = 2;
6115             }
6116             targetrighthandmorphness = 1;
6117         }
6118
6119         terrainnormal = terrain.getNormal(coords.x, coords.z);
6120
6121         if (Animation::animations[animTarget].attack != reversal) {
6122             if (!isnormal(coords.x)) {
6123                 coords = oldcoords;
6124             }
6125             oldcoords = coords;
6126         }
6127
6128         flatfacing = 0;
6129         flatfacing.z = 1;
6130
6131         flatfacing = DoRotation(flatfacing, 0, yaw, 0);
6132         facing = flatfacing;
6133         ReflectVector(&facing, terrainnormal);
6134         Normalise(&facing);
6135
6136         if (isRun() ||
6137             animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
6138             if (onterrain) {
6139                 targettilt2 = -facing.y * 20;
6140             } else {
6141                 targettilt2 = 0;
6142             }
6143         }
6144         onterrain = 0;
6145         if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) {
6146             targettilt2 = 0;
6147         }
6148         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6149             flatvelocity = velocity;
6150             flatvelocity.y = 0;
6151             flatvelspeed = findLength(&flatvelocity);
6152             targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
6153             targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
6154             if (velocity.y < 0) {
6155                 targettilt2 *= -1;
6156             }
6157             if (velocity.y < 0) {
6158                 targettilt *= -1;
6159             }
6160             if (targettilt > 25) {
6161                 targettilt = 25;
6162             }
6163             if (targettilt < -25) {
6164                 targettilt = -25;
6165             }
6166         }
6167
6168         if (targettilt2 > 45) {
6169             targettilt2 = 45;
6170         }
6171         if (targettilt2 < -45) {
6172             targettilt2 = -45;
6173         }
6174         if (abs(tilt2 - targettilt2) < multiplier * 400) {
6175             tilt2 = targettilt2;
6176         } else if (tilt2 > targettilt2) {
6177             tilt2 -= multiplier * 400;
6178         } else if (tilt2 < targettilt2) {
6179             tilt2 += multiplier * 400;
6180         }
6181         if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
6182             if (tilt2 > 25) {
6183                 tilt2 = 25;
6184             }
6185             if (tilt2 < -25) {
6186                 tilt2 = -25;
6187             }
6188         }
6189
6190         if (!isnormal(targettilt) && targettilt) {
6191             targettilt = 0;
6192         }
6193         if (!isnormal(targettilt2) && targettilt2) {
6194             targettilt2 = 0;
6195         }
6196
6197         //Running velocity
6198         if (animTarget == rabbittackleanim) {
6199             velocity += facing * multiplier * speed * 700 * scale;
6200             velspeed = findLength(&velocity);
6201             if (velspeed > speed * 65 * scale) {
6202                 velocity /= velspeed;
6203                 velspeed = speed * 65 * scale;
6204                 velocity *= velspeed;
6205             }
6206             velocity.y += gravity * multiplier * 20;
6207             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6208             velspeed = findLength(&velocity);
6209             velocity = flatfacing * velspeed;
6210         }
6211         if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
6212             if (isRun() || animTarget == rabbitkickanim) {
6213                 velocity += facing * multiplier * speed * 700 * scale;
6214                 velspeed = findLength(&velocity);
6215                 if (velspeed > speed * 45 * scale) {
6216                     velocity /= velspeed;
6217                     velspeed = speed * 45 * scale;
6218                     velocity *= velspeed;
6219                 }
6220                 velocity.y += gravity * multiplier * 20;
6221                 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6222                 velspeed = findLength(&velocity);
6223                 if (velspeed < speed * 30 * scale) {
6224                     velspeed = speed * 30 * scale;
6225                 }
6226                 velocity = flatfacing * velspeed;
6227             }
6228         } else if (isRun()) {
6229             velocity += facing * multiplier * speed * 700 * scale;
6230             velspeed = findLength(&velocity);
6231             if (creature == rabbittype) {
6232                 if (velspeed > speed * 55 * scale) {
6233                     velocity /= velspeed;
6234                     velspeed = speed * 55 * scale;
6235                     velocity *= velspeed;
6236                 }
6237             }
6238             if (creature == wolftype) {
6239                 if (velspeed > speed * 75 * scale) {
6240                     velocity /= velspeed;
6241                     velspeed = speed * 75 * scale;
6242                     velocity *= velspeed;
6243                 }
6244             }
6245             velocity.y += gravity * multiplier * 20;
6246             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6247             velspeed = findLength(&velocity);
6248             velocity = flatfacing * velspeed;
6249         }
6250
6251         if (animTarget == rollanim && targetFrame().label != 6) {
6252             velocity += facing * multiplier * speed * 700 * scale;
6253             velspeed = findLength(&velocity);
6254             if (velspeed > speed * 45 * scale) {
6255                 velocity /= velspeed;
6256                 velspeed = speed * 45 * scale;
6257                 velocity *= velspeed;
6258             }
6259             velocity.y += gravity * multiplier * 20;
6260             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6261             velspeed = findLength(&velocity);
6262             velocity = flatfacing * velspeed;
6263         }
6264
6265         if (animTarget == sneakanim || animTarget == walkanim) {
6266             velocity += facing * multiplier * speed * 700 * scale;
6267             velspeed = findLength(&velocity);
6268             if (velspeed > speed * 12 * scale) {
6269                 velocity /= velspeed;
6270                 velspeed = speed * 12 * scale;
6271                 velocity *= velspeed;
6272             }
6273             velocity.y += gravity * multiplier * 20;
6274             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6275             velspeed = findLength(&velocity);
6276             velocity = flatfacing * velspeed;
6277         }
6278
6279         if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
6280             velocity += facing * multiplier * speed * 700 * scale;
6281             velspeed = findLength(&velocity);
6282             if (velspeed > speed * 2 * scale) {
6283                 velocity /= velspeed;
6284                 velspeed = speed * 2 * scale;
6285                 velocity *= velspeed;
6286             }
6287             velocity.y += gravity * multiplier * 20;
6288             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6289             velspeed = findLength(&velocity);
6290             velocity = flatfacing * velspeed;
6291         }
6292
6293         if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
6294             velocity -= facing * multiplier * speed * 700 * scale;
6295             velspeed = findLength(&velocity);
6296             if (velspeed > speed * 2 * scale) {
6297                 velocity /= velspeed;
6298                 velspeed = speed * 2 * scale;
6299                 velocity *= velspeed;
6300             }
6301             velocity.y += gravity * multiplier * 20;
6302             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6303             velspeed = findLength(&velocity);
6304             velocity = flatfacing * velspeed * -1;
6305         }
6306
6307         if (animTarget == fightsidestep) {
6308             velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
6309             velspeed = findLength(&velocity);
6310             if (velspeed > speed * 12 * scale) {
6311                 velocity /= velspeed;
6312                 velspeed = speed * 12 * scale;
6313                 velocity *= velspeed;
6314             }
6315             velocity.y += gravity * multiplier * 20;
6316             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6317             velspeed = findLength(&velocity);
6318             velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
6319         }
6320
6321         if (animTarget == staggerbackhighanim) {
6322             coords -= facing * multiplier * speed * 16 * scale;
6323             velocity = 0;
6324         }
6325         if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
6326             coords -= facing * multiplier * speed * 20 * scale;
6327             velocity = 0;
6328         }
6329
6330         if (animTarget == backhandspringanim) {
6331             //coords-=facing*multiplier*50*scale;
6332             velocity += facing * multiplier * speed * 700 * scale * -1;
6333             velspeed = findLength(&velocity);
6334             if (velspeed > speed * 50 * scale) {
6335                 velocity /= velspeed;
6336                 velspeed = speed * 50 * scale;
6337                 velocity *= velspeed;
6338             }
6339             velocity.y += gravity * multiplier * 20;
6340             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6341             velspeed = findLength(&velocity);
6342             velocity = flatfacing * velspeed * -1;
6343         }
6344         if (animTarget == dodgebackanim) {
6345             //coords-=facing*multiplier*50*scale;
6346             velocity += facing * multiplier * speed * 700 * scale * -1;
6347             velspeed = findLength(&velocity);
6348             if (velspeed > speed * 60 * scale) {
6349                 velocity /= velspeed;
6350                 velspeed = speed * 60 * scale;
6351                 velocity *= velspeed;
6352             }
6353             velocity.y += gravity * multiplier * 20;
6354             ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
6355             velspeed = findLength(&velocity);
6356             velocity = flatfacing * velspeed * -1;
6357         }
6358
6359         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6360             velspeed = findLength(&velocity);
6361         }
6362
6363         if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
6364             velocity.y += gravity * multiplier;
6365         }
6366
6367         if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6368             coords += velocity * multiplier;
6369         }
6370
6371         if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6372             if (isFlip() && targetFrame().label == 7) {
6373                 RagDoll(0);
6374             }
6375
6376             if (animTarget == jumpupanim) {
6377                 jumppower = -4;
6378                 animTarget = getIdle();
6379             }
6380             target = 0;
6381             frameTarget = 0;
6382             onterrain = 1;
6383
6384             if (id == 0) {
6385                 pause_sound(whooshsound);
6386                 OPENAL_SetVolume(channels[whooshsound], 0);
6387             }
6388
6389             if (animTarget == jumpdownanim || isFlip()) {
6390                 if (isFlip()) {
6391                     jumppower = -4;
6392                 }
6393                 animTarget = getLanding();
6394                 emit_sound_at(landsound, coords, 128.);
6395
6396                 if (id == 0) {
6397                     addEnvSound(coords);
6398                 }
6399             }
6400         }
6401
6402         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) {
6403             coords.y += gravity * multiplier * 2;
6404         }
6405         if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
6406             coords.y = terrain.getHeight(coords.x, coords.z);
6407             onterrain = 1;
6408         }
6409
6410         if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || Animation::animations[animTarget].attack || (animTarget == rollanim && targetFrame().label == 6)) {
6411             velspeed = findLength(&velocity);
6412             velocity.y = 0;
6413             if (velspeed < multiplier * 300 * scale) {
6414                 velocity = 0;
6415             } else {
6416                 velocity -= velocity / velspeed * multiplier * 300 * scale;
6417             }
6418             if (velspeed > 5 && (isLanding() || isLandhard())) {
6419                 skiddingdelay += multiplier;
6420                 if (skiddelay <= 0) {
6421                     FootLand(leftfoot, .5);
6422                     FootLand(rightfoot, .5);
6423                     skiddelay = .02;
6424                 }
6425             } else {
6426                 skiddingdelay = 0;
6427             }
6428         }
6429
6430         if (isLandhard()) {
6431             velspeed = findLength(&velocity);
6432             velocity = 0;
6433             if (velspeed > 5 && (isLanding() || isLandhard())) {
6434                 skiddingdelay += multiplier;
6435                 if (skiddelay <= 0) {
6436                     FootLand(leftfoot, .5);
6437                     FootLand(rightfoot, .5);
6438                     skiddelay = .02;
6439                 }
6440             } else {
6441                 skiddingdelay = 0;
6442             }
6443         }
6444
6445         if (skiddingdelay < 0) {
6446             skiddingdelay += multiplier;
6447         }
6448         if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
6449             skiddingdelay = -1;
6450             if (!onterrain || environment == grassyenvironment) {
6451                 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
6452             } else {
6453                 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
6454             }
6455         }
6456
6457         if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
6458             terrainnormal = victim->coords - coords;
6459             Normalise(&terrainnormal);
6460             targetyaw = -asin(0 - terrainnormal.x);
6461             targetyaw *= 360 / 6.28;
6462             if (terrainnormal.z < 0) {
6463                 targetyaw = 180 - targetyaw;
6464             }
6465             targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
6466         }
6467
6468         if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
6469             targetyaw = victim->targetyaw;
6470         }
6471         if (animTarget == rabbittacklinganim) {
6472             coords = victim->coords;
6473         }
6474     }
6475     skeleton.oldfree = skeleton.free;
6476
6477     XYZ midterrain;
6478     midterrain = 0;
6479     midterrain.x = terrain.size * terrain.scale / 2;
6480     midterrain.z = terrain.size * terrain.scale / 2;
6481     if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
6482         XYZ tempposit;
6483         tempposit = coords - midterrain;
6484         tempposit.y = 0;
6485         Normalise(&tempposit);
6486         tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
6487         coords.x = tempposit.x + midterrain.x;
6488         coords.z = tempposit.z + midterrain.z;
6489     }
6490 }
6491
6492 /* EFFECT
6493  * inverse kinematics helper function
6494  */
6495 void IKHelper(Person* p, float interp)
6496 {
6497     XYZ point, change, change2;
6498     float heightleft, heightright;
6499
6500     // TODO: implement localToWorld and worldToLocal
6501     //       but keep in mind it won't be the same math if player is ragdolled or something
6502     //       - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6503     //       then comb through code for places where to use it
6504
6505     // point = localToWorld(jointPos(leftfoot))
6506     point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6507     // adjust height of foot
6508     heightleft = terrain.getHeight(point.x, point.z) + .04;
6509     point.y = heightleft;
6510     change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6511     change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6512     // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6513     p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6514     // move ankle along with foot
6515     p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6516     // average knee pos between old and new pos
6517     p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6518
6519     // do same as above for right leg
6520     point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6521     heightright = terrain.getHeight(point.x, point.z) + .04;
6522     point.y = heightright;
6523     change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6524     change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6525     p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6526     p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6527     p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6528
6529     // fix up skeleton now that we've moved body parts?
6530     p->skeleton.DoConstraints(&p->coords, &p->scale);
6531 }
6532
6533 /* EFFECT
6534  * MONSTER
6535  * TODO: ???
6536  */
6537 int Person::DrawSkeleton()
6538 {
6539     int oldplayerdetail;
6540     if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6541         if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6542             calcrot = 1;
6543         }
6544
6545         if (headless) {
6546             headmorphness = 0;
6547             headmorphstart = 6;
6548             headmorphend = 6;
6549         }
6550
6551         glAlphaFunc(GL_GREATER, 0.0001);
6552         XYZ terrainlight;
6553         float terrainheight;
6554         float distance;
6555         if (!isnormal(yaw)) {
6556             yaw = 0;
6557         }
6558         if (!isnormal(tilt)) {
6559             tilt = 0;
6560         }
6561         if (!isnormal(tilt2)) {
6562             tilt2 = 0;
6563         }
6564         oldplayerdetail = playerdetail;
6565         playerdetail = 0;
6566         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6567             playerdetail = 1;
6568         }
6569         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6570             playerdetail = 1;
6571         }
6572         if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6573             playerdetail = 1;
6574         }
6575         if (id == 0) {
6576             playerdetail = 1;
6577         }
6578         if (playerdetail != oldplayerdetail) {
6579             updatedelay = 0;
6580             normalsupdatedelay = 0;
6581         }
6582         static float updatedelaychange;
6583         static float morphness;
6584         static float framemult;
6585         if (calcrot) {
6586             skeleton.FindForwards();
6587             if (howactive == typesittingwall) {
6588                 skeleton.specialforward[1] = 0;
6589                 skeleton.specialforward[1].z = 1;
6590             }
6591         }
6592         static XYZ mid;
6593         static float M[16];
6594         static int k;
6595         static int weaponattachmuscle;
6596         static int weaponrotatemuscle;
6597         static XYZ weaponpoint;
6598         static int start, endthing;
6599         if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6600             if (!isSleeping() && !isSitting()) {
6601                 // TODO: give these meaningful names
6602                 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6603                 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6604
6605                 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6606                     IKHelper(this, 1);
6607                     if (creature == wolftype) {
6608                         IKHelper(this, 1);
6609                     }
6610                 }
6611
6612                 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6613                     IKHelper(this, target);
6614                     if (creature == wolftype) {
6615                         IKHelper(this, target);
6616                     }
6617                 }
6618
6619                 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6620                     IKHelper(this, 1 - target);
6621                     if (creature == wolftype) {
6622                         IKHelper(this, 1 - target);
6623                     }
6624                 }
6625             }
6626
6627             if (!skeleton.free && (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || targetFrame().label == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping())) {
6628                 DoHead();
6629             } else {
6630                 targetheadyaw = -targetyaw;
6631                 targetheadpitch = 0;
6632                 if (Animation::animations[animTarget].attack == 3) {
6633                     targetheadyaw += 180;
6634                 }
6635             }
6636             for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6637                 skeleton.drawmodel.vertex[i] = 0;
6638                 skeleton.drawmodel.vertex[i].y = 999;
6639             }
6640             for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6641                 skeleton.drawmodellow.vertex[i] = 0;
6642                 skeleton.drawmodellow.vertex[i].y = 999;
6643             }
6644             for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6645                 skeleton.drawmodelclothes.vertex[i] = 0;
6646                 skeleton.drawmodelclothes.vertex[i].y = 999;
6647             }
6648             for (unsigned int i = 0; i < skeleton.muscles.size(); i++) {
6649                 // convenience renames
6650                 const int p1 = skeleton.muscles[i].parent1->label;
6651                 const int p2 = skeleton.muscles[i].parent2->label;
6652
6653                 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6654                     morphness = 0;
6655                     start = 0;
6656                     endthing = 0;
6657
6658                     if (p1 == righthand || p2 == righthand) {
6659                         morphness = righthandmorphness;
6660                         start = righthandmorphstart;
6661                         endthing = righthandmorphend;
6662                     }
6663                     if (p1 == lefthand || p2 == lefthand) {
6664                         morphness = lefthandmorphness;
6665                         start = lefthandmorphstart;
6666                         endthing = lefthandmorphend;
6667                     }
6668                     if (p1 == head || p2 == head) {
6669                         morphness = headmorphness;
6670                         start = headmorphstart;
6671                         endthing = headmorphend;
6672                     }
6673                     if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6674                         morphness = chestmorphness;
6675                         start = chestmorphstart;
6676                         endthing = chestmorphend;
6677                     }
6678                     if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6679                         morphness = tailmorphness;
6680                         start = tailmorphstart;
6681                         endthing = tailmorphend;
6682                     }
6683                     if (calcrot) {
6684                         skeleton.FindRotationMuscle(i, animTarget);
6685                     }
6686                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6687                     glMatrixMode(GL_MODELVIEW);
6688                     glPushMatrix();
6689                     glLoadIdentity();
6690                     if (!skeleton.free) {
6691                         glRotatef(tilt2, 1, 0, 0);
6692                     }
6693                     if (!skeleton.free) {
6694                         glRotatef(tilt, 0, 0, 1);
6695                     }
6696
6697                     glTranslatef(mid.x, mid.y, mid.z);
6698
6699                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6700                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6701
6702                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6703                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6704
6705                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6706                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6707
6708                     if (playerdetail || skeleton.free == 3) {
6709                         for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6710                             XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6711                             XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6712                             glMatrixMode(GL_MODELVIEW);
6713                             glPushMatrix();
6714                             if (p1 == abdomen || p2 == abdomen) {
6715                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(1).x,
6716                                              (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(1).y,
6717                                              (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(1).z);
6718                             }
6719                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6720                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(2).x,
6721                                              (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(2).y,
6722                                              (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(2).z);
6723                             }
6724                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6725                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(3).x,
6726                                              (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(3).y,
6727                                              (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(3).z);
6728                             }
6729                             if (p1 == head || p2 == head) {
6730                                 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportion(0).x,
6731                                              (v0.y * (1 - morphness) + v1.y * morphness) * getProportion(0).y,
6732                                              (v0.z * (1 - morphness) + v1.z * morphness) * getProportion(0).z);
6733                             }
6734                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6735                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6736                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6737                             skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6738                             glPopMatrix();
6739                         }
6740                     }
6741                     if (!playerdetail || skeleton.free == 3) {
6742                         for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6743                             XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6744                             glMatrixMode(GL_MODELVIEW);
6745                             glPushMatrix();
6746                             if (p1 == abdomen || p2 == abdomen) {
6747                                 glTranslatef(v0.x * getProportion(1).x,
6748                                              v0.y * getProportion(1).y,
6749                                              v0.z * getProportion(1).z);
6750                             }
6751                             if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6752                                 glTranslatef(v0.x * getProportion(2).x,
6753                                              v0.y * getProportion(2).y,
6754                                              v0.z * getProportion(2).z);
6755                             }
6756                             if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6757                                 glTranslatef(v0.x * getProportion(3).x,
6758                                              v0.y * getProportion(3).y,
6759                                              v0.z * getProportion(3).z);
6760                             }
6761                             if (p1 == head || p2 == head) {
6762                                 glTranslatef(v0.x * getProportion(0).x,
6763                                              v0.y * getProportion(0).y,
6764                                              v0.z * getProportion(0).z);
6765                             }
6766
6767                             glGetFloatv(GL_MODELVIEW_MATRIX, M);
6768                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6769                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6770                             skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6771                             glPopMatrix();
6772                         }
6773                     }
6774                     glPopMatrix();
6775                 }
6776                 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6777                     mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6778
6779                     glMatrixMode(GL_MODELVIEW);
6780                     glPushMatrix();
6781                     glLoadIdentity();
6782                     if (!skeleton.free) {
6783                         glRotatef(tilt2, 1, 0, 0);
6784                     }
6785                     if (!skeleton.free) {
6786                         glRotatef(tilt, 0, 0, 1);
6787                     }
6788                     glTranslatef(mid.x, mid.y, mid.z);
6789                     skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6790                     glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6791
6792                     skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6793                     glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6794
6795                     skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6796                     glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6797
6798                     for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6799                         XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6800                         glMatrixMode(GL_MODELVIEW);
6801                         glPushMatrix();
6802                         if (p1 == abdomen || p2 == abdomen) {
6803                             glTranslatef(v0.x * getProportion(1).x,
6804                                          v0.y * getProportion(1).y,
6805                                          v0.z * getProportion(1).z);
6806                         }
6807                         if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) {
6808                             glTranslatef(v0.x * getProportion(2).x,
6809                                          v0.y * getProportion(2).y,
6810                                          v0.z * getProportion(2).z);
6811                         }
6812                         if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) {
6813                             glTranslatef(v0.x * getProportion(3).x,
6814                                          v0.y * getProportion(3).y,
6815                                          v0.z * getProportion(3).z);
6816                         }
6817                         if (p1 == head || p2 == head) {
6818                             glTranslatef(v0.x * getProportion(0).x,
6819                                          v0.y * getProportion(0).y,
6820                                          v0.z * getProportion(0).z);
6821                         }
6822                         glGetFloatv(GL_MODELVIEW_MATRIX, M);
6823                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6824                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6825                         skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6826                         glPopMatrix();
6827                     }
6828                     glPopMatrix();
6829                 }
6830                 updatedelay = 1 + (float)(Random() % 100) / 1000;
6831             }
6832             if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6833                 normalsupdatedelay = 1;
6834                 if (playerdetail || skeleton.free == 3) {
6835                     skeleton.drawmodel.CalculateNormals(0);
6836                 }
6837                 if (!playerdetail || skeleton.free == 3) {
6838                     skeleton.drawmodellow.CalculateNormals(0);
6839                 }
6840                 if (skeleton.clothes) {
6841                     skeleton.drawmodelclothes.CalculateNormals(0);
6842                 }
6843             } else {
6844                 if (playerdetail || skeleton.free == 3) {
6845                     skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6846                 }
6847                 if (!playerdetail || skeleton.free == 3) {
6848                     skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6849                 }
6850                 if (skeleton.clothes) {
6851                     skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6852                 }
6853             }
6854         }
6855         framemult = .01;
6856         updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6857         if (updatedelaychange > -realmultiplier * 30) {
6858             updatedelaychange = -realmultiplier * 30;
6859         }
6860         if (updatedelaychange > -framemult * 4) {
6861             updatedelaychange = -framemult * 4;
6862         }
6863         if (skeleton.free == 1) {
6864             updatedelaychange *= 6;
6865         }
6866         if (id == 0) {
6867             updatedelaychange *= 8;
6868         }
6869         updatedelay += updatedelaychange;
6870
6871         glMatrixMode(GL_MODELVIEW);
6872         glPushMatrix();
6873         glTranslatef(coords.x, coords.y - .02, coords.z);
6874         if (!skeleton.free) {
6875             glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6876             glRotatef(yaw, 0, 1, 0);
6877         }
6878         if (showpoints) {
6879             glPointSize(5);
6880             glColor4f(.4, 1, .4, 1);
6881             glDisable(GL_LIGHTING);
6882             glDisable(GL_TEXTURE_2D);
6883             glBegin(GL_POINTS);
6884             if (playerdetail) {
6885                 for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6886                     XYZ& v0 = skeleton.drawmodel.vertex[i];
6887                     glVertex3f(v0.x, v0.y, v0.z);
6888                 }
6889             }
6890             glEnd();
6891             glBegin(GL_LINES);
6892
6893             if (playerdetail) {
6894                 for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) {
6895                     const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0);
6896                     const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1);
6897                     const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2);
6898                     glVertex3f(v0.x, v0.y, v0.z);
6899                     glVertex3f(v1.x, v1.y, v1.z);
6900                     glVertex3f(v1.x, v1.y, v1.z);
6901                     glVertex3f(v2.x, v2.y, v2.z);
6902                     glVertex3f(v2.x, v2.y, v2.z);
6903                     glVertex3f(v0.x, v0.y, v0.z);
6904                 }
6905             }
6906
6907             glEnd();
6908         }
6909
6910         terrainlight = terrain.getLighting(coords.x, coords.z);
6911         distance = distsq(&viewer, &coords);
6912         distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6913         if (distance > 1) {
6914             distance = 1;
6915         }
6916         if (distance > 0) {
6917             terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6918             if (terrainheight < 1) {
6919                 terrainheight = 1;
6920             }
6921             if (terrainheight > 1.7) {
6922                 terrainheight = 1.7;
6923             }
6924
6925             glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6926             glDisable(GL_BLEND);
6927             glAlphaFunc(GL_GREATER, 0.0001);
6928             glEnable(GL_TEXTURE_2D);
6929             if (cellophane) {
6930                 glDisable(GL_TEXTURE_2D);
6931                 glColor4f(.7, .35, 0, .5);
6932                 glDepthMask(0);
6933                 glEnable(GL_LIGHTING);
6934                 glEnable(GL_BLEND);
6935             }
6936             if (Tutorial::active && id != 0) {
6937                 glColor4f(.7, .7, .7, 0.6);
6938                 glDepthMask(0);
6939                 glEnable(GL_LIGHTING);
6940                 glEnable(GL_BLEND);
6941                 if (canattack && cananger) {
6942                     if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6943                         glDisable(GL_TEXTURE_2D);
6944                         glColor4f(1, 0, 0, 0.8);
6945                     }
6946                 }
6947                 glMatrixMode(GL_TEXTURE);
6948                 glPushMatrix();
6949                 glTranslatef(0, -smoketex, 0);
6950                 glTranslatef(-smoketex, 0, 0);
6951             }
6952             if (playerdetail) {
6953                 if (!showpoints) {
6954                     if (Tutorial::active && (id != 0)) {
6955                         skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6956                     } else {
6957                         skeleton.drawmodel.draw();
6958                     }
6959                 }
6960             }
6961             if (!playerdetail) {
6962                 if (Tutorial::active && (id != 0)) {
6963                     skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6964                 } else {
6965                     skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6966                 }
6967             }
6968
6969             if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) {
6970                 if (Tutorial::active && id != 0) {
6971                     glPopMatrix();
6972                     glMatrixMode(GL_MODELVIEW);
6973                     glEnable(GL_TEXTURE_2D);
6974                     glColor4f(.7, .7, .7, 0.6);
6975                     glDepthMask(0);
6976                     glEnable(GL_LIGHTING);
6977                     glEnable(GL_BLEND);
6978                     if (canattack && cananger) {
6979                         if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6980                             glDisable(GL_TEXTURE_2D);
6981                             glColor4f(1, 0, 0, 0.8);
6982                         }
6983                     }
6984                     glMatrixMode(GL_TEXTURE);
6985                     glPushMatrix();
6986                     glTranslatef(0, -smoketex * .6, 0);
6987                     glTranslatef(smoketex * .6, 0, 0);
6988                     if (playerdetail) {
6989                         if (!showpoints) {
6990                             if (Tutorial::active && (id != 0)) {
6991                                 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6992                             } else {
6993                                 skeleton.drawmodel.draw();
6994                             }
6995                         }
6996                     }
6997                     if (!playerdetail) {
6998                         if (Tutorial::active && (id != 0)) {
6999                             skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
7000                         } else {
7001                             skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
7002                         }
7003                     }
7004                 }
7005             }
7006
7007             if (Tutorial::active && id != 0) {
7008                 glPopMatrix();
7009                 glMatrixMode(GL_MODELVIEW);
7010                 glEnable(GL_TEXTURE_2D);
7011             }
7012             if (skeleton.clothes) {
7013                 glDepthMask(0);
7014                 glEnable(GL_BLEND);
7015                 if (!immediate) {
7016                     skeleton.drawmodelclothes.draw();
7017                 }
7018                 if (immediate) {
7019                     skeleton.drawmodelclothes.drawimmediate();
7020                 }
7021                 glDepthMask(1);
7022             }
7023         }
7024         glPopMatrix();
7025
7026         if (num_weapons > 0) {
7027             for (k = 0; k < num_weapons; k++) {
7028                 int i = weaponids[k];
7029                 if (weaponactive == k) {
7030                     if (weapons[i].getType() != staff) {
7031                         for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7032                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7033                                 weaponattachmuscle = j;
7034                             }
7035                         }
7036                         for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7037                             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].vertices.size() > 0) {
7038                                 weaponrotatemuscle = j;
7039                             }
7040                         }
7041                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7042                         if (creature == wolftype) {
7043                             weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
7044                         }
7045                     }
7046                     if (weapons[i].getType() == staff) {
7047                         for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7048                             if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
7049                                 weaponattachmuscle = j;
7050                             }
7051                         }
7052                         for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7053                             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].vertices.size() > 0) {
7054                                 weaponrotatemuscle = j;
7055                             }
7056                         }
7057                         //weaponpoint=jointPos(rightwrist);
7058                         weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
7059                         //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
7060                         XYZ tempnormthing, vec1, vec2;
7061                         vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
7062                         vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
7063                         CrossProduct(&vec1, &vec2, &tempnormthing);
7064                         Normalise(&tempnormthing);
7065                         if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) {
7066                             weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
7067                         }
7068                     }
7069                 }
7070                 if (weaponactive != k && weaponstuck != k) {
7071                     if (weapons[i].getType() == knife) {
7072                         weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
7073                     }
7074                     if (weapons[i].getType() == sword) {
7075                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7076                     }
7077                     if (weapons[i].getType() == staff) {
7078                         weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
7079                     }
7080                     for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7081                         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].vertices.size() > 0) {
7082                             weaponrotatemuscle = j;
7083                         }
7084                     }
7085                 }
7086                 if (weaponstuck == k) {
7087                     if (weaponstuckwhere == 0) {
7088                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
7089                     } else {
7090                         weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
7091                     }
7092                     for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
7093                         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].vertices.size() > 0) {
7094                             weaponrotatemuscle = j;
7095                         }
7096                     }
7097                 }
7098                 if (skeleton.free) {
7099                     weapons[i].position = weaponpoint * scale + coords;
7100                     weapons[i].bigrotation = 0;
7101                     weapons[i].bigtilt = 0;
7102                     weapons[i].bigtilt2 = 0;
7103                 } else {
7104                     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;
7105                     weapons[i].bigrotation = yaw;
7106                     weapons[i].bigtilt = tilt;
7107                     weapons[i].bigtilt2 = tilt2;
7108                 }
7109                 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
7110                 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
7111                 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
7112                 if (weaponactive == k) {
7113                     if (weapons[i].getType() == knife) {
7114                         weapons[i].smallrotation = 180;
7115                         weapons[i].smallrotation2 = 0;
7116                         if (isCrouch() || wasCrouch()) {
7117                             weapons[i].smallrotation2 = 20;
7118                         }
7119                         if (animTarget == hurtidleanim) {
7120                             weapons[i].smallrotation2 = 50;
7121                         }
7122                         if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
7123                             XYZ temppoint1, temppoint2;
7124                             float distance;
7125
7126                             temppoint1 = jointPos(righthand);
7127                             temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7128                             distance = findDistance(&temppoint1, &temppoint2);
7129                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7130                             weapons[i].rotation2 *= 360 / 6.28;
7131                             temppoint1.y = 0;
7132                             temppoint2.y = 0;
7133                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7134                             weapons[i].rotation1 *= 360 / 6.28;
7135                             weapons[i].rotation3 = 0;
7136                             weapons[i].smallrotation = -90;
7137                             weapons[i].smallrotation2 = 0;
7138                             if (temppoint1.x > temppoint2.x) {
7139                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7140                             }
7141                         }
7142                         if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
7143                             XYZ temppoint1, temppoint2;
7144                             float distance;
7145
7146                             temppoint1 = jointPos(righthand);
7147                             temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7148                             distance = findDistance(&temppoint1, &temppoint2);
7149                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7150                             weapons[i].rotation2 *= 360 / 6.28;
7151                             temppoint1.y = 0;
7152                             temppoint2.y = 0;
7153                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7154                             weapons[i].rotation1 *= 360 / 6.28;
7155                             weapons[i].rotation3 = 0;
7156                             weapons[i].smallrotation = 90;
7157                             weapons[i].smallrotation2 = 0;
7158                             if (temppoint1.x > temppoint2.x) {
7159                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7160                             }
7161                         }
7162                         if (animTarget == knifethrowanim) {
7163                             weapons[i].smallrotation = 90;
7164                             //weapons[i].smallrotation2=-90;
7165                             weapons[i].smallrotation2 = 0;
7166                             weapons[i].rotation1 = 0;
7167                             weapons[i].rotation2 = 0;
7168                             weapons[i].rotation3 = 0;
7169                         }
7170                         if (animTarget == knifesneakattackanim && frameTarget < 5) {
7171                             weapons[i].smallrotation = -90;
7172                             weapons[i].rotation1 = 0;
7173                             weapons[i].rotation2 = 0;
7174                             weapons[i].rotation3 = 0;
7175                         }
7176                     }
7177                     if (weapons[i].getType() == sword) {
7178                         weapons[i].smallrotation = 0;
7179                         weapons[i].smallrotation2 = 0;
7180                         if (animTarget == knifethrowanim) {
7181                             weapons[i].smallrotation = -90;
7182                             weapons[i].smallrotation2 = 0;
7183                             weapons[i].rotation1 = 0;
7184                             weapons[i].rotation2 = 0;
7185                             weapons[i].rotation3 = 0;
7186                         }
7187                         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)) {
7188                             XYZ temppoint1, temppoint2;
7189                             float distance;
7190
7191                             temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7192                             temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7193                             distance = findDistance(&temppoint1, &temppoint2);
7194                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7195                             weapons[i].rotation2 *= 360 / 6.28;
7196                             temppoint1.y = 0;
7197                             temppoint2.y = 0;
7198                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7199                             weapons[i].rotation1 *= 360 / 6.28;
7200                             weapons[i].rotation3 = 0;
7201                             weapons[i].smallrotation = 90;
7202                             weapons[i].smallrotation2 = 0;
7203                             if (temppoint1.x > temppoint2.x) {
7204                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7205                             }
7206                         }
7207                     }
7208                     if (weapons[i].getType() == staff) {
7209                         weapons[i].smallrotation = 100;
7210                         weapons[i].smallrotation2 = 0;
7211                         if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
7212                             XYZ temppoint1, temppoint2;
7213                             float distance;
7214
7215                             temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
7216                             temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
7217                             distance = findDistance(&temppoint1, &temppoint2);
7218                             weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
7219                             weapons[i].rotation2 *= 360 / 6.28;
7220                             temppoint1.y = 0;
7221                             temppoint2.y = 0;
7222                             weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
7223                             weapons[i].rotation1 *= 360 / 6.28;
7224                             weapons[i].rotation3 = 0;
7225                             weapons[i].smallrotation = 90;
7226                             weapons[i].smallrotation2 = 0;
7227                             if (temppoint1.x > temppoint2.x) {
7228                                 weapons[i].rotation1 = 360 - weapons[i].rotation1;
7229                             }
7230                         }
7231                     }
7232                 }
7233                 if (weaponactive != k && weaponstuck != k) {
7234                     if (weapons[i].getType() == knife) {
7235                         weapons[i].smallrotation = -70;
7236                         weapons[i].smallrotation2 = 10;
7237                     }
7238                     if (weapons[i].getType() == sword) {
7239                         weapons[i].smallrotation = -100;
7240                         weapons[i].smallrotation2 = -8;
7241                     }
7242                     if (weapons[i].getType() == staff) {
7243                         weapons[i].smallrotation = -100;
7244                         weapons[i].smallrotation2 = -8;
7245                     }
7246                 }
7247                 if (weaponstuck == k) {
7248                     if (weaponstuckwhere == 0) {
7249                         weapons[i].smallrotation = 180;
7250                     } else {
7251                         weapons[i].smallrotation = 0;
7252                     }
7253                     weapons[i].smallrotation2 = 10;
7254                 }
7255             }
7256         }
7257     }
7258
7259     calcrot = 0;
7260     if (skeleton.free) {
7261         calcrot = 1;
7262     }
7263     if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) {
7264         calcrot = 1;
7265     }
7266     if (animCurrent != animTarget) {
7267         calcrot = 1;
7268     }
7269     if (skeleton.free == 2) {
7270         calcrot = 0;
7271     }
7272
7273     return 0;
7274 }
7275
7276 /* FUNCTION?
7277  */
7278 int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model)
7279 {
7280     static float distance;
7281     static float olddistance;
7282     static int intersecting;
7283     static int firstintersecting;
7284     static XYZ point;
7285     static XYZ oldp1;
7286     static XYZ start, end;
7287     static float slopethreshold = -.4;
7288
7289     firstintersecting = -1;
7290
7291     oldp1 = *p1;
7292     *p1 = *p1 - *move;
7293     if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) {
7294         return -1;
7295     }
7296     if (*rotate) {
7297         *p1 = DoRotation(*p1, 0, -*rotate, 0);
7298     }
7299     for (int i = 0; i < 4; i++) {
7300         for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7301             if (model->Triangles[j].facenormal.y <= slopethreshold) {
7302                 intersecting = 0;
7303                 distance = abs((model->Triangles[j].facenormal.x * p1->x) + (model->Triangles[j].facenormal.y * p1->y) + (model->Triangles[j].facenormal.z * p1->z) - ((model->Triangles[j].facenormal.x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->Triangles[j].facenormal.y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->Triangles[j].facenormal.z * model->vertex[model->Triangles[j].vertex[0]].z)));
7304                 if (distance < radius) {
7305                     point = *p1 - model->Triangles[j].facenormal * distance;
7306                     if (PointInTriangle(&point, model->Triangles[j].facenormal, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]])) {
7307                         intersecting = 1;
7308                     }
7309                     if (!intersecting) {
7310                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7311                                                                 &model->vertex[model->Triangles[j].vertex[1]],
7312                                                                 p1, &radius);
7313                     }
7314                     if (!intersecting) {
7315                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
7316                                                                 &model->vertex[model->Triangles[j].vertex[2]],
7317                                                                 p1, &radius);
7318                     }
7319                     if (!intersecting) {
7320                         intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
7321                                                                 &model->vertex[model->Triangles[j].vertex[2]],
7322                                                                 p1, &radius);
7323                     }
7324                     end = *p1 - point;
7325                     if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7326                         start = *p1;
7327                         end = *p1;
7328                         end.y -= radius;
7329                         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->Triangles[j].facenormal, &point)) {
7330                             p1->y = point.y + radius;
7331                             if ((animTarget == jumpdownanim || isFlip())) {
7332                                 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) {
7333                                     RagDoll(0);
7334                                 }
7335
7336                                 if (animTarget == jumpupanim) {
7337                                     jumppower = -4;
7338                                     animTarget = getIdle();
7339                                 }
7340                                 target = 0;
7341                                 frameTarget = 0;
7342                                 onterrain = 1;
7343
7344                                 if (id == 0) {
7345                                     pause_sound(whooshsound);
7346                                     OPENAL_SetVolume(channels[whooshsound], 0);
7347                                 }
7348
7349                                 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
7350                                     if (isFlip()) {
7351                                         jumppower = -4;
7352                                     }
7353                                     animTarget = getLanding();
7354                                     emit_sound_at(landsound, coords, 128.);
7355
7356                                     if (id == 0) {
7357                                         addEnvSound(coords);
7358                                     }
7359                                 }
7360                             }
7361                         }
7362                     }
7363                 }
7364                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7365                     olddistance = distance;
7366                     firstintersecting = j;
7367                     *p = point;
7368                 }
7369             }
7370         }
7371         for (unsigned int j = 0; j < model->Triangles.size(); j++) {
7372             if (model->Triangles[j].facenormal.y > slopethreshold) {
7373                 intersecting = 0;
7374                 start = *p1;
7375                 start.y -= radius / 4;
7376                 XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]];
7377                 XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]];
7378                 XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]];
7379                 distance = abs((model->Triangles[j].facenormal.x * start.x) + (model->Triangles[j].facenormal.y * start.y) + (model->Triangles[j].facenormal.z * start.z) - ((model->Triangles[j].facenormal.x * v0.x) + (model->Triangles[j].facenormal.y * v0.y) + (model->Triangles[j].facenormal.z * v0.z)));
7380                 if (distance < radius * .5) {
7381                     point = start - model->Triangles[j].facenormal * distance;
7382                     if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) {
7383                         intersecting = 1;
7384                     }
7385                     if (!intersecting) {
7386                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
7387                     }
7388                     if (!intersecting) {
7389                         intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7390                     }
7391                     if (!intersecting) {
7392                         intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
7393                     }
7394                     end = *p1 - point;
7395                     if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) {
7396                         if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
7397                             start = velocity;
7398                             velocity -= DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
7399                             if (findLengthfast(&start) < findLengthfast(&velocity)) {
7400                                 velocity = start;
7401                             }
7402                         }
7403                         *p1 += model->Triangles[j].facenormal * (distance - radius * .5);
7404                     }
7405                 }
7406                 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
7407                     olddistance = distance;
7408                     firstintersecting = j;
7409                     *p = point;
7410                 }
7411             }
7412         }
7413     }
7414     if (*rotate) {
7415         *p = DoRotation(*p, 0, *rotate, 0);
7416     }
7417     *p = *p + *move;
7418     if (*rotate) {
7419         *p1 = DoRotation(*p1, 0, *rotate, 0);
7420     }
7421     *p1 += *move;
7422     return firstintersecting;
7423 }
7424
7425 int findPathDist(int start, int end)
7426 {
7427     int connected;
7428     int closest;
7429
7430     unsigned int smallestcount = 1000;
7431     for (char i = 0; i < 50; i++) {
7432         unsigned int count = 0;
7433         int last = start;
7434         int last2 = -1;
7435         int last3 = -1;
7436         int last4 = -1;
7437         while (last != end && count < 30) {
7438             closest = -1;
7439             for (int j = 0; j < Game::numpathpoints; j++) {
7440                 if (j != last && j != last2 && j != last3 && j != last4) {
7441                     connected = 0;
7442                     if (Game::numpathpointconnect[j]) {
7443                         for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7444                             if (Game::pathpointconnect[j][k] == last) {
7445                                 connected = 1;
7446                             }
7447                         }
7448                     }
7449                     if (!connected) {
7450                         if (Game::numpathpointconnect[last]) {
7451                             for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
7452                                 if (Game::pathpointconnect[last][k] == j) {
7453                                     connected = 1;
7454                                 }
7455                             }
7456                         }
7457                     }
7458                     if (connected) {
7459                         if (closest == -1 || Random() % 2 == 0) {
7460                             closest = j;
7461                         }
7462                     }
7463                 }
7464             }
7465             last4 = last3;
7466             last3 = last2;
7467             last2 = last;
7468             last = closest;
7469             count++;
7470         }
7471         if (count < smallestcount) {
7472             smallestcount = count;
7473         }
7474     }
7475     return smallestcount;
7476 }
7477
7478 void Person::takeWeapon(int weaponId)
7479 {
7480     weaponactive = 0;
7481     weapons[weaponId].owner = id;
7482     if (num_weapons > 0) {
7483         weaponids[num_weapons] = weaponids[0];
7484     }
7485     num_weapons++;
7486     weaponids[0] = weaponId;
7487 }
7488
7489 void Person::addClothes()
7490 {
7491     if (numclothes > 0) {
7492         for (int i = 0; i < numclothes; i++) {
7493             addClothes(i);
7494         }
7495         DoMipmaps();
7496     }
7497 }
7498
7499 bool Person::addClothes(const int& clothesId)
7500 {
7501     LOGFUNC;
7502     const std::string fileName = clothes[clothesId];
7503
7504     GLubyte* array = &skeleton.skinText[0];
7505
7506     //Load Image
7507     ImageRec texture;
7508     bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
7509
7510     float alphanum;
7511     //Is it valid?
7512     if (opened) {
7513         float tintr = clothestintr[clothesId];
7514         float tintg = clothestintg[clothesId];
7515         float tintb = clothestintb[clothesId];
7516
7517         if (tintr > 1) {
7518             tintr = 1;
7519         }
7520         if (tintg > 1) {
7521             tintg = 1;
7522         }
7523         if (tintb > 1) {
7524             tintb = 1;
7525         }
7526
7527         if (tintr < 0) {
7528             tintr = 0;
7529         }
7530         if (tintg < 0) {
7531             tintg = 0;
7532         }
7533         if (tintb < 0) {
7534             tintb = 0;
7535         }
7536
7537         int bytesPerPixel = texture.bpp / 8;
7538
7539         int tempnum = 0;
7540         alphanum = 255;
7541         for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
7542             if (bytesPerPixel == 3) {
7543                 alphanum = 255;
7544             } else if ((i + 1) % 4 == 0) {
7545                 alphanum = texture.data[i];
7546             }
7547             if ((i + 1) % 4 || bytesPerPixel == 3) {
7548                 if ((i % 4) == 0) {
7549                     texture.data[i] *= tintr;
7550                 }
7551                 if ((i % 4) == 1) {
7552                     texture.data[i] *= tintg;
7553                 }
7554                 if ((i % 4) == 2) {
7555                     texture.data[i] *= tintb;
7556                 }
7557                 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
7558                 tempnum++;
7559             }
7560         }
7561         return 1;
7562     } else {
7563         return 0;
7564     }
7565 }
7566
7567 void Person::doAI()
7568 {
7569     if (aitype != playercontrolled && !Dialog::inDialog()) {
7570         jumpclimb = 0;
7571         //disable movement in editor
7572         if (Game::editorenabled) {
7573             stunned = 1;
7574         }
7575
7576         pause = 0;
7577         if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
7578             Person::players[0]->coords.y > coords.y + 2 &&
7579             !Person::players[0]->onterrain) {
7580             pause = 1;
7581         }
7582
7583         //pathfinding
7584         if (aitype == pathfindtype) {
7585             if (finalpathfindpoint == -1) {
7586                 float closestdistance;
7587                 float tempdist = 0.0f;
7588                 int closest;
7589                 XYZ colpoint;
7590                 closest = -1;
7591                 closestdistance = -1;
7592                 for (int j = 0; j < Game::numpathpoints; j++) {
7593                     if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7594                         closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7595                         closest = j;
7596                         finaltarget = Game::pathpoint[j];
7597                     }
7598                 }
7599                 finalpathfindpoint = closest;
7600                 for (int j = 0; j < Game::numpathpoints; j++) {
7601                     for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7602                         DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7603                         if (sq(tempdist) < closestdistance) {
7604                             if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7605                                 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7606                                 closestdistance = sq(tempdist);
7607                                 closest = j;
7608                                 finaltarget = colpoint;
7609                             }
7610                         }
7611                     }
7612                 }
7613                 finalpathfindpoint = closest;
7614             }
7615             if (targetpathfindpoint == -1) {
7616                 float closestdistance;
7617                 float tempdist = 0.0f;
7618                 int closest;
7619                 XYZ colpoint;
7620                 closest = -1;
7621                 closestdistance = -1;
7622                 if (lastpathfindpoint == -1) {
7623                     for (int j = 0; j < Game::numpathpoints; j++) {
7624                         if (j != lastpathfindpoint) {
7625                             if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7626                                 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7627                                 closest = j;
7628                             }
7629                         }
7630                     }
7631                     targetpathfindpoint = closest;
7632                     for (int j = 0; j < Game::numpathpoints; j++) {
7633                         if (j != lastpathfindpoint) {
7634                             for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7635                                 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
7636                                 if (sq(tempdist) < closestdistance) {
7637                                     if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7638                                         findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7639                                         closestdistance = sq(tempdist);
7640                                         closest = j;
7641                                     }
7642                                 }
7643                             }
7644                         }
7645                     }
7646                     targetpathfindpoint = closest;
7647                 } else {
7648                     for (int j = 0; j < Game::numpathpoints; j++) {
7649                         if (j != lastpathfindpoint &&
7650                             j != lastpathfindpoint2 &&
7651                             j != lastpathfindpoint3 &&
7652                             j != lastpathfindpoint4) {
7653                             bool connected = 0;
7654                             if (Game::numpathpointconnect[j]) {
7655                                 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7656                                     if (Game::pathpointconnect[j][k] == lastpathfindpoint) {
7657                                         connected = 1;
7658                                     }
7659                                 }
7660                             }
7661                             if (!connected) {
7662                                 if (Game::numpathpointconnect[lastpathfindpoint]) {
7663                                     for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) {
7664                                         if (Game::pathpointconnect[lastpathfindpoint][k] == j) {
7665                                             connected = 1;
7666                                         }
7667                                     }
7668                                 }
7669                             }
7670                             if (connected) {
7671                                 tempdist = findPathDist(j, finalpathfindpoint);
7672                                 if (closest == -1 || tempdist < closestdistance) {
7673                                     closestdistance = tempdist;
7674                                     closest = j;
7675                                 }
7676                             }
7677                         }
7678                     }
7679                     targetpathfindpoint = closest;
7680                 }
7681             }
7682             losupdatedelay -= multiplier;
7683
7684             targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7685             lookyaw = targetyaw;
7686
7687             //reached target point
7688             if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7689                 lastpathfindpoint4 = lastpathfindpoint3;
7690                 lastpathfindpoint3 = lastpathfindpoint2;
7691                 lastpathfindpoint2 = lastpathfindpoint;
7692                 lastpathfindpoint = targetpathfindpoint;
7693                 if (lastpathfindpoint2 == -1) {
7694                     lastpathfindpoint2 = lastpathfindpoint;
7695                 }
7696                 if (lastpathfindpoint3 == -1) {
7697                     lastpathfindpoint3 = lastpathfindpoint2;
7698                 }
7699                 if (lastpathfindpoint4 == -1) {
7700                     lastpathfindpoint4 = lastpathfindpoint3;
7701                 }
7702                 targetpathfindpoint = -1;
7703             }
7704             if (distsqflat(&coords, &finalfinaltarget) <
7705                     distsqflat(&coords, &finaltarget) ||
7706                 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7707                 lastpathfindpoint == finalpathfindpoint) {
7708                 aitype = passivetype;
7709             }
7710
7711             forwardkeydown = 1;
7712             leftkeydown = 0;
7713             backkeydown = 0;
7714             rightkeydown = 0;
7715             crouchkeydown = 0;
7716             attackkeydown = 0;
7717             throwkeydown = 0;
7718
7719             if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7720                 targetyaw += 90 * (whichdirection * 2 - 1);
7721             }
7722
7723             if (collided < 1 || animTarget != jumpupanim) {
7724                 jumpkeydown = 0;
7725             }
7726             if ((collided > .8 && jumppower >= 5)) {
7727                 jumpkeydown = 1;
7728             }
7729
7730             if ((!Tutorial::active || cananger) &&
7731                 hostile &&
7732                 !Person::players[0]->dead &&
7733                 distsq(&coords, &Person::players[0]->coords) < 400 &&
7734                 occluded < 25) {
7735                 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7736                     Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7737                     !Game::editorenabled &&
7738                     (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) {
7739                     aitype = attacktypecutoff;
7740                 }
7741                 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7742                     Animation::animations[Person::players[0]->animTarget].height == highheight &&
7743                     !Game::editorenabled) {
7744                     aitype = attacktypecutoff;
7745                 }
7746
7747                 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7748                     losupdatedelay = .2;
7749                     for (unsigned j = 0; j < Person::players.size(); j++) {
7750                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7751                             if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7752                                 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7753                                     if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7754                                         if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) {
7755                                             if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(DoRotation(jointPos(head), 0, yaw, 0) * scale + coords, DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords) ||
7756                                                 (Person::players[j]->animTarget == hanganim &&
7757                                                  normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7758                                                 aitype = searchtype;
7759                                                 lastchecktime = 12;
7760                                                 lastseen = Person::players[j]->coords;
7761                                                 lastseentime = 12;
7762                                             }
7763                                         }
7764                                     }
7765                                 }
7766                             }
7767                         }
7768                     }
7769                 }
7770             }
7771             if (aitype == attacktypecutoff && Game::musictype != 2) {
7772                 if (creature != wolftype) {
7773                     stunned = .6;
7774                     surprised = .6;
7775                 }
7776             }
7777         }
7778
7779         if (aitype != passivetype && Game::leveltime > .5) {
7780             howactive = typeactive;
7781         }
7782
7783         if (aitype == passivetype) {
7784             aiupdatedelay -= multiplier;
7785             losupdatedelay -= multiplier;
7786             lastseentime += multiplier;
7787             pausetime -= multiplier;
7788             if (lastseentime > 1) {
7789                 lastseentime = 1;
7790             }
7791
7792             if (aiupdatedelay < 0) {
7793                 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7794                     targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7795                     lookyaw = targetyaw;
7796                     aiupdatedelay = .05;
7797
7798                     if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7799                         if (waypointtype[waypoint] == wppause) {
7800                             pausetime = 4;
7801                         }
7802                         waypoint++;
7803                         if (waypoint > numwaypoints - 1) {
7804                             waypoint = 0;
7805                         }
7806                     }
7807                 }
7808
7809                 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7810                     forwardkeydown = 1;
7811                 } else {
7812                     forwardkeydown = 0;
7813                 }
7814                 leftkeydown = 0;
7815                 backkeydown = 0;
7816                 rightkeydown = 0;
7817                 crouchkeydown = 0;
7818                 attackkeydown = 0;
7819                 throwkeydown = 0;
7820
7821                 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7822                     if (!avoidsomething) {
7823                         targetyaw += 90 * (whichdirection * 2 - 1);
7824                     } else {
7825                         XYZ leftpos, rightpos;
7826                         float leftdist, rightdist;
7827                         leftpos = coords + DoRotation(facing, 0, 90, 0);
7828                         rightpos = coords - DoRotation(facing, 0, 90, 0);
7829                         leftdist = distsq(&leftpos, &avoidwhere);
7830                         rightdist = distsq(&rightpos, &avoidwhere);
7831                         if (leftdist < rightdist) {
7832                             targetyaw += 90;
7833                         } else {
7834                             targetyaw -= 90;
7835                         }
7836                     }
7837                 }
7838             }
7839             if (collided < 1 || animTarget != jumpupanim) {
7840                 jumpkeydown = 0;
7841             }
7842             if ((collided > .8 && jumppower >= 5)) {
7843                 jumpkeydown = 1;
7844             }
7845
7846             //hearing sounds
7847             if (!Game::editorenabled) {
7848                 if (howactive <= typesleeping) {
7849                     if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) {
7850                         for (int j = 0; j < numenvsounds; j++) {
7851                             float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7852                             if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) {
7853                                 aitype = attacktypecutoff;
7854                             }
7855                         }
7856                     }
7857                 }
7858
7859                 if (aitype != passivetype) {
7860                     if (howactive == typesleeping) {
7861                         setTargetAnimation(getupfromfrontanim);
7862                     }
7863                     howactive = typeactive;
7864                 }
7865             }
7866
7867             if (howactive < typesleeping &&
7868                 ((!Tutorial::active || cananger) && hostile) &&
7869                 !Person::players[0]->dead &&
7870                 distsq(&coords, &Person::players[0]->coords) < 400 &&
7871                 occluded < 25) {
7872                 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7873                     Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) {
7874                     aitype = attacktypecutoff;
7875                 }
7876                 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7877                     Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) {
7878                     aitype = attacktypecutoff;
7879                 }
7880
7881                 //wolf smell
7882                 if (creature == wolftype) {
7883                     XYZ windsmell;
7884                     for (unsigned j = 0; j < Person::players.size(); j++) {
7885                         if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7886                             float smelldistance = 50;
7887                             if (j == 0 && Person::players[j]->num_weapons > 0) {
7888                                 if (weapons[Person::players[j]->weaponids[0]].bloody) {
7889                                     smelldistance = 100;
7890                                 }
7891                                 if (Person::players[j]->num_weapons == 2) {
7892                                     if (weapons[Person::players[j]->weaponids[1]].bloody) {
7893                                         smelldistance = 100;
7894                                     }
7895                                 }
7896                             }
7897                             if (j != 0) {
7898                                 smelldistance = 100;
7899                             }
7900                             windsmell = windvector;
7901                             Normalise(&windsmell);
7902                             windsmell = windsmell * 2 + Person::players[j]->coords;
7903                             if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) {
7904                                 aitype = attacktypecutoff;
7905                             }
7906                         }
7907                     }
7908                 }
7909
7910                 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7911                     losupdatedelay = .2;
7912                     for (unsigned j = 0; j < Person::players.size(); j++) {
7913                         if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7914                             if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) {
7915                                 if (distsq(&coords, &Person::players[j]->coords) < 400) {
7916                                     if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) {
7917                                         if ((-1 == Object::checkcollide(
7918                                                        DoRotation(jointPos(head), 0, yaw, 0) *
7919                                                                scale +
7920                                                            coords,
7921                                                        DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) *
7922                                                                Person::players[j]->scale +
7923                                                            Person::players[j]->coords) &&
7924                                              !Person::players[j]->isWallJump()) ||
7925                                             (Person::players[j]->animTarget == hanganim &&
7926                                              normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7927                                             lastseentime -= .2;
7928                                             if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) {
7929                                                 lastseentime -= .4;
7930                                             } else {
7931                                                 lastseentime -= .6;
7932                                             }
7933                                         }
7934                                     }
7935                                 }
7936                             }
7937                             if (lastseentime <= 0) {
7938                                 aitype = searchtype;
7939                                 lastchecktime = 12;
7940                                 lastseen = Person::players[j]->coords;
7941                                 lastseentime = 12;
7942                             }
7943                         }
7944                     }
7945                 }
7946             }
7947             //alerted surprise
7948             if (aitype == attacktypecutoff && Game::musictype != 2) {
7949                 if (creature != wolftype) {
7950                     stunned = .6;
7951                     surprised = .6;
7952                 }
7953                 if (creature == wolftype) {
7954                     stunned = .47;
7955                     surprised = .47;
7956                 }
7957                 numseen++;
7958             }
7959         }
7960
7961         //search for player
7962         int j;
7963         if (aitype == searchtype) {
7964             aiupdatedelay -= multiplier;
7965             losupdatedelay -= multiplier;
7966             if (!pause) {
7967                 lastseentime -= multiplier;
7968             }
7969             lastchecktime -= multiplier;
7970
7971             if (isRun() && !onground) {
7972                 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7973                     XYZ test2 = coords + facing;
7974                     test2.y += 5;
7975                     XYZ test = coords + facing;
7976                     test.y -= 10;
7977                     j = Object::checkcollide(test2, test, laststanding);
7978                     if (j == -1) {
7979                         j = Object::checkcollide(test2, test);
7980                     }
7981                     if (j == -1) {
7982                         velocity = 0;
7983                         setTargetAnimation(getStop());
7984                         targetyaw += 180;
7985                         stunned = .5;
7986                         //aitype=passivetype;
7987                         aitype = pathfindtype;
7988                         finalfinaltarget = waypoints[waypoint];
7989                         finalpathfindpoint = -1;
7990                         targetpathfindpoint = -1;
7991                         lastpathfindpoint = -1;
7992                         lastpathfindpoint2 = -1;
7993                         lastpathfindpoint3 = -1;
7994                         lastpathfindpoint4 = -1;
7995                     } else {
7996                         laststanding = j;
7997                     }
7998                 }
7999             }
8000             //check out last seen location
8001             if (aiupdatedelay < 0) {
8002                 targetyaw = roughDirectionTo(coords, lastseen);
8003                 lookyaw = targetyaw;
8004                 aiupdatedelay = .05;
8005                 forwardkeydown = 1;
8006
8007                 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
8008                     forwardkeydown = 0;
8009                     aiupdatedelay = 1;
8010                     lastseen.x += (float(Random() % 100) - 50) / 25;
8011                     lastseen.z += (float(Random() % 100) - 50) / 25;
8012                     lastchecktime = 3;
8013                 }
8014
8015                 leftkeydown = 0;
8016                 backkeydown = 0;
8017                 rightkeydown = 0;
8018                 crouchkeydown = 0;
8019                 attackkeydown = 0;
8020                 throwkeydown = 0;
8021
8022                 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8023                     if (!avoidsomething) {
8024                         targetyaw += 90 * (whichdirection * 2 - 1);
8025                     } else {
8026                         XYZ leftpos, rightpos;
8027                         float leftdist, rightdist;
8028                         leftpos = coords + DoRotation(facing, 0, 90, 0);
8029                         rightpos = coords - DoRotation(facing, 0, 90, 0);
8030                         leftdist = distsq(&leftpos, &avoidwhere);
8031                         rightdist = distsq(&rightpos, &avoidwhere);
8032                         if (leftdist < rightdist) {
8033                             targetyaw += 90;
8034                         } else {
8035                             targetyaw -= 90;
8036                         }
8037                     }
8038                 }
8039             }
8040             if (collided < 1 || animTarget != jumpupanim) {
8041                 jumpkeydown = 0;
8042             }
8043             if ((collided > .8 && jumppower >= 5)) {
8044                 jumpkeydown = 1;
8045             }
8046
8047             if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) {
8048                 for (int k = 0; k < numenvsounds; k++) {
8049                     if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
8050                         aitype = attacktypecutoff;
8051                     }
8052                 }
8053             }
8054
8055             if (!Person::players[0]->dead &&
8056                 losupdatedelay < 0 &&
8057                 !Game::editorenabled &&
8058                 occluded < 2 &&
8059                 ((!Tutorial::active || cananger) && hostile)) {
8060                 losupdatedelay = .2;
8061                 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
8062                     aitype = attacktypecutoff;
8063                     lastseentime = 1;
8064                 }
8065                 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) {
8066                     //TODO: factor out canSeePlayer()
8067                     if (distsq(&coords, &Person::players[0]->coords) < 400) {
8068                         if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8069                             if ((Object::checkcollide(
8070                                      DoRotation(jointPos(head), 0, yaw, 0) *
8071                                              scale +
8072                                          coords,
8073                                      DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) *
8074                                              Person::players[0]->scale +
8075                                          Person::players[0]->coords) == -1) ||
8076                                 (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
8077                                 /* //TODO: changed j to 0 on a whim, make sure this is correct
8078                                 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
8079                                     Person::players[j]->facing,coords-Person::players[j]->coords)<0)
8080                                 */
8081                                 aitype = attacktypecutoff;
8082                                 lastseentime = 1;
8083                             }
8084                         }
8085                     }
8086                 }
8087             }
8088             //player escaped
8089             if (lastseentime < 0) {
8090                 //aitype=passivetype;
8091                 numescaped++;
8092                 aitype = pathfindtype;
8093                 finalfinaltarget = waypoints[waypoint];
8094                 finalpathfindpoint = -1;
8095                 targetpathfindpoint = -1;
8096                 lastpathfindpoint = -1;
8097                 lastpathfindpoint2 = -1;
8098                 lastpathfindpoint3 = -1;
8099                 lastpathfindpoint4 = -1;
8100             }
8101         }
8102
8103         if (aitype != gethelptype) {
8104             runninghowlong = 0;
8105         }
8106
8107         //get help from buddies
8108         if (aitype == gethelptype) {
8109             runninghowlong += multiplier;
8110             aiupdatedelay -= multiplier;
8111
8112             if (aiupdatedelay < 0 || ally == 0) {
8113                 aiupdatedelay = .2;
8114
8115                 //find closest ally
8116                 //TODO: factor out closest search somehow
8117                 if (!ally) {
8118                     int closest = -1;
8119                     float closestdist = -1;
8120                     for (unsigned k = 0; k < Person::players.size(); k++) {
8121                         if ((k != id) && (k != 0) && !Person::players[k]->dead &&
8122                             (Person::players[k]->howactive < typedead1) &&
8123                             !Person::players[k]->skeleton.free &&
8124                             (Person::players[k]->aitype == passivetype)) {
8125                             float distance = distsq(&coords, &Person::players[k]->coords);
8126                             if (closestdist == -1 || distance < closestdist) {
8127                                 closestdist = distance;
8128                                 closest = k;
8129                             }
8130                         }
8131                     }
8132                     if (closest != -1) {
8133                         ally = closest;
8134                     } else {
8135                         ally = 0;
8136                     }
8137                     lastseen = Person::players[0]->coords;
8138                     lastseentime = 12;
8139                 }
8140
8141                 lastchecktime = 12;
8142
8143                 XYZ facing = coords;
8144                 XYZ flatfacing = Person::players[ally]->coords;
8145                 facing.y += jointPos(head).y * scale;
8146                 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
8147                 if (-1 != Object::checkcollide(facing, flatfacing)) {
8148                     lastseentime -= .1;
8149                 }
8150
8151                 //no available ally, run back to player
8152                 if (ally <= 0 ||
8153                     Person::players[ally]->skeleton.free ||
8154                     Person::players[ally]->aitype != passivetype ||
8155                     lastseentime <= 0) {
8156                     aitype = searchtype;
8157                     lastseentime = 12;
8158                 }
8159
8160                 //seek out ally
8161                 if (ally > 0) {
8162                     targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
8163                     lookyaw = targetyaw;
8164                     aiupdatedelay = .05;
8165                     forwardkeydown = 1;
8166
8167                     if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
8168                         aitype = searchtype;
8169                         lastseentime = 12;
8170                         Person::players[ally]->aitype = searchtype;
8171                         if (Person::players[ally]->lastseentime < lastseentime) {
8172                             Person::players[ally]->lastseen = lastseen;
8173                             Person::players[ally]->lastseentime = lastseentime;
8174                             Person::players[ally]->lastchecktime = lastchecktime;
8175                         }
8176                     }
8177
8178                     if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8179                         if (!avoidsomething) {
8180                             targetyaw += 90 * (whichdirection * 2 - 1);
8181                         } else {
8182                             XYZ leftpos, rightpos;
8183                             float leftdist, rightdist;
8184                             leftpos = coords + DoRotation(facing, 0, 90, 0);
8185                             rightpos = coords - DoRotation(facing, 0, 90, 0);
8186                             leftdist = distsq(&leftpos, &avoidwhere);
8187                             rightdist = distsq(&rightpos, &avoidwhere);
8188                             if (leftdist < rightdist) {
8189                                 targetyaw += 90;
8190                             } else {
8191                                 targetyaw -= 90;
8192                             }
8193                         }
8194                     }
8195                 }
8196
8197                 leftkeydown = 0;
8198                 backkeydown = 0;
8199                 rightkeydown = 0;
8200                 crouchkeydown = 0;
8201                 attackkeydown = 0;
8202             }
8203             if (collided < 1 || animTarget != jumpupanim) {
8204                 jumpkeydown = 0;
8205             }
8206             if (collided > .8 && jumppower >= 5) {
8207                 jumpkeydown = 1;
8208             }
8209         }
8210
8211         //retreiving a weapon on the ground
8212         if (aitype == getweapontype) {
8213             aiupdatedelay -= multiplier;
8214             lastchecktime -= multiplier;
8215
8216             if (aiupdatedelay < 0) {
8217                 aiupdatedelay = .2;
8218
8219                 //ALLY IS WEPON
8220                 if (ally < 0) {
8221                     int closest = -1;
8222                     float closestdist = -1;
8223                     for (unsigned k = 0; k < weapons.size(); k++) {
8224                         if (weapons[k].owner == -1) {
8225                             float distance = distsq(&coords, &weapons[k].position);
8226                             if (closestdist == -1 || distance < closestdist) {
8227                                 closestdist = distance;
8228                                 closest = k;
8229                             }
8230                         }
8231                     }
8232                     if (closest != -1) {
8233                         ally = closest;
8234                     } else {
8235                         ally = -1;
8236                     }
8237                 }
8238
8239                 lastseentime = 12;
8240
8241                 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) {
8242                     if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
8243                         aitype = attacktypecutoff;
8244                         lastseentime = 1;
8245                     }
8246                 }
8247                 if (!Person::players[0]->dead) {
8248                     if (ally >= 0) {
8249                         if (weapons[ally].owner != -1 ||
8250                             distsq(&coords, &weapons[ally].position) > 16) {
8251                             aitype = attacktypecutoff;
8252                             lastseentime = 1;
8253                         }
8254                         //TODO: factor these out as moveToward()
8255                         targetyaw = roughDirectionTo(coords, weapons[ally].position);
8256                         lookyaw = targetyaw;
8257                         aiupdatedelay = .05;
8258                         forwardkeydown = 1;
8259
8260                         if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8261                             if (!avoidsomething) {
8262                                 targetyaw += 90 * (whichdirection * 2 - 1);
8263                             } else {
8264                                 XYZ leftpos, rightpos;
8265                                 float leftdist, rightdist;
8266                                 leftpos = coords + DoRotation(facing, 0, 90, 0);
8267                                 rightpos = coords - DoRotation(facing, 0, 90, 0);
8268                                 leftdist = distsq(&leftpos, &avoidwhere);
8269                                 rightdist = distsq(&rightpos, &avoidwhere);
8270                                 if (leftdist < rightdist) {
8271                                     targetyaw += 90;
8272                                 } else {
8273                                     targetyaw -= 90;
8274                                 }
8275                             }
8276                         }
8277                     }
8278                 }
8279
8280                 leftkeydown = 0;
8281                 backkeydown = 0;
8282                 rightkeydown = 0;
8283                 attackkeydown = 0;
8284                 throwkeydown = 1;
8285                 crouchkeydown = 0;
8286                 if (animTarget != crouchremoveknifeanim &&
8287                     animTarget != removeknifeanim) {
8288                     throwtogglekeydown = 0;
8289                 }
8290                 drawkeydown = 0;
8291             }
8292             if (collided < 1 || animTarget != jumpupanim) {
8293                 jumpkeydown = 0;
8294             }
8295             if ((collided > .8 && jumppower >= 5)) {
8296                 jumpkeydown = 1;
8297             }
8298         }
8299
8300         if (aitype == attacktypecutoff) {
8301             aiupdatedelay -= multiplier;
8302             //dodge or reverse rabbit kicks, knife throws, flips
8303             if (damage < damagetolerance * 2 / 3) {
8304                 if ((Person::players[0]->animTarget == rabbitkickanim ||
8305                      Person::players[0]->animTarget == knifethrowanim ||
8306                      (Person::players[0]->isFlip() &&
8307                       normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
8308                     !Person::players[0]->skeleton.free &&
8309                     (aiupdatedelay < .1)) {
8310                     attackkeydown = 0;
8311                     if (isIdle()) {
8312                         crouchkeydown = 1;
8313                     }
8314                     if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
8315                         if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
8316                             if (isIdle() || isCrouch() || isRun() || isFlip()) {
8317                                 if (abs(Random() % 2) == 0) {
8318                                     setTargetAnimation(backhandspringanim);
8319                                 } else {
8320                                     setTargetAnimation(rollanim);
8321                                 }
8322                                 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
8323                                 wentforweapon = 0;
8324                             }
8325                             if (animTarget == jumpupanim || animTarget == jumpdownanim) {
8326                                 setTargetAnimation(flipanim);
8327                             }
8328                         }
8329                     }
8330                     forwardkeydown = 0;
8331                     aiupdatedelay = .02;
8332                 }
8333             }
8334             //get confused by flips
8335             if (Person::players[0]->isFlip() &&
8336                 !Person::players[0]->skeleton.free &&
8337                 Person::players[0]->animTarget != walljumprightkickanim &&
8338                 Person::players[0]->animTarget != walljumpleftkickanim) {
8339                 if (distsq(&Person::players[0]->coords, &coords) < 25) {
8340                     if ((1 - damage / damagetolerance) > .5) {
8341                         stunned = 1;
8342                     }
8343                 }
8344             }
8345             //go for weapon on the ground
8346             if (wentforweapon < 3) {
8347                 for (unsigned k = 0; k < weapons.size(); k++) {
8348                     if (creature != wolftype) {
8349                         if (num_weapons == 0 &&
8350                             weapons[k].owner == -1 &&
8351                             weapons[k].velocity.x == 0 &&
8352                             weapons[k].velocity.z == 0 &&
8353                             weapons[k].velocity.y == 0) {
8354                             if (distsq(&coords, &weapons[k].position) < 16) {
8355                                 wentforweapon++;
8356                                 lastchecktime = 6;
8357                                 aitype = getweapontype;
8358                                 ally = -1;
8359                             }
8360                         }
8361                     }
8362                 }
8363             }
8364             //dodge/reverse walljump kicks
8365             if (damage < damagetolerance / 2) {
8366                 if (Animation::animations[animTarget].height != highheight) {
8367                     if (damage < damagetolerance * .5 &&
8368                         ((Person::players[0]->animTarget == walljumprightkickanim ||
8369                           Person::players[0]->animTarget == walljumpleftkickanim) &&
8370                          ((aiupdatedelay < .15 &&
8371                            difficulty == 2) ||
8372                           (aiupdatedelay < .08 &&
8373                            difficulty != 2)))) {
8374                         crouchkeydown = 1;
8375                     }
8376                 }
8377             }
8378             //walked off a ledge (?)
8379             if (isRun() && !onground) {
8380                 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
8381                     XYZ test2 = coords + facing;
8382                     test2.y += 5;
8383                     XYZ test = coords + facing;
8384                     test.y -= 10;
8385                     j = Object::checkcollide(test2, test, laststanding);
8386                     if (j == -1) {
8387                         j = Object::checkcollide(test2, test);
8388                     }
8389                     if (j == -1) {
8390                         velocity = 0;
8391                         setTargetAnimation(getStop());
8392                         targetyaw += 180;
8393                         stunned = .5;
8394                         aitype = pathfindtype;
8395                         finalfinaltarget = waypoints[waypoint];
8396                         finalpathfindpoint = -1;
8397                         targetpathfindpoint = -1;
8398                         lastpathfindpoint = -1;
8399                         lastpathfindpoint2 = -1;
8400                         lastpathfindpoint3 = -1;
8401                         lastpathfindpoint4 = -1;
8402                     } else {
8403                         laststanding = j;
8404                     }
8405                 }
8406             }
8407             //lose sight of player in the air (?)
8408             if (Person::players[0]->coords.y > coords.y + 5 &&
8409                 Animation::animations[Person::players[0]->animTarget].height != highheight &&
8410                 !Person::players[0]->onterrain) {
8411                 aitype = pathfindtype;
8412                 finalfinaltarget = waypoints[waypoint];
8413                 finalpathfindpoint = -1;
8414                 targetpathfindpoint = -1;
8415                 lastpathfindpoint = -1;
8416                 lastpathfindpoint2 = -1;
8417                 lastpathfindpoint3 = -1;
8418                 lastpathfindpoint4 = -1;
8419             }
8420             //it's time to think (?)
8421             if (aiupdatedelay < 0 &&
8422                 !Animation::animations[animTarget].attack &&
8423                 animTarget != staggerbackhighanim &&
8424                 animTarget != staggerbackhardanim &&
8425                 animTarget != backhandspringanim &&
8426                 animTarget != dodgebackanim) {
8427                 //draw weapon
8428                 if (weaponactive == -1 && num_weapons > 0) {
8429                     drawkeydown = Random() % 2;
8430                 } else {
8431                     drawkeydown = 0;
8432                 }
8433                 rabbitkickenabled = Random() % 2;
8434                 //chase player
8435                 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
8436                 XYZ targetpoint = Person::players[0]->coords;
8437                 float vellength = findLength(&velocity);
8438                 if (vellength != 0 &&
8439                     distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) {
8440                     targetpoint += Person::players[0]->velocity *
8441                                    findDistance(&Person::players[0]->coords, &coords) / vellength;
8442                 }
8443                 targetyaw = roughDirectionTo(coords, targetpoint);
8444                 lookyaw = targetyaw;
8445                 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
8446
8447                 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1)) {
8448                     forwardkeydown = 1;
8449                 } else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
8450                             distsq(&coords, &Person::players[0]->coords) < 9) &&
8451                            Person::players[0]->weaponactive != -1) {
8452                     forwardkeydown = 1;
8453                 } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) {
8454                     forwardkeydown = 1;
8455                 } else {
8456                     forwardkeydown = 0;
8457                 }
8458                 //chill out around the corpse
8459                 if (Person::players[0]->dead) {
8460                     forwardkeydown = 0;
8461                     if (Random() % 10 == 0) {
8462                         forwardkeydown = 1;
8463                     }
8464                     if (Random() % 100 == 0) {
8465                         aitype = pathfindtype;
8466                         finalfinaltarget = waypoints[waypoint];
8467                         finalpathfindpoint = -1;
8468                         targetpathfindpoint = -1;
8469                         lastpathfindpoint = -1;
8470                         lastpathfindpoint2 = -1;
8471                         lastpathfindpoint3 = -1;
8472                         lastpathfindpoint4 = -1;
8473                     }
8474                 }
8475                 leftkeydown = 0;
8476                 backkeydown = 0;
8477                 rightkeydown = 0;
8478                 crouchkeydown = 0;
8479                 throwkeydown = 0;
8480
8481                 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
8482                     targetyaw += 90 * (whichdirection * 2 - 1);
8483                 }
8484                 //attack!!!
8485                 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype) {
8486                     attackkeydown = 1;
8487                 } else {
8488                     attackkeydown = 0;
8489                 }
8490                 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) {
8491                     attackkeydown = 0;
8492                 }
8493
8494                 //TODO: wat
8495                 if (aitype != playercontrolled &&
8496                     (isIdle() ||
8497                      isCrouch() ||
8498                      isRun())) {
8499                     int target = -2;
8500                     for (unsigned j = 0; j < Person::players.size(); j++) {
8501                         if (j != id && !Person::players[j]->skeleton.free &&
8502                             Person::players[j]->hasvictim &&
8503                             (Tutorial::active && reversaltrain ||
8504                              Random() % 2 == 0 && difficulty == 2 ||
8505                              Random() % 4 == 0 && difficulty == 1 ||
8506                              Random() % 8 == 0 && difficulty == 0 ||
8507                              Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
8508                                  Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
8509                                  (Random() % 2 == 0 || difficulty == 2) ||
8510                              (isIdle() || isRun()) &&
8511                                  Person::players[j]->weaponactive != -1 ||
8512                              Person::players[j]->animTarget == swordslashanim &&
8513                                  weaponactive != -1 ||
8514                              Person::players[j]->animTarget == staffhitanim ||
8515                              Person::players[j]->animTarget == staffspinhitanim)) {
8516                             if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
8517                                 Person::players[j]->victim == Person::players[id] &&
8518                                 (Person::players[j]->animTarget == sweepanim ||
8519                                  Person::players[j]->animTarget == spinkickanim ||
8520                                  Person::players[j]->animTarget == staffhitanim ||
8521                                  Person::players[j]->animTarget == staffspinhitanim ||
8522                                  Person::players[j]->animTarget == winduppunchanim ||
8523                                  Person::players[j]->animTarget == upunchanim ||
8524                                  Person::players[j]->animTarget == wolfslapanim ||
8525                                  Person::players[j]->animTarget == knifeslashstartanim ||
8526                                  Person::players[j]->animTarget == swordslashanim &&
8527                                      (distsq(&Person::players[j]->coords, &coords) < 2 ||
8528                                       weaponactive != -1))) {
8529                                 if (target >= 0) {
8530                                     target = -1;
8531                                 } else {
8532                                     target = j;
8533                                 }
8534                             }
8535                         }
8536                     }
8537                     if (target >= 0) {
8538                         Person::players[target]->Reverse();
8539                     }
8540                 }
8541
8542                 if (collided < 1) {
8543                     jumpkeydown = 0;
8544                 }
8545                 if (collided > .8 && jumppower >= 5 ||
8546                     distsq(&coords, &Person::players[0]->coords) > 400 &&
8547                         onterrain &&
8548                         creature == rabbittype) {
8549                     jumpkeydown = 1;
8550                 }
8551                 //TODO: why are we controlling the human?
8552                 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) {
8553                     Person::players[0]->jumpkeydown = 0;
8554                 }
8555                 if (Person::players[0]->animTarget == jumpdownanim &&
8556                     distsq(&Person::players[0]->coords, &coords) < 40) {
8557                     crouchkeydown = 1;
8558                 }
8559                 if (jumpkeydown) {
8560                     attackkeydown = 0;
8561                 }
8562
8563                 if (Tutorial::active) {
8564                     if (!canattack) {
8565                         attackkeydown = 0;
8566                     }
8567                 }
8568
8569                 XYZ facing = coords;
8570                 XYZ flatfacing = Person::players[0]->coords;
8571                 facing.y += jointPos(head).y * scale;
8572                 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
8573                 if (occluded >= 2) {
8574                     if (-1 != Object::checkcollide(facing, flatfacing)) {
8575                         if (!pause) {
8576                             lastseentime -= .2;
8577                         }
8578                         if (lastseentime <= 0 &&
8579                             (creature != wolftype ||
8580                              weaponstuck == -1)) {
8581                             aitype = searchtype;
8582                             lastchecktime = 12;
8583                             lastseen = Person::players[0]->coords;
8584                             lastseentime = 12;
8585                         }
8586                     } else {
8587                         lastseentime = 1;
8588                     }
8589                 }
8590             }
8591         }
8592         if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
8593             (aitype == attacktypecutoff ||
8594              aitype == searchtype)) {
8595             if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
8596                 XYZ test = Person::players[0]->coords;
8597                 test.y -= 40;
8598                 if (-1 == Object::checkcollide(Person::players[0]->coords, test)) {
8599                     stunned = 1;
8600                 }
8601             }
8602         }
8603         //stunned
8604         if (aitype == passivetype && !(numwaypoints > 1) ||
8605             stunned > 0 ||
8606             pause && damage > superpermanentdamage) {
8607             if (pause) {
8608                 lastseentime = 1;
8609             }
8610             targetyaw = yaw;
8611             forwardkeydown = 0;
8612             leftkeydown = 0;
8613             backkeydown = 0;
8614             rightkeydown = 0;
8615             jumpkeydown = 0;
8616             attackkeydown = 0;
8617             crouchkeydown = 0;
8618             throwkeydown = 0;
8619         }
8620
8621         XYZ facing;
8622         facing = 0;
8623         facing.z = -1;
8624
8625         XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
8626         facing = flatfacing;
8627
8628         if (aitype == attacktypecutoff) {
8629             targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
8630             targetheadpitch = pitchTo(coords, Person::players[0]->coords);
8631         } else if (howactive >= typesleeping) {
8632             targetheadyaw = targetyaw;
8633             targetheadpitch = 0;
8634         } else {
8635             if (interestdelay <= 0) {
8636                 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
8637                 headtarget = coords;
8638                 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
8639                 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
8640                 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
8641                 headtarget += facing * 1.5;
8642             }
8643             targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
8644             targetheadpitch = pitchTo(coords, headtarget);
8645         }
8646     }
8647 }