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