2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
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.
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.
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/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/openal_wrapper.hpp"
25 #include "Audio/Sounds.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Utils/Folders.hpp"
30 #include "Tutorial.hpp"
32 extern float multiplier;
33 extern Terrain terrain;
35 extern int environment;
37 extern FRUSTUM frustum;
39 extern float realmultiplier;
41 extern float slomodelay;
42 extern bool cellophane;
43 extern float texdetail;
44 extern float realtexdetail;
45 extern GLubyte bloodText[512 * 512 * 3];
46 extern GLubyte wolfbloodText[512 * 512 * 3];
47 extern int bloodtoggle;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern float smoketex;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern bool gamestarted;
70 extern XYZ envsound[30];
71 extern float envsoundvol[30];
72 extern int numenvsounds;
73 extern float envsoundlife[30];
75 extern XYZ windvector;
77 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
82 animCurrent(bounceidleanim),
83 animTarget(bounceidleanim),
90 howactive(typeactive),
92 superruntoggle(false),
93 lastattack(0), lastattack2(0), lastattack3(0),
94 currentoffset(), targetoffset(), offset(),
126 rabbitkickenabled(false),
135 damagetolerance(200),
138 superpermanentdamage(0),
152 bleedx(0), bleedy(0),
156 headyaw(0), headpitch(0),
157 targetheadyaw(0), targetheadpitch(0),
168 normalsupdatedelay(0),
171 forwardkeydown(false),
172 forwardstogglekeydown(false),
177 jumptogglekeydown(false),
178 crouchkeydown(false),
179 crouchtogglekeydown(false),
181 drawtogglekeydown(false),
183 throwtogglekeydown(false),
184 attackkeydown(false),
189 crouchkeydowntime(0),
203 whichdirection(false),
204 whichdirectiondelay(0),
205 avoidsomething(false),
214 lefthandmorphness(0),
215 righthandmorphness(0),
219 targetlefthandmorphness(0),
220 targetrighthandmorphness(0),
221 targetheadmorphness(1),
222 targetchestmorphness(0),
223 targettailmorphness(0),
224 lefthandmorphstart(0), lefthandmorphend(0),
225 righthandmorphstart(0), righthandmorphend(0),
226 headmorphstart(0), headmorphend(0),
227 chestmorphstart(0), chestmorphend(0),
228 tailmorphstart(0), tailmorphend(0),
231 highreversaldelay(0),
234 creature(rabbittype),
281 finalpathfindpoint(0),
282 targetpathfindpoint(0),
283 lastpathfindpoint(0),
284 lastpathfindpoint2(0),
285 lastpathfindpoint3(0),
286 lastpathfindpoint4(0),
303 neckspurtparticledelay(0),
307 rabbitkickragdoll(false),
315 /* Read a person in tfile. Throws an error if it’s not valid */
316 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
319 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
321 funpackf(tfile, "Bi", &howactive);
323 howactive = typeactive;
326 funpackf(tfile, "Bf", &scale);
331 funpackf(tfile, "Bb", &immobile);
336 funpackf(tfile, "Bf", &yaw);
341 if (num_weapons < 0 || num_weapons > 5) {
342 throw InvalidPersonException();
344 if (num_weapons > 0 && num_weapons < 5) {
345 for (int j = 0; j < num_weapons; j++) {
346 weaponids[j] = weapons.size();
348 funpackf(tfile, "Bi", &type);
349 weapons.push_back(Weapon(type, id));
352 funpackf(tfile, "Bi", &numwaypoints);
353 for (int j = 0; j < numwaypoints; j++) {
354 funpackf(tfile, "Bf", &waypoints[j].x);
355 funpackf(tfile, "Bf", &waypoints[j].y);
356 funpackf(tfile, "Bf", &waypoints[j].z);
358 funpackf(tfile, "Bi", &waypointtype[j]);
360 waypointtype[j] = wpkeepwalking;
364 funpackf(tfile, "Bi", &waypoint);
365 if (waypoint > (numwaypoints - 1)) {
369 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
370 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
371 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
372 funpackf(tfile, "Bf Bf", &power, &speedmult);
374 float headprop, legprop, armprop, bodyprop;
377 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
385 if (creature == wolftype) {
386 proportionhead = 1.1 * headprop;
387 proportionbody = 1.1 * bodyprop;
388 proportionarms = 1.1 * armprop;
389 proportionlegs = 1.1 * legprop;
390 } else if (creature == rabbittype) {
391 proportionhead = 1.2 * headprop;
392 proportionbody = 1.05 * bodyprop;
393 proportionarms = 1.00 * armprop;
394 proportionlegs = 1.1 * legprop;
395 proportionlegs.y = 1.05 * legprop;
398 funpackf(tfile, "Bi", &numclothes);
399 for (int k = 0; k < numclothes; k++) {
401 funpackf(tfile, "Bi", &templength);
402 for (int l = 0; l < templength; l++)
403 funpackf(tfile, "Bb", &clothes[k][l]);
404 clothes[k][templength] = '\0';
405 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
411 if (creature == wolftype) {
413 damagetolerance = 300;
420 realoldcoords = coords;
423 void Person::skeletonLoad(bool clothes)
426 if (creature != wolftype) {
428 "Skeleton/BasicFigure",
429 "Skeleton/BasicFigureLow",
430 "Skeleton/RabbitBelt",
432 "Models/Body2.solid",
433 "Models/Body3.solid",
434 "Models/Body4.solid",
435 "Models/Body5.solid",
436 "Models/Body6.solid",
437 "Models/Body7.solid",
438 "Models/BodyLow.solid",
444 "Skeleton/BasicFigureWolf",
445 "Skeleton/BasicFigureWolfLow",
446 "Skeleton/RabbitBelt",
448 "Models/Wolf2.solid",
449 "Models/Wolf3.solid",
450 "Models/Wolf4.solid",
451 "Models/Wolf5.solid",
452 "Models/Wolf6.solid",
453 "Models/Wolf7.solid",
454 "Models/WolfLow.solid",
460 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
466 * GameTick/doPlayerCollisions
468 void Person::CheckKick()
471 && (animTarget == rabbitkickanim
473 && victim != this->shared_from_this()
475 && animCurrent == rabbitkickanim)
476 && distsq(&coords, &victim->coords) < 1.2
477 && !victim->skeleton.free))
480 if (Animation::animations[victim->animTarget].height != lowheight) {
481 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
482 XYZ relative = velocity;
484 Normalise(&relative);
488 if (!Tutorial::active)
489 emit_sound_at(heavyimpactsound, victim->coords);
491 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
492 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
495 victim->DoDamage(100 * damagemult / victim->protectionhigh);
501 animTarget = backflipanim;
503 velocity = facing * -10;
507 resume_stream(whooshsound);
509 award_bonus(id, cannon);
510 } else if (victim->isCrouch()) {
511 animTarget = rabbitkickreversedanim;
512 animCurrent = rabbitkickreversedanim;
513 victim->animCurrent = rabbitkickreversalanim;
514 victim->animTarget = rabbitkickreversalanim;
520 victim->oldcoords = victim->coords;
521 coords = victim->coords;
522 victim->targetyaw = targetyaw;
523 victim->victim = this->shared_from_this();
530 * GameTick/doPlayerCollisions - spread fire between players
531 * GameTick/doDevKeys - press f to ignite
532 * Person::DoStuff - spread fire from lit campfires and bushes
534 void Person::CatchFire()
536 XYZ flatfacing, flatvelocity;
538 for (int i = 0; i < 10; i++) {
539 howmany = fabs(Random() % (skeleton.joints.size()));
541 flatvelocity = skeleton.joints[howmany].velocity;
542 flatfacing = skeleton.joints[howmany].position * scale + coords;
544 flatvelocity = velocity;
545 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
547 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
552 emit_sound_at(firestartsound, coords);
554 emit_stream_at(stream_firesound, coords);
562 * idle animation for this creature (depending on status)
564 int Person::getIdle()
566 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
568 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
569 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
570 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
571 victim->id < Person::players.size())) {
572 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
573 if (creature == rabbittype)
574 return fightidleanim;
575 if (creature == wolftype)
578 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
579 if (weapons[weaponids[weaponactive]].getType() == knife)
580 return knifefightidleanim;
581 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
582 return swordfightidlebothanim;
583 if (weapons[weaponids[weaponactive]].getType() == sword)
584 return swordfightidleanim;
585 if (weapons[weaponids[weaponactive]].getType() == staff)
586 return swordfightidleanim;
588 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
589 return fightsidestep;
591 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
593 if (howactive == typesitting) return sitanim;
594 if (howactive == typesittingwall) return sitwallanim;
595 if (howactive == typesleeping) return sleepanim;
596 if (howactive == typedead1) return dead1anim;
597 if (howactive == typedead2) return dead2anim;
598 if (howactive == typedead3) return dead3anim;
599 if (howactive == typedead4) return dead4anim;
600 if (creature == rabbittype) return bounceidleanim;
601 if (creature == wolftype) return wolfidle;
606 * crouch animation for this creature
608 int Person::getCrouch()
610 if (creature == rabbittype)
612 if (creature == wolftype)
613 return wolfcrouchanim;
618 * running animation for this creature (can be upright or all fours)
622 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
624 if (creature == wolftype && (!superruntoggle))
627 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
628 return rabbitrunninganim;
629 if (creature == wolftype && (superruntoggle))
630 return wolfrunninganim;
636 int Person::getStop()
638 if (creature == rabbittype)
640 if (creature == wolftype)
647 int Person::getLanding()
649 if (creature == rabbittype)
651 if (creature == wolftype)
658 int Person::getLandhard()
660 if (creature == rabbittype)
662 if (creature == wolftype)
663 return wolflandhardanim;
670 * Person::DoAnimations
673 SolidHitBonus(int playerid)
675 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
676 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
678 award_bonus(playerid, solidhit);
682 * spawns blood effects
684 void Person::DoBlood(float howmuch, int which)
686 // FIXME: should abstract out inputs
687 static int bleedxint, bleedyint;
689 if (bloodtoggle && !Tutorial::active) {
690 if (bleeding <= 0 && spurt) {
692 for (int i = 0; i < 3; i++) {
693 // emit blood particles
696 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
697 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
698 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
699 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
702 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
703 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
704 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
705 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
708 if (Random() % 2 == 0) // 50% chance
709 for (int i = 0; i < 3; i++) {
710 if (Random() % 2 != 0) {
711 // emit teeth particles
714 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
715 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
718 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
719 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
723 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
725 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
727 Sprite::setLastSpriteSpecial(3); // sets it to teeth
732 // FIXME: manipulating attributes
733 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
736 if (creature == rabbittype)
737 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
738 bleedxint = abs(Random() % 512);
739 bleedyint = abs(Random() % 512);
741 if (creature == wolftype)
742 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
743 bleedxint = abs(Random() % 512);
744 bleedyint = abs(Random() % 512);
748 bleedy /= realtexdetail;
749 bleedx /= realtexdetail;
750 direction = abs(Random() % 2) * 2 - 1;
759 * spawns big blood effects and ???
760 * modifies character's skin texture
762 void Person::DoBloodBig(float howmuch, int which)
764 static int bleedxint, bleedyint, i, j;
766 if (howmuch && id == 0)
769 if (!Tutorial::active || id == 0)
770 if (aitype != playercontrolled && howmuch > 0) {
774 if (creature == wolftype) {
775 int i = abs(Random() % 2);
777 whichsound = snarlsound;
779 whichsound = snarl2sound;
781 if (creature == rabbittype) {
782 int i = abs(Random() % 2);
784 whichsound = rabbitpainsound;
785 if (i == 1 && howmuch >= 2)
786 whichsound = rabbitpain1sound;
789 if (whichsound != -1) {
790 emit_sound_at(whichsound, coords);
795 if (id == 0 && howmuch > 0) {
799 if (bloodtoggle && decals && !Tutorial::active) {
800 if (bleeding <= 0 && spurt) {
802 for (int i = 0; i < 3; i++) {
803 // emit blood particles
804 // FIXME: copypaste from above
807 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
808 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
809 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
810 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
813 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
814 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
815 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
816 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
821 // weird texture manipulation code follows.
822 // looks like this is painting blood onto the character's skin texture
823 // FIXME: surely there's a better way
825 int offsetx = 0, offsety = 0;
827 offsety = Random() % 40;
828 offsetx = abs(Random() % 60);
830 if (which == 190 || which == 185) {
831 offsety = Random() % 40;
832 offsetx = abs(Random() % 100) - 20;
835 offsety = Random() % 10;
836 offsetx = Random() % 10;
839 offsety = Random() % 20;
840 offsetx = Random() % 20;
842 if (which == 220 || which == 215) {
852 if (creature == rabbittype)
853 for (i = 0; i < 512; i++) {
854 for (j = 0; j < 512; j++) {
855 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
856 if (i < startx) startx = i;
857 if (j < starty) starty = j;
858 if (i > endx) endx = i;
859 if (j > endy) endy = j;
863 if (creature == wolftype)
864 for (i = 0; i < 512; i++) {
865 for (j = 0; j < 512; j++) {
866 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
867 if (i < startx) startx = i;
868 if (j < starty) starty = j;
869 if (i > endx) endx = i;
870 if (j > endy) endy = j;
880 if (startx < 0) startx = 0;
881 if (starty < 0) starty = 0;
882 if (endx > 512 - 1) endx = 512 - 1;
883 if (endy > 512 - 1) endy = 512 - 1;
884 if (endx < startx) endx = startx;
885 if (endy < starty) endy = starty;
887 startx /= realtexdetail;
888 starty /= realtexdetail;
889 endx /= realtexdetail;
890 endy /= realtexdetail;
892 int texdetailint = realtexdetail;
894 if (creature == rabbittype)
895 for (i = startx; i < endx; i++) {
896 for (j = starty; j < endy; j++) {
897 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
898 color = Random() % 85 + 170;
899 where = i * skeleton.skinsize * 3 + j * 3;
900 if (skeleton.skinText[where + 0] > color / 2)
901 skeleton.skinText[where + 0] = color / 2;
902 skeleton.skinText[where + 1] = 0;
903 skeleton.skinText[where + 2] = 0;
907 if (creature == wolftype)
908 for (i = startx; i < endx; i++) {
909 for (j = starty; j < endy; j++) {
910 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
911 color = Random() % 85 + 170;
912 where = i * skeleton.skinsize * 3 + j * 3;
913 if (skeleton.skinText[where + 0] > color / 2)
914 skeleton.skinText[where + 0] = color / 2;
915 skeleton.skinText[where + 1] = 0;
916 skeleton.skinText[where + 2] = 0;
920 skeleton.drawmodel.textureptr.bind();
925 if (creature == rabbittype)
926 while (bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
927 bleedxint = abs(Random() % 512);
928 bleedyint = abs(Random() % 512);
930 if (creature == wolftype)
931 while (wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || wolfbloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) {
932 bleedxint = abs(Random() % 512);
933 bleedyint = abs(Random() % 512);
935 bleedy = bleedxint + offsetx;
936 bleedx = bleedyint + offsety;
937 bleedy /= realtexdetail;
938 bleedx /= realtexdetail;
943 if (bleedx > skeleton.skinsize - 1)
944 bleedx = skeleton.skinsize - 1;
945 if (bleedy > skeleton.skinsize - 1)
946 bleedy = skeleton.skinsize - 1;
947 direction = abs(Random() % 2) * 2 - 1;
950 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
951 deathbleeding += bleeding;
952 bloodloss += bleeding * 3;
954 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
955 if (abs(Random() % 2) == 0) {
956 aitype = gethelptype;
959 aitype = attacktypecutoff;
967 * similar to DoBloodBig
969 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
973 static XYZ startpoint, endpoint, colpoint, movepoint;
974 static float rotationpoint;
976 static XYZ p1, p2, p3, p0;
979 float coordsx, coordsy;
982 if (bloodtoggle && decals && !Tutorial::active) {
985 where = DoRotation(where, 0, -yaw, 0);
993 // ray testing for a tri in the character model
994 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
995 if (whichtri != -1) {
996 // low level geometry math
998 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
999 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
1000 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
1002 bary.x = distsq(&p0, &p1);
1003 bary.y = distsq(&p0, &p2);
1004 bary.z = distsq(&p0, &p3);
1006 total = bary.x + bary.y + bary.z;
1011 bary.x = 1 - bary.x;
1012 bary.y = 1 - bary.y;
1013 bary.z = 1 - bary.z;
1015 total = bary.x + bary.y + bary.z;
1021 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1022 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1023 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1024 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1025 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1026 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1027 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;
1028 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;
1030 if (bleeding <= 0 && spurt) {
1032 for (int i = 0; i < 3; i++) {
1033 // emit blood particles
1034 // FIXME: more copypaste code
1036 if (skeleton.free) {
1037 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1038 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1039 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1040 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1043 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1044 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1045 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1046 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1051 // texture manipulation follows
1053 int offsetx = 0, offsety = 0;
1054 offsetx = (1 + coordsy) * 512 - 291;
1055 offsety = coordsx * 512 - 437;
1062 if (creature == rabbittype)
1063 for (i = 0; i < 512; i++) {
1064 for (j = 0; j < 512; j++) {
1065 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1066 if (i < startx) startx = i;
1067 if (j < starty) starty = j;
1068 if (i > endx) endx = i;
1069 if (j > endy) endy = j;
1073 if (creature == wolftype)
1074 for (i = 0; i < 512; i++) {
1075 for (j = 0; j < 512; j++) {
1076 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1077 if (i < startx) startx = i;
1078 if (j < starty) starty = j;
1079 if (i > endx) endx = i;
1080 if (j > endy) endy = j;
1089 if (startx < 0) startx = 0;
1090 if (starty < 0) starty = 0;
1091 if (endx > 512 - 1) endx = 512 - 1;
1092 if (endy > 512 - 1) endy = 512 - 1;
1093 if (endx < startx) endx = startx;
1094 if (endy < starty) endy = starty;
1096 startx /= realtexdetail;
1097 starty /= realtexdetail;
1098 endx /= realtexdetail;
1099 endy /= realtexdetail;
1101 int texdetailint = realtexdetail;
1103 if (creature == rabbittype)
1104 for (i = startx; i < endx; i++) {
1105 for (j = starty; j < endy; j++) {
1106 if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1107 color = Random() % 85 + 170;
1108 where = i * skeleton.skinsize * 3 + j * 3;
1109 if (skeleton.skinText[where + 0] > color / 2)
1110 skeleton.skinText[where + 0] = color / 2;
1111 skeleton.skinText[where + 1] = 0;
1112 skeleton.skinText[where + 2] = 0;
1113 } else if (bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1114 color = Random() % 85 + 170;
1115 where = i * skeleton.skinsize * 3 + j * 3;
1116 if (skeleton.skinText[where + 0] > color / 2)
1117 skeleton.skinText[where + 0] = color / 2;
1118 skeleton.skinText[where + 1] = 0;
1119 skeleton.skinText[where + 2] = 0;
1123 if (creature == wolftype)
1124 for (i = startx; i < endx; i++) {
1125 for (j = starty; j < endy; j++) {
1126 if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) {
1127 color = Random() % 85 + 170;
1128 where = i * skeleton.skinsize * 3 + j * 3;
1129 if (skeleton.skinText[where + 0] > color / 2)
1130 skeleton.skinText[where + 0] = color / 2;
1131 skeleton.skinText[where + 1] = 0;
1132 skeleton.skinText[where + 2] = 0;
1133 } else if (wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && wolfbloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) {
1134 color = Random() % 85 + 170;
1135 where = i * skeleton.skinsize * 3 + j * 3;
1136 if (skeleton.skinText[where + 0] > color / 2)
1137 skeleton.skinText[where + 0] = color / 2;
1138 skeleton.skinText[where + 1] = 0;
1139 skeleton.skinText[where + 2] = 0;
1143 skeleton.drawmodel.textureptr.bind();
1146 bleedy = (1 + coordsy) * 512;
1147 bleedx = coordsx * 512;
1148 bleedy /= realtexdetail;
1149 bleedx /= realtexdetail;
1154 if (bleedx > skeleton.skinsize - 1)
1155 bleedx = skeleton.skinsize - 1;
1156 if (bleedy > skeleton.skinsize - 1)
1157 bleedy = skeleton.skinsize - 1;
1158 direction = abs(Random() % 2) * 2 - 1;
1163 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1164 deathbleeding += bleeding;
1165 bloodloss += bleeding * 3;
1167 if (!Tutorial::active && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1168 if (abs(Random() % 2) == 0) {
1169 aitype = gethelptype;
1172 aitype = attacktypecutoff;
1183 * guessing this performs a reversal
1185 void Person::Reverse()
1187 if (!((victim->aitype == playercontrolled
1189 || staggerdelay <= 0)
1190 && victim->animTarget != jumpupanim
1191 && victim->animTarget != jumpdownanim
1192 && (!Tutorial::active || cananger)
1196 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1197 && (victim->id != 0 || difficulty >= 2)
1198 && (creature != wolftype || victim->creature == wolftype))
1201 if (animTarget == sweepanim) {
1202 animTarget = sweepreversedanim;
1203 animCurrent = sweepreversedanim;
1204 victim->animCurrent = sweepreversalanim;
1205 victim->animTarget = sweepreversalanim;
1207 if (animTarget == spinkickanim) {
1208 animTarget = spinkickreversedanim;
1209 animCurrent = spinkickreversedanim;
1210 victim->animCurrent = spinkickreversalanim;
1211 victim->animTarget = spinkickreversalanim;
1213 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1214 if (animTarget == rabbittacklinganim) {
1217 victim->frameCurrent = 6;
1218 victim->frameTarget = 7;
1220 animTarget = upunchreversedanim;
1221 animCurrent = upunchreversedanim;
1222 victim->animCurrent = upunchreversalanim;
1223 victim->animTarget = upunchreversalanim;
1225 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1226 if (victim->weaponactive != -1) {
1227 victim->throwtogglekeydown = 1;
1228 XYZ tempVelocity = victim->velocity * .2;
1229 if (tempVelocity.x == 0)
1230 tempVelocity.x = .1;
1231 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1232 victim->num_weapons--;
1233 if (victim->num_weapons) {
1234 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1235 if (victim->weaponstuck == victim->num_weapons)
1236 victim->weaponstuck = 0;
1239 victim->weaponactive = -1;
1240 for (unsigned j = 0; j < Person::players.size(); j++) {
1241 Person::players[j]->wentforweapon = 0;
1245 animTarget = staffhitreversedanim;
1246 animCurrent = staffhitreversedanim;
1247 victim->animCurrent = staffhitreversalanim;
1248 victim->animTarget = staffhitreversalanim;
1250 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1251 if (victim->weaponactive != -1) {
1252 victim->throwtogglekeydown = 1;
1253 XYZ tempVelocity = victim->velocity * .2;
1254 if (tempVelocity.x == 0)
1255 tempVelocity.x = .1;
1256 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1257 victim->num_weapons--;
1258 if (victim->num_weapons) {
1259 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1260 if (victim->weaponstuck == victim->num_weapons)
1261 victim->weaponstuck = 0;
1264 victim->weaponactive = -1;
1265 for (unsigned j = 0; j < Person::players.size(); j++) {
1266 Person::players[j]->wentforweapon = 0;
1269 animTarget = staffspinhitreversedanim;
1270 animCurrent = staffspinhitreversedanim;
1271 victim->animCurrent = staffspinhitreversalanim;
1272 victim->animTarget = staffspinhitreversalanim;
1274 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1275 if (victim->weaponactive != -1) {
1276 victim->throwtogglekeydown = 1;
1277 XYZ tempVelocity = victim->velocity * .2;
1278 if (tempVelocity.x == 0)
1279 tempVelocity.x = .1;
1280 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1281 victim->num_weapons--;
1282 if (victim->num_weapons) {
1283 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1284 if (victim->weaponstuck == victim->num_weapons)
1285 victim->weaponstuck = 0;
1288 victim->weaponactive = -1;
1289 for (unsigned j = 0; j < Person::players.size(); j++) {
1290 Person::players[j]->wentforweapon = 0;
1293 animTarget = swordslashreversedanim;
1294 animCurrent = swordslashreversedanim;
1295 victim->animCurrent = swordslashreversalanim;
1296 victim->animTarget = swordslashreversalanim;
1298 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1299 if (victim->weaponactive != -1) {
1300 victim->throwtogglekeydown = 1;
1301 XYZ tempVelocity = victim->velocity * .2;
1302 if (tempVelocity.x == 0)
1303 tempVelocity.x = .1;
1304 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1305 victim->num_weapons--;
1306 if (victim->num_weapons) {
1307 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1308 if (victim->weaponstuck == victim->num_weapons)
1309 victim->weaponstuck = 0;
1312 victim->weaponactive = -1;
1313 for (unsigned j = 0; j < Person::players.size(); j++) {
1314 Person::players[j]->wentforweapon = 0;
1317 animTarget = knifeslashreversedanim;
1318 animCurrent = knifeslashreversedanim;
1319 victim->animCurrent = knifeslashreversalanim;
1320 victim->animTarget = knifeslashreversalanim;
1322 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1323 victim->targettilt2 = targettilt2;
1324 victim->frameCurrent = frameCurrent;
1325 victim->frameTarget = frameTarget;
1326 victim->target = target;
1327 victim->velocity = 0;
1328 victim->oldcoords = victim->coords;
1329 victim->coords = coords;
1330 victim->targetyaw = targetyaw;
1331 victim->yaw = targetyaw;
1332 victim->victim = this->shared_from_this();
1334 if (animTarget == winduppunchanim) {
1335 animTarget = winduppunchblockedanim;
1336 victim->animTarget = blockhighleftanim;
1337 victim->frameTarget = 1;
1338 victim->target = .5;
1339 victim->victim = this->shared_from_this();
1340 victim->targetyaw = targetyaw + 180;
1342 if (animTarget == wolfslapanim) {
1343 animTarget = winduppunchblockedanim;
1344 victim->animTarget = blockhighleftanim;
1345 victim->frameTarget = 1;
1346 victim->target = .5;
1347 victim->victim = this->shared_from_this();
1348 victim->targetyaw = targetyaw + 180;
1350 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1351 animTarget = swordslashparriedanim;
1352 parriedrecently = .4;
1353 victim->parriedrecently = 0;
1354 victim->animTarget = swordslashparryanim;
1355 victim->frameTarget = 1;
1356 victim->target = .5;
1357 victim->victim = this->shared_from_this();
1358 victim->targetyaw = targetyaw + 180;
1360 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1361 if (victim->weaponactive != -1) {
1362 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1363 if (weapons[victim->weaponids[0]].getType() == staff)
1364 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1365 if (weapons[weaponids[0]].getType() == staff)
1366 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1367 emit_sound_at(swordstaffsound, victim->coords);
1369 emit_sound_at(metalhitsound, victim->coords);
1373 victim->Puff(righthand);
1375 victim->frameTarget = 0;
1376 victim->animTarget = staggerbackhighanim;
1377 victim->targetyaw = targetyaw + 180;
1379 aim = DoRotation(facing, 0, 90, 0) * 21;
1381 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1382 victim->num_weapons--;
1383 if (victim->num_weapons) {
1384 victim->weaponids[0] = victim->weaponids[num_weapons];
1385 if (victim->weaponstuck == victim->num_weapons)
1386 victim->weaponstuck = 0;
1388 victim->weaponactive = -1;
1389 for (unsigned i = 0; i < Person::players.size(); i++) {
1390 Person::players[i]->wentforweapon = 0;
1394 if (abs(Random() % 20) == 0) {
1395 if (weaponactive != -1) {
1396 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1397 if (weapons[victim->weaponids[0]].getType() == staff)
1398 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1399 if (weapons[weaponids[0]].getType() == staff)
1400 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1402 emit_sound_at(swordstaffsound, coords);
1404 emit_sound_at(metalhitsound, coords);
1412 animTarget = staggerbackhighanim;
1413 targetyaw = targetyaw + 180;
1415 aim = DoRotation(facing, 0, 90, 0) * 21;
1417 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1420 weaponids[0] = weaponids[num_weapons];
1421 if (weaponstuck == num_weapons)
1425 for (unsigned i = 0; i < Person::players.size(); i++) {
1426 Person::players[i]->wentforweapon = 0;
1433 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1434 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1435 victim->animTarget = dodgebackanim;
1436 victim->frameTarget = 0;
1440 rotatetarget = coords - victim->coords;
1441 Normalise(&rotatetarget);
1442 victim->targetyaw = -asin(0 - rotatetarget.x);
1443 victim->targetyaw *= 360 / 6.28;
1444 if (rotatetarget.z < 0)
1445 victim->targetyaw = 180 - victim->targetyaw;
1447 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1449 victim->lastattack3 = victim->lastattack2;
1450 victim->lastattack2 = victim->lastattack;
1451 victim->lastattack = victim->animTarget;
1453 victim->animTarget = sweepanim;
1454 victim->frameTarget = 0;
1458 rotatetarget = coords - victim->coords;
1459 Normalise(&rotatetarget);
1460 victim->targetyaw = -asin(0 - rotatetarget.x);
1461 victim->targetyaw *= 360 / 6.28;
1462 if (rotatetarget.z < 0)
1463 victim->targetyaw = 180 - victim->targetyaw;
1465 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1467 victim->lastattack3 = victim->lastattack2;
1468 victim->lastattack2 = victim->lastattack;
1469 victim->lastattack = victim->animTarget;
1474 victim->velocity = 0;
1476 if (aitype != playercontrolled) {
1478 if (escapednum < 2) {
1479 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1480 if ((Random() % chances) == 0) {
1486 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1493 void Person::DoDamage(float howmuch)
1495 // subtract health (temporary?)
1496 if (!Tutorial::active)
1497 damage += howmuch / power;
1500 damagedealt += howmuch / power;
1502 damagetaken += howmuch / power;
1505 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1508 if (!Tutorial::active)
1509 permanentdamage += howmuch / 2 / power;
1510 if (!Tutorial::active)
1511 superpermanentdamage += howmuch / 4 / power;
1513 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1515 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1519 camerashake += howmuch / 100;
1520 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1521 blackout = damage / damagetolerance;
1526 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1527 aitype = attacktypecutoff;
1528 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1529 if (abs(Random() % 2) == 0) {
1530 aitype = gethelptype;
1533 aitype = attacktypecutoff;
1537 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1540 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1541 if (skeleton.free) {
1542 flatvelocity2 = skeleton.joints[i].velocity;
1543 flatfacing2 = skeleton.joints[i].position * scale + coords;
1545 flatvelocity2 = velocity;
1546 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1548 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1549 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1550 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1551 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1552 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1553 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1556 emit_sound_at(splattersound, coords);
1561 if (!dead && creature == wolftype) {
1562 award_bonus(0, Wolfbonus);
1569 if (!Tutorial::active || id == 0)
1570 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1571 int whichsound = -1;
1573 if (creature == wolftype) {
1574 int i = abs(Random() % 2);
1576 whichsound = snarlsound;
1578 whichsound = snarl2sound;
1580 if (creature == rabbittype) {
1581 int i = abs(Random() % 2);
1583 whichsound = rabbitpainsound;
1584 if (i == 1 && damage > damagetolerance)
1585 whichsound = rabbitpain1sound;
1588 if (whichsound != -1) {
1589 emit_sound_at(whichsound, coords);
1590 addEnvSound(coords);
1597 * calculate/animate head facing direction?
1599 void Person::DoHead()
1601 static XYZ rotatearound;
1603 static float lookspeed = 500;
1605 if (!freeze && !winfreeze) {
1608 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1609 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1611 while (targetheadyaw > 180)targetheadyaw -= 360;
1612 while (targetheadyaw < -180)targetheadyaw += 360;
1614 if (targetheadyaw > 160)
1615 targetheadpitch = targetheadpitch * -1;
1616 if (targetheadyaw < -160)
1617 targetheadpitch = targetheadpitch * -1;
1618 if (targetheadyaw > 160)
1619 targetheadyaw = targetheadyaw - 180;
1620 if (targetheadyaw < -160)
1621 targetheadyaw = targetheadyaw + 180;
1623 if (targetheadpitch > 120)
1624 targetheadpitch = 120;
1625 if (targetheadpitch < -120)
1626 targetheadpitch = -120;
1627 if (targetheadyaw > 120)
1628 targetheadyaw = 120;
1629 if (targetheadyaw < -120)
1630 targetheadyaw = -120;
1633 targetheadpitch = 0;
1635 if (targetheadyaw > 80)
1637 if (targetheadyaw < -80)
1638 targetheadyaw = -80;
1639 if (targetheadpitch > 50)
1640 targetheadpitch = 50;
1641 if (targetheadpitch < -50)
1642 targetheadpitch = -50;
1645 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1646 headyaw = targetheadyaw;
1647 else if (headyaw > targetheadyaw) {
1648 headyaw -= multiplier * lookspeed;
1649 } else if (headyaw < targetheadyaw) {
1650 headyaw += multiplier * lookspeed;
1653 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1654 headpitch = targetheadpitch;
1655 else if (headpitch > targetheadpitch) {
1656 headpitch -= multiplier * lookspeed / 2;
1657 } else if (headpitch < targetheadpitch) {
1658 headpitch += multiplier * lookspeed / 2;
1661 rotatearound = jointPos(neck);
1662 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1666 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1667 facing = DoRotation(facing, headpitch * .4, 0, 0);
1668 facing = DoRotation(facing, 0, headyaw * .4, 0);
1671 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1672 facing = DoRotation(facing, headpitch * .8, 0, 0);
1673 facing = DoRotation(facing, 0, headyaw * .8, 0);
1676 if (animTarget == walkanim) {
1677 facing = DoRotation(facing, headpitch * .6, 0, 0);
1678 facing = DoRotation(facing, 0, headyaw * .6, 0);
1681 skeleton.specialforward[0] = facing;
1682 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1683 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1684 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1685 skeleton.FindRotationMuscle(i, animTarget);
1692 * ragdolls character?
1694 void Person::RagDoll(bool checkcollision)
1699 if (!skeleton.free) {
1702 if (id == 0 && isFlip())
1709 facing = DoRotation(facing, 0, yaw, 0);
1711 skeleton.freetime = 0;
1713 skeleton.longdead = 0;
1716 skeleton.broken = 0;
1717 skeleton.spinny = 1;
1719 skeleton.freefall = 1;
1721 if (!isnormal(velocity.x)) velocity.x = 0;
1722 if (!isnormal(velocity.y)) velocity.y = 0;
1723 if (!isnormal(velocity.z)) velocity.z = 0;
1724 if (!isnormal(yaw)) yaw = 0;
1725 if (!isnormal(coords.x)) coords = 0;
1726 if (!isnormal(tilt)) tilt = 0;
1727 if (!isnormal(tilt2)) tilt2 = 0;
1729 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1730 skeleton.joints[i].delay = 0;
1731 skeleton.joints[i].locked = 0;
1732 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1733 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1734 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1735 skeleton.joints[i].position.y += .1;
1736 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1737 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1740 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1741 skeleton.joints[i].velocity = 0;
1742 skeleton.joints[i].velchange = 0;
1744 skeleton.DoConstraints(&coords, &scale);
1745 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1746 skeleton.DoConstraints(&coords, &scale);
1747 skeleton.DoConstraints(&coords, &scale);
1748 skeleton.DoConstraints(&coords, &scale);
1749 skeleton.DoConstraints(&coords, &scale);
1752 speed = targetFrame().speed * 2;
1753 if (currentFrame().speed > targetFrame().speed) {
1754 speed = currentFrame().speed * 2;
1757 speed = transspeed * 2;
1761 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1762 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1763 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);
1765 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1766 change.x = (float)(Random() % 100) / 100;
1767 change.y = (float)(Random() % 100) / 100;
1768 change.z = (float)(Random() % 100) / 100;
1769 skeleton.joints[i].velocity += change;
1770 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1772 change.x = (float)(Random() % 100) / 100;
1773 change.y = (float)(Random() % 100) / 100;
1774 change.z = (float)(Random() % 100) / 100;
1775 skeleton.joints[i].velchange += change;
1776 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1779 if (checkcollision) {
1782 if (!skeleton.joints.empty()) {
1785 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1786 average += skeleton.joints[j].position;
1788 average /= skeleton.joints.size();
1789 coords += average * scale;
1790 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1791 skeleton.joints[j].position -= average;
1795 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1796 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1797 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1798 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1799 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1802 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1803 coords.x = lowpoint.x;
1804 coords.z = lowpoint.z;
1813 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1814 velocity += skeleton.joints[i].velocity * scale;
1816 velocity /= skeleton.joints.size();
1819 if (Random() % 2 == 0) {
1820 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1821 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1822 weapons[weaponids[0]].velocity.x += .01;
1825 weaponids[0] = weaponids[num_weapons];
1826 if (weaponstuck == num_weapons)
1830 for (unsigned i = 0; i < Person::players.size(); i++) {
1831 Person::players[i]->wentforweapon = 0;
1836 animTarget = bounceidleanim;
1837 animCurrent = bounceidleanim;
1847 void Person::FootLand(bodypart whichfoot, float opacity)
1849 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1850 cerr << "FootLand called on wrong bodypart" << endl;
1853 static XYZ terrainlight;
1854 static XYZ footvel, footpoint;
1855 if (opacity >= 1 || skiddelay <= 0) {
1858 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1859 if (distsq(&footpoint, &viewer))
1860 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1861 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1862 footvel = velocity / 5;
1865 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1866 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1867 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1868 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1869 if (environment == snowyenvironment) {
1870 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1872 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1874 } else if (environment == grassyenvironment) {
1875 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1876 } else if (environment == desertenvironment) {
1877 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1879 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1883 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1884 footvel = velocity / 5;
1887 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1888 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1889 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1896 * make a puff effect at a body part (dust effect?)
1898 void Person::Puff(int whichlabel)
1900 static XYZ footvel, footpoint;
1903 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1904 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1908 * I think I added this in an attempt to clean up code
1910 void Person::setAnimation(int animation)
1912 animTarget = animation;
1921 void Person::DoAnimations()
1923 if (!skeleton.free) {
1924 static float oldtarget;
1926 if (isIdle() && animCurrent != getIdle())
1927 normalsupdatedelay = 0;
1929 if (animTarget == tempanim || animCurrent == tempanim) {
1930 Animation::animations[tempanim] = tempanimation;
1932 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1938 vel[0] = velocity.x;
1939 vel[1] = velocity.y;
1940 vel[2] = velocity.z;
1943 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1944 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1946 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1948 if (!crouchkeydown && velocity.y >= -15)
1951 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1956 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1958 if (normaldotproduct(targfacing, velocity) >= -.3)
1959 animTarget = flipanim;
1961 animTarget = backflipanim;
1962 crouchtogglekeydown = 1;
1970 if (Animation::animations[animTarget].attack != reversed)
1972 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1973 crouchtogglekeydown = 0;
1974 if (aitype == playercontrolled)
1977 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1980 crouchtogglekeydown = 1;
1984 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1986 normalsupdatedelay = 0;
1990 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1992 emit_sound_at(fireendsound, coords);
1993 pause_sound(stream_firesound);
1997 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1998 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
2000 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2001 if (normaldotproduct(victim->facing, facing) > 0)
2002 victim->animTarget = rabbittackledbackanim;
2004 victim->animTarget = rabbittackledfrontanim;
2005 victim->frameTarget = 2;
2008 victim->targetyaw = yaw;
2009 if (victim->aitype == gethelptype)
2010 victim->DoDamage(victim->damagetolerance - victim->damage);
2011 //victim->DoDamage(30);
2012 if (creature == wolftype) {
2014 emit_sound_at(clawslicesound, victim->coords);
2016 victim->DoBloodBig(1 / victim->armorhead, 210);
2018 award_bonus(id, TackleBonus,
2019 victim->aitype == gethelptype ? 50 : 0);
2023 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2024 if (weapons[weaponids[0]].getType() == knife) {
2025 if (weaponactive == -1)
2027 else if (weaponactive == 0)
2030 if (weaponactive == -1) {
2031 emit_sound_at(knifesheathesound, coords);
2033 if (weaponactive != -1) {
2034 emit_sound_at(knifedrawsound, coords, 128);
2037 drawtogglekeydown = 1;
2040 if (!Tutorial::active || id == 0)
2041 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2042 int whichsound = -1;
2044 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2045 if (targetFrame().label == 1)
2046 whichsound = footstepsound;
2048 whichsound = footstepsound2;
2049 if (targetFrame().label == 1)
2050 FootLand(leftfoot, 1);
2051 if (targetFrame().label == 2)
2052 FootLand(rightfoot, 1);
2053 if (targetFrame().label == 3 && isRun()) {
2054 FootLand(rightfoot, 1);
2055 FootLand(leftfoot, 1);
2059 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2060 if (targetFrame().label == 1)
2061 whichsound = footstepsound3;
2063 whichsound = footstepsound4;
2067 if (targetFrame().label == 1)
2068 whichsound = footstepsound3;
2070 whichsound = footstepsound4;
2072 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2073 if (Animation::animations[animTarget].attack != neutral) {
2074 unsigned r = abs(Random() % 3);
2076 whichsound = lowwhooshsound;
2078 whichsound = midwhooshsound;
2080 whichsound = highwhooshsound;
2082 if (Animation::animations[animTarget].attack == neutral) {
2083 whichsound = movewhooshsound;
2085 } else if (targetFrame().label == 4) {
2086 whichsound = knifeswishsound;
2088 if (targetFrame().label == 8 && !Tutorial::active) {
2089 whichsound = landsound2;
2092 if (whichsound != -1) {
2093 emit_sound_at(whichsound, coords, 256.);
2096 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2097 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2098 addEnvSound(coords, 15);
2100 addEnvSound(coords, 6);
2105 if (targetFrame().label == 3) {
2107 emit_sound_at(whichsound, coords, 128.);
2113 if (!Tutorial::active || id == 0)
2114 if (speechdelay <= 0)
2115 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2116 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2117 int whichsound = -1;
2118 if (targetFrame().label == 4 && aitype != playercontrolled) {
2119 if (Animation::animations[animTarget].attack != neutral) {
2120 unsigned r = abs(Random() % 4);
2121 if (creature == rabbittype) {
2122 if (r == 0) whichsound = rabbitattacksound;
2123 if (r == 1) whichsound = rabbitattack2sound;
2124 if (r == 2) whichsound = rabbitattack3sound;
2125 if (r == 3) whichsound = rabbitattack4sound;
2127 if (creature == wolftype) {
2128 if (r == 0) whichsound = barksound;
2129 if (r == 1) whichsound = bark2sound;
2130 if (r == 2) whichsound = bark3sound;
2131 if (r == 3) whichsound = barkgrowlsound;
2137 if (whichsound != -1) {
2138 emit_sound_at(whichsound, coords);
2144 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2145 FootLand(leftfoot, 1);
2146 FootLand(rightfoot, 1);
2150 currentoffset = targetoffset;
2151 frameTarget = frameCurrent;
2152 animCurrent = animTarget;
2155 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2156 for (unsigned i = 0; i < weapons.size(); i++) {
2157 if (weapons[i].owner == -1)
2158 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2159 if (distsq(&coords, &weapons[i].position) >= 1) {
2160 if (weapons[i].getType() != staff) {
2161 emit_sound_at(knifedrawsound, coords, 128.);
2170 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2171 for (unsigned i = 0; i < weapons.size(); i++) {
2172 bool willwork = true;
2173 if (weapons[i].owner != -1)
2174 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2175 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2176 if (Person::players[weapons[i].owner]->num_weapons > 1)
2178 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2179 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2180 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2181 bool fleshstuck = false;
2182 if (weapons[i].owner != -1)
2183 if (victim->weaponstuck != -1) {
2184 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2189 emit_sound_at(fleshstabremovesound, coords, 128.);
2191 if (weapons[i].getType() != staff) {
2192 emit_sound_at(knifedrawsound, coords, 128.);
2195 if (weapons[i].owner != -1) {
2196 victim = Person::players[weapons[i].owner];
2197 if (victim->num_weapons == 1)
2198 victim->num_weapons = 0;
2200 victim->num_weapons = 1;
2202 //victim->weaponactive=-1;
2203 victim->skeleton.longdead = 0;
2204 victim->skeleton.free = 1;
2205 victim->skeleton.broken = 0;
2207 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2208 victim->skeleton.joints[j].velchange = 0;
2209 victim->skeleton.joints[j].locked = 0;
2215 Normalise(&relative);
2216 XYZ footvel, footpoint;
2218 footpoint = weapons[i].position;
2219 if (victim->weaponstuck != -1) {
2220 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2222 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2223 weapons[i].bloody = 2;
2224 weapons[i].blooddrip = 5;
2225 victim->weaponstuck = -1;
2228 if (victim->num_weapons > 0) {
2229 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2230 victim->weaponstuck = 0;
2231 if (victim->weaponids[0] == int(i))
2232 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2235 victim->jointVel(abdomen) += relative * 6;
2236 victim->jointVel(neck) += relative * 6;
2237 victim->jointVel(rightshoulder) += relative * 6;
2238 victim->jointVel(leftshoulder) += relative * 6;
2246 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2247 if (weaponactive == -1)
2249 else if (weaponactive == 0) {
2251 if (num_weapons == 2) {
2253 buffer = weaponids[0];
2254 weaponids[0] = weaponids[1];
2255 weaponids[1] = buffer;
2258 if (weaponactive == -1) {
2259 emit_sound_at(knifesheathesound, coords, 128.);
2261 if (weaponactive != -1) {
2262 emit_sound_at(knifedrawsound, coords, 128.);
2267 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2268 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2269 Normalise(&rotatetarget);
2270 targetyaw = -asin(0 - rotatetarget.x);
2271 targetyaw *= 360 / 6.28;
2272 if (rotatetarget.z < 0)
2273 targetyaw = 180 - targetyaw;
2275 if (animTarget == walljumprightkickanim)
2277 if (animTarget == walljumpleftkickanim)
2283 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2286 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2291 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2292 animTarget = rabbittackleanim;
2294 emit_sound_at(jumpsound, coords);
2302 targetloc = velocity;
2303 Normalise(&targetloc);
2304 targetloc += coords;
2305 for (unsigned i = 0; i < Person::players.size(); i++) {
2307 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2308 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2312 if (closestid != -1)
2313 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2315 victim = Person::players[closestid];
2316 coords = victim->coords;
2317 animCurrent = rabbittacklinganim;
2318 animTarget = rabbittacklinganim;
2322 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2323 rotatetarget = coords - victim->coords;
2324 Normalise(&rotatetarget);
2325 targetyaw = -asin(0 - rotatetarget.x);
2326 targetyaw *= 360 / 6.28;
2327 if (rotatetarget.z < 0)
2328 targetyaw = 180 - targetyaw;
2330 if (animTarget != rabbitrunninganim) {
2331 emit_sound_at(jumpsound, coords, 128.);
2337 float damagemult = 1 * power;
2338 if (creature == wolftype)
2339 damagemult = 2.5 * power;
2341 damagemult /= victim->damagetolerance / 200;
2343 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)) {
2344 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2345 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2349 if (Random() % 2 || creature == wolftype) {
2352 if (creature == wolftype)
2355 if (!Tutorial::active) {
2356 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2358 if (creature == wolftype) {
2359 emit_sound_at(clawslicesound, victim->coords, 128.);
2361 victim->DoBloodBig(2 / victim->armorhead, 175);
2365 relative = victim->coords - coords;
2367 Normalise(&relative);
2368 relative = DoRotation(relative, 0, -90, 0);
2369 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2370 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2372 victim->jointVel(head) += relative * damagemult * 200;
2374 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2380 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2381 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2385 if (Random() % 2 || creature == wolftype) {
2387 if (creature == wolftype)
2390 emit_sound_at(whooshhitsound, victim->coords);
2391 if (creature == wolftype) {
2392 emit_sound_at(clawslicesound, victim->coords, 128.);
2394 victim->DoBloodBig(2, 175);
2398 relative = victim->coords - coords;
2400 Normalise(&relative);
2402 Normalise(&relative);
2403 relative = DoRotation(relative, 0, 90, 0);
2404 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2405 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2407 victim->jointVel(head) += relative * damagemult * 100;
2409 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2413 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2414 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2420 if (!Tutorial::active) {
2421 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2423 if (creature == wolftype) {
2424 emit_sound_at(clawslicesound, victim->coords, 128.);
2426 victim->DoBloodBig(2 / victim->armorhead, 175);
2432 Normalise(&relative);
2433 relative = DoRotation(relative, 0, -90, 0);
2434 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2435 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2437 victim->jointVel(head) += relative * damagemult * 200;
2439 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2441 if (victim->damage > victim->damagetolerance)
2442 award_bonus(id, style);
2448 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2449 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2455 if (!Tutorial::active) {
2456 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2458 if (creature == wolftype) {
2459 emit_sound_at(clawslicesound, victim->coords, 128.);
2461 victim->DoBloodBig(2 / victim->armorhead, 175);
2467 Normalise(&relative);
2468 relative = DoRotation(relative, 0, 90, 0);
2469 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2470 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2472 victim->jointVel(head) += relative * damagemult * 200;
2474 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2476 if (victim->damage > victim->damagetolerance)
2477 award_bonus(id, style);
2483 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2484 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2492 emit_sound_at(whooshhitsound, victim->coords);
2495 relative = victim->coords - coords;
2497 Normalise(&relative);
2498 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2499 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2501 victim->jointVel(head) += relative * damagemult * 100;
2503 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2507 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2508 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2512 emit_sound_at(whooshhitsound, victim->coords, 128.);
2514 victim->skeleton.longdead = 0;
2515 victim->skeleton.free = 1;
2516 victim->skeleton.broken = 0;
2517 victim->skeleton.spinny = 1;
2519 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2520 victim->skeleton.joints[i].velchange = 0;
2521 victim->skeleton.joints[i].delay = 0;
2522 victim->skeleton.joints[i].locked = 0;
2523 //victim->skeleton.joints[i].velocity=0;
2529 Normalise(&relative);
2530 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2531 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2532 victim->skeleton.joints[i].position.y += relative.y * .3;
2533 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2534 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2536 victim->Puff(abdomen);
2537 victim->jointVel(abdomen).y = relative.y * 400;
2541 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2542 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2546 if (!Tutorial::active) {
2547 emit_sound_at(heavyimpactsound, coords, 128.);
2550 relative = victim->coords - coords;
2552 Normalise(&relative);
2553 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2554 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2556 victim->Puff(abdomen);
2557 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2561 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2562 victim->jointVel(abdomen) += relative * damagemult * 300;
2566 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2567 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2571 if (!Tutorial::active) {
2572 emit_sound_at(thudsound, coords);
2575 victim->skeleton.longdead = 0;
2576 victim->skeleton.free = 1;
2577 victim->skeleton.broken = 0;
2578 victim->skeleton.spinny = 1;
2580 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2581 victim->skeleton.joints[i].velchange = 0;
2582 //victim->skeleton.joints[i].delay=0;
2583 victim->skeleton.joints[i].locked = 0;
2586 relative = victim->coords - coords;
2587 Normalise(&relative);
2589 Normalise(&relative);
2590 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2591 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2596 victim->Puff(abdomen);
2597 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2598 victim->jointVel(abdomen) += relative * damagemult * 200;
2607 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2610 if (!victim->skeleton.free)
2614 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2615 emit_sound_at(knifesheathesound, coords, 128.);
2618 if (victim && hasvictim) {
2619 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2621 XYZ where, startpoint, endpoint, movepoint, colpoint;
2622 float rotationpoint;
2624 if (weapons[weaponids[weaponactive]].getType() == knife) {
2625 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2626 where -= victim->coords;
2627 if (!victim->skeleton.free)
2628 where = DoRotation(where, 0, -victim->yaw, 0);
2631 startpoint.y += 100;
2635 if (weapons[weaponids[weaponactive]].getType() == sword) {
2636 where = weapons[weaponids[weaponactive]].position;
2637 where -= victim->coords;
2638 if (!victim->skeleton.free)
2639 where = DoRotation(where, 0, -victim->yaw, 0);
2641 where = weapons[weaponids[weaponactive]].tippoint;
2642 where -= victim->coords;
2643 if (!victim->skeleton.free)
2644 where = DoRotation(where, 0, -victim->yaw, 0);
2647 if (weapons[weaponids[weaponactive]].getType() == staff) {
2648 where = weapons[weaponids[weaponactive]].position;
2649 where -= victim->coords;
2650 if (!victim->skeleton.free)
2651 where = DoRotation(where, 0, -victim->yaw, 0);
2653 where = weapons[weaponids[weaponactive]].tippoint;
2654 where -= victim->coords;
2655 if (!victim->skeleton.free)
2656 where = DoRotation(where, 0, -victim->yaw, 0);
2661 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2663 if (whichtri != -1) {
2664 if (victim->dead != 2) {
2665 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2667 award_bonus(id, FinishedBonus);
2670 weapons[weaponids[weaponactive]].bloody = 2;
2672 victim->skeleton.longdead = 0;
2673 victim->skeleton.free = 1;
2674 victim->skeleton.broken = 0;
2676 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2677 victim->skeleton.joints[i].velchange = 0;
2678 victim->skeleton.joints[i].locked = 0;
2679 //victim->skeleton.joints[i].velocity=0;
2681 emit_sound_at(fleshstabsound, coords, 128);
2684 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2685 weapons[weaponids[weaponactive]].blooddrip += 5;
2686 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2688 if (whichtri == -1) {
2690 emit_sound_at(knifesheathesound, coords, 128.);
2696 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2698 emit_sound_at(knifedrawsound, coords, 128);
2701 if (victim && hasvictim) {
2702 XYZ footvel, footpoint;
2704 emit_sound_at(fleshstabremovesound, coords, 128.);
2707 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2709 if (weapons[weaponids[weaponactive]].getType() == sword) {
2710 XYZ where, startpoint, endpoint, movepoint;
2711 float rotationpoint;
2714 where = weapons[weaponids[weaponactive]].position;
2715 where -= victim->coords;
2716 if (!victim->skeleton.free)
2717 where = DoRotation(where, 0, -victim->yaw, 0);
2719 where = weapons[weaponids[weaponactive]].tippoint;
2720 where -= victim->coords;
2721 if (!victim->skeleton.free)
2722 where = DoRotation(where, 0, -victim->yaw, 0);
2727 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2728 footpoint += victim->coords;
2730 if (whichtri == -1) {
2731 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2734 if (weapons[weaponids[weaponactive]].getType() == staff) {
2735 XYZ where, startpoint, endpoint, movepoint;
2736 float rotationpoint;
2739 where = weapons[weaponids[weaponactive]].position;
2740 where -= victim->coords;
2741 if (!victim->skeleton.free)
2742 where = DoRotation(where, 0, -victim->yaw, 0);
2744 where = weapons[weaponids[weaponactive]].tippoint;
2745 where -= victim->coords;
2746 if (!victim->skeleton.free)
2747 where = DoRotation(where, 0, -victim->yaw, 0);
2752 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2753 footpoint += victim->coords;
2755 if (whichtri == -1) {
2756 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2759 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2761 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2762 victim->skeleton.longdead = 0;
2763 victim->skeleton.free = 1;
2764 victim->skeleton.broken = 0;
2766 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2767 victim->skeleton.joints[i].velchange = 0;
2768 victim->skeleton.joints[i].locked = 0;
2769 //victim->skeleton.joints[i].velocity=0;
2775 Normalise(&relative);
2776 //victim->Puff(abdomen);
2778 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2780 if (victim->bloodloss < victim->damagetolerance) {
2781 victim->bloodloss += 1000;
2785 victim->jointVel(abdomen) += relative * damagemult * 20;
2789 if (!hasvictim && onterrain) {
2790 weapons[weaponids[weaponactive]].bloody = 0;
2791 weapons[weaponids[weaponactive]].blooddrip = 0;
2795 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2796 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2804 if (!Tutorial::active) {
2805 emit_sound_at(heavyimpactsound, victim->coords, 128);
2810 relative = victim->coords - coords;
2812 Normalise(&relative);
2813 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2814 victim->skeleton.joints[i].velocity = relative * 30;
2816 victim->jointVel(head) += relative * damagemult * 150;
2818 victim->frameTarget = 0;
2819 victim->animTarget = staggerbackhardanim;
2820 victim->targetyaw = targetyaw + 180;
2822 victim->stunned = 1;
2825 victim->Puff(abdomen);
2826 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2833 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2834 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2838 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2839 if (!Tutorial::active) {
2840 emit_sound_at(thudsound, victim->coords);
2842 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2843 if (!Tutorial::active) {
2844 emit_sound_at(whooshhitsound, victim->coords);
2847 if (!Tutorial::active) {
2848 emit_sound_at(heavyimpactsound, victim->coords);
2852 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2855 relative = victim->coords - coords;
2857 Normalise(&relative);
2859 Normalise(&relative);
2860 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2861 victim->skeleton.joints[i].velocity = relative * 5;
2863 victim->jointVel(abdomen) += relative * damagemult * 400;
2865 victim->frameTarget = 0;
2866 victim->animTarget = staggerbackhardanim;
2867 victim->targetyaw = targetyaw + 180;
2869 victim->stunned = 1;
2871 victim->Puff(abdomen);
2872 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2878 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2879 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2880 if (victim->id == 0)
2882 emit_sound_at(landsound2, victim->coords);
2888 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2889 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2890 if (victim->id == 0)
2893 if (weaponactive != -1) {
2894 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2895 if (weapons[victim->weaponids[0]].getType() == staff)
2896 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2897 if (weapons[weaponids[0]].getType() == staff)
2898 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2900 emit_sound_at(swordstaffsound, victim->coords);
2902 emit_sound_at(metalhitsound, victim->coords);
2910 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2911 if (weaponactive != -1) {
2914 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);
2916 weapons[weaponids[0]].thrown(aim * 50);
2919 weaponids[0] = weaponids[num_weapons];
2925 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2927 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2929 if (!Tutorial::active)
2930 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2932 award_bonus(id, Slicebonus);
2933 if (!Tutorial::active) {
2934 emit_sound_at(knifeslicesound, victim->coords);
2936 //victim->jointVel(abdomen)+=relative*damagemult*200;
2937 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2938 if (victim->id != 0 || difficulty == 2) {
2939 victim->frameTarget = 0;
2940 victim->animTarget = staggerbackhardanim;
2941 victim->targetyaw = targetyaw + 180;
2945 victim->lowreversaldelay = 0;
2946 victim->highreversaldelay = 0;
2947 if (aitype != playercontrolled)
2948 weaponmissdelay = .6;
2950 if (!Tutorial::active)
2951 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2952 weapons[weaponids[weaponactive]].bloody = 1;
2953 if (!Tutorial::active)
2954 weapons[weaponids[weaponactive]].blooddrip += 3;
2956 XYZ footvel, footpoint;
2958 if (skeleton.free) {
2959 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2961 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2963 if (!Tutorial::active) {
2965 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2966 footvel = DoRotation(facing, 0, 90, 0) * .8;
2968 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2969 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2970 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2971 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2973 if (Tutorial::active) {
2974 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2976 victim->DoDamage(damagemult * 0);
2979 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2980 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2981 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2982 award_bonus(id, Slashbonus);
2984 if (!Tutorial::active) {
2985 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2986 victim->DoBloodBig(2 / victim->armorhigh, 190);
2988 victim->DoBloodBig(2 / victim->armorhigh, 185);
2989 victim->deathbleeding = 1;
2990 emit_sound_at(swordslicesound, victim->coords);
2992 //victim->jointVel(abdomen)+=relative*damagemult*200;
2993 if (!Tutorial::active) {
2994 victim->frameTarget = 0;
2995 victim->animTarget = staggerbackhardanim;
2996 victim->targetyaw = targetyaw + 180;
3000 if (!Tutorial::active) {
3001 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3002 weapons[weaponids[weaponactive]].bloody = 1;
3003 weapons[weaponids[weaponactive]].blooddrip += 3;
3005 float bloodlossamount;
3006 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3007 victim->bloodloss += bloodlossamount / victim->armorhigh;
3008 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
3009 victim->DoDamage(damagemult * 0);
3011 XYZ footvel, footpoint;
3013 if (skeleton.free) {
3014 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3016 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3019 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3020 footvel = DoRotation(facing, 0, 90, 0) * .8;
3022 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3023 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3024 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3025 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3028 if (victim->weaponactive != -1) {
3029 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3030 if (weapons[victim->weaponids[0]].getType() == staff)
3031 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3032 if (weapons[weaponids[0]].getType() == staff)
3033 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3035 emit_sound_at(swordstaffsound, victim->coords);
3037 emit_sound_at(metalhitsound, victim->coords);
3043 victim->Puff(righthand);
3045 victim->frameTarget = 0;
3046 victim->animTarget = staggerbackhighanim;
3047 victim->targetyaw = targetyaw + 180;
3049 aim = DoRotation(facing, 0, 90, 0) * 21;
3051 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3052 victim->num_weapons--;
3053 if (victim->num_weapons) {
3054 victim->weaponids[0] = victim->weaponids[num_weapons];
3055 if (victim->weaponstuck == victim->num_weapons)
3056 victim->weaponstuck = 0;
3058 victim->weaponactive = -1;
3059 for (unsigned i = 0; i < Person::players.size(); i++) {
3060 Person::players[i]->wentforweapon = 0;
3067 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3068 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3069 if (!Tutorial::active) {
3070 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3074 if (Random() % 2 || creature == wolftype) {
3077 emit_sound_at(staffheadsound, victim->coords);
3081 relative = victim->coords - coords;
3083 Normalise(&relative);
3084 relative = DoRotation(relative, 0, 90, 0);
3086 Normalise(&relative);
3087 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3088 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3090 victim->jointVel(head) += relative * damagemult * 230;
3091 victim->jointVel(neck) += relative * damagemult * 230;
3093 if (!Tutorial::active) {
3094 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3096 award_bonus(id, solidhit, 30);
3101 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3102 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3103 if (!Tutorial::active) {
3104 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3108 if (Random() % 2 || creature == wolftype) {
3111 emit_sound_at(staffheadsound, victim->coords);
3115 relative = victim->coords - coords;
3117 Normalise(&relative);
3118 relative = DoRotation(relative, 0, -90, 0);
3119 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3120 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3122 victim->jointVel(head) += relative * damagemult * 220;
3123 victim->jointVel(neck) += relative * damagemult * 220;
3125 if (!Tutorial::active) {
3126 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3128 award_bonus(id, solidhit, 60);
3133 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3134 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3136 if (!Tutorial::active) {
3138 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3141 if (Random() % 2 || creature == wolftype) {
3144 emit_sound_at(staffbodysound, victim->coords);
3146 victim->skeleton.longdead = 0;
3147 victim->skeleton.free = 1;
3148 victim->skeleton.broken = 0;
3150 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3151 victim->skeleton.joints[i].velchange = 0;
3152 victim->skeleton.joints[i].locked = 0;
3153 //victim->skeleton.joints[i].velocity=0;
3160 Normalise(&relative);
3161 if (!victim->dead) {
3162 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3163 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3165 victim->jointVel(abdomen) += relative * damagemult * 40;
3168 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3169 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3172 victim->Puff(abdomen);
3173 if (!Tutorial::active) {
3174 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3176 if (!victim->dead) {
3177 award_bonus(id, solidhit, 40);
3183 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3184 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3189 relative = victim->coords - coords;
3191 Normalise(&relative);
3195 if (Animation::animations[victim->animTarget].height == lowheight) {
3201 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3202 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3204 victim->jointVel(head) += relative * damagemult * 200;
3205 if (!Tutorial::active) {
3206 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3209 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3210 if (victim->howactive == typesleeping)
3211 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3212 if (creature == wolftype) {
3213 emit_sound_at(clawslicesound, victim->coords, 128.);
3215 victim->DoBloodBig(2 / victim->armorhead, 175);
3218 if (victim->damage >= victim->damagetolerance)
3220 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3221 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3223 victim->jointVel(abdomen) += relative * damagemult * 200;
3224 victim->frameTarget = 0;
3225 victim->animTarget = staggerbackhighanim;
3226 victim->targetyaw = targetyaw + 180;
3228 if (!Tutorial::active) {
3229 emit_sound_at(landsound2, victim->coords, 128.);
3231 victim->Puff(abdomen);
3232 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3233 if (creature == wolftype) {
3234 emit_sound_at(clawslicesound, victim->coords, 128.);
3236 victim->DoBloodBig(2 / victim->armorhigh, 170);
3243 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3244 if ((victim->animTarget != jumpupanim) &&
3245 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3246 (victim != this->shared_from_this())) {
3250 if (!Tutorial::active) {
3251 emit_sound_at(landsound2, victim->coords, 128.);
3254 relative = victim->coords - coords;
3256 Normalise(&relative);
3258 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3261 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3262 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3264 relative = DoRotation(relative, 0, -90, 0);
3266 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3267 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)
3268 victim->skeleton.joints[i].velocity = relative * 80;
3270 victim->Puff(rightankle);
3271 victim->Puff(leftankle);
3272 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3274 if (victim->damage >= victim->damagetolerance)
3276 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3277 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3279 relative = DoRotation(relative, 0, -90, 0);
3280 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3281 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)
3282 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3284 victim->jointVel(abdomen) += relative * damagemult * 200;
3285 victim->frameTarget = 0;
3286 victim->animTarget = staggerbackhighanim;
3287 victim->targetyaw = targetyaw + 180;
3289 if (!Tutorial::active) {
3290 emit_sound_at(landsound2, victim->coords, 128.);
3292 victim->Puff(abdomen);
3293 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3301 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3302 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3310 if (!Tutorial::active) {
3311 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3313 if (creature == wolftype) {
3314 emit_sound_at(clawslicesound, victim->coords, 128);
3316 victim->DoBloodBig(2 / victim->armorhigh, 170);
3320 relative = victim->coords - oldcoords;
3322 Normalise(&relative);
3323 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3324 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3326 victim->jointVel(abdomen) += relative * damagemult * 200;
3327 victim->Puff(abdomen);
3328 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3330 award_bonus(id, Reversal);
3333 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3334 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3335 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3336 takeWeapon(victim->weaponids[victim->weaponactive]);
3337 victim->num_weapons--;
3338 if (victim->num_weapons > 0) {
3339 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3341 victim->weaponactive = -1;
3346 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3354 emit_sound_at(whooshhitsound, victim->coords, 128.);
3357 relative = victim->coords - oldcoords;
3359 Normalise(&relative);
3360 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3361 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3363 victim->jointVel(abdomen) += relative * damagemult * 200;
3365 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3368 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3377 award_bonus(id, staffreversebonus);
3379 if (!Tutorial::active) {
3380 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3383 award_bonus(id, staffreversebonus); // Huh, again?
3386 relative = victim->coords - oldcoords;
3388 Normalise(&relative);
3389 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3390 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3392 victim->jointVel(abdomen) += relative * damagemult * 200;
3394 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3397 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3403 Normalise(&relative);
3405 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3406 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3408 victim->jointVel(lefthand) *= .1;
3409 victim->jointVel(leftwrist) *= .2;
3410 victim->jointVel(leftelbow) *= .5;
3411 victim->jointVel(leftshoulder) *= .7;
3412 victim->jointVel(righthand) *= .1;
3413 victim->jointVel(rightwrist) *= .2;
3414 victim->jointVel(rightelbow) *= .5;
3415 victim->jointVel(rightshoulder) *= .7;
3417 victim->Puff(abdomen);
3418 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3420 award_bonus(id, Reversal);
3424 if (weaponactive != -1 || creature == wolftype)
3426 if (creature == rabbittype && weaponactive != -1)
3427 if (weapons[weaponids[0]].getType() == staff)
3430 if (weaponactive != -1) {
3431 victim->DoBloodBig(2 / victim->armorhigh, 225);
3432 emit_sound_at(knifeslicesound, victim->coords);
3433 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3434 weapons[weaponids[weaponactive]].bloody = 1;
3435 weapons[weaponids[weaponactive]].blooddrip += 3;
3437 if (weaponactive == -1 && creature == wolftype) {
3438 emit_sound_at(clawslicesound, victim->coords, 128.);
3440 victim->DoBloodBig(2 / victim->armorhigh, 175);
3447 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3453 Normalise(&relative);
3455 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3456 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3458 victim->jointVel(lefthand) *= .1 - 1;
3459 victim->jointVel(leftwrist) *= .2 - 1;
3460 victim->jointVel(leftelbow) *= .5 - 1;
3461 victim->jointVel(leftshoulder) *= .7 - 1;
3462 victim->jointVel(righthand) *= .1 - 1;
3463 victim->jointVel(rightwrist) *= .2 - 1;
3464 victim->jointVel(rightelbow) *= .5 - 1;
3465 victim->jointVel(rightshoulder) *= .7 - 1;
3467 award_bonus(id, swordreversebonus);
3470 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3478 if (!Tutorial::active) {
3479 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3483 relative = victim->coords - oldcoords;
3485 Normalise(&relative);
3486 relative = DoRotation(relative, 0, -90, 0);
3487 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3488 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3490 victim->jointVel(abdomen) += relative * damagemult * 200;
3491 victim->Puff(abdomen);
3492 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3494 award_bonus(id, Reversal);
3497 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3500 victim->skeleton.spinny = 0;
3502 relative = facing * -1;
3504 Normalise(&relative);
3505 if (victim->id == 0)
3507 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3508 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3510 victim->damage = victim->damagetolerance;
3511 victim->permanentdamage = victim->damagetolerance - 1;
3514 if (weaponactive != -1 || creature == wolftype)
3516 if (creature == rabbittype && weaponactive != -1)
3517 if (weapons[weaponids[0]].getType() == staff)
3520 if (weaponactive != -1) {
3521 victim->DoBloodBig(200, 225);
3522 emit_sound_at(knifeslicesound, victim->coords);
3524 weapons[weaponids[weaponactive]].bloody = 2;
3525 weapons[weaponids[weaponactive]].blooddrip += 5;
3528 if (creature == wolftype && weaponactive == -1) {
3529 emit_sound_at(clawslicesound, victim->coords, 128.);
3531 victim->DoBloodBig(2, 175);
3534 award_bonus(id, spinecrusher);
3537 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3538 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3540 if (animTarget == knifefollowanim)
3541 victim->DoBloodBig(200, 210);
3542 if (animTarget == knifesneakattackanim) {
3543 XYZ footvel, footpoint;
3545 footpoint = weapons[weaponids[0]].tippoint;
3547 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3548 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3549 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3550 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3551 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3552 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3553 victim->DoBloodBig(200, 195);
3554 award_bonus(id, tracheotomy);
3556 if (animTarget == knifefollowanim) {
3557 award_bonus(id, Stabbonus);
3558 XYZ footvel, footpoint;
3560 footpoint = weapons[weaponids[0]].tippoint;
3562 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3563 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3564 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3565 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3566 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3567 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3570 victim->bloodloss += 10000;
3571 victim->velocity = 0;
3572 emit_sound_at(fleshstabsound, victim->coords);
3574 weapons[weaponids[weaponactive]].bloody = 2;
3575 weapons[weaponids[weaponactive]].blooddrip += 5;
3579 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3581 victim->velocity = 0;
3582 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3583 victim->skeleton.joints[i].velocity = 0;
3585 if (animTarget == knifefollowanim) {
3587 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3588 victim->skeleton.joints[i].velocity = 0;
3591 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3592 emit_sound_at(fleshstabremovesound, victim->coords);
3594 weapons[weaponids[weaponactive]].bloody = 2;
3595 weapons[weaponids[weaponactive]].blooddrip += 5;
3597 XYZ footvel, footpoint;
3599 footpoint = weapons[weaponids[0]].tippoint;
3601 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3602 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3603 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3604 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3605 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3606 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3610 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3611 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3612 award_bonus(id, backstab);
3616 XYZ footvel, footpoint;
3618 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3620 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3621 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3622 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3623 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3624 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3625 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3626 victim->DoBloodBig(200, 180);
3627 victim->DoBloodBig(200, 215);
3628 victim->bloodloss += 10000;
3629 victim->velocity = 0;
3630 emit_sound_at(fleshstabsound, victim->coords);
3632 weapons[weaponids[weaponactive]].bloody = 2;
3633 weapons[weaponids[weaponactive]].blooddrip += 5;
3637 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3639 victim->velocity = 0;
3640 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3641 victim->skeleton.joints[i].velocity = 0;
3643 if (weaponactive != -1) {
3644 emit_sound_at(fleshstabremovesound, victim->coords);
3646 weapons[weaponids[weaponactive]].bloody = 2;
3647 weapons[weaponids[weaponactive]].blooddrip += 5;
3649 XYZ footvel, footpoint;
3651 footpoint = weapons[weaponids[0]].tippoint;
3653 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3654 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3655 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3656 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3657 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3658 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3662 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3670 if (weaponactive == -1) {
3671 if (!Tutorial::active) {
3672 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3677 if (weaponactive != -1 || creature == wolftype)
3679 if (creature == rabbittype && weaponactive != -1)
3680 if (weapons[weaponids[0]].getType() == staff)
3683 if (weaponactive != -1) {
3684 victim->DoBloodBig(2 / victim->armorhead, 225);
3685 emit_sound_at(knifeslicesound, victim->coords);
3686 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3687 weapons[weaponids[weaponactive]].bloody = 1;
3688 weapons[weaponids[weaponactive]].blooddrip += 3;
3690 if (weaponactive == -1 && creature == wolftype) {
3691 emit_sound_at(clawslicesound, victim->coords, 128.);
3693 victim->DoBloodBig(2 / victim->armorhead, 175);
3697 award_bonus(id, Reversal);
3702 relative = facing * -1;
3704 Normalise(&relative);
3705 relative = DoRotation(relative, 0, 90, 0);
3707 Normalise(&relative);
3708 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3709 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3711 victim->jointVel(head) += relative * damagemult * 200;
3712 if (victim->damage < victim->damagetolerance - 100)
3713 victim->velocity = relative * 200;
3714 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3715 victim->velocity = 0;
3718 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))) {
3722 relative = facing * -1;
3724 Normalise(&relative);
3725 relative = DoRotation(relative, 0, 90, 0);
3727 Normalise(&relative);
3728 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3729 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3731 victim->jointVel(head) += relative * damagemult * 200;
3734 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3735 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3736 award_bonus(id, reverseko);
3742 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3745 animTarget = getIdle();
3746 FootLand(leftfoot, 1);
3747 FootLand(rightfoot, 1);
3749 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3750 animTarget = rollanim;
3752 emit_sound_at(movewhooshsound, coords, 128.);
3754 if (animCurrent == staggerbackhighanim) {
3755 animTarget = getIdle();
3757 if (animCurrent == staggerbackhardanim) {
3758 animTarget = getIdle();
3760 if (animCurrent == removeknifeanim) {
3761 animTarget = getIdle();
3763 if (animCurrent == crouchremoveknifeanim) {
3764 animTarget = getCrouch();
3766 if (animCurrent == backhandspringanim) {
3767 animTarget = getIdle();
3769 if (animCurrent == dodgebackanim) {
3770 animTarget = getIdle();
3772 if (animCurrent == drawleftanim) {
3773 animTarget = getIdle();
3775 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3776 animTarget = getIdle();
3777 if (animCurrent == crouchdrawrightanim) {
3778 animTarget = getCrouch();
3780 if (weaponactive == -1)
3782 else if (weaponactive == 0) {
3784 if (num_weapons == 2) {
3786 buffer = weaponids[0];
3787 weaponids[0] = weaponids[1];
3788 weaponids[1] = buffer;
3792 if (weaponactive == -1) {
3793 emit_sound_at(knifesheathesound, coords, 128.);
3795 if (weaponactive != -1) {
3796 emit_sound_at(knifedrawsound, coords, 128.);
3799 if (animCurrent == rollanim) {
3800 animTarget = getCrouch();
3801 FootLand(leftfoot, 1);
3802 FootLand(rightfoot, 1);
3805 if (animTarget == walljumprightkickanim) {
3808 if (animTarget == walljumpleftkickanim) {
3811 animTarget = jumpdownanim;
3813 if (animCurrent == climbanim) {
3814 animTarget = getCrouch();
3816 coords += facing * .1;
3817 if (!isnormal(coords.x))
3827 if (animTarget == rabbitkickreversalanim) {
3828 animTarget = getCrouch();
3831 if (animTarget == jumpreversalanim) {
3832 animTarget = getCrouch();
3835 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3836 if (attackkeydown && animTarget != walljumpfrontanim) {
3838 float closestdist = -1;
3840 if (Person::players.size() > 1)
3841 for (unsigned i = 0; i < Person::players.size(); i++) {
3842 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3843 distance = distsq(&Person::players[i]->coords, &coords);
3844 if (closestdist == -1 || distance < closestdist) {
3845 closestdist = distance;
3850 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3851 victim = Person::players[closest];
3852 animTarget = walljumprightkickanim;
3854 XYZ rotatetarget = victim->coords - coords;
3855 Normalise(&rotatetarget);
3856 yaw = -asin(0 - rotatetarget.x);
3858 if (rotatetarget.z < 0)
3860 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3861 velocity = (victim->coords - coords) * 4;
3866 if (animTarget == walljumpbackanim) {
3867 animTarget = backflipanim;
3869 velocity = facing * -8;
3872 resume_stream(whooshsound);
3874 if (animTarget == walljumprightanim) {
3875 animTarget = rightflipanim;
3879 velocity = DoRotation(facing, 0, 30, 0) * -8;
3882 if (animTarget == walljumpfrontanim) {
3883 animTarget = frontflipanim;
3887 velocity = facing * 8;
3891 resume_stream(whooshsound);
3893 if (animTarget == walljumpleftanim) {
3894 if (attackkeydown) {
3896 float closestdist = -1;
3898 if (Person::players.size() > 1)
3899 for (unsigned i = 0; i < Person::players.size(); i++) {
3900 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3901 distance = distsq(&Person::players[i]->coords, &coords);
3902 if (closestdist == -1 || distance < closestdist) {
3903 closestdist = distance;
3908 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3909 victim = Person::players[closest];
3910 animTarget = walljumpleftkickanim;
3912 XYZ rotatetarget = victim->coords - coords;
3913 Normalise(&rotatetarget);
3914 yaw = -asin(0 - rotatetarget.x);
3916 if (rotatetarget.z < 0)
3918 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3919 velocity = (victim->coords - coords) * 4;
3924 if (animTarget != walljumpleftkickanim) {
3925 animTarget = leftflipanim;
3929 velocity = DoRotation(facing, 0, -30, 0) * -8;
3933 resume_stream(whooshsound);
3935 if (animTarget == sneakattackanim) {
3936 animCurrent = getCrouch();
3937 animTarget = getCrouch();
3944 transspeed = 1000000;
3945 targetheadyaw += 180;
3946 coords -= facing * .7;
3948 coords.y = terrain.getHeight(coords.x, coords.z);
3952 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3953 animTarget = getIdle();
3956 coords.y = terrain.getHeight(coords.x, coords.z);
3960 if (animCurrent == knifefollowanim) {
3961 animTarget = getIdle();
3964 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3965 float ycoords = oldcoords.y;
3966 animTarget = getStop();
3971 transspeed = 1000000;
3972 targetheadyaw += 180;
3973 if (!isnormal(coords.x))
3975 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3976 oldcoords = coords + facing * .5;
3977 else if (animCurrent == sweepreversalanim)
3978 oldcoords = coords + facing * 1.1;
3979 else if (animCurrent == upunchreversalanim) {
3980 oldcoords = coords + facing * 1.5;
3983 targetheadyaw += 180;
3986 } else if (animCurrent == knifeslashreversalanim) {
3987 oldcoords = coords + facing * .5;
3990 targetheadyaw += 90;
3993 } else if (animCurrent == staffspinhitreversalanim) {
3996 targetheadyaw += 180;
4001 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4003 oldcoords.y = ycoords;
4004 currentoffset = coords - oldcoords;
4010 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4015 if (Animation::animations[animTarget].attack == reversed) {
4017 if (animTarget == sweepreversedanim)
4019 animTarget = backhandspringanim;
4021 emit_sound_at(landsound, coords, 128);
4023 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4024 animTarget = rollanim;
4027 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4028 coords.y = oldcoords.y;
4030 if (animCurrent == knifeslashreversedanim) {
4031 animTarget = rollanim;
4036 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4037 coords.y = oldcoords.y;
4041 animTarget = jumpdownanim;
4044 animTarget = getIdle();
4046 animTarget = getIdle();
4047 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4048 animTarget = getIdle();
4050 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4051 coords.y = oldcoords.y;
4052 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4053 targetoffset.y = coords.y;
4055 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4056 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4057 currentoffset.y -= (coords.y - targetoffset.y);
4058 coords.y = targetoffset.y;
4060 normalsupdatedelay = 0;
4062 if (animCurrent == upunchanim) {
4063 animTarget = getStop();
4064 normalsupdatedelay = 0;
4067 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4071 if (num_weapons > 0)
4072 if (weapons[0].getType() == staff)
4078 rabbitkickragdoll = 1;
4080 if (animCurrent == rabbitkickreversedanim) {
4086 skeleton.spinny = 0;
4087 SolidHitBonus(!id); // FIXME: tricky id
4091 animTarget = rollanim;
4094 pause_sound(whooshsound);
4098 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4102 skeleton.spinny = 0;
4104 if (animCurrent == jumpreversedanim) {
4110 skeleton.spinny = 0;
4111 SolidHitBonus(!id); // FIXME: tricky id
4115 animTarget = rollanim;
4116 coords += facing * 2;
4118 pause_sound(whooshsound);
4123 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) {
4124 animTarget = getupfromfrontanim;
4126 } else if (Animation::animations[animCurrent].attack == normalattack) {
4127 animTarget = getIdle();
4130 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4131 animTarget = blockhighleftstrikeanim;
4133 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4134 animTarget = getIdle();
4137 if (animCurrent == spinkickanim && victim->skeleton.free) {
4138 if (creature == rabbittype)
4139 animTarget = fightidleanim;
4144 if (isIdle() && !wasIdle())
4145 normalsupdatedelay = 0;
4147 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4148 animTarget = jumpdownanim;
4151 if (!skeleton.free) {
4153 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4154 if (!isRun() || !wasRun()) {
4155 if (targetFrame().speed > currentFrame().speed)
4156 target += multiplier * targetFrame().speed * speed * 2;
4157 if (targetFrame().speed <= currentFrame().speed)
4158 target += multiplier * currentFrame().speed * speed * 2;
4160 if (isRun() && wasRun()) {
4162 tempspeed = velspeed;
4163 if (tempspeed < 10 * speedmult)
4164 tempspeed = 10 * speedmult;
4165 /* FIXME - mixed of target and current here, is that intended? */
4166 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4168 } else if (transspeed)
4169 target += multiplier * transspeed * speed * 2;
4171 if (!isRun() || !wasRun()) {
4172 if (targetFrame().speed > currentFrame().speed)
4173 target += multiplier * targetFrame().speed * 2;
4174 if (targetFrame().speed <= currentFrame().speed)
4175 target += multiplier * currentFrame().speed * 2;
4179 if (animCurrent != animTarget)
4180 target = (target + oldtarget) / 2;
4183 frameCurrent = frameTarget;
4187 rot = targetrot * target;
4188 yaw += rot - oldrot;
4194 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4195 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4197 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4199 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4200 skeleton.joints[i].position = currentFrame().joints[i].position;
4203 skeleton.FindForwards();
4205 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4206 if (skeleton.muscles[i].visible) {
4207 skeleton.FindRotationMuscle(i, animTarget);
4210 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4211 if (skeleton.muscles[i].visible) {
4212 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4213 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4214 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4215 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4216 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4217 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4222 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4223 skeleton.joints[i].position = targetFrame().joints[i].position;
4226 skeleton.FindForwards();
4228 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4229 if (skeleton.muscles[i].visible) {
4230 skeleton.FindRotationMuscle(i, animTarget);
4233 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4234 if (skeleton.muscles[i].visible) {
4235 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4236 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4237 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4238 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4239 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4240 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4241 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4242 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4243 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4244 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4245 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4246 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4251 oldanimCurrent = animCurrent;
4252 oldanimTarget = animTarget;
4253 oldframeTarget = frameTarget;
4254 oldframeCurrent = frameCurrent;
4256 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4257 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4258 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4260 offset = currentoffset * (1 - target) + targetoffset * target;
4261 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4262 if (skeleton.muscles[i].visible) {
4263 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4264 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4265 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4270 if (isLanding() && landhard) {
4273 animTarget = getLandhard();
4286 void Person::DoStuff()
4288 static XYZ terrainnormal;
4289 static XYZ flatfacing;
4290 static XYZ flatvelocity;
4291 static float flatvelspeed;
4293 static int bloodsize;
4294 static int startx, starty, endx, endy;
4295 static GLubyte color;
4296 static XYZ bloodvel;
4298 onfiredelay -= multiplier;
4299 if (onfiredelay < 0 && onfire) {
4300 if (Random() % 2 == 0) {
4306 crouchkeydowntime += multiplier;
4308 crouchkeydowntime = 0;
4309 jumpkeydowntime += multiplier;
4310 if (!jumpkeydown && skeleton.free)
4311 jumpkeydowntime = 0;
4313 if (hostile || damage > 0 || bloodloss > 0)
4316 if (isIdle() || isRun())
4319 if (num_weapons == 1 && weaponactive != -1)
4323 blooddimamount -= multiplier * .3;
4324 speechdelay -= multiplier;
4325 texupdatedelay -= multiplier;
4326 interestdelay -= multiplier;
4327 flamedelay -= multiplier;
4328 parriedrecently -= multiplier;
4330 victim = this->shared_from_this();
4335 speed = 1.1 * speedmult;
4337 speed = 1.0 * speedmult;
4339 rabbitkickragdoll = 0;
4343 if (id != 0 && (creature == rabbittype || difficulty != 2))
4345 if (id != 0 && creature == wolftype && difficulty == 2) {
4347 if (aitype != passivetype) {
4349 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) {
4355 if (animTarget == wolfrunninganim && !superruntoggle) {
4356 animTarget = getRun();
4360 if (weaponactive == -1 && num_weapons > 0) {
4361 if (weapons[weaponids[0]].getType() == staff) {
4367 burnt += multiplier;
4371 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4373 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4379 vel[0] = velocity.x;
4380 vel[1] = velocity.y;
4381 vel[2] = velocity.z;
4384 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4385 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4389 while (flamedelay < 0 && onfire) {
4391 int howmany = fabs(Random() % (skeleton.joints.size()));
4392 if (skeleton.free) {
4393 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4394 flatfacing = skeleton.joints[howmany].position * scale + coords;
4396 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4397 flatvelocity = (coords - oldcoords) / multiplier / 2;
4399 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4402 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4404 int howmany = fabs(Random() % (skeleton.joints.size()));
4405 if (skeleton.free) {
4406 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4407 flatfacing = skeleton.joints[howmany].position * scale + coords;
4409 flatvelocity = (coords - oldcoords) / multiplier / 2;
4410 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4412 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4416 bleeding -= multiplier * .3;
4417 if (bloodtoggle == 2) {
4418 skeleton.drawmodel.textureptr.bind();
4419 if ((bleeding <= 0) && (detail != 2))
4424 if (neckspurtamount > 0) {
4425 neckspurtamount -= multiplier;
4426 neckspurtdelay -= multiplier * 3;
4427 neckspurtparticledelay -= multiplier * 3;
4428 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4431 if (skeleton.free) {
4432 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4433 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4434 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4436 bloodvel.z = 5 * neckspurtamount;
4437 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4438 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4439 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4441 neckspurtparticledelay = .05;
4443 if (neckspurtdelay < 0) {
4448 if (deathbleeding > 0 && dead != 2) {
4449 if (deathbleeding < 5)
4450 bleeddelay -= deathbleeding * multiplier / 4;
4452 bleeddelay -= 5 * multiplier / 4;
4453 if (bleeddelay < 0 && bloodtoggle) {
4458 if (skeleton.free) {
4459 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4460 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4462 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4463 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4467 bloodloss += deathbleeding * multiplier * 80;
4468 deathbleeding -= multiplier * 1.6;
4469 if (deathbleeding < 0)
4471 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4472 if (weaponactive != -1) {
4473 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4474 weapons[weaponids[0]].velocity.x += .01;
4477 weaponids[0] = weaponids[num_weapons];
4478 if (weaponstuck == num_weapons)
4482 for (unsigned i = 0; i < Person::players.size(); i++) {
4483 Person::players[i]->wentforweapon = 0;
4491 if (!dead && creature == wolftype) {
4492 award_bonus(0, Wolfbonus);
4495 if (animTarget == knifefollowedanim && !skeleton.free) {
4496 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4497 skeleton.joints[i].velocity = 0;
4498 skeleton.joints[i].velocity.y = -2;
4501 if (id != 0 && unconscioustime > .1) {
4509 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4510 texupdatedelay = .12;
4512 bloodsize = 5 - realtexdetail;
4516 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4517 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4518 endx = startx + bloodsize;
4519 endy = starty + bloodsize;
4529 if (endx > skeleton.skinsize - 1) {
4530 endx = skeleton.skinsize - 1;
4533 if (endy > skeleton.skinsize - 1) {
4534 endy = skeleton.skinsize - 1;
4542 for (i = startx; i < endx; i++) {
4543 for (int j = starty; j < endy; j++) {
4544 if (Random() % 2 == 0) {
4545 color = Random() % 85 + 170;
4546 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4547 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4548 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4549 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4554 skeleton.drawmodel.textureptr.bind();
4558 if (skeleton.free) {
4559 bleedx += 4 * direction / realtexdetail;
4561 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4563 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4565 bleedy -= 4 / realtexdetail;
4567 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4569 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4573 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4574 righthandmorphness = targetrighthandmorphness;
4575 righthandmorphstart = righthandmorphend;
4576 } else if (righthandmorphness > targetrighthandmorphness) {
4577 righthandmorphness -= multiplier * 4;
4578 } else if (righthandmorphness < targetrighthandmorphness) {
4579 righthandmorphness += multiplier * 4;
4582 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4583 lefthandmorphness = targetlefthandmorphness;
4584 lefthandmorphstart = lefthandmorphend;
4585 } else if (lefthandmorphness > targetlefthandmorphness) {
4586 lefthandmorphness -= multiplier * 4;
4587 } else if (lefthandmorphness < targetlefthandmorphness) {
4588 lefthandmorphness += multiplier * 4;
4591 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4592 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4593 tailmorphness = targettailmorphness;
4594 tailmorphstart = tailmorphend;
4595 } else if (tailmorphness > targettailmorphness) {
4596 tailmorphness -= multiplier * 10;
4597 } else if (tailmorphness < targettailmorphness) {
4598 tailmorphness += multiplier * 10;
4602 if (creature == wolftype) {
4603 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4604 tailmorphness = targettailmorphness;
4605 tailmorphstart = tailmorphend;
4606 } else if (tailmorphness > targettailmorphness) {
4607 tailmorphness -= multiplier * 2;
4608 } else if (tailmorphness < targettailmorphness) {
4609 tailmorphness += multiplier * 2;
4613 if (headmorphend == 3 || headmorphstart == 3) {
4614 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4615 headmorphness = targetheadmorphness;
4616 headmorphstart = headmorphend;
4617 } else if (headmorphness > targetheadmorphness) {
4618 headmorphness -= multiplier * 7;
4619 } else if (headmorphness < targetheadmorphness) {
4620 headmorphness += multiplier * 7;
4622 } else if (headmorphend == 5 || headmorphstart == 5) {
4623 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4624 headmorphness = targetheadmorphness;
4625 headmorphstart = headmorphend;
4626 } else if (headmorphness > targetheadmorphness) {
4627 headmorphness -= multiplier * 10;
4628 } else if (headmorphness < targetheadmorphness) {
4629 headmorphness += multiplier * 10;
4632 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4633 headmorphness = targetheadmorphness;
4634 headmorphstart = headmorphend;
4635 } else if (headmorphness > targetheadmorphness) {
4636 headmorphness -= multiplier * 4;
4637 } else if (headmorphness < targetheadmorphness) {
4638 headmorphness += multiplier * 4;
4642 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4643 chestmorphness = targetchestmorphness;
4644 chestmorphstart = chestmorphend;
4645 } else if (chestmorphness > targetchestmorphness) {
4646 chestmorphness -= multiplier;
4647 } else if (chestmorphness < targetchestmorphness) {
4648 chestmorphness += multiplier;
4651 if (dead != 2 && howactive <= typesleeping) {
4652 if (chestmorphstart == 0 && chestmorphend == 0) {
4654 targetchestmorphness = 1;
4657 if (chestmorphstart != 0 && chestmorphend != 0) {
4659 targetchestmorphness = 1;
4661 if (environment == snowyenvironment) {
4664 if (skeleton.free) {
4665 footvel = skeleton.specialforward[0] * -1;
4666 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4668 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4669 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4671 if (animTarget == sleepanim)
4672 footvel = DoRotation(footvel, 0, 90, 0);
4673 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4677 if (!dead && howactive < typesleeping) {
4678 blinkdelay -= multiplier * 2;
4679 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4681 targetheadmorphness = 1;
4683 blinkdelay = (float)(abs(Random() % 40)) / 5;
4685 if (headmorphstart == 3 && headmorphend == 3) {
4687 targetheadmorphness = 1;
4692 twitchdelay -= multiplier * 1.5;
4693 if (animTarget != hurtidleanim) {
4694 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4696 targetheadmorphness = 1;
4698 twitchdelay = (float)(abs(Random() % 40)) / 5;
4700 if (headmorphstart == 5 && headmorphend == 5) {
4702 targetheadmorphness = 1;
4706 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4707 twitchdelay3 -= multiplier * 1;
4708 if (Random() % 2 == 0) {
4709 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4710 righthandmorphness = 0;
4711 targetrighthandmorphness = 1;
4712 righthandmorphend = 1;
4713 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4715 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4716 righthandmorphness = 0;
4717 targetrighthandmorphness = 1;
4718 righthandmorphend = 0;
4721 if (Random() % 2 == 0) {
4722 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4723 lefthandmorphness = 0;
4724 targetlefthandmorphness = 1;
4725 lefthandmorphend = 1;
4726 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4728 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4729 lefthandmorphness = 0;
4730 targetlefthandmorphness = 1;
4731 lefthandmorphend = 0;
4737 if (creature == rabbittype) {
4738 if (howactive < typesleeping)
4739 twitchdelay2 -= multiplier * 1.5;
4741 twitchdelay2 -= multiplier * 0.5;
4742 if (howactive <= typesleeping) {
4743 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4745 targettailmorphness = 1;
4747 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4749 if (tailmorphstart == 1 && tailmorphend == 1) {
4751 targettailmorphness = 1;
4754 if (tailmorphstart == 2 && tailmorphend == 2) {
4756 targettailmorphness = 1;
4763 if (creature == wolftype) {
4764 twitchdelay2 -= multiplier * 1.5;
4765 if (tailmorphend != 0)
4766 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4768 targettailmorphness = 1;
4772 if (tailmorphend != 5)
4773 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4775 targettailmorphness = 1;
4779 if (twitchdelay2 <= 0) {
4780 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4782 targettailmorphness = 1;
4785 if (tailmorphstart == 1 && tailmorphend == 1) {
4787 targettailmorphness = 1;
4790 if (tailmorphstart == 2 && tailmorphend == 2) {
4792 targettailmorphness = 1;
4795 if (tailmorphstart == 3 && tailmorphend == 3) {
4797 targettailmorphness = 1;
4800 if (tailmorphstart == 4 && tailmorphend == 4) {
4802 targettailmorphness = 1;
4809 unconscioustime = 0;
4811 if (dead == 1 || howactive == typesleeping) {
4812 unconscioustime += multiplier;
4813 //If unconscious, close eyes and mouth
4814 if (righthandmorphend != 0)
4815 righthandmorphness = 0;
4816 righthandmorphend = 0;
4817 targetrighthandmorphness = 1;
4819 if (lefthandmorphend != 0)
4820 lefthandmorphness = 0;
4821 lefthandmorphend = 0;
4822 targetlefthandmorphness = 1;
4824 if (headmorphend != 3 && headmorphend != 5)
4827 targetheadmorphness = 1;
4831 if (howactive > typesleeping) {
4834 if (bloodtoggle && !bled) {
4835 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4837 if (bloodtoggle && !bled)
4838 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4839 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4840 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4844 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4849 if (dead == 2 || howactive > typesleeping) {
4850 //If dead, open mouth and hands
4851 if (righthandmorphend != 0)
4852 righthandmorphness = 0;
4853 righthandmorphend = 0;
4854 targetrighthandmorphness = 1;
4856 if (lefthandmorphend != 0)
4857 lefthandmorphness = 0;
4858 lefthandmorphend = 0;
4859 targetlefthandmorphness = 1;
4861 if (headmorphend != 2)
4864 targetheadmorphness = 1;
4867 if (stunned > 0 && !dead && headmorphend != 2) {
4868 if (headmorphend != 4)
4871 targetheadmorphness = 1;
4874 if (damage > damagetolerance && !dead) {
4877 unconscioustime = 0;
4879 if (creature == wolftype) {
4880 award_bonus(0, Wolfbonus);
4885 if (weaponactive != -1) {
4886 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4887 weapons[weaponids[0]].velocity.x += .01;
4890 weaponids[0] = weaponids[num_weapons];
4891 if (weaponstuck == num_weapons)
4895 for (unsigned i = 0; i < Person::players.size(); i++) {
4896 Person::players[i]->wentforweapon = 0;
4902 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4911 damage -= multiplier * 13;
4913 permanentdamage -= multiplier * 4;
4914 if (isIdle() || isCrouch()) {
4916 permanentdamage -= multiplier * 4;
4920 if (permanentdamage < 0)
4921 permanentdamage = 0;
4922 if (superpermanentdamage < 0)
4923 superpermanentdamage = 0;
4924 if (permanentdamage < superpermanentdamage) {
4925 permanentdamage = superpermanentdamage;
4927 if (damage < permanentdamage) {
4928 damage = permanentdamage;
4930 if (dead == 1 && damage < damagetolerance) {
4934 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4935 skeleton.joints[i].velocity = 0;
4938 if (permanentdamage > damagetolerance && dead != 2) {
4941 if (weaponactive != -1) {
4942 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4943 weapons[weaponids[0]].velocity.x += .01;
4946 weaponids[0] = weaponids[num_weapons];
4947 if (weaponstuck == num_weapons)
4951 for (unsigned i = 0; i < Person::players.size(); i++) {
4952 Person::players[i]->wentforweapon = 0;
4958 if (!dead && creature == wolftype) {
4959 award_bonus(0, Wolfbonus);
4962 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4963 award_bonus(id, touchofdeath);
4964 if (id != 0 && unconscioustime > .1) {
4972 emit_sound_at(breaksound, coords);
4975 if (skeleton.free == 1) {
4977 pause_sound(whooshsound);
4980 //If knocked over, open hands and close mouth
4981 if (righthandmorphend != 0)
4982 righthandmorphness = 0;
4983 righthandmorphend = 0;
4984 targetrighthandmorphness = 1;
4986 if (lefthandmorphend != 0)
4987 lefthandmorphness = 0;
4988 lefthandmorphend = 0;
4989 targetlefthandmorphness = 1;
4991 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4992 if (headmorphend != 0)
4995 targetheadmorphness = 1;
4999 skeleton.DoGravity(&scale);
5001 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5002 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5003 award_bonus(id, deepimpact);
5004 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5008 if (!skeleton.joints.empty()) {
5009 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5010 average += skeleton.joints[j].position;
5012 average /= skeleton.joints.size();
5013 coords += average * scale;
5014 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5015 skeleton.joints[j].position -= average;
5017 average /= multiplier;
5021 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5022 velocity += skeleton.joints[i].velocity * scale;
5024 velocity /= skeleton.joints.size();
5026 if (!isnormal(velocity.x) && velocity.x) {
5030 if (findLength(&average) < 10 && dead && skeleton.free) {
5031 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5032 if (skeleton.longdead > 2000) {
5033 if (skeleton.longdead > 6000) {
5035 pause_sound(whooshsound);
5040 if (dead == 2 && bloodloss < damagetolerance) {
5042 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5044 if (bloodtoggle && !bled) {
5045 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5047 if (bloodtoggle && !bled)
5048 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5049 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5050 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5051 float size = .2 * 1.2;
5054 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5058 if (dead == 2 && bloodloss >= damagetolerance) {
5060 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5063 if (bloodtoggle && !bled) {
5064 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5066 if (bloodtoggle && !bled)
5067 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5068 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5069 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5073 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5080 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5081 bool canrecover = 1;
5082 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5083 startpoint = coords;
5086 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5088 if (velocity.y < -30)
5090 for (i = 0; i < Object::objects.size(); i++) {
5091 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5092 colviewer = startpoint;
5093 coltarget = endpoint;
5094 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5103 terrainnormal = jointPos(groin) - jointPos(abdomen);
5104 if (joint(groin).locked && joint(abdomen).locked) {
5105 terrainnormal = jointPos(groin) - jointPos(abdomen);
5106 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5108 if (joint(abdomen).locked && joint(neck).locked) {
5109 terrainnormal = jointPos(abdomen) - jointPos(neck);
5110 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5112 if (joint(groin).locked && joint(neck).locked) {
5113 terrainnormal = jointPos(groin) - jointPos(neck);
5114 middle = (jointPos(groin) + jointPos(neck)) / 2;
5116 Normalise(&terrainnormal);
5118 targetyaw = -asin(0 - terrainnormal.x);
5119 targetyaw *= 360 / 6.28;
5120 if (terrainnormal.z < 0)
5121 targetyaw = 180 - targetyaw;
5125 animTarget = flipanim;
5126 crouchtogglekeydown = 1;
5131 animCurrent = tempanim;
5135 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5136 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5137 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5142 if (findLength(&average) < 10 && !dead && skeleton.free) {
5143 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5144 if (skeleton.longdead > (damage + 500) * 1.5) {
5146 pause_sound(whooshsound);
5152 terrainnormal = jointPos(groin) - jointPos(abdomen);
5153 if (joint(groin).locked && joint(abdomen).locked) {
5154 terrainnormal = jointPos(groin) - jointPos(abdomen);
5155 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5157 if (joint(abdomen).locked && joint(neck).locked) {
5158 terrainnormal = jointPos(abdomen) - jointPos(neck);
5159 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5161 if (joint(groin).locked && joint(neck).locked) {
5162 terrainnormal = jointPos(groin) - jointPos(neck);
5163 middle = (jointPos(groin) + jointPos(neck)) / 2;
5165 Normalise(&terrainnormal);
5167 targetyaw = -asin(0 - terrainnormal.x);
5168 targetyaw *= 360 / 6.28;
5169 if (terrainnormal.z < 0)
5170 targetyaw = 180 - targetyaw;
5173 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5176 if (skeleton.forward.y < 0) {
5177 animTarget = getupfrombackanim;
5181 if (skeleton.forward.y > -.3) {
5182 animTarget = getupfromfrontanim;
5190 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5191 animTarget = rollanim;
5192 targetyaw = lookyaw;
5209 if ( !leftkeydown && !rightkeydown)
5216 if (abs(targettilt2) > 50)
5218 animCurrent = tempanim;
5221 tilt2 = targettilt2;
5223 if (middle.y > 0 && animTarget != rollanim)
5224 targetoffset.y = middle.y + 1;
5226 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5227 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5228 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5235 if (num_weapons > 0)
5236 if (weapons[0].getType() == staff)
5238 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5239 if (velocity.y > -30) {
5241 tempvelocity = velocity;
5242 Normalise(&tempvelocity);
5243 targetyaw = -asin(0 - tempvelocity.x);
5244 targetyaw *= 360 / 6.28;
5246 targetyaw = 180 - targetyaw;
5250 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5251 animTarget = rollanim;
5254 animTarget = backhandspringanim;
5260 emit_sound_at(movewhooshsound, coords, 128.);
5262 animCurrent = animTarget;
5263 frameCurrent = frameTarget - 1;
5275 if (skeleton.freefall == 0)
5280 if (aitype != passivetype || skeleton.free == 1)
5281 if (findLengthfast(&velocity) > .1)
5282 for (i = 0; i < Object::objects.size(); i++) {
5283 if (Object::objects[i]->type == firetype)
5284 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) {
5286 if (!Object::objects[i]->onfire) {
5287 emit_sound_at(firestartsound, Object::objects[i]->position);
5289 Object::objects[i]->onfire = 1;
5292 if (Object::objects[i]->onfire) {
5297 if (Object::objects[i]->type == bushtype)
5298 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) {
5300 if (!Object::objects[i]->onfire) {
5301 emit_sound_at(firestartsound, Object::objects[i]->position);
5303 Object::objects[i]->onfire = 1;
5307 if (Object::objects[i]->onfire) {
5311 if (Object::objects[i]->messedwith <= 0) {
5315 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5318 addEnvSound(coords, 4 * findLength(&velocity));
5322 if (environment == grassyenvironment)
5323 howmany = findLength(&velocity) * 4;
5324 if (environment == snowyenvironment)
5325 howmany = findLength(&velocity) * 2;
5327 if (environment != desertenvironment)
5328 for (int j = 0; j < howmany; j++) {
5329 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5330 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5331 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5334 pos.x += float(abs(Random() % 100) - 50) / 200;
5335 pos.y += float(abs(Random() % 100) - 50) / 200;
5336 pos.z += float(abs(Random() % 100) - 50) / 200;
5337 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);
5338 Sprite::setLastSpriteSpecial(1);
5340 howmany = findLength(&velocity) * 4;
5342 if (environment == snowyenvironment)
5343 for (int j = 0; j < howmany; j++) {
5344 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5345 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5346 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5349 pos.x += float(abs(Random() % 100) - 50) / 200;
5350 pos.y += float(abs(Random() % 100) - 50) / 200;
5351 pos.z += float(abs(Random() % 100) - 50) / 200;
5352 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5353 Sprite::setLastSpriteSpecial(2);
5356 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5357 Object::objects[i]->roty += velocity.z * multiplier * 6;
5358 Object::objects[i]->messedwith = .5;
5361 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5362 if (Object::objects[i]->pitch == 0)
5365 tempcoord = coords - Object::objects[i]->position;
5366 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5367 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5368 tempcoord += Object::objects[i]->position;
5370 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) {
5371 if (Object::objects[i]->messedwith <= 0) {
5375 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5378 addEnvSound(coords, 4 * findLength(&velocity));
5382 if (environment == grassyenvironment)
5383 howmany = findLength(&velocity) * 4;
5384 if (environment == snowyenvironment)
5385 howmany = findLength(&velocity) * 2;
5387 if (environment != desertenvironment)
5388 for (int j = 0; j < howmany; j++) {
5389 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5390 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5391 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5393 pos += velocity * .1;
5395 pos.x += float(abs(Random() % 100) - 50) / 150;
5396 pos.y += float(abs(Random() % 100) - 50) / 150;
5397 pos.z += float(abs(Random() % 100) - 50) / 150;
5398 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);
5399 Sprite::setLastSpriteSpecial(1);
5401 howmany = findLength(&velocity) * 4;
5403 if (environment == snowyenvironment)
5404 for (int j = 0; j < howmany; j++) {
5405 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5406 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5407 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5409 pos += velocity * .1;
5411 pos.x += float(abs(Random() % 100) - 50) / 150;
5412 pos.y += float(abs(Random() % 100) - 50) / 150;
5413 pos.z += float(abs(Random() % 100) - 50) / 150;
5414 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5415 Sprite::setLastSpriteSpecial(2);
5418 Object::objects[i]->messedwith = .5;
5423 if (!skeleton.free) {
5426 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5429 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5431 if (Tutorial::active && id != 0)
5433 if (play && aitype != playercontrolled) {
5434 int whichsound = -1;
5435 i = abs(Random() % 4);
5436 if (speechdelay <= 0) {
5437 if (creature == rabbittype) {
5439 whichsound = rabbitchitter;
5441 whichsound = rabbitchitter2;
5443 if (creature == wolftype) {
5445 whichsound = growlsound;
5447 whichsound = growl2sound;
5452 if (whichsound != -1) {
5453 emit_sound_at(whichsound, coords);
5457 if (animTarget == staggerbackhighanim)
5459 if (animTarget == staggerbackhardanim)
5461 staggerdelay -= multiplier;
5462 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5464 if (velocity.y < -30 && animTarget == jumpdownanim)
5466 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5467 animTarget = getIdle();
5471 weaponmissdelay -= multiplier;
5472 highreversaldelay -= multiplier;
5473 lowreversaldelay -= multiplier;
5474 lastcollide -= multiplier;
5475 skiddelay -= multiplier;
5476 if (!isnormal(velocity.x) && velocity.x) {
5479 if (!isnormal(targettilt) && targettilt) {
5482 if (!isnormal(targettilt2) && targettilt2) {
5485 if (!isnormal(targetyaw) && targetyaw) {
5489 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5490 //open hands and close mouth
5491 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5492 righthandmorphness = 0;
5493 righthandmorphend = 0;
5494 targetrighthandmorphness = 1;
5497 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5498 lefthandmorphness = 0;
5499 lefthandmorphend = 0;
5500 targetlefthandmorphness = 1;
5503 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5506 targetheadmorphness = 1;
5510 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) {
5511 //open hands and mouth
5512 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5513 righthandmorphness = 0;
5514 righthandmorphend = 0;
5515 targetrighthandmorphness = 1;
5518 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5519 lefthandmorphness = 0;
5520 lefthandmorphend = 0;
5521 targetlefthandmorphness = 1;
5524 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5527 targetheadmorphness = 1;
5531 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5532 //close hands and mouth
5533 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5534 righthandmorphness = 0;
5535 righthandmorphend = 1;
5536 targetrighthandmorphness = 1;
5539 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5540 lefthandmorphness = 0;
5541 lefthandmorphend = 1;
5542 targetlefthandmorphness = 1;
5545 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5548 targetheadmorphness = 1;
5552 if (animTarget == spinkickanim || animTarget == staffspinhitreversalanim || animTarget == staffspinhitreversedanim || animTarget == staffhitreversalanim || animTarget == staffhitreversedanim || animTarget == hurtidleanim || animTarget == winduppunchanim || animTarget == swordslashreversalanim || animTarget == swordslashreversedanim || animTarget == knifeslashreversalanim || animTarget == knifeslashreversedanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == knifefollowedanim || animTarget == killanim || animTarget == dropkickanim || animTarget == upunchanim || animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim || animTarget == staffgroundsmashanim || animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == lowkickanim || animTarget == sweepreversedanim || animTarget == rabbitkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversalanim || animTarget == jumpreversedanim) {
5553 //close hands and yell
5554 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5555 righthandmorphness = 0;
5556 righthandmorphend = 1;
5557 targetrighthandmorphness = 1;
5560 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5561 lefthandmorphness = 0;
5562 lefthandmorphend = 1;
5563 targetlefthandmorphness = 1;
5566 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5569 targetheadmorphness = 1;
5576 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5577 (victim->aitype != searchtype) && (aitype != passivetype) &&
5578 (aitype != searchtype) && (victim->id < Person::players.size())) {
5579 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5583 if (!dead && animTarget != hurtidleanim)
5584 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5585 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5588 targetheadmorphness = 1;
5592 if (weaponactive != -1) {
5593 if (weapons[weaponids[weaponactive]].getType() != staff) {
5594 righthandmorphstart = 1;
5595 righthandmorphend = 1;
5597 if (weapons[weaponids[weaponactive]].getType() == staff) {
5598 righthandmorphstart = 2;
5599 righthandmorphend = 2;
5601 targetrighthandmorphness = 1;
5604 terrainnormal = terrain.getNormal(coords.x, coords.z);
5606 if (Animation::animations[animTarget].attack != reversal) {
5607 if (!isnormal(coords.x))
5615 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5616 facing = flatfacing;
5617 ReflectVector(&facing, terrainnormal);
5620 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5622 targettilt2 = -facing.y * 20;
5627 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5629 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5630 flatvelocity = velocity;
5632 flatvelspeed = findLength(&flatvelocity);
5633 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5634 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5639 if (targettilt > 25)
5641 if (targettilt < -25)
5645 if (targettilt2 > 45)
5647 if (targettilt2 < -45)
5649 if (abs(tilt2 - targettilt2) < multiplier * 400)
5650 tilt2 = targettilt2;
5651 else if (tilt2 > targettilt2) {
5652 tilt2 -= multiplier * 400;
5653 } else if (tilt2 < targettilt2) {
5654 tilt2 += multiplier * 400;
5656 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5663 if (!isnormal(targettilt) && targettilt) {
5666 if (!isnormal(targettilt2) && targettilt2) {
5671 if (animTarget == rabbittackleanim) {
5672 velocity += facing * multiplier * speed * 700 * scale;
5673 velspeed = findLength(&velocity);
5674 if (velspeed > speed * 65 * scale) {
5675 velocity /= velspeed;
5676 velspeed = speed * 65 * scale;
5677 velocity *= velspeed;
5679 velocity.y += gravity * multiplier * 20;
5680 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5681 velspeed = findLength(&velocity);
5682 velocity = flatfacing * velspeed;
5684 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5685 if (isRun() || animTarget == rabbitkickanim) {
5686 velocity += facing * multiplier * speed * 700 * scale;
5687 velspeed = findLength(&velocity);
5688 if (velspeed > speed * 45 * scale) {
5689 velocity /= velspeed;
5690 velspeed = speed * 45 * scale;
5691 velocity *= velspeed;
5693 velocity.y += gravity * multiplier * 20;
5694 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5695 velspeed = findLength(&velocity);
5696 if (velspeed < speed * 30 * scale)
5697 velspeed = speed * 30 * scale;
5698 velocity = flatfacing * velspeed;
5700 } else if (isRun()) {
5701 velocity += facing * multiplier * speed * 700 * scale;
5702 velspeed = findLength(&velocity);
5703 if (creature == rabbittype) {
5704 if (velspeed > speed * 55 * scale) {
5705 velocity /= velspeed;
5706 velspeed = speed * 55 * scale;
5707 velocity *= velspeed;
5710 if (creature == wolftype) {
5711 if (velspeed > speed * 75 * scale) {
5712 velocity /= velspeed;
5713 velspeed = speed * 75 * scale;
5714 velocity *= velspeed;
5717 velocity.y += gravity * multiplier * 20;
5718 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5719 velspeed = findLength(&velocity);
5720 velocity = flatfacing * velspeed;
5723 if (animTarget == rollanim && targetFrame().label != 6) {
5724 velocity += facing * multiplier * speed * 700 * scale;
5725 velspeed = findLength(&velocity);
5726 if (velspeed > speed * 45 * scale) {
5727 velocity /= velspeed;
5728 velspeed = speed * 45 * scale;
5729 velocity *= velspeed;
5731 velocity.y += gravity * multiplier * 20;
5732 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5733 velspeed = findLength(&velocity);
5734 velocity = flatfacing * velspeed;
5737 if (animTarget == sneakanim || animTarget == walkanim) {
5738 velocity += facing * multiplier * speed * 700 * scale;
5739 velspeed = findLength(&velocity);
5740 if (velspeed > speed * 12 * scale) {
5741 velocity /= velspeed;
5742 velspeed = speed * 12 * scale;
5743 velocity *= velspeed;
5745 velocity.y += gravity * multiplier * 20;
5746 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5747 velspeed = findLength(&velocity);
5748 velocity = flatfacing * velspeed;
5751 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5752 velocity += facing * multiplier * speed * 700 * scale;
5753 velspeed = findLength(&velocity);
5754 if (velspeed > speed * 2 * scale) {
5755 velocity /= velspeed;
5756 velspeed = speed * 2 * scale;
5757 velocity *= velspeed;
5759 velocity.y += gravity * multiplier * 20;
5760 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5761 velspeed = findLength(&velocity);
5762 velocity = flatfacing * velspeed;
5766 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5767 velocity -= facing * multiplier * speed * 700 * scale;
5768 velspeed = findLength(&velocity);
5769 if (velspeed > speed * 2 * scale) {
5770 velocity /= velspeed;
5771 velspeed = speed * 2 * scale;
5772 velocity *= velspeed;
5774 velocity.y += gravity * multiplier * 20;
5775 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5776 velspeed = findLength(&velocity);
5777 velocity = flatfacing * velspeed * -1;
5780 if (animTarget == fightsidestep) {
5781 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5782 velspeed = findLength(&velocity);
5783 if (velspeed > speed * 12 * scale) {
5784 velocity /= velspeed;
5785 velspeed = speed * 12 * scale;
5786 velocity *= velspeed;
5788 velocity.y += gravity * multiplier * 20;
5789 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5790 velspeed = findLength(&velocity);
5791 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5794 if (animTarget == staggerbackhighanim) {
5795 coords -= facing * multiplier * speed * 16 * scale;
5798 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5799 coords -= facing * multiplier * speed * 20 * scale;
5803 if (animTarget == backhandspringanim) {
5804 //coords-=facing*multiplier*50*scale;
5805 velocity += facing * multiplier * speed * 700 * scale * -1;
5806 velspeed = findLength(&velocity);
5807 if (velspeed > speed * 50 * scale) {
5808 velocity /= velspeed;
5809 velspeed = speed * 50 * scale;
5810 velocity *= velspeed;
5812 velocity.y += gravity * multiplier * 20;
5813 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5814 velspeed = findLength(&velocity);
5815 velocity = flatfacing * velspeed * -1;
5817 if (animTarget == dodgebackanim) {
5818 //coords-=facing*multiplier*50*scale;
5819 velocity += facing * multiplier * speed * 700 * scale * -1;
5820 velspeed = findLength(&velocity);
5821 if (velspeed > speed * 60 * scale) {
5822 velocity /= velspeed;
5823 velspeed = speed * 60 * scale;
5824 velocity *= velspeed;
5826 velocity.y += gravity * multiplier * 20;
5827 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5828 velspeed = findLength(&velocity);
5829 velocity = flatfacing * velspeed * -1;
5832 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5833 velspeed = findLength(&velocity);
5837 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5838 velocity.y += gravity * multiplier;
5841 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5842 coords += velocity * multiplier;
5844 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5845 if (isFlip() && targetFrame().label == 7)
5848 if (animTarget == jumpupanim) {
5850 animTarget = getIdle();
5857 pause_sound(whooshsound);
5858 OPENAL_SetVolume(channels[whooshsound], 0);
5861 if (animTarget == jumpdownanim || isFlip()) {
5862 if (isFlip())jumppower = -4;
5863 animTarget = getLanding();
5864 emit_sound_at(landsound, coords, 128.);
5867 addEnvSound(coords);
5872 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5873 coords.y += gravity * multiplier * 2;
5874 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5875 coords.y = terrain.getHeight(coords.x, coords.z);
5880 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)) {
5881 velspeed = findLength(&velocity);
5883 if (velspeed < multiplier * 300 * scale) {
5886 velocity -= velocity / velspeed * multiplier * 300 * scale;
5887 if (velspeed > 5 && (isLanding() || isLandhard())) {
5888 skiddingdelay += multiplier;
5889 if (skiddelay <= 0) {
5890 FootLand(leftfoot, .5);
5891 FootLand(rightfoot, .5);
5899 velspeed = findLength(&velocity);
5901 if (velspeed < multiplier * 600 * scale) {
5904 velocity -= velocity / velspeed * multiplier * 600 * scale;
5906 if (velspeed > 5 && (isLanding() || isLandhard())) {
5907 skiddingdelay += multiplier;
5908 if (skiddelay <= 0) {
5909 FootLand(leftfoot, .5);
5910 FootLand(rightfoot, .5);
5917 if (skiddingdelay < 0)
5918 skiddingdelay += multiplier;
5919 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5921 if (!onterrain || environment == grassyenvironment) {
5922 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5924 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5928 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5929 terrainnormal = victim->coords - coords;
5930 Normalise(&terrainnormal);
5931 targetyaw = -asin(0 - terrainnormal.x);
5932 targetyaw *= 360 / 6.28;
5933 if (terrainnormal.z < 0)
5934 targetyaw = 180 - targetyaw;
5935 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5938 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5939 targetyaw = victim->targetyaw;
5941 if (animTarget == rabbittacklinganim) {
5942 coords = victim->coords;
5945 skeleton.oldfree = skeleton.free;
5949 midterrain.x = terrain.size * terrain.scale / 2;
5950 midterrain.z = terrain.size * terrain.scale / 2;
5951 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5953 tempposit = coords - midterrain;
5955 Normalise(&tempposit);
5956 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5957 coords.x = tempposit.x + midterrain.x;
5958 coords.z = tempposit.z + midterrain.z;
5964 * inverse kinematics helper function
5966 void IKHelper(Person *p, float interp)
5968 XYZ point, change, change2;
5969 float heightleft, heightright;
5971 // TODO: implement localToWorld and worldToLocal
5972 // but keep in mind it won't be the same math if player is ragdolled or something
5973 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5974 // then comb through code for places where to use it
5976 // point = localToWorld(jointPos(leftfoot))
5977 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5978 // adjust height of foot
5979 heightleft = terrain.getHeight(point.x, point.z) + .04;
5980 point.y = heightleft;
5981 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5982 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5983 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5984 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5985 // move ankle along with foot
5986 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5987 // average knee pos between old and new pos
5988 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5990 // do same as above for right leg
5991 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5992 heightright = terrain.getHeight(point.x, point.z) + .04;
5993 point.y = heightright;
5994 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5995 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5996 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5997 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5998 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6000 // fix up skeleton now that we've moved body parts?
6001 p->skeleton.DoConstraints(&p->coords, &p->scale);
6008 int Person::DrawSkeleton()
6010 int oldplayerdetail;
6011 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6012 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6022 glAlphaFunc(GL_GREATER, 0.0001);
6024 float terrainheight;
6028 if (!isnormal(tilt))
6030 if (!isnormal(tilt2))
6032 oldplayerdetail = playerdetail;
6034 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6037 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6040 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6045 if (playerdetail != oldplayerdetail) {
6047 normalsupdatedelay = 0;
6049 static float updatedelaychange;
6050 static float morphness;
6051 static float framemult;
6053 skeleton.FindForwards();
6054 if (howactive == typesittingwall) {
6055 skeleton.specialforward[1] = 0;
6056 skeleton.specialforward[1].z = 1;
6062 static int weaponattachmuscle;
6063 static int weaponrotatemuscle;
6064 static XYZ weaponpoint;
6065 static int start, endthing;
6066 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6067 if (!isSleeping() && !isSitting()) {
6068 // TODO: give these meaningful names
6069 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6070 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6071 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6072 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6074 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6076 if (creature == wolftype)
6080 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6081 IKHelper(this, target);
6082 if (creature == wolftype)
6083 IKHelper(this, target);
6086 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6087 IKHelper(this, 1 - target);
6088 if (creature == wolftype)
6089 IKHelper(this, 1 - target);
6093 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()))
6096 targetheadyaw = -targetyaw;
6097 targetheadpitch = 0;
6098 if (Animation::animations[animTarget].attack == 3)
6099 targetheadyaw += 180;
6101 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6102 skeleton.drawmodel.vertex[i] = 0;
6103 skeleton.drawmodel.vertex[i].y = 999;
6105 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6106 skeleton.drawmodellow.vertex[i] = 0;
6107 skeleton.drawmodellow.vertex[i].y = 999;
6109 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6110 skeleton.drawmodelclothes.vertex[i] = 0;
6111 skeleton.drawmodelclothes.vertex[i].y = 999;
6113 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6114 // convenience renames
6115 const int p1 = skeleton.muscles[i].parent1->label;
6116 const int p2 = skeleton.muscles[i].parent2->label;
6118 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6123 if (p1 == righthand || p2 == righthand) {
6124 morphness = righthandmorphness;
6125 start = righthandmorphstart;
6126 endthing = righthandmorphend;
6128 if (p1 == lefthand || p2 == lefthand) {
6129 morphness = lefthandmorphness;
6130 start = lefthandmorphstart;
6131 endthing = lefthandmorphend;
6133 if (p1 == head || p2 == head) {
6134 morphness = headmorphness;
6135 start = headmorphstart;
6136 endthing = headmorphend;
6138 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6139 morphness = chestmorphness;
6140 start = chestmorphstart;
6141 endthing = chestmorphend;
6143 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6144 morphness = tailmorphness;
6145 start = tailmorphstart;
6146 endthing = tailmorphend;
6149 skeleton.FindRotationMuscle(i, animTarget);
6150 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6151 glMatrixMode(GL_MODELVIEW);
6155 glRotatef(tilt2, 1, 0, 0);
6157 glRotatef(tilt, 0, 0, 1);
6160 glTranslatef(mid.x, mid.y, mid.z);
6162 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6163 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6165 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6166 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6168 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6169 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6171 if (playerdetail || skeleton.free == 3) {
6172 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6173 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6174 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6175 glMatrixMode(GL_MODELVIEW);
6177 if (p1 == abdomen || p2 == abdomen)
6178 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6179 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6180 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6181 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6182 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6183 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6184 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6185 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6186 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6187 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6188 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6189 if (p1 == head || p2 == head)
6190 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6191 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6192 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6193 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6194 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6195 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6196 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6200 if (!playerdetail || skeleton.free == 3) {
6201 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6202 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6203 glMatrixMode(GL_MODELVIEW);
6205 if (p1 == abdomen || p2 == abdomen)
6206 glTranslatef(v0.x * proportionbody.x,
6207 v0.y * proportionbody.y,
6208 v0.z * proportionbody.z);
6209 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6210 glTranslatef(v0.x * proportionarms.x,
6211 v0.y * proportionarms.y,
6212 v0.z * proportionarms.z);
6213 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6214 glTranslatef(v0.x * proportionlegs.x,
6215 v0.y * proportionlegs.y,
6216 v0.z * proportionlegs.z);
6217 if (p1 == head || p2 == head)
6218 glTranslatef(v0.x * proportionhead.x,
6219 v0.y * proportionhead.y,
6220 v0.z * proportionhead.z);
6222 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6223 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6224 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6225 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6231 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6232 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6234 glMatrixMode(GL_MODELVIEW);
6238 glRotatef(tilt2, 1, 0, 0);
6240 glRotatef(tilt, 0, 0, 1);
6241 glTranslatef(mid.x, mid.y, mid.z);
6242 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6243 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6245 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6246 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6248 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6249 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6251 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6252 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6253 glMatrixMode(GL_MODELVIEW);
6255 if (p1 == abdomen || p2 == abdomen)
6256 glTranslatef(v0.x * proportionbody.x,
6257 v0.y * proportionbody.y,
6258 v0.z * proportionbody.z);
6259 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6260 glTranslatef(v0.x * proportionarms.x,
6261 v0.y * proportionarms.y,
6262 v0.z * proportionarms.z);
6263 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6264 glTranslatef(v0.x * proportionlegs.x,
6265 v0.y * proportionlegs.y,
6266 v0.z * proportionlegs.z);
6267 if (p1 == head || p2 == head)
6268 glTranslatef(v0.x * proportionhead.x,
6269 v0.y * proportionhead.y,
6270 v0.z * proportionhead.z);
6271 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6272 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6273 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6274 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6279 updatedelay = 1 + (float)(Random() % 100) / 1000;
6281 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6282 normalsupdatedelay = 1;
6283 if (playerdetail || skeleton.free == 3)
6284 skeleton.drawmodel.CalculateNormals(0);
6285 if (!playerdetail || skeleton.free == 3)
6286 skeleton.drawmodellow.CalculateNormals(0);
6287 if (skeleton.clothes)
6288 skeleton.drawmodelclothes.CalculateNormals(0);
6290 if (playerdetail || skeleton.free == 3)
6291 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6292 if (!playerdetail || skeleton.free == 3)
6293 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6294 if (skeleton.clothes) {
6295 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6300 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6301 if (updatedelaychange > -realmultiplier * 30)
6302 updatedelaychange = -realmultiplier * 30;
6303 if (updatedelaychange > -framemult * 4)
6304 updatedelaychange = -framemult * 4;
6305 if (skeleton.free == 1)
6306 updatedelaychange *= 6;
6308 updatedelaychange *= 8;
6309 updatedelay += updatedelaychange;
6311 glMatrixMode(GL_MODELVIEW);
6313 glTranslatef(coords.x, coords.y - .02, coords.z);
6314 if (!skeleton.free) {
6315 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6316 glRotatef(yaw, 0, 1, 0);
6320 glColor4f(.4, 1, .4, 1);
6321 glDisable(GL_LIGHTING);
6322 glDisable(GL_TEXTURE_2D);
6325 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6326 XYZ &v0 = skeleton.drawmodel.vertex[i];
6327 glVertex3f(v0.x, v0.y, v0.z);
6333 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6334 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6335 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6336 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6337 glVertex3f(v0.x, v0.y, v0.z);
6338 glVertex3f(v1.x, v1.y, v1.z);
6339 glVertex3f(v1.x, v1.y, v1.z);
6340 glVertex3f(v2.x, v2.y, v2.z);
6341 glVertex3f(v2.x, v2.y, v2.z);
6342 glVertex3f(v0.x, v0.y, v0.z);
6348 terrainlight = terrain.getLighting(coords.x, coords.z);
6349 distance = distsq(&viewer, &coords);
6350 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6354 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6355 if (terrainheight < 1)
6357 if (terrainheight > 1.7)
6358 terrainheight = 1.7;
6360 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6361 glDisable(GL_BLEND);
6362 glAlphaFunc(GL_GREATER, 0.0001);
6363 glEnable(GL_TEXTURE_2D);
6365 glDisable(GL_TEXTURE_2D);
6366 glColor4f(.7, .35, 0, .5);
6368 glEnable(GL_LIGHTING);
6371 if (Tutorial::active && id != 0) {
6372 glColor4f(.7, .7, .7, 0.6);
6374 glEnable(GL_LIGHTING);
6376 if (canattack && cananger)
6377 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6378 glDisable(GL_TEXTURE_2D);
6379 glColor4f(1, 0, 0, 0.8);
6381 glMatrixMode(GL_TEXTURE);
6383 glTranslatef(0, -smoketex, 0);
6384 glTranslatef(-smoketex, 0, 0);
6388 if (Tutorial::active && (id != 0))
6389 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6391 skeleton.drawmodel.draw();
6394 if (!playerdetail) {
6395 if (Tutorial::active && (id != 0))
6396 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6398 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6401 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6402 if (Tutorial::active && id != 0) {
6404 glMatrixMode(GL_MODELVIEW);
6405 glEnable(GL_TEXTURE_2D);
6406 glColor4f(.7, .7, .7, 0.6);
6408 glEnable(GL_LIGHTING);
6410 if (canattack && cananger)
6411 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6412 glDisable(GL_TEXTURE_2D);
6413 glColor4f(1, 0, 0, 0.8);
6415 glMatrixMode(GL_TEXTURE);
6417 glTranslatef(0, -smoketex * .6, 0);
6418 glTranslatef(smoketex * .6, 0, 0);
6421 if (Tutorial::active && (id != 0))
6422 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6424 skeleton.drawmodel.draw();
6427 if (!playerdetail) {
6428 if (Tutorial::active && (id != 0))
6429 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6431 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6436 if (Tutorial::active && id != 0) {
6438 glMatrixMode(GL_MODELVIEW);
6439 glEnable(GL_TEXTURE_2D);
6441 if (skeleton.clothes) {
6445 skeleton.drawmodelclothes.draw();
6447 skeleton.drawmodelclothes.drawimmediate();
6453 if (num_weapons > 0) {
6454 for (k = 0; k < num_weapons; k++) {
6456 if (weaponactive == k) {
6457 if (weapons[i].getType() != staff) {
6458 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6459 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6460 weaponattachmuscle = j;
6463 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6464 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) {
6465 weaponrotatemuscle = j;
6468 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6469 if (creature == wolftype)
6470 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6472 if (weapons[i].getType() == staff) {
6473 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6474 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6475 weaponattachmuscle = j;
6478 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6479 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) {
6480 weaponrotatemuscle = j;
6483 //weaponpoint=jointPos(rightwrist);
6484 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6485 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6486 XYZ tempnormthing, vec1, vec2;
6487 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6488 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6489 CrossProduct(&vec1, &vec2, &tempnormthing);
6490 Normalise(&tempnormthing);
6491 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6492 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6495 if (weaponactive != k && weaponstuck != k) {
6496 if (weapons[i].getType() == knife)
6497 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6498 if (weapons[i].getType() == sword)
6499 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6500 if (weapons[i].getType() == staff)
6501 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6502 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6503 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) {
6504 weaponrotatemuscle = j;
6508 if (weaponstuck == k) {
6509 if (weaponstuckwhere == 0)
6510 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6512 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6513 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6514 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) {
6515 weaponrotatemuscle = j;
6519 if (skeleton.free) {
6520 weapons[i].position = weaponpoint * scale + coords;
6521 weapons[i].bigrotation = 0;
6522 weapons[i].bigtilt = 0;
6523 weapons[i].bigtilt2 = 0;
6525 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;
6526 weapons[i].bigrotation = yaw;
6527 weapons[i].bigtilt = tilt;
6528 weapons[i].bigtilt2 = tilt2;
6530 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6531 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6532 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6533 if (weaponactive == k) {
6534 if (weapons[i].getType() == knife) {
6535 weapons[i].smallrotation = 180;
6536 weapons[i].smallrotation2 = 0;
6537 if (isCrouch() || wasCrouch()) {
6538 weapons[i].smallrotation2 = 20;
6540 if (animTarget == hurtidleanim) {
6541 weapons[i].smallrotation2 = 50;
6543 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6544 XYZ temppoint1, temppoint2;
6547 temppoint1 = jointPos(righthand);
6548 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6549 distance = findDistance(&temppoint1, &temppoint2);
6550 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6551 weapons[i].rotation2 *= 360 / 6.28;
6554 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6555 weapons[i].rotation1 *= 360 / 6.28;
6556 weapons[i].rotation3 = 0;
6557 weapons[i].smallrotation = -90;
6558 weapons[i].smallrotation2 = 0;
6559 if (temppoint1.x > temppoint2.x)
6560 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6562 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6563 XYZ temppoint1, temppoint2;
6566 temppoint1 = jointPos(righthand);
6567 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6568 distance = findDistance(&temppoint1, &temppoint2);
6569 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6570 weapons[i].rotation2 *= 360 / 6.28;
6573 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6574 weapons[i].rotation1 *= 360 / 6.28;
6575 weapons[i].rotation3 = 0;
6576 weapons[i].smallrotation = 90;
6577 weapons[i].smallrotation2 = 0;
6578 if (temppoint1.x > temppoint2.x)
6579 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6581 if (animTarget == knifethrowanim) {
6582 weapons[i].smallrotation = 90;
6583 //weapons[i].smallrotation2=-90;
6584 weapons[i].smallrotation2 = 0;
6585 weapons[i].rotation1 = 0;
6586 weapons[i].rotation2 = 0;
6587 weapons[i].rotation3 = 0;
6589 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6590 weapons[i].smallrotation = -90;
6591 weapons[i].rotation1 = 0;
6592 weapons[i].rotation2 = 0;
6593 weapons[i].rotation3 = 0;
6596 if (weapons[i].getType() == sword) {
6597 weapons[i].smallrotation = 0;
6598 weapons[i].smallrotation2 = 0;
6599 if (animTarget == knifethrowanim) {
6600 weapons[i].smallrotation = -90;
6601 weapons[i].smallrotation2 = 0;
6602 weapons[i].rotation1 = 0;
6603 weapons[i].rotation2 = 0;
6604 weapons[i].rotation3 = 0;
6606 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)) {
6607 XYZ temppoint1, temppoint2;
6610 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6611 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6612 distance = findDistance(&temppoint1, &temppoint2);
6613 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6614 weapons[i].rotation2 *= 360 / 6.28;
6617 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6618 weapons[i].rotation1 *= 360 / 6.28;
6619 weapons[i].rotation3 = 0;
6620 weapons[i].smallrotation = 90;
6621 weapons[i].smallrotation2 = 0;
6622 if (temppoint1.x > temppoint2.x)
6623 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6626 if (weapons[i].getType() == staff) {
6627 weapons[i].smallrotation = 100;
6628 weapons[i].smallrotation2 = 0;
6629 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6630 XYZ temppoint1, temppoint2;
6633 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6634 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6635 distance = findDistance(&temppoint1, &temppoint2);
6636 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6637 weapons[i].rotation2 *= 360 / 6.28;
6640 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6641 weapons[i].rotation1 *= 360 / 6.28;
6642 weapons[i].rotation3 = 0;
6643 weapons[i].smallrotation = 90;
6644 weapons[i].smallrotation2 = 0;
6645 if (temppoint1.x > temppoint2.x)
6646 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6650 if (weaponactive != k && weaponstuck != k) {
6651 if (weapons[i].getType() == knife) {
6652 weapons[i].smallrotation = -70;
6653 weapons[i].smallrotation2 = 10;
6655 if (weapons[i].getType() == sword) {
6656 weapons[i].smallrotation = -100;
6657 weapons[i].smallrotation2 = -8;
6659 if (weapons[i].getType() == staff) {
6660 weapons[i].smallrotation = -100;
6661 weapons[i].smallrotation2 = -8;
6664 if (weaponstuck == k) {
6665 if (weaponstuckwhere == 0)
6666 weapons[i].smallrotation = 180;
6668 weapons[i].smallrotation = 0;
6669 weapons[i].smallrotation2 = 10;
6678 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6680 if (animCurrent != animTarget)
6682 if (skeleton.free == 2)
6691 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6694 static float distance;
6695 static float olddistance;
6696 static int intersecting;
6697 static int firstintersecting;
6700 static XYZ start, end;
6701 static float slopethreshold = -.4;
6703 firstintersecting = -1;
6707 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6710 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6711 for (i = 0; i < 4; i++) {
6712 for (j = 0; j < model->TriangleNum; j++) {
6713 if (model->facenormals[j].y <= slopethreshold) {
6715 distance = abs((model->facenormals[j].x * p1->x) + (model->facenormals[j].y * p1->y) + (model->facenormals[j].z * p1->z) - ((model->facenormals[j].x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->facenormals[j].y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->facenormals[j].z * model->vertex[model->Triangles[j].vertex[0]].z)));
6716 if (distance < radius) {
6717 point = *p1 - model->facenormals[j] * distance;
6718 if (PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))
6721 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6722 &model->vertex[model->Triangles[j].vertex[1]],
6725 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6726 &model->vertex[model->Triangles[j].vertex[2]],
6729 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6730 &model->vertex[model->Triangles[j].vertex[2]],
6733 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6737 if (LineFacetd(&start, &end, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], &model->facenormals[j], &point)) {
6738 p1->y = point.y + radius;
6739 if ((animTarget == jumpdownanim || isFlip())) {
6740 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6743 if (animTarget == jumpupanim) {
6745 animTarget = getIdle();
6752 pause_sound(whooshsound);
6753 OPENAL_SetVolume(channels[whooshsound], 0);
6756 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6759 animTarget = getLanding();
6760 emit_sound_at(landsound, coords, 128.);
6763 addEnvSound(coords);
6770 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6771 olddistance = distance;
6772 firstintersecting = j;
6777 for (j = 0; j < model->TriangleNum; j++) {
6778 if (model->facenormals[j].y > slopethreshold) {
6781 start.y -= radius / 4;
6782 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6783 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6784 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6785 distance = abs((model->facenormals[j].x * start.x)
6786 + (model->facenormals[j].y * start.y)
6787 + (model->facenormals[j].z * start.z)
6788 - ((model->facenormals[j].x * v0.x)
6789 + (model->facenormals[j].y * v0.y)
6790 + (model->facenormals[j].z * v0.z)));
6791 if (distance < radius * .5) {
6792 point = start - model->facenormals[j] * distance;
6793 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6796 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6798 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6800 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6802 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6803 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6805 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6806 if (findLengthfast(&start) < findLengthfast(&velocity))
6809 *p1 += model->facenormals[j] * (distance - radius * .5);
6812 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6813 olddistance = distance;
6814 firstintersecting = j;
6821 *p = DoRotation(*p, 0, *rotate, 0);
6824 *p1 = DoRotation(*p1, 0, *rotate, 0);
6826 return firstintersecting;
6829 int findPathDist(int start, int end)
6831 int smallestcount, count, connected;
6832 int last, last2, last3, last4;
6835 smallestcount = 1000;
6836 for (int i = 0; i < 50; i++) {
6842 while (last != end && count < 30) {
6844 for (int j = 0; j < Game::numpathpoints; j++) {
6845 if (j != last && j != last2 && j != last3 && j != last4) {
6847 if (Game::numpathpointconnect[j])
6848 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6849 if (Game::pathpointconnect[j][k] == last)connected = 1;
6852 if (Game::numpathpointconnect[last])
6853 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6854 if (Game::pathpointconnect[last][k] == j)connected = 1;
6857 if (closest == -1 || Random() % 2 == 0) {
6868 if (count < smallestcount)
6869 smallestcount = count;
6871 return smallestcount;
6874 void Person::takeWeapon(int weaponId)
6877 weapons[weaponId].owner = id;
6878 if (num_weapons > 0) {
6879 weaponids[num_weapons] = weaponids[0];
6882 weaponids[0] = weaponId;
6885 void Person::addClothes()
6887 if (numclothes > 0) {
6888 for (int i = 0; i < numclothes; i++) {
6895 bool Person::addClothes(const int& clothesId)
6898 const std::string fileName = clothes[clothesId];
6900 GLubyte* array = &skeleton.skinText[0];
6904 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6909 float tintr = clothestintr[clothesId];
6910 float tintg = clothestintg[clothesId];
6911 float tintb = clothestintb[clothesId];
6913 if (tintr > 1) tintr = 1;
6914 if (tintg > 1) tintg = 1;
6915 if (tintb > 1) tintb = 1;
6917 if (tintr < 0) tintr = 0;
6918 if (tintg < 0) tintg = 0;
6919 if (tintb < 0) tintb = 0;
6921 int bytesPerPixel = texture.bpp / 8;
6925 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6926 if (bytesPerPixel == 3)
6928 else if ((i + 1) % 4 == 0)
6929 alphanum = texture.data[i];
6930 if ((i + 1) % 4 || bytesPerPixel == 3) {
6932 texture.data[i] *= tintr;
6934 texture.data[i] *= tintg;
6936 texture.data[i] *= tintb;
6937 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6949 if (aitype != playercontrolled && !Dialog::inDialog()) {
6951 //disable movement in editor
6952 if (Game::editorenabled)
6956 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6957 Person::players[0]->coords.y > coords.y + 2 &&
6958 !Person::players[0]->onterrain)
6962 if (aitype == pathfindtype) {
6963 if (finalpathfindpoint == -1) {
6964 float closestdistance;
6969 closestdistance = -1;
6970 for (int j = 0; j < Game::numpathpoints; j++) {
6971 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
6972 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
6974 finaltarget = Game::pathpoint[j];
6977 finalpathfindpoint = closest;
6978 for (int j = 0; j < Game::numpathpoints; j++) {
6979 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6980 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
6981 if (sq(tempdist) < closestdistance)
6982 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
6983 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
6984 closestdistance = sq(tempdist);
6986 finaltarget = colpoint;
6990 finalpathfindpoint = closest;
6993 if (targetpathfindpoint == -1) {
6994 float closestdistance;
6999 closestdistance = -1;
7000 if (lastpathfindpoint == -1) {
7001 for (int j = 0; j < Game::numpathpoints; j++) {
7002 if (j != lastpathfindpoint)
7003 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7004 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7008 targetpathfindpoint = closest;
7009 for (int j = 0; j < Game::numpathpoints; j++)
7010 if (j != lastpathfindpoint)
7011 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7012 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7013 if (sq(tempdist) < closestdistance) {
7014 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7015 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7016 closestdistance = sq(tempdist);
7021 targetpathfindpoint = closest;
7023 for (int j = 0; j < Game::numpathpoints; j++)
7024 if (j != lastpathfindpoint &&
7025 j != lastpathfindpoint2 &&
7026 j != lastpathfindpoint3 &&
7027 j != lastpathfindpoint4) {
7029 if (Game::numpathpointconnect[j])
7030 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7031 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7034 if (Game::numpathpointconnect[lastpathfindpoint])
7035 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7036 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7039 tempdist = findPathDist(j, finalpathfindpoint);
7040 if (closest == -1 || tempdist < closestdistance) {
7041 closestdistance = tempdist;
7046 targetpathfindpoint = closest;
7049 losupdatedelay -= multiplier;
7051 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7052 lookyaw = targetyaw;
7054 //reached target point
7055 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7056 lastpathfindpoint4 = lastpathfindpoint3;
7057 lastpathfindpoint3 = lastpathfindpoint2;
7058 lastpathfindpoint2 = lastpathfindpoint;
7059 lastpathfindpoint = targetpathfindpoint;
7060 if (lastpathfindpoint2 == -1)
7061 lastpathfindpoint2 = lastpathfindpoint;
7062 if (lastpathfindpoint3 == -1)
7063 lastpathfindpoint3 = lastpathfindpoint2;
7064 if (lastpathfindpoint4 == -1)
7065 lastpathfindpoint4 = lastpathfindpoint3;
7066 targetpathfindpoint = -1;
7068 if ( distsqflat(&coords, &finalfinaltarget) <
7069 distsqflat(&coords, &finaltarget) ||
7070 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7071 lastpathfindpoint == finalpathfindpoint) {
7072 aitype = passivetype;
7083 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7084 targetyaw += 90 * (whichdirection * 2 - 1);
7086 if (collided < 1 || animTarget != jumpupanim)
7088 if ((collided > .8 && jumppower >= 5))
7091 if ((!Tutorial::active || cananger) &&
7093 !Person::players[0]->dead &&
7094 distsq(&coords, &Person::players[0]->coords) < 400 &&
7096 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7097 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7098 !Game::editorenabled &&
7099 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7100 aitype = attacktypecutoff;
7101 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7102 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7103 !Game::editorenabled)
7104 aitype = attacktypecutoff;
7106 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7107 losupdatedelay = .2;
7108 for (unsigned j = 0; j < Person::players.size(); j++)
7109 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7110 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7111 if (distsq(&coords, &Person::players[j]->coords) < 400)
7112 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7113 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7114 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7115 DoRotation(jointPos(head), 0, yaw, 0)
7117 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7118 *Person::players[j]->scale + Person::players[j]->coords) ||
7119 (Person::players[j]->animTarget == hanganim &&
7120 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7121 aitype = searchtype;
7123 lastseen = Person::players[j]->coords;
7128 if (aitype == attacktypecutoff && Game::musictype != 2)
7129 if (creature != wolftype) {
7135 if (aitype != passivetype && Game::leveltime > .5)
7136 howactive = typeactive;
7138 if (aitype == passivetype) {
7139 aiupdatedelay -= multiplier;
7140 losupdatedelay -= multiplier;
7141 lastseentime += multiplier;
7142 pausetime -= multiplier;
7143 if (lastseentime > 1)
7146 if (aiupdatedelay < 0) {
7147 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7148 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7149 lookyaw = targetyaw;
7150 aiupdatedelay = .05;
7152 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7153 if (waypointtype[waypoint] == wppause)
7156 if (waypoint > numwaypoints - 1)
7162 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7173 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7174 if (!avoidsomething)
7175 targetyaw += 90 * (whichdirection * 2 - 1);
7177 XYZ leftpos, rightpos;
7178 float leftdist, rightdist;
7179 leftpos = coords + DoRotation(facing, 0, 90, 0);
7180 rightpos = coords - DoRotation(facing, 0, 90, 0);
7181 leftdist = distsq(&leftpos, &avoidwhere);
7182 rightdist = distsq(&rightpos, &avoidwhere);
7183 if (leftdist < rightdist)
7190 if (collided < 1 || animTarget != jumpupanim)
7192 if ((collided > .8 && jumppower >= 5))
7197 if (!Game::editorenabled) {
7198 if (howactive <= typesleeping)
7199 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7200 for (int j = 0; j < numenvsounds; j++) {
7201 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7202 if (vol > 0 && distsq(&coords, &envsound[j]) <
7203 2 * (vol + vol * (creature == rabbittype) * 3))
7204 aitype = attacktypecutoff;
7207 if (aitype != passivetype) {
7208 if (howactive == typesleeping)
7209 setAnimation(getupfromfrontanim);
7210 howactive = typeactive;
7214 if (howactive < typesleeping &&
7215 ((!Tutorial::active || cananger) && hostile) &&
7216 !Person::players[0]->dead &&
7217 distsq(&coords, &Person::players[0]->coords) < 400 &&
7219 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7220 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7221 aitype = attacktypecutoff;
7222 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7223 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7224 aitype = attacktypecutoff;
7227 if (creature == wolftype) {
7229 for (unsigned j = 0; j < Person::players.size(); j++) {
7230 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7231 float smelldistance = 50;
7232 if (j == 0 && Person::players[j]->num_weapons > 0) {
7233 if (weapons[Person::players[j]->weaponids[0]].bloody)
7234 smelldistance = 100;
7235 if (Person::players[j]->num_weapons == 2)
7236 if (weapons[Person::players[j]->weaponids[1]].bloody)
7237 smelldistance = 100;
7240 smelldistance = 100;
7241 windsmell = windvector;
7242 Normalise(&windsmell);
7243 windsmell = windsmell * 2 + Person::players[j]->coords;
7244 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7245 aitype = attacktypecutoff;
7250 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7251 losupdatedelay = .2;
7252 for (unsigned j = 0; j < Person::players.size(); j++) {
7253 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7254 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7255 if (distsq(&coords, &Person::players[j]->coords) < 400)
7256 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7257 if ((-1 == Object::checkcollide(
7258 DoRotation(jointPos(head), 0, yaw, 0)*
7260 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7261 Person::players[j]->scale + Person::players[j]->coords) &&
7262 !Person::players[j]->isWallJump()) ||
7263 (Person::players[j]->animTarget == hanganim &&
7264 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7266 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7271 if (lastseentime <= 0) {
7272 aitype = searchtype;
7274 lastseen = Person::players[j]->coords;
7282 if (aitype == attacktypecutoff && Game::musictype != 2) {
7283 if (creature != wolftype) {
7287 if (creature == wolftype) {
7297 if (aitype == searchtype) {
7298 aiupdatedelay -= multiplier;
7299 losupdatedelay -= multiplier;
7301 lastseentime -= multiplier;
7302 lastchecktime -= multiplier;
7304 if (isRun() && !onground) {
7305 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7306 XYZ test2 = coords + facing;
7308 XYZ test = coords + facing;
7310 j = Object::checkcollide(test2, test, laststanding);
7312 j = Object::checkcollide(test2, test);
7315 setAnimation(getStop());
7318 //aitype=passivetype;
7319 aitype = pathfindtype;
7320 finalfinaltarget = waypoints[waypoint];
7321 finalpathfindpoint = -1;
7322 targetpathfindpoint = -1;
7323 lastpathfindpoint = -1;
7324 lastpathfindpoint2 = -1;
7325 lastpathfindpoint3 = -1;
7326 lastpathfindpoint4 = -1;
7331 //check out last seen location
7332 if (aiupdatedelay < 0) {
7333 targetyaw = roughDirectionTo(coords, lastseen);
7334 lookyaw = targetyaw;
7335 aiupdatedelay = .05;
7338 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7341 lastseen.x += (float(Random() % 100) - 50) / 25;
7342 lastseen.z += (float(Random() % 100) - 50) / 25;
7353 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7354 if (!avoidsomething)
7355 targetyaw += 90 * (whichdirection * 2 - 1);
7357 XYZ leftpos, rightpos;
7358 float leftdist, rightdist;
7359 leftpos = coords + DoRotation(facing, 0, 90, 0);
7360 rightpos = coords - DoRotation(facing, 0, 90, 0);
7361 leftdist = distsq(&leftpos, &avoidwhere);
7362 rightdist = distsq(&rightpos, &avoidwhere);
7363 if (leftdist < rightdist)
7370 if (collided < 1 || animTarget != jumpupanim)
7372 if ((collided > .8 && jumppower >= 5))
7375 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7376 for (int k = 0; k < numenvsounds; k++) {
7377 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7378 aitype = attacktypecutoff;
7382 if (!Person::players[0]->dead &&
7383 losupdatedelay < 0 &&
7384 !Game::editorenabled &&
7386 ((!Tutorial::active || cananger) && hostile)) {
7387 losupdatedelay = .2;
7388 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7389 aitype = attacktypecutoff;
7392 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7393 //TODO: factor out canSeePlayer()
7394 if (distsq(&coords, &Person::players[0]->coords) < 400)
7395 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7396 if ((Object::checkcollide(
7397 DoRotation(jointPos(head), 0, yaw, 0)*
7399 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7400 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7401 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7402 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7403 /* //TODO: changed j to 0 on a whim, make sure this is correct
7404 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7405 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7407 aitype = attacktypecutoff;
7412 if (lastseentime < 0) {
7413 //aitype=passivetype;
7415 aitype = pathfindtype;
7416 finalfinaltarget = waypoints[waypoint];
7417 finalpathfindpoint = -1;
7418 targetpathfindpoint = -1;
7419 lastpathfindpoint = -1;
7420 lastpathfindpoint2 = -1;
7421 lastpathfindpoint3 = -1;
7422 lastpathfindpoint4 = -1;
7426 if (aitype != gethelptype)
7429 //get help from buddies
7430 if (aitype == gethelptype) {
7431 runninghowlong += multiplier;
7432 aiupdatedelay -= multiplier;
7434 if (aiupdatedelay < 0 || ally == 0) {
7438 //TODO: factor out closest search somehow
7441 float closestdist = -1;
7442 for (unsigned k = 0; k < Person::players.size(); k++) {
7443 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7444 (Person::players[k]->howactive < typedead1) &&
7445 !Person::players[k]->skeleton.free &&
7446 (Person::players[k]->aitype == passivetype)) {
7447 float distance = distsq(&coords, &Person::players[k]->coords);
7448 if (closestdist == -1 || distance < closestdist) {
7449 closestdist = distance;
7455 if (closest != -1) {
7460 lastseen = Person::players[0]->coords;
7467 XYZ facing = coords;
7468 XYZ flatfacing = Person::players[ally]->coords;
7469 facing.y += jointPos(head).y * scale;
7470 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7471 if (-1 != Object::checkcollide(facing, flatfacing))
7474 //no available ally, run back to player
7476 Person::players[ally]->skeleton.free ||
7477 Person::players[ally]->aitype != passivetype ||
7478 lastseentime <= 0) {
7479 aitype = searchtype;
7485 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7486 lookyaw = targetyaw;
7487 aiupdatedelay = .05;
7490 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7491 aitype = searchtype;
7493 Person::players[ally]->aitype = searchtype;
7494 if (Person::players[ally]->lastseentime < lastseentime) {
7495 Person::players[ally]->lastseen = lastseen;
7496 Person::players[ally]->lastseentime = lastseentime;
7497 Person::players[ally]->lastchecktime = lastchecktime;
7501 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7502 if (!avoidsomething)
7503 targetyaw += 90 * (whichdirection * 2 - 1);
7505 XYZ leftpos, rightpos;
7506 float leftdist, rightdist;
7507 leftpos = coords + DoRotation(facing, 0, 90, 0);
7508 rightpos = coords - DoRotation(facing, 0, 90, 0);
7509 leftdist = distsq(&leftpos, &avoidwhere);
7510 rightdist = distsq(&rightpos, &avoidwhere);
7511 if (leftdist < rightdist)
7525 if (collided < 1 || animTarget != jumpupanim)
7527 if (collided > .8 && jumppower >= 5)
7531 //retreiving a weapon on the ground
7532 if (aitype == getweapontype) {
7533 aiupdatedelay -= multiplier;
7534 lastchecktime -= multiplier;
7536 if (aiupdatedelay < 0) {
7542 float closestdist = -1;
7543 for (unsigned k = 0; k < weapons.size(); k++)
7544 if (weapons[k].owner == -1) {
7545 float distance = distsq(&coords, &weapons[k].position);
7546 if (closestdist == -1 || distance < closestdist) {
7547 closestdist = distance;
7560 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7561 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7562 aitype = attacktypecutoff;
7565 if (!Person::players[0]->dead)
7567 if (weapons[ally].owner != -1 ||
7568 distsq(&coords, &weapons[ally].position) > 16) {
7569 aitype = attacktypecutoff;
7572 //TODO: factor these out as moveToward()
7573 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7574 lookyaw = targetyaw;
7575 aiupdatedelay = .05;
7579 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7580 if (!avoidsomething)
7581 targetyaw += 90 * (whichdirection * 2 - 1);
7583 XYZ leftpos, rightpos;
7584 float leftdist, rightdist;
7585 leftpos = coords + DoRotation(facing, 0, 90, 0);
7586 rightpos = coords - DoRotation(facing, 0, 90, 0);
7587 leftdist = distsq(&leftpos, &avoidwhere);
7588 rightdist = distsq(&rightpos, &avoidwhere);
7589 if (leftdist < rightdist)
7603 if (animTarget != crouchremoveknifeanim &&
7604 animTarget != removeknifeanim)
7605 throwtogglekeydown = 0;
7608 if (collided < 1 || animTarget != jumpupanim)
7610 if ((collided > .8 && jumppower >= 5))
7614 if (aitype == attacktypecutoff) {
7615 aiupdatedelay -= multiplier;
7616 //dodge or reverse rabbit kicks, knife throws, flips
7617 if (damage < damagetolerance * 2 / 3)
7618 if ((Person::players[0]->animTarget == rabbitkickanim ||
7619 Person::players[0]->animTarget == knifethrowanim ||
7620 (Person::players[0]->isFlip() &&
7621 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7622 !Person::players[0]->skeleton.free &&
7623 (aiupdatedelay < .1)) {
7627 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7628 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7629 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7630 if (abs(Random() % 2) == 0)
7631 setAnimation(backhandspringanim);
7633 setAnimation(rollanim);
7634 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7637 if (animTarget == jumpupanim || animTarget == jumpdownanim)
7638 setAnimation(flipanim);
7642 aiupdatedelay = .02;
7644 //get confused by flips
7645 if (Person::players[0]->isFlip() &&
7646 !Person::players[0]->skeleton.free &&
7647 Person::players[0]->animTarget != walljumprightkickanim &&
7648 Person::players[0]->animTarget != walljumpleftkickanim) {
7649 if (distsq(&Person::players[0]->coords, &coords) < 25)
7650 if ((1 - damage / damagetolerance) > .5)
7653 //go for weapon on the ground
7654 if (wentforweapon < 3)
7655 for (unsigned k = 0; k < weapons.size(); k++)
7656 if (creature != wolftype)
7657 if (num_weapons == 0 &&
7658 weapons[k].owner == -1 &&
7659 weapons[k].velocity.x == 0 &&
7660 weapons[k].velocity.z == 0 &&
7661 weapons[k].velocity.y == 0) {
7662 if (distsq(&coords, &weapons[k].position) < 16) {
7665 aitype = getweapontype;
7669 //dodge/reverse walljump kicks
7670 if (damage < damagetolerance / 2)
7671 if (Animation::animations[animTarget].height != highheight)
7672 if (damage < damagetolerance * .5 &&
7673 ((Person::players[0]->animTarget == walljumprightkickanim ||
7674 Person::players[0]->animTarget == walljumpleftkickanim) &&
7675 ((aiupdatedelay < .15 &&
7677 (aiupdatedelay < .08 &&
7678 difficulty != 2)))) {
7681 //walked off a ledge (?)
7682 if (isRun() && !onground)
7683 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7684 XYZ test2 = coords + facing;
7686 XYZ test = coords + facing;
7688 j = Object::checkcollide(test2, test, laststanding);
7690 j = Object::checkcollide(test2, test);
7693 setAnimation(getStop());
7696 aitype = pathfindtype;
7697 finalfinaltarget = waypoints[waypoint];
7698 finalpathfindpoint = -1;
7699 targetpathfindpoint = -1;
7700 lastpathfindpoint = -1;
7701 lastpathfindpoint2 = -1;
7702 lastpathfindpoint3 = -1;
7703 lastpathfindpoint4 = -1;
7707 //lose sight of player in the air (?)
7708 if (Person::players[0]->coords.y > coords.y + 5 &&
7709 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7710 !Person::players[0]->onterrain) {
7711 aitype = pathfindtype;
7712 finalfinaltarget = waypoints[waypoint];
7713 finalpathfindpoint = -1;
7714 targetpathfindpoint = -1;
7715 lastpathfindpoint = -1;
7716 lastpathfindpoint2 = -1;
7717 lastpathfindpoint3 = -1;
7718 lastpathfindpoint4 = -1;
7720 //it's time to think (?)
7721 if (aiupdatedelay < 0 &&
7722 !Animation::animations[animTarget].attack &&
7723 animTarget != staggerbackhighanim &&
7724 animTarget != staggerbackhardanim &&
7725 animTarget != backhandspringanim &&
7726 animTarget != dodgebackanim) {
7728 if (weaponactive == -1 && num_weapons > 0)
7729 drawkeydown = Random() % 2;
7732 rabbitkickenabled = Random() % 2;
7734 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7735 XYZ targetpoint = Person::players[0]->coords;
7736 if (distsq(&Person::players[0]->coords, &coords) <
7737 distsq(&rotatetarget, &coords))
7738 targetpoint += Person::players[0]->velocity *
7739 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7740 targetyaw = roughDirectionTo(coords, targetpoint);
7741 lookyaw = targetyaw;
7742 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7744 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7746 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7747 distsq(&coords, &Person::players[0]->coords) < 9) &&
7748 Person::players[0]->weaponactive != -1)
7750 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7754 //chill out around the corpse
7755 if (Person::players[0]->dead) {
7757 if (Random() % 10 == 0)
7759 if (Random() % 100 == 0) {
7760 aitype = pathfindtype;
7761 finalfinaltarget = waypoints[waypoint];
7762 finalpathfindpoint = -1;
7763 targetpathfindpoint = -1;
7764 lastpathfindpoint = -1;
7765 lastpathfindpoint2 = -1;
7766 lastpathfindpoint3 = -1;
7767 lastpathfindpoint4 = -1;
7776 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7777 targetyaw += 90 * (whichdirection * 2 - 1);
7779 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7783 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7787 if (aitype != playercontrolled &&
7792 for (unsigned j = 0; j < Person::players.size(); j++)
7793 if (j != id && !Person::players[j]->skeleton.free &&
7794 Person::players[j]->hasvictim &&
7795 (Tutorial::active && reversaltrain ||
7796 Random() % 2 == 0 && difficulty == 2 ||
7797 Random() % 4 == 0 && difficulty == 1 ||
7798 Random() % 8 == 0 && difficulty == 0 ||
7799 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7800 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7801 (Random() % 2 == 0 || difficulty == 2) ||
7802 (isIdle() || isRun()) &&
7803 Person::players[j]->weaponactive != -1 ||
7804 Person::players[j]->animTarget == swordslashanim &&
7805 weaponactive != -1 ||
7806 Person::players[j]->animTarget == staffhitanim ||
7807 Person::players[j]->animTarget == staffspinhitanim))
7808 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7809 Person::players[j]->victim == Person::players[id] &&
7810 (Person::players[j]->animTarget == sweepanim ||
7811 Person::players[j]->animTarget == spinkickanim ||
7812 Person::players[j]->animTarget == staffhitanim ||
7813 Person::players[j]->animTarget == staffspinhitanim ||
7814 Person::players[j]->animTarget == winduppunchanim ||
7815 Person::players[j]->animTarget == upunchanim ||
7816 Person::players[j]->animTarget == wolfslapanim ||
7817 Person::players[j]->animTarget == knifeslashstartanim ||
7818 Person::players[j]->animTarget == swordslashanim &&
7819 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7820 weaponactive != -1))) {
7828 Person::players[target]->Reverse();
7833 if (collided > .8 && jumppower >= 5 ||
7834 distsq(&coords, &Person::players[0]->coords) > 400 &&
7836 creature == rabbittype)
7838 //TODO: why are we controlling the human?
7839 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7840 Person::players[0]->jumpkeydown = 0;
7841 if (Person::players[0]->animTarget == jumpdownanim &&
7842 distsq(&Person::players[0]->coords, &coords) < 40)
7847 if (Tutorial::active)
7852 XYZ facing = coords;
7853 XYZ flatfacing = Person::players[0]->coords;
7854 facing.y += jointPos(head).y * scale;
7855 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7857 if (-1 != Object::checkcollide(facing, flatfacing)) {
7860 if (lastseentime <= 0 &&
7861 (creature != wolftype ||
7862 weaponstuck == -1)) {
7863 aitype = searchtype;
7865 lastseen = Person::players[0]->coords;
7872 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7873 (aitype == attacktypecutoff ||
7874 aitype == searchtype))
7875 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7876 XYZ test = Person::players[0]->coords;
7878 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7882 if (aitype == passivetype && !(numwaypoints > 1) ||
7884 pause && damage > superpermanentdamage) {
7903 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7904 facing = flatfacing;
7906 if (aitype == attacktypecutoff) {
7907 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7908 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7909 } else if (howactive >= typesleeping) {
7910 targetheadyaw = targetyaw;
7911 targetheadpitch = 0;
7913 if (interestdelay <= 0) {
7914 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7915 headtarget = coords;
7916 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7917 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7918 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7919 headtarget += facing * 1.5;
7921 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7922 targetheadpitch = pitchTo(coords, headtarget);