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