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