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))
3828 if (animTarget == rabbitkickreversalanim) {
3829 animTarget = getCrouch();
3832 if (animTarget == jumpreversalanim) {
3833 animTarget = getCrouch();
3836 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3837 if (attackkeydown && animTarget != walljumpfrontanim) {
3839 float closestdist = -1;
3841 if (Person::players.size() > 1)
3842 for (unsigned i = 0; i < Person::players.size(); i++) {
3843 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3844 distance = distsq(&Person::players[i]->coords, &coords);
3845 if (closestdist == -1 || distance < closestdist) {
3846 closestdist = distance;
3851 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3852 victim = Person::players[closest];
3853 animTarget = walljumprightkickanim;
3855 XYZ rotatetarget = victim->coords - coords;
3856 Normalise(&rotatetarget);
3857 yaw = -asin(0 - rotatetarget.x);
3859 if (rotatetarget.z < 0)
3861 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3862 velocity = (victim->coords - coords) * 4;
3867 if (animTarget == walljumpbackanim) {
3868 animTarget = backflipanim;
3870 velocity = facing * -8;
3873 resume_stream(whooshsound);
3875 if (animTarget == walljumprightanim) {
3876 animTarget = rightflipanim;
3880 velocity = DoRotation(facing, 0, 30, 0) * -8;
3883 if (animTarget == walljumpfrontanim) {
3884 animTarget = frontflipanim;
3888 velocity = facing * 8;
3892 resume_stream(whooshsound);
3894 if (animTarget == walljumpleftanim) {
3895 if (attackkeydown) {
3897 float closestdist = -1;
3899 if (Person::players.size() > 1)
3900 for (unsigned i = 0; i < Person::players.size(); i++) {
3901 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3902 distance = distsq(&Person::players[i]->coords, &coords);
3903 if (closestdist == -1 || distance < closestdist) {
3904 closestdist = distance;
3909 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3910 victim = Person::players[closest];
3911 animTarget = walljumpleftkickanim;
3913 XYZ rotatetarget = victim->coords - coords;
3914 Normalise(&rotatetarget);
3915 yaw = -asin(0 - rotatetarget.x);
3917 if (rotatetarget.z < 0)
3919 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3920 velocity = (victim->coords - coords) * 4;
3925 if (animTarget != walljumpleftkickanim) {
3926 animTarget = leftflipanim;
3930 velocity = DoRotation(facing, 0, -30, 0) * -8;
3934 resume_stream(whooshsound);
3936 if (animTarget == sneakattackanim) {
3937 animCurrent = getCrouch();
3938 animTarget = getCrouch();
3945 transspeed = 1000000;
3946 targetheadyaw += 180;
3947 coords -= facing * .7;
3949 coords.y = terrain.getHeight(coords.x, coords.z);
3953 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3954 animTarget = getIdle();
3957 coords.y = terrain.getHeight(coords.x, coords.z);
3961 if (animCurrent == knifefollowanim) {
3962 animTarget = getIdle();
3965 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3966 float ycoords = oldcoords.y;
3967 animTarget = getStop();
3972 transspeed = 1000000;
3973 targetheadyaw += 180;
3974 if (!isnormal(coords.x))
3976 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3977 oldcoords = coords + facing * .5;
3978 else if (animCurrent == sweepreversalanim)
3979 oldcoords = coords + facing * 1.1;
3980 else if (animCurrent == upunchreversalanim) {
3981 oldcoords = coords + facing * 1.5;
3984 targetheadyaw += 180;
3987 } else if (animCurrent == knifeslashreversalanim) {
3988 oldcoords = coords + facing * .5;
3991 targetheadyaw += 90;
3994 } else if (animCurrent == staffspinhitreversalanim) {
3997 targetheadyaw += 180;
4002 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4004 oldcoords.y = ycoords;
4005 currentoffset = coords - oldcoords;
4011 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4016 if (Animation::animations[animTarget].attack == reversed) {
4018 if (animTarget == sweepreversedanim)
4020 animTarget = backhandspringanim;
4022 emit_sound_at(landsound, coords, 128);
4024 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4025 animTarget = rollanim;
4028 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4029 coords.y = oldcoords.y;
4031 if (animCurrent == knifeslashreversedanim) {
4032 animTarget = rollanim;
4037 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4038 coords.y = oldcoords.y;
4042 animTarget = jumpdownanim;
4045 animTarget = getIdle();
4047 animTarget = getIdle();
4048 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4049 animTarget = getIdle();
4051 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4052 coords.y = oldcoords.y;
4053 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4054 targetoffset.y = coords.y;
4056 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4057 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4058 currentoffset.y -= (coords.y - targetoffset.y);
4059 coords.y = targetoffset.y;
4061 normalsupdatedelay = 0;
4063 if (animCurrent == upunchanim) {
4064 animTarget = getStop();
4065 normalsupdatedelay = 0;
4068 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4072 if (num_weapons > 0)
4073 if (weapons[0].getType() == staff)
4079 rabbitkickragdoll = 1;
4081 if (animCurrent == rabbitkickreversedanim) {
4087 skeleton.spinny = 0;
4088 SolidHitBonus(!id); // FIXME: tricky id
4092 animTarget = rollanim;
4095 pause_sound(whooshsound);
4099 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4103 skeleton.spinny = 0;
4105 if (animCurrent == jumpreversedanim) {
4111 skeleton.spinny = 0;
4112 SolidHitBonus(!id); // FIXME: tricky id
4116 animTarget = rollanim;
4117 coords += facing * 2;
4119 pause_sound(whooshsound);
4124 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) {
4125 animTarget = getupfromfrontanim;
4127 } else if (Animation::animations[animCurrent].attack == normalattack) {
4128 animTarget = getIdle();
4131 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4132 animTarget = blockhighleftstrikeanim;
4134 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4135 animTarget = getIdle();
4138 if (animCurrent == spinkickanim && victim->skeleton.free) {
4139 if (creature == rabbittype)
4140 animTarget = fightidleanim;
4145 if (isIdle() && !wasIdle())
4146 normalsupdatedelay = 0;
4148 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4149 animTarget = jumpdownanim;
4152 if (!skeleton.free) {
4154 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4155 if (!isRun() || !wasRun()) {
4156 if (targetFrame().speed > currentFrame().speed)
4157 target += multiplier * targetFrame().speed * speed * 2;
4158 if (targetFrame().speed <= currentFrame().speed)
4159 target += multiplier * currentFrame().speed * speed * 2;
4161 if (isRun() && wasRun()) {
4163 tempspeed = velspeed;
4164 if (tempspeed < 10 * speedmult)
4165 tempspeed = 10 * speedmult;
4166 /* FIXME - mixed of target and current here, is that intended? */
4167 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4169 } else if (transspeed)
4170 target += multiplier * transspeed * speed * 2;
4172 if (!isRun() || !wasRun()) {
4173 if (targetFrame().speed > currentFrame().speed)
4174 target += multiplier * targetFrame().speed * 2;
4175 if (targetFrame().speed <= currentFrame().speed)
4176 target += multiplier * currentFrame().speed * 2;
4180 if (animCurrent != animTarget)
4181 target = (target + oldtarget) / 2;
4184 frameCurrent = frameTarget;
4188 rot = targetrot * target;
4189 yaw += rot - oldrot;
4195 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4196 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4198 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4200 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4201 skeleton.joints[i].position = currentFrame().joints[i].position;
4204 skeleton.FindForwards();
4206 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4207 if (skeleton.muscles[i].visible) {
4208 skeleton.FindRotationMuscle(i, animTarget);
4211 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4212 if (skeleton.muscles[i].visible) {
4213 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4214 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4215 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4216 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4217 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4218 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4223 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4224 skeleton.joints[i].position = targetFrame().joints[i].position;
4227 skeleton.FindForwards();
4229 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4230 if (skeleton.muscles[i].visible) {
4231 skeleton.FindRotationMuscle(i, animTarget);
4234 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4235 if (skeleton.muscles[i].visible) {
4236 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4237 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4238 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4239 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4240 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4241 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4242 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4243 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4244 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4245 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4246 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4247 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4252 oldanimCurrent = animCurrent;
4253 oldanimTarget = animTarget;
4254 oldframeTarget = frameTarget;
4255 oldframeCurrent = frameCurrent;
4257 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4258 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4259 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4261 offset = currentoffset * (1 - target) + targetoffset * target;
4262 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4263 if (skeleton.muscles[i].visible) {
4264 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4265 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4266 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4271 if (isLanding() && landhard) {
4274 animTarget = getLandhard();
4287 void Person::DoStuff()
4289 static XYZ terrainnormal;
4290 static XYZ flatfacing;
4291 static XYZ flatvelocity;
4292 static float flatvelspeed;
4294 static int bloodsize;
4295 static int startx, starty, endx, endy;
4296 static GLubyte color;
4297 static XYZ bloodvel;
4299 onfiredelay -= multiplier;
4300 if (onfiredelay < 0 && onfire) {
4301 if (Random() % 2 == 0) {
4307 crouchkeydowntime += multiplier;
4309 crouchkeydowntime = 0;
4310 jumpkeydowntime += multiplier;
4311 if (!jumpkeydown && skeleton.free)
4312 jumpkeydowntime = 0;
4314 if (hostile || damage > 0 || bloodloss > 0)
4317 if (isIdle() || isRun())
4320 if (num_weapons == 1 && weaponactive != -1)
4324 blooddimamount -= multiplier * .3;
4325 speechdelay -= multiplier;
4326 texupdatedelay -= multiplier;
4327 interestdelay -= multiplier;
4328 flamedelay -= multiplier;
4329 parriedrecently -= multiplier;
4331 victim = this->shared_from_this();
4336 speed = 1.1 * speedmult;
4338 speed = 1.0 * speedmult;
4340 rabbitkickragdoll = 0;
4344 if (id != 0 && (creature == rabbittype || difficulty != 2))
4346 if (id != 0 && creature == wolftype && difficulty == 2) {
4348 if (aitype != passivetype) {
4350 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) {
4356 if (animTarget == wolfrunninganim && !superruntoggle) {
4357 animTarget = getRun();
4361 if (weaponactive == -1 && num_weapons > 0) {
4362 if (weapons[weaponids[0]].getType() == staff) {
4368 burnt += multiplier;
4372 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4374 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4380 vel[0] = velocity.x;
4381 vel[1] = velocity.y;
4382 vel[2] = velocity.z;
4385 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4386 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4390 while (flamedelay < 0 && onfire) {
4392 int howmany = fabs(Random() % (skeleton.joints.size()));
4393 if (skeleton.free) {
4394 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4395 flatfacing = skeleton.joints[howmany].position * scale + coords;
4397 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4398 flatvelocity = (coords - oldcoords) / multiplier / 2;
4400 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4403 while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) {
4405 int howmany = fabs(Random() % (skeleton.joints.size()));
4406 if (skeleton.free) {
4407 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4408 flatfacing = skeleton.joints[howmany].position * scale + coords;
4410 flatvelocity = (coords - oldcoords) / multiplier / 2;
4411 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4413 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4417 bleeding -= multiplier * .3;
4418 if (bloodtoggle == 2) {
4419 skeleton.drawmodel.textureptr.bind();
4420 if ((bleeding <= 0) && (detail != 2))
4425 if (neckspurtamount > 0) {
4426 neckspurtamount -= multiplier;
4427 neckspurtdelay -= multiplier * 3;
4428 neckspurtparticledelay -= multiplier * 3;
4429 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4432 if (skeleton.free) {
4433 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4434 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4435 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4437 bloodvel.z = 5 * neckspurtamount;
4438 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4439 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4440 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4442 neckspurtparticledelay = .05;
4444 if (neckspurtdelay < 0) {
4449 if (deathbleeding > 0 && dead != 2) {
4450 if (deathbleeding < 5)
4451 bleeddelay -= deathbleeding * multiplier / 4;
4453 bleeddelay -= 5 * multiplier / 4;
4454 if (bleeddelay < 0 && bloodtoggle) {
4459 if (skeleton.free) {
4460 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4461 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4463 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4464 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4468 bloodloss += deathbleeding * multiplier * 80;
4469 deathbleeding -= multiplier * 1.6;
4470 if (deathbleeding < 0)
4472 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4473 if (weaponactive != -1) {
4474 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4475 weapons[weaponids[0]].velocity.x += .01;
4478 weaponids[0] = weaponids[num_weapons];
4479 if (weaponstuck == num_weapons)
4483 for (unsigned i = 0; i < Person::players.size(); i++) {
4484 Person::players[i]->wentforweapon = 0;
4492 if (!dead && creature == wolftype) {
4493 award_bonus(0, Wolfbonus);
4496 if (animTarget == knifefollowedanim && !skeleton.free) {
4497 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4498 skeleton.joints[i].velocity = 0;
4499 skeleton.joints[i].velocity.y = -2;
4502 if (id != 0 && unconscioustime > .1) {
4510 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4511 texupdatedelay = .12;
4513 bloodsize = 5 - realtexdetail;
4517 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4518 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4519 endx = startx + bloodsize;
4520 endy = starty + bloodsize;
4530 if (endx > skeleton.skinsize - 1) {
4531 endx = skeleton.skinsize - 1;
4534 if (endy > skeleton.skinsize - 1) {
4535 endy = skeleton.skinsize - 1;
4543 for (i = startx; i < endx; i++) {
4544 for (int j = starty; j < endy; j++) {
4545 if (Random() % 2 == 0) {
4546 color = Random() % 85 + 170;
4547 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4548 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4549 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4550 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4555 skeleton.drawmodel.textureptr.bind();
4559 if (skeleton.free) {
4560 bleedx += 4 * direction / realtexdetail;
4562 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4564 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4566 bleedy -= 4 / realtexdetail;
4568 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4570 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4574 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4575 righthandmorphness = targetrighthandmorphness;
4576 righthandmorphstart = righthandmorphend;
4577 } else if (righthandmorphness > targetrighthandmorphness) {
4578 righthandmorphness -= multiplier * 4;
4579 } else if (righthandmorphness < targetrighthandmorphness) {
4580 righthandmorphness += multiplier * 4;
4583 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4584 lefthandmorphness = targetlefthandmorphness;
4585 lefthandmorphstart = lefthandmorphend;
4586 } else if (lefthandmorphness > targetlefthandmorphness) {
4587 lefthandmorphness -= multiplier * 4;
4588 } else if (lefthandmorphness < targetlefthandmorphness) {
4589 lefthandmorphness += multiplier * 4;
4592 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4593 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4594 tailmorphness = targettailmorphness;
4595 tailmorphstart = tailmorphend;
4596 } else if (tailmorphness > targettailmorphness) {
4597 tailmorphness -= multiplier * 10;
4598 } else if (tailmorphness < targettailmorphness) {
4599 tailmorphness += multiplier * 10;
4603 if (creature == wolftype) {
4604 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4605 tailmorphness = targettailmorphness;
4606 tailmorphstart = tailmorphend;
4607 } else if (tailmorphness > targettailmorphness) {
4608 tailmorphness -= multiplier * 2;
4609 } else if (tailmorphness < targettailmorphness) {
4610 tailmorphness += multiplier * 2;
4614 if (headmorphend == 3 || headmorphstart == 3) {
4615 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4616 headmorphness = targetheadmorphness;
4617 headmorphstart = headmorphend;
4618 } else if (headmorphness > targetheadmorphness) {
4619 headmorphness -= multiplier * 7;
4620 } else if (headmorphness < targetheadmorphness) {
4621 headmorphness += multiplier * 7;
4623 } else if (headmorphend == 5 || headmorphstart == 5) {
4624 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4625 headmorphness = targetheadmorphness;
4626 headmorphstart = headmorphend;
4627 } else if (headmorphness > targetheadmorphness) {
4628 headmorphness -= multiplier * 10;
4629 } else if (headmorphness < targetheadmorphness) {
4630 headmorphness += multiplier * 10;
4633 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4634 headmorphness = targetheadmorphness;
4635 headmorphstart = headmorphend;
4636 } else if (headmorphness > targetheadmorphness) {
4637 headmorphness -= multiplier * 4;
4638 } else if (headmorphness < targetheadmorphness) {
4639 headmorphness += multiplier * 4;
4643 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4644 chestmorphness = targetchestmorphness;
4645 chestmorphstart = chestmorphend;
4646 } else if (chestmorphness > targetchestmorphness) {
4647 chestmorphness -= multiplier;
4648 } else if (chestmorphness < targetchestmorphness) {
4649 chestmorphness += multiplier;
4652 if (dead != 2 && howactive <= typesleeping) {
4653 if (chestmorphstart == 0 && chestmorphend == 0) {
4655 targetchestmorphness = 1;
4658 if (chestmorphstart != 0 && chestmorphend != 0) {
4660 targetchestmorphness = 1;
4662 if (environment == snowyenvironment) {
4665 if (skeleton.free) {
4666 footvel = skeleton.specialforward[0] * -1;
4667 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4669 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4670 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4672 if (animTarget == sleepanim)
4673 footvel = DoRotation(footvel, 0, 90, 0);
4674 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4678 if (!dead && howactive < typesleeping) {
4679 blinkdelay -= multiplier * 2;
4680 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4682 targetheadmorphness = 1;
4684 blinkdelay = (float)(abs(Random() % 40)) / 5;
4686 if (headmorphstart == 3 && headmorphend == 3) {
4688 targetheadmorphness = 1;
4693 twitchdelay -= multiplier * 1.5;
4694 if (animTarget != hurtidleanim) {
4695 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4697 targetheadmorphness = 1;
4699 twitchdelay = (float)(abs(Random() % 40)) / 5;
4701 if (headmorphstart == 5 && headmorphend == 5) {
4703 targetheadmorphness = 1;
4707 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4708 twitchdelay3 -= multiplier * 1;
4709 if (Random() % 2 == 0) {
4710 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4711 righthandmorphness = 0;
4712 targetrighthandmorphness = 1;
4713 righthandmorphend = 1;
4714 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4716 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4717 righthandmorphness = 0;
4718 targetrighthandmorphness = 1;
4719 righthandmorphend = 0;
4722 if (Random() % 2 == 0) {
4723 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4724 lefthandmorphness = 0;
4725 targetlefthandmorphness = 1;
4726 lefthandmorphend = 1;
4727 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4729 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4730 lefthandmorphness = 0;
4731 targetlefthandmorphness = 1;
4732 lefthandmorphend = 0;
4738 if (creature == rabbittype) {
4739 if (howactive < typesleeping)
4740 twitchdelay2 -= multiplier * 1.5;
4742 twitchdelay2 -= multiplier * 0.5;
4743 if (howactive <= typesleeping) {
4744 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4746 targettailmorphness = 1;
4748 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4750 if (tailmorphstart == 1 && tailmorphend == 1) {
4752 targettailmorphness = 1;
4755 if (tailmorphstart == 2 && tailmorphend == 2) {
4757 targettailmorphness = 1;
4764 if (creature == wolftype) {
4765 twitchdelay2 -= multiplier * 1.5;
4766 if (tailmorphend != 0)
4767 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4769 targettailmorphness = 1;
4773 if (tailmorphend != 5)
4774 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4776 targettailmorphness = 1;
4780 if (twitchdelay2 <= 0) {
4781 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4783 targettailmorphness = 1;
4786 if (tailmorphstart == 1 && tailmorphend == 1) {
4788 targettailmorphness = 1;
4791 if (tailmorphstart == 2 && tailmorphend == 2) {
4793 targettailmorphness = 1;
4796 if (tailmorphstart == 3 && tailmorphend == 3) {
4798 targettailmorphness = 1;
4801 if (tailmorphstart == 4 && tailmorphend == 4) {
4803 targettailmorphness = 1;
4810 unconscioustime = 0;
4812 if (dead == 1 || howactive == typesleeping) {
4813 unconscioustime += multiplier;
4814 //If unconscious, close eyes and mouth
4815 if (righthandmorphend != 0)
4816 righthandmorphness = 0;
4817 righthandmorphend = 0;
4818 targetrighthandmorphness = 1;
4820 if (lefthandmorphend != 0)
4821 lefthandmorphness = 0;
4822 lefthandmorphend = 0;
4823 targetlefthandmorphness = 1;
4825 if (headmorphend != 3 && headmorphend != 5)
4828 targetheadmorphness = 1;
4832 if (howactive > typesleeping) {
4835 if (bloodtoggle && !bled) {
4836 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4838 if (bloodtoggle && !bled)
4839 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4840 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4841 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4845 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4850 if (dead == 2 || howactive > typesleeping) {
4851 //If dead, open mouth and hands
4852 if (righthandmorphend != 0)
4853 righthandmorphness = 0;
4854 righthandmorphend = 0;
4855 targetrighthandmorphness = 1;
4857 if (lefthandmorphend != 0)
4858 lefthandmorphness = 0;
4859 lefthandmorphend = 0;
4860 targetlefthandmorphness = 1;
4862 if (headmorphend != 2)
4865 targetheadmorphness = 1;
4868 if (stunned > 0 && !dead && headmorphend != 2) {
4869 if (headmorphend != 4)
4872 targetheadmorphness = 1;
4875 if (damage > damagetolerance && !dead) {
4878 unconscioustime = 0;
4880 if (creature == wolftype) {
4881 award_bonus(0, Wolfbonus);
4886 if (weaponactive != -1) {
4887 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4888 weapons[weaponids[0]].velocity.x += .01;
4891 weaponids[0] = weaponids[num_weapons];
4892 if (weaponstuck == num_weapons)
4896 for (unsigned i = 0; i < Person::players.size(); i++) {
4897 Person::players[i]->wentforweapon = 0;
4903 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4912 damage -= multiplier * 13;
4914 permanentdamage -= multiplier * 4;
4915 if (isIdle() || isCrouch()) {
4917 permanentdamage -= multiplier * 4;
4921 if (permanentdamage < 0)
4922 permanentdamage = 0;
4923 if (superpermanentdamage < 0)
4924 superpermanentdamage = 0;
4925 if (permanentdamage < superpermanentdamage) {
4926 permanentdamage = superpermanentdamage;
4928 if (damage < permanentdamage) {
4929 damage = permanentdamage;
4931 if (dead == 1 && damage < damagetolerance) {
4935 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4936 skeleton.joints[i].velocity = 0;
4939 if (permanentdamage > damagetolerance && dead != 2) {
4942 if (weaponactive != -1) {
4943 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4944 weapons[weaponids[0]].velocity.x += .01;
4947 weaponids[0] = weaponids[num_weapons];
4948 if (weaponstuck == num_weapons)
4952 for (unsigned i = 0; i < Person::players.size(); i++) {
4953 Person::players[i]->wentforweapon = 0;
4959 if (!dead && creature == wolftype) {
4960 award_bonus(0, Wolfbonus);
4963 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4964 award_bonus(id, touchofdeath);
4965 if (id != 0 && unconscioustime > .1) {
4973 emit_sound_at(breaksound, coords);
4976 if (skeleton.free == 1) {
4978 pause_sound(whooshsound);
4981 //If knocked over, open hands and close mouth
4982 if (righthandmorphend != 0)
4983 righthandmorphness = 0;
4984 righthandmorphend = 0;
4985 targetrighthandmorphness = 1;
4987 if (lefthandmorphend != 0)
4988 lefthandmorphness = 0;
4989 lefthandmorphend = 0;
4990 targetlefthandmorphness = 1;
4992 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4993 if (headmorphend != 0)
4996 targetheadmorphness = 1;
5000 skeleton.DoGravity(&scale);
5002 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5003 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5004 award_bonus(id, deepimpact);
5005 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5009 if (!skeleton.joints.empty()) {
5010 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5011 average += skeleton.joints[j].position;
5013 average /= skeleton.joints.size();
5014 coords += average * scale;
5015 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5016 skeleton.joints[j].position -= average;
5018 average /= multiplier;
5022 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5023 velocity += skeleton.joints[i].velocity * scale;
5025 velocity /= skeleton.joints.size();
5027 if (!isnormal(velocity.x) && velocity.x) {
5031 if (findLength(&average) < 10 && dead && skeleton.free) {
5032 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5033 if (skeleton.longdead > 2000) {
5034 if (skeleton.longdead > 6000) {
5036 pause_sound(whooshsound);
5041 if (dead == 2 && bloodloss < damagetolerance) {
5043 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5045 if (bloodtoggle && !bled) {
5046 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5048 if (bloodtoggle && !bled)
5049 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5050 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5051 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5052 float size = .2 * 1.2;
5055 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5059 if (dead == 2 && bloodloss >= damagetolerance) {
5061 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5064 if (bloodtoggle && !bled) {
5065 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5067 if (bloodtoggle && !bled)
5068 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5069 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5070 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5074 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5081 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5082 bool canrecover = 1;
5083 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5084 startpoint = coords;
5087 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5089 if (velocity.y < -30)
5091 for (i = 0; i < Object::objects.size(); i++) {
5092 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5093 colviewer = startpoint;
5094 coltarget = endpoint;
5095 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5104 terrainnormal = jointPos(groin) - jointPos(abdomen);
5105 if (joint(groin).locked && joint(abdomen).locked) {
5106 terrainnormal = jointPos(groin) - jointPos(abdomen);
5107 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5109 if (joint(abdomen).locked && joint(neck).locked) {
5110 terrainnormal = jointPos(abdomen) - jointPos(neck);
5111 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5113 if (joint(groin).locked && joint(neck).locked) {
5114 terrainnormal = jointPos(groin) - jointPos(neck);
5115 middle = (jointPos(groin) + jointPos(neck)) / 2;
5117 Normalise(&terrainnormal);
5119 targetyaw = -asin(0 - terrainnormal.x);
5120 targetyaw *= 360 / 6.28;
5121 if (terrainnormal.z < 0)
5122 targetyaw = 180 - targetyaw;
5126 animTarget = flipanim;
5127 crouchtogglekeydown = 1;
5132 animCurrent = tempanim;
5136 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5137 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5138 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5143 if (findLength(&average) < 10 && !dead && skeleton.free) {
5144 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5145 if (skeleton.longdead > (damage + 500) * 1.5) {
5147 pause_sound(whooshsound);
5153 terrainnormal = jointPos(groin) - jointPos(abdomen);
5154 if (joint(groin).locked && joint(abdomen).locked) {
5155 terrainnormal = jointPos(groin) - jointPos(abdomen);
5156 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5158 if (joint(abdomen).locked && joint(neck).locked) {
5159 terrainnormal = jointPos(abdomen) - jointPos(neck);
5160 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5162 if (joint(groin).locked && joint(neck).locked) {
5163 terrainnormal = jointPos(groin) - jointPos(neck);
5164 middle = (jointPos(groin) + jointPos(neck)) / 2;
5166 Normalise(&terrainnormal);
5168 targetyaw = -asin(0 - terrainnormal.x);
5169 targetyaw *= 360 / 6.28;
5170 if (terrainnormal.z < 0)
5171 targetyaw = 180 - targetyaw;
5174 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5177 if (skeleton.forward.y < 0) {
5178 animTarget = getupfrombackanim;
5182 if (skeleton.forward.y > -.3) {
5183 animTarget = getupfromfrontanim;
5191 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5192 animTarget = rollanim;
5193 targetyaw = lookyaw;
5210 if ( !leftkeydown && !rightkeydown)
5217 if (abs(targettilt2) > 50)
5219 animCurrent = tempanim;
5222 tilt2 = targettilt2;
5224 if (middle.y > 0 && animTarget != rollanim)
5225 targetoffset.y = middle.y + 1;
5227 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5228 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5229 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5236 if (num_weapons > 0)
5237 if (weapons[0].getType() == staff)
5239 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5240 if (velocity.y > -30) {
5242 tempvelocity = velocity;
5243 Normalise(&tempvelocity);
5244 targetyaw = -asin(0 - tempvelocity.x);
5245 targetyaw *= 360 / 6.28;
5247 targetyaw = 180 - targetyaw;
5251 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5252 animTarget = rollanim;
5255 animTarget = backhandspringanim;
5261 emit_sound_at(movewhooshsound, coords, 128.);
5263 animCurrent = animTarget;
5264 frameCurrent = frameTarget - 1;
5276 if (skeleton.freefall == 0)
5281 if (aitype != passivetype || skeleton.free == 1)
5282 if (findLengthfast(&velocity) > .1)
5283 for (i = 0; i < Object::objects.size(); i++) {
5284 if (Object::objects[i]->type == firetype)
5285 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) {
5287 if (!Object::objects[i]->onfire) {
5288 emit_sound_at(firestartsound, Object::objects[i]->position);
5290 Object::objects[i]->onfire = 1;
5293 if (Object::objects[i]->onfire) {
5298 if (Object::objects[i]->type == bushtype)
5299 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) {
5301 if (!Object::objects[i]->onfire) {
5302 emit_sound_at(firestartsound, Object::objects[i]->position);
5304 Object::objects[i]->onfire = 1;
5308 if (Object::objects[i]->onfire) {
5312 if (Object::objects[i]->messedwith <= 0) {
5316 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5319 addEnvSound(coords, 4 * findLength(&velocity));
5323 if (environment == grassyenvironment)
5324 howmany = findLength(&velocity) * 4;
5325 if (environment == snowyenvironment)
5326 howmany = findLength(&velocity) * 2;
5328 if (environment != desertenvironment)
5329 for (int j = 0; j < howmany; j++) {
5330 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5331 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5332 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5335 pos.x += float(abs(Random() % 100) - 50) / 200;
5336 pos.y += float(abs(Random() % 100) - 50) / 200;
5337 pos.z += float(abs(Random() % 100) - 50) / 200;
5338 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);
5339 Sprite::setLastSpriteSpecial(1);
5341 howmany = findLength(&velocity) * 4;
5343 if (environment == snowyenvironment)
5344 for (int j = 0; j < howmany; j++) {
5345 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5346 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5347 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5350 pos.x += float(abs(Random() % 100) - 50) / 200;
5351 pos.y += float(abs(Random() % 100) - 50) / 200;
5352 pos.z += float(abs(Random() % 100) - 50) / 200;
5353 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5354 Sprite::setLastSpriteSpecial(2);
5357 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5358 Object::objects[i]->roty += velocity.z * multiplier * 6;
5359 Object::objects[i]->messedwith = .5;
5362 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5363 if (Object::objects[i]->pitch == 0)
5366 tempcoord = coords - Object::objects[i]->position;
5367 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5368 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5369 tempcoord += Object::objects[i]->position;
5371 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) {
5372 if (Object::objects[i]->messedwith <= 0) {
5376 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5379 addEnvSound(coords, 4 * findLength(&velocity));
5383 if (environment == grassyenvironment)
5384 howmany = findLength(&velocity) * 4;
5385 if (environment == snowyenvironment)
5386 howmany = findLength(&velocity) * 2;
5388 if (environment != desertenvironment)
5389 for (int j = 0; j < howmany; j++) {
5390 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5391 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5392 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5394 pos += velocity * .1;
5396 pos.x += float(abs(Random() % 100) - 50) / 150;
5397 pos.y += float(abs(Random() % 100) - 50) / 150;
5398 pos.z += float(abs(Random() % 100) - 50) / 150;
5399 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);
5400 Sprite::setLastSpriteSpecial(1);
5402 howmany = findLength(&velocity) * 4;
5404 if (environment == snowyenvironment)
5405 for (int j = 0; j < howmany; j++) {
5406 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5407 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5408 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5410 pos += velocity * .1;
5412 pos.x += float(abs(Random() % 100) - 50) / 150;
5413 pos.y += float(abs(Random() % 100) - 50) / 150;
5414 pos.z += float(abs(Random() % 100) - 50) / 150;
5415 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5416 Sprite::setLastSpriteSpecial(2);
5419 Object::objects[i]->messedwith = .5;
5424 if (!skeleton.free) {
5427 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5430 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5432 if (Tutorial::active && id != 0)
5434 if (play && aitype != playercontrolled) {
5435 int whichsound = -1;
5436 i = abs(Random() % 4);
5437 if (speechdelay <= 0) {
5438 if (creature == rabbittype) {
5440 whichsound = rabbitchitter;
5442 whichsound = rabbitchitter2;
5444 if (creature == wolftype) {
5446 whichsound = growlsound;
5448 whichsound = growl2sound;
5453 if (whichsound != -1) {
5454 emit_sound_at(whichsound, coords);
5458 if (animTarget == staggerbackhighanim)
5460 if (animTarget == staggerbackhardanim)
5462 staggerdelay -= multiplier;
5463 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5465 if (velocity.y < -30 && animTarget == jumpdownanim)
5467 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5468 animTarget = getIdle();
5472 weaponmissdelay -= multiplier;
5473 highreversaldelay -= multiplier;
5474 lowreversaldelay -= multiplier;
5475 lastcollide -= multiplier;
5476 skiddelay -= multiplier;
5477 if (!isnormal(velocity.x) && velocity.x) {
5480 if (!isnormal(targettilt) && targettilt) {
5483 if (!isnormal(targettilt2) && targettilt2) {
5486 if (!isnormal(targetyaw) && targetyaw) {
5490 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5491 //open hands and close mouth
5492 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5493 righthandmorphness = 0;
5494 righthandmorphend = 0;
5495 targetrighthandmorphness = 1;
5498 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5499 lefthandmorphness = 0;
5500 lefthandmorphend = 0;
5501 targetlefthandmorphness = 1;
5504 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5507 targetheadmorphness = 1;
5511 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) {
5512 //open hands and mouth
5513 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5514 righthandmorphness = 0;
5515 righthandmorphend = 0;
5516 targetrighthandmorphness = 1;
5519 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5520 lefthandmorphness = 0;
5521 lefthandmorphend = 0;
5522 targetlefthandmorphness = 1;
5525 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5528 targetheadmorphness = 1;
5532 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5533 //close hands and mouth
5534 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5535 righthandmorphness = 0;
5536 righthandmorphend = 1;
5537 targetrighthandmorphness = 1;
5540 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5541 lefthandmorphness = 0;
5542 lefthandmorphend = 1;
5543 targetlefthandmorphness = 1;
5546 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5549 targetheadmorphness = 1;
5553 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) {
5554 //close hands and yell
5555 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5556 righthandmorphness = 0;
5557 righthandmorphend = 1;
5558 targetrighthandmorphness = 1;
5561 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5562 lefthandmorphness = 0;
5563 lefthandmorphend = 1;
5564 targetlefthandmorphness = 1;
5567 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5570 targetheadmorphness = 1;
5577 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5578 (victim->aitype != searchtype) && (aitype != passivetype) &&
5579 (aitype != searchtype) && (victim->id < Person::players.size())) {
5580 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5584 if (!dead && animTarget != hurtidleanim)
5585 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5586 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5589 targetheadmorphness = 1;
5593 if (weaponactive != -1) {
5594 if (weapons[weaponids[weaponactive]].getType() != staff) {
5595 righthandmorphstart = 1;
5596 righthandmorphend = 1;
5598 if (weapons[weaponids[weaponactive]].getType() == staff) {
5599 righthandmorphstart = 2;
5600 righthandmorphend = 2;
5602 targetrighthandmorphness = 1;
5605 terrainnormal = terrain.getNormal(coords.x, coords.z);
5607 if (Animation::animations[animTarget].attack != reversal) {
5608 if (!isnormal(coords.x))
5616 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5617 facing = flatfacing;
5618 ReflectVector(&facing, terrainnormal);
5621 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5623 targettilt2 = -facing.y * 20;
5628 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5630 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5631 flatvelocity = velocity;
5633 flatvelspeed = findLength(&flatvelocity);
5634 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5635 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5640 if (targettilt > 25)
5642 if (targettilt < -25)
5646 if (targettilt2 > 45)
5648 if (targettilt2 < -45)
5650 if (abs(tilt2 - targettilt2) < multiplier * 400)
5651 tilt2 = targettilt2;
5652 else if (tilt2 > targettilt2) {
5653 tilt2 -= multiplier * 400;
5654 } else if (tilt2 < targettilt2) {
5655 tilt2 += multiplier * 400;
5657 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5664 if (!isnormal(targettilt) && targettilt) {
5667 if (!isnormal(targettilt2) && targettilt2) {
5672 if (animTarget == rabbittackleanim) {
5673 velocity += facing * multiplier * speed * 700 * scale;
5674 velspeed = findLength(&velocity);
5675 if (velspeed > speed * 65 * scale) {
5676 velocity /= velspeed;
5677 velspeed = speed * 65 * scale;
5678 velocity *= velspeed;
5680 velocity.y += gravity * multiplier * 20;
5681 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5682 velspeed = findLength(&velocity);
5683 velocity = flatfacing * velspeed;
5685 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5686 if (isRun() || animTarget == rabbitkickanim) {
5687 velocity += facing * multiplier * speed * 700 * scale;
5688 velspeed = findLength(&velocity);
5689 if (velspeed > speed * 45 * scale) {
5690 velocity /= velspeed;
5691 velspeed = speed * 45 * scale;
5692 velocity *= velspeed;
5694 velocity.y += gravity * multiplier * 20;
5695 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5696 velspeed = findLength(&velocity);
5697 if (velspeed < speed * 30 * scale)
5698 velspeed = speed * 30 * scale;
5699 velocity = flatfacing * velspeed;
5701 } else if (isRun()) {
5702 velocity += facing * multiplier * speed * 700 * scale;
5703 velspeed = findLength(&velocity);
5704 if (creature == rabbittype) {
5705 if (velspeed > speed * 55 * scale) {
5706 velocity /= velspeed;
5707 velspeed = speed * 55 * scale;
5708 velocity *= velspeed;
5711 if (creature == wolftype) {
5712 if (velspeed > speed * 75 * scale) {
5713 velocity /= velspeed;
5714 velspeed = speed * 75 * scale;
5715 velocity *= velspeed;
5718 velocity.y += gravity * multiplier * 20;
5719 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5720 velspeed = findLength(&velocity);
5721 velocity = flatfacing * velspeed;
5724 if (animTarget == rollanim && targetFrame().label != 6) {
5725 velocity += facing * multiplier * speed * 700 * scale;
5726 velspeed = findLength(&velocity);
5727 if (velspeed > speed * 45 * scale) {
5728 velocity /= velspeed;
5729 velspeed = speed * 45 * scale;
5730 velocity *= velspeed;
5732 velocity.y += gravity * multiplier * 20;
5733 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5734 velspeed = findLength(&velocity);
5735 velocity = flatfacing * velspeed;
5738 if (animTarget == sneakanim || animTarget == walkanim) {
5739 velocity += facing * multiplier * speed * 700 * scale;
5740 velspeed = findLength(&velocity);
5741 if (velspeed > speed * 12 * scale) {
5742 velocity /= velspeed;
5743 velspeed = speed * 12 * scale;
5744 velocity *= velspeed;
5746 velocity.y += gravity * multiplier * 20;
5747 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5748 velspeed = findLength(&velocity);
5749 velocity = flatfacing * velspeed;
5752 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5753 velocity += facing * multiplier * speed * 700 * scale;
5754 velspeed = findLength(&velocity);
5755 if (velspeed > speed * 2 * scale) {
5756 velocity /= velspeed;
5757 velspeed = speed * 2 * scale;
5758 velocity *= velspeed;
5760 velocity.y += gravity * multiplier * 20;
5761 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5762 velspeed = findLength(&velocity);
5763 velocity = flatfacing * velspeed;
5767 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5768 velocity -= facing * multiplier * speed * 700 * scale;
5769 velspeed = findLength(&velocity);
5770 if (velspeed > speed * 2 * scale) {
5771 velocity /= velspeed;
5772 velspeed = speed * 2 * scale;
5773 velocity *= velspeed;
5775 velocity.y += gravity * multiplier * 20;
5776 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5777 velspeed = findLength(&velocity);
5778 velocity = flatfacing * velspeed * -1;
5781 if (animTarget == fightsidestep) {
5782 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5783 velspeed = findLength(&velocity);
5784 if (velspeed > speed * 12 * scale) {
5785 velocity /= velspeed;
5786 velspeed = speed * 12 * scale;
5787 velocity *= velspeed;
5789 velocity.y += gravity * multiplier * 20;
5790 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5791 velspeed = findLength(&velocity);
5792 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5795 if (animTarget == staggerbackhighanim) {
5796 coords -= facing * multiplier * speed * 16 * scale;
5799 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5800 coords -= facing * multiplier * speed * 20 * scale;
5804 if (animTarget == backhandspringanim) {
5805 //coords-=facing*multiplier*50*scale;
5806 velocity += facing * multiplier * speed * 700 * scale * -1;
5807 velspeed = findLength(&velocity);
5808 if (velspeed > speed * 50 * scale) {
5809 velocity /= velspeed;
5810 velspeed = speed * 50 * scale;
5811 velocity *= velspeed;
5813 velocity.y += gravity * multiplier * 20;
5814 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5815 velspeed = findLength(&velocity);
5816 velocity = flatfacing * velspeed * -1;
5818 if (animTarget == dodgebackanim) {
5819 //coords-=facing*multiplier*50*scale;
5820 velocity += facing * multiplier * speed * 700 * scale * -1;
5821 velspeed = findLength(&velocity);
5822 if (velspeed > speed * 60 * scale) {
5823 velocity /= velspeed;
5824 velspeed = speed * 60 * scale;
5825 velocity *= velspeed;
5827 velocity.y += gravity * multiplier * 20;
5828 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5829 velspeed = findLength(&velocity);
5830 velocity = flatfacing * velspeed * -1;
5833 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5834 velspeed = findLength(&velocity);
5838 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5839 velocity.y += gravity * multiplier;
5842 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5843 coords += velocity * multiplier;
5845 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5846 if (isFlip() && targetFrame().label == 7)
5849 if (animTarget == jumpupanim) {
5851 animTarget = getIdle();
5858 pause_sound(whooshsound);
5859 OPENAL_SetVolume(channels[whooshsound], 0);
5862 if (animTarget == jumpdownanim || isFlip()) {
5863 if (isFlip())jumppower = -4;
5864 animTarget = getLanding();
5865 emit_sound_at(landsound, coords, 128.);
5868 addEnvSound(coords);
5873 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5874 coords.y += gravity * multiplier * 2;
5875 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5876 coords.y = terrain.getHeight(coords.x, coords.z);
5881 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)) {
5882 velspeed = findLength(&velocity);
5884 if (velspeed < multiplier * 300 * scale) {
5887 velocity -= velocity / velspeed * multiplier * 300 * scale;
5888 if (velspeed > 5 && (isLanding() || isLandhard())) {
5889 skiddingdelay += multiplier;
5890 if (skiddelay <= 0) {
5891 FootLand(leftfoot, .5);
5892 FootLand(rightfoot, .5);
5900 velspeed = findLength(&velocity);
5902 if (velspeed < multiplier * 600 * scale) {
5905 velocity -= velocity / velspeed * multiplier * 600 * scale;
5907 if (velspeed > 5 && (isLanding() || isLandhard())) {
5908 skiddingdelay += multiplier;
5909 if (skiddelay <= 0) {
5910 FootLand(leftfoot, .5);
5911 FootLand(rightfoot, .5);
5918 if (skiddingdelay < 0)
5919 skiddingdelay += multiplier;
5920 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5922 if (!onterrain || environment == grassyenvironment) {
5923 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5925 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5929 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5930 terrainnormal = victim->coords - coords;
5931 Normalise(&terrainnormal);
5932 targetyaw = -asin(0 - terrainnormal.x);
5933 targetyaw *= 360 / 6.28;
5934 if (terrainnormal.z < 0)
5935 targetyaw = 180 - targetyaw;
5936 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5939 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5940 targetyaw = victim->targetyaw;
5942 if (animTarget == rabbittacklinganim) {
5943 coords = victim->coords;
5946 skeleton.oldfree = skeleton.free;
5950 midterrain.x = terrain.size * terrain.scale / 2;
5951 midterrain.z = terrain.size * terrain.scale / 2;
5952 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5954 tempposit = coords - midterrain;
5956 Normalise(&tempposit);
5957 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5958 coords.x = tempposit.x + midterrain.x;
5959 coords.z = tempposit.z + midterrain.z;
5965 * inverse kinematics helper function
5967 void IKHelper(Person *p, float interp)
5969 XYZ point, change, change2;
5970 float heightleft, heightright;
5972 // TODO: implement localToWorld and worldToLocal
5973 // but keep in mind it won't be the same math if player is ragdolled or something
5974 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5975 // then comb through code for places where to use it
5977 // point = localToWorld(jointPos(leftfoot))
5978 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5979 // adjust height of foot
5980 heightleft = terrain.getHeight(point.x, point.z) + .04;
5981 point.y = heightleft;
5982 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5983 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5984 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5985 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5986 // move ankle along with foot
5987 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5988 // average knee pos between old and new pos
5989 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5991 // do same as above for right leg
5992 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5993 heightright = terrain.getHeight(point.x, point.z) + .04;
5994 point.y = heightright;
5995 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5996 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5997 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5998 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5999 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6001 // fix up skeleton now that we've moved body parts?
6002 p->skeleton.DoConstraints(&p->coords, &p->scale);
6009 int Person::DrawSkeleton()
6011 int oldplayerdetail;
6012 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6013 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6023 glAlphaFunc(GL_GREATER, 0.0001);
6025 float terrainheight;
6029 if (!isnormal(tilt))
6031 if (!isnormal(tilt2))
6033 oldplayerdetail = playerdetail;
6035 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6038 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6041 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6046 if (playerdetail != oldplayerdetail) {
6048 normalsupdatedelay = 0;
6050 static float updatedelaychange;
6051 static float morphness;
6052 static float framemult;
6054 skeleton.FindForwards();
6055 if (howactive == typesittingwall) {
6056 skeleton.specialforward[1] = 0;
6057 skeleton.specialforward[1].z = 1;
6063 static int weaponattachmuscle;
6064 static int weaponrotatemuscle;
6065 static XYZ weaponpoint;
6066 static int start, endthing;
6067 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6068 if (!isSleeping() && !isSitting()) {
6069 // TODO: give these meaningful names
6070 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6071 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6072 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6073 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6075 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6077 if (creature == wolftype)
6081 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6082 IKHelper(this, target);
6083 if (creature == wolftype)
6084 IKHelper(this, target);
6087 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6088 IKHelper(this, 1 - target);
6089 if (creature == wolftype)
6090 IKHelper(this, 1 - target);
6094 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()))
6097 targetheadyaw = -targetyaw;
6098 targetheadpitch = 0;
6099 if (Animation::animations[animTarget].attack == 3)
6100 targetheadyaw += 180;
6102 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6103 skeleton.drawmodel.vertex[i] = 0;
6104 skeleton.drawmodel.vertex[i].y = 999;
6106 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6107 skeleton.drawmodellow.vertex[i] = 0;
6108 skeleton.drawmodellow.vertex[i].y = 999;
6110 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6111 skeleton.drawmodelclothes.vertex[i] = 0;
6112 skeleton.drawmodelclothes.vertex[i].y = 999;
6114 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6115 // convenience renames
6116 const int p1 = skeleton.muscles[i].parent1->label;
6117 const int p2 = skeleton.muscles[i].parent2->label;
6119 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6124 if (p1 == righthand || p2 == righthand) {
6125 morphness = righthandmorphness;
6126 start = righthandmorphstart;
6127 endthing = righthandmorphend;
6129 if (p1 == lefthand || p2 == lefthand) {
6130 morphness = lefthandmorphness;
6131 start = lefthandmorphstart;
6132 endthing = lefthandmorphend;
6134 if (p1 == head || p2 == head) {
6135 morphness = headmorphness;
6136 start = headmorphstart;
6137 endthing = headmorphend;
6139 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6140 morphness = chestmorphness;
6141 start = chestmorphstart;
6142 endthing = chestmorphend;
6144 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6145 morphness = tailmorphness;
6146 start = tailmorphstart;
6147 endthing = tailmorphend;
6150 skeleton.FindRotationMuscle(i, animTarget);
6151 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6152 glMatrixMode(GL_MODELVIEW);
6156 glRotatef(tilt2, 1, 0, 0);
6158 glRotatef(tilt, 0, 0, 1);
6161 glTranslatef(mid.x, mid.y, mid.z);
6163 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6164 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6166 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6167 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6169 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6170 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6172 if (playerdetail || skeleton.free == 3) {
6173 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6174 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6175 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6176 glMatrixMode(GL_MODELVIEW);
6178 if (p1 == abdomen || p2 == abdomen)
6179 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6180 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6181 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6182 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6183 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6184 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6185 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6186 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6187 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6188 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6189 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6190 if (p1 == head || p2 == head)
6191 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6192 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6193 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6194 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6195 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6196 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6197 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6201 if (!playerdetail || skeleton.free == 3) {
6202 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6203 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6204 glMatrixMode(GL_MODELVIEW);
6206 if (p1 == abdomen || p2 == abdomen)
6207 glTranslatef(v0.x * proportionbody.x,
6208 v0.y * proportionbody.y,
6209 v0.z * proportionbody.z);
6210 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6211 glTranslatef(v0.x * proportionarms.x,
6212 v0.y * proportionarms.y,
6213 v0.z * proportionarms.z);
6214 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6215 glTranslatef(v0.x * proportionlegs.x,
6216 v0.y * proportionlegs.y,
6217 v0.z * proportionlegs.z);
6218 if (p1 == head || p2 == head)
6219 glTranslatef(v0.x * proportionhead.x,
6220 v0.y * proportionhead.y,
6221 v0.z * proportionhead.z);
6223 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6224 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6225 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6226 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6232 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6233 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6235 glMatrixMode(GL_MODELVIEW);
6239 glRotatef(tilt2, 1, 0, 0);
6241 glRotatef(tilt, 0, 0, 1);
6242 glTranslatef(mid.x, mid.y, mid.z);
6243 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6244 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6246 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6247 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6249 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6250 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6252 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6253 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6254 glMatrixMode(GL_MODELVIEW);
6256 if (p1 == abdomen || p2 == abdomen)
6257 glTranslatef(v0.x * proportionbody.x,
6258 v0.y * proportionbody.y,
6259 v0.z * proportionbody.z);
6260 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6261 glTranslatef(v0.x * proportionarms.x,
6262 v0.y * proportionarms.y,
6263 v0.z * proportionarms.z);
6264 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6265 glTranslatef(v0.x * proportionlegs.x,
6266 v0.y * proportionlegs.y,
6267 v0.z * proportionlegs.z);
6268 if (p1 == head || p2 == head)
6269 glTranslatef(v0.x * proportionhead.x,
6270 v0.y * proportionhead.y,
6271 v0.z * proportionhead.z);
6272 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6273 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6274 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6275 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6280 updatedelay = 1 + (float)(Random() % 100) / 1000;
6282 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6283 normalsupdatedelay = 1;
6284 if (playerdetail || skeleton.free == 3)
6285 skeleton.drawmodel.CalculateNormals(0);
6286 if (!playerdetail || skeleton.free == 3)
6287 skeleton.drawmodellow.CalculateNormals(0);
6288 if (skeleton.clothes)
6289 skeleton.drawmodelclothes.CalculateNormals(0);
6291 if (playerdetail || skeleton.free == 3)
6292 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6293 if (!playerdetail || skeleton.free == 3)
6294 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6295 if (skeleton.clothes) {
6296 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6301 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6302 if (updatedelaychange > -realmultiplier * 30)
6303 updatedelaychange = -realmultiplier * 30;
6304 if (updatedelaychange > -framemult * 4)
6305 updatedelaychange = -framemult * 4;
6306 if (skeleton.free == 1)
6307 updatedelaychange *= 6;
6309 updatedelaychange *= 8;
6310 updatedelay += updatedelaychange;
6312 glMatrixMode(GL_MODELVIEW);
6314 glTranslatef(coords.x, coords.y - .02, coords.z);
6315 if (!skeleton.free) {
6316 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6317 glRotatef(yaw, 0, 1, 0);
6321 glColor4f(.4, 1, .4, 1);
6322 glDisable(GL_LIGHTING);
6323 glDisable(GL_TEXTURE_2D);
6326 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6327 XYZ &v0 = skeleton.drawmodel.vertex[i];
6328 glVertex3f(v0.x, v0.y, v0.z);
6334 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6335 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6336 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6337 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6338 glVertex3f(v0.x, v0.y, v0.z);
6339 glVertex3f(v1.x, v1.y, v1.z);
6340 glVertex3f(v1.x, v1.y, v1.z);
6341 glVertex3f(v2.x, v2.y, v2.z);
6342 glVertex3f(v2.x, v2.y, v2.z);
6343 glVertex3f(v0.x, v0.y, v0.z);
6349 terrainlight = terrain.getLighting(coords.x, coords.z);
6350 distance = distsq(&viewer, &coords);
6351 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6355 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6356 if (terrainheight < 1)
6358 if (terrainheight > 1.7)
6359 terrainheight = 1.7;
6361 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6362 glDisable(GL_BLEND);
6363 glAlphaFunc(GL_GREATER, 0.0001);
6364 glEnable(GL_TEXTURE_2D);
6366 glDisable(GL_TEXTURE_2D);
6367 glColor4f(.7, .35, 0, .5);
6369 glEnable(GL_LIGHTING);
6372 if (Tutorial::active && id != 0) {
6373 glColor4f(.7, .7, .7, 0.6);
6375 glEnable(GL_LIGHTING);
6377 if (canattack && cananger)
6378 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6379 glDisable(GL_TEXTURE_2D);
6380 glColor4f(1, 0, 0, 0.8);
6382 glMatrixMode(GL_TEXTURE);
6384 glTranslatef(0, -smoketex, 0);
6385 glTranslatef(-smoketex, 0, 0);
6389 if (Tutorial::active && (id != 0))
6390 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6392 skeleton.drawmodel.draw();
6395 if (!playerdetail) {
6396 if (Tutorial::active && (id != 0))
6397 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6399 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6402 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6403 if (Tutorial::active && id != 0) {
6405 glMatrixMode(GL_MODELVIEW);
6406 glEnable(GL_TEXTURE_2D);
6407 glColor4f(.7, .7, .7, 0.6);
6409 glEnable(GL_LIGHTING);
6411 if (canattack && cananger)
6412 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6413 glDisable(GL_TEXTURE_2D);
6414 glColor4f(1, 0, 0, 0.8);
6416 glMatrixMode(GL_TEXTURE);
6418 glTranslatef(0, -smoketex * .6, 0);
6419 glTranslatef(smoketex * .6, 0, 0);
6422 if (Tutorial::active && (id != 0))
6423 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6425 skeleton.drawmodel.draw();
6428 if (!playerdetail) {
6429 if (Tutorial::active && (id != 0))
6430 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6432 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6437 if (Tutorial::active && id != 0) {
6439 glMatrixMode(GL_MODELVIEW);
6440 glEnable(GL_TEXTURE_2D);
6442 if (skeleton.clothes) {
6446 skeleton.drawmodelclothes.draw();
6448 skeleton.drawmodelclothes.drawimmediate();
6454 if (num_weapons > 0) {
6455 for (k = 0; k < num_weapons; k++) {
6457 if (weaponactive == k) {
6458 if (weapons[i].getType() != staff) {
6459 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6460 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6461 weaponattachmuscle = j;
6464 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6465 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) {
6466 weaponrotatemuscle = j;
6469 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6470 if (creature == wolftype)
6471 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6473 if (weapons[i].getType() == staff) {
6474 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6475 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6476 weaponattachmuscle = j;
6479 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6480 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) {
6481 weaponrotatemuscle = j;
6484 //weaponpoint=jointPos(rightwrist);
6485 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6486 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6487 XYZ tempnormthing, vec1, vec2;
6488 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6489 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6490 CrossProduct(&vec1, &vec2, &tempnormthing);
6491 Normalise(&tempnormthing);
6492 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6493 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6496 if (weaponactive != k && weaponstuck != k) {
6497 if (weapons[i].getType() == knife)
6498 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6499 if (weapons[i].getType() == sword)
6500 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6501 if (weapons[i].getType() == staff)
6502 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6503 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6504 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) {
6505 weaponrotatemuscle = j;
6509 if (weaponstuck == k) {
6510 if (weaponstuckwhere == 0)
6511 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6513 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6514 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6515 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) {
6516 weaponrotatemuscle = j;
6520 if (skeleton.free) {
6521 weapons[i].position = weaponpoint * scale + coords;
6522 weapons[i].bigrotation = 0;
6523 weapons[i].bigtilt = 0;
6524 weapons[i].bigtilt2 = 0;
6526 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;
6527 weapons[i].bigrotation = yaw;
6528 weapons[i].bigtilt = tilt;
6529 weapons[i].bigtilt2 = tilt2;
6531 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6532 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6533 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6534 if (weaponactive == k) {
6535 if (weapons[i].getType() == knife) {
6536 weapons[i].smallrotation = 180;
6537 weapons[i].smallrotation2 = 0;
6538 if (isCrouch() || wasCrouch()) {
6539 weapons[i].smallrotation2 = 20;
6541 if (animTarget == hurtidleanim) {
6542 weapons[i].smallrotation2 = 50;
6544 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6545 XYZ temppoint1, temppoint2;
6548 temppoint1 = jointPos(righthand);
6549 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6550 distance = findDistance(&temppoint1, &temppoint2);
6551 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6552 weapons[i].rotation2 *= 360 / 6.28;
6555 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6556 weapons[i].rotation1 *= 360 / 6.28;
6557 weapons[i].rotation3 = 0;
6558 weapons[i].smallrotation = -90;
6559 weapons[i].smallrotation2 = 0;
6560 if (temppoint1.x > temppoint2.x)
6561 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6563 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6564 XYZ temppoint1, temppoint2;
6567 temppoint1 = jointPos(righthand);
6568 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6569 distance = findDistance(&temppoint1, &temppoint2);
6570 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6571 weapons[i].rotation2 *= 360 / 6.28;
6574 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6575 weapons[i].rotation1 *= 360 / 6.28;
6576 weapons[i].rotation3 = 0;
6577 weapons[i].smallrotation = 90;
6578 weapons[i].smallrotation2 = 0;
6579 if (temppoint1.x > temppoint2.x)
6580 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6582 if (animTarget == knifethrowanim) {
6583 weapons[i].smallrotation = 90;
6584 //weapons[i].smallrotation2=-90;
6585 weapons[i].smallrotation2 = 0;
6586 weapons[i].rotation1 = 0;
6587 weapons[i].rotation2 = 0;
6588 weapons[i].rotation3 = 0;
6590 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6591 weapons[i].smallrotation = -90;
6592 weapons[i].rotation1 = 0;
6593 weapons[i].rotation2 = 0;
6594 weapons[i].rotation3 = 0;
6597 if (weapons[i].getType() == sword) {
6598 weapons[i].smallrotation = 0;
6599 weapons[i].smallrotation2 = 0;
6600 if (animTarget == knifethrowanim) {
6601 weapons[i].smallrotation = -90;
6602 weapons[i].smallrotation2 = 0;
6603 weapons[i].rotation1 = 0;
6604 weapons[i].rotation2 = 0;
6605 weapons[i].rotation3 = 0;
6607 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)) {
6608 XYZ temppoint1, temppoint2;
6611 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6612 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6613 distance = findDistance(&temppoint1, &temppoint2);
6614 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6615 weapons[i].rotation2 *= 360 / 6.28;
6618 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6619 weapons[i].rotation1 *= 360 / 6.28;
6620 weapons[i].rotation3 = 0;
6621 weapons[i].smallrotation = 90;
6622 weapons[i].smallrotation2 = 0;
6623 if (temppoint1.x > temppoint2.x)
6624 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6627 if (weapons[i].getType() == staff) {
6628 weapons[i].smallrotation = 100;
6629 weapons[i].smallrotation2 = 0;
6630 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6631 XYZ temppoint1, temppoint2;
6634 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6635 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6636 distance = findDistance(&temppoint1, &temppoint2);
6637 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6638 weapons[i].rotation2 *= 360 / 6.28;
6641 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6642 weapons[i].rotation1 *= 360 / 6.28;
6643 weapons[i].rotation3 = 0;
6644 weapons[i].smallrotation = 90;
6645 weapons[i].smallrotation2 = 0;
6646 if (temppoint1.x > temppoint2.x)
6647 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6651 if (weaponactive != k && weaponstuck != k) {
6652 if (weapons[i].getType() == knife) {
6653 weapons[i].smallrotation = -70;
6654 weapons[i].smallrotation2 = 10;
6656 if (weapons[i].getType() == sword) {
6657 weapons[i].smallrotation = -100;
6658 weapons[i].smallrotation2 = -8;
6660 if (weapons[i].getType() == staff) {
6661 weapons[i].smallrotation = -100;
6662 weapons[i].smallrotation2 = -8;
6665 if (weaponstuck == k) {
6666 if (weaponstuckwhere == 0)
6667 weapons[i].smallrotation = 180;
6669 weapons[i].smallrotation = 0;
6670 weapons[i].smallrotation2 = 10;
6679 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6681 if (animCurrent != animTarget)
6683 if (skeleton.free == 2)
6692 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6695 static float distance;
6696 static float olddistance;
6697 static int intersecting;
6698 static int firstintersecting;
6701 static XYZ start, end;
6702 static float slopethreshold = -.4;
6704 firstintersecting = -1;
6708 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6711 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6712 for (i = 0; i < 4; i++) {
6713 for (j = 0; j < model->TriangleNum; j++) {
6714 if (model->facenormals[j].y <= slopethreshold) {
6716 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)));
6717 if (distance < radius) {
6718 point = *p1 - model->facenormals[j] * distance;
6719 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]]))
6722 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6723 &model->vertex[model->Triangles[j].vertex[1]],
6726 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6727 &model->vertex[model->Triangles[j].vertex[2]],
6730 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6731 &model->vertex[model->Triangles[j].vertex[2]],
6734 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6738 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)) {
6739 p1->y = point.y + radius;
6740 if ((animTarget == jumpdownanim || isFlip())) {
6741 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6744 if (animTarget == jumpupanim) {
6746 animTarget = getIdle();
6753 pause_sound(whooshsound);
6754 OPENAL_SetVolume(channels[whooshsound], 0);
6757 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6760 animTarget = getLanding();
6761 emit_sound_at(landsound, coords, 128.);
6764 addEnvSound(coords);
6771 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6772 olddistance = distance;
6773 firstintersecting = j;
6778 for (j = 0; j < model->TriangleNum; j++) {
6779 if (model->facenormals[j].y > slopethreshold) {
6782 start.y -= radius / 4;
6783 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6784 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6785 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6786 distance = abs((model->facenormals[j].x * start.x)
6787 + (model->facenormals[j].y * start.y)
6788 + (model->facenormals[j].z * start.z)
6789 - ((model->facenormals[j].x * v0.x)
6790 + (model->facenormals[j].y * v0.y)
6791 + (model->facenormals[j].z * v0.z)));
6792 if (distance < radius * .5) {
6793 point = start - model->facenormals[j] * distance;
6794 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6797 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6799 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6801 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6803 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6804 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6806 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6807 if (findLengthfast(&start) < findLengthfast(&velocity))
6810 *p1 += model->facenormals[j] * (distance - radius * .5);
6813 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6814 olddistance = distance;
6815 firstintersecting = j;
6822 *p = DoRotation(*p, 0, *rotate, 0);
6825 *p1 = DoRotation(*p1, 0, *rotate, 0);
6827 return firstintersecting;
6830 int findPathDist(int start, int end)
6832 int smallestcount, count, connected;
6833 int last, last2, last3, last4;
6836 smallestcount = 1000;
6837 for (int i = 0; i < 50; i++) {
6843 while (last != end && count < 30) {
6845 for (int j = 0; j < Game::numpathpoints; j++) {
6846 if (j != last && j != last2 && j != last3 && j != last4) {
6848 if (Game::numpathpointconnect[j])
6849 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6850 if (Game::pathpointconnect[j][k] == last)connected = 1;
6853 if (Game::numpathpointconnect[last])
6854 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6855 if (Game::pathpointconnect[last][k] == j)connected = 1;
6858 if (closest == -1 || Random() % 2 == 0) {
6869 if (count < smallestcount)
6870 smallestcount = count;
6872 return smallestcount;
6875 void Person::takeWeapon(int weaponId)
6878 weapons[weaponId].owner = id;
6879 if (num_weapons > 0) {
6880 weaponids[num_weapons] = weaponids[0];
6883 weaponids[0] = weaponId;
6886 void Person::addClothes()
6888 if (numclothes > 0) {
6889 for (int i = 0; i < numclothes; i++) {
6896 bool Person::addClothes(const int& clothesId)
6899 const std::string fileName = clothes[clothesId];
6901 GLubyte* array = &skeleton.skinText[0];
6905 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6910 float tintr = clothestintr[clothesId];
6911 float tintg = clothestintg[clothesId];
6912 float tintb = clothestintb[clothesId];
6914 if (tintr > 1) tintr = 1;
6915 if (tintg > 1) tintg = 1;
6916 if (tintb > 1) tintb = 1;
6918 if (tintr < 0) tintr = 0;
6919 if (tintg < 0) tintg = 0;
6920 if (tintb < 0) tintb = 0;
6922 int bytesPerPixel = texture.bpp / 8;
6926 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6927 if (bytesPerPixel == 3)
6929 else if ((i + 1) % 4 == 0)
6930 alphanum = texture.data[i];
6931 if ((i + 1) % 4 || bytesPerPixel == 3) {
6933 texture.data[i] *= tintr;
6935 texture.data[i] *= tintg;
6937 texture.data[i] *= tintb;
6938 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6948 extern float sq(float n);
6949 extern float roughDirectionTo(XYZ start, XYZ end);
6950 extern float pitchTo(XYZ start, XYZ end);
6954 if (aitype != playercontrolled && !Dialog::inDialog()) {
6956 //disable movement in editor
6957 if (Game::editorenabled)
6961 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6962 Person::players[0]->coords.y > coords.y + 2 &&
6963 !Person::players[0]->onterrain)
6967 if (aitype == pathfindtype) {
6968 if (finalpathfindpoint == -1) {
6969 float closestdistance;
6974 closestdistance = -1;
6975 for (int j = 0; j < Game::numpathpoints; j++) {
6976 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
6977 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
6979 finaltarget = Game::pathpoint[j];
6982 finalpathfindpoint = closest;
6983 for (int j = 0; j < Game::numpathpoints; j++) {
6984 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6985 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
6986 if (sq(tempdist) < closestdistance)
6987 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
6988 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
6989 closestdistance = sq(tempdist);
6991 finaltarget = colpoint;
6995 finalpathfindpoint = closest;
6998 if (targetpathfindpoint == -1) {
6999 float closestdistance;
7004 closestdistance = -1;
7005 if (lastpathfindpoint == -1) {
7006 for (int j = 0; j < Game::numpathpoints; j++) {
7007 if (j != lastpathfindpoint)
7008 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7009 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7013 targetpathfindpoint = closest;
7014 for (int j = 0; j < Game::numpathpoints; j++)
7015 if (j != lastpathfindpoint)
7016 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7017 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7018 if (sq(tempdist) < closestdistance) {
7019 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7020 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7021 closestdistance = sq(tempdist);
7026 targetpathfindpoint = closest;
7028 for (int j = 0; j < Game::numpathpoints; j++)
7029 if (j != lastpathfindpoint &&
7030 j != lastpathfindpoint2 &&
7031 j != lastpathfindpoint3 &&
7032 j != lastpathfindpoint4) {
7034 if (Game::numpathpointconnect[j])
7035 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7036 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7039 if (Game::numpathpointconnect[lastpathfindpoint])
7040 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7041 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7044 tempdist = findPathDist(j, finalpathfindpoint);
7045 if (closest == -1 || tempdist < closestdistance) {
7046 closestdistance = tempdist;
7051 targetpathfindpoint = closest;
7054 losupdatedelay -= multiplier;
7056 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7057 lookyaw = targetyaw;
7059 //reached target point
7060 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7061 lastpathfindpoint4 = lastpathfindpoint3;
7062 lastpathfindpoint3 = lastpathfindpoint2;
7063 lastpathfindpoint2 = lastpathfindpoint;
7064 lastpathfindpoint = targetpathfindpoint;
7065 if (lastpathfindpoint2 == -1)
7066 lastpathfindpoint2 = lastpathfindpoint;
7067 if (lastpathfindpoint3 == -1)
7068 lastpathfindpoint3 = lastpathfindpoint2;
7069 if (lastpathfindpoint4 == -1)
7070 lastpathfindpoint4 = lastpathfindpoint3;
7071 targetpathfindpoint = -1;
7073 if ( distsqflat(&coords, &finalfinaltarget) <
7074 distsqflat(&coords, &finaltarget) ||
7075 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7076 lastpathfindpoint == finalpathfindpoint) {
7077 aitype = passivetype;
7088 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7089 targetyaw += 90 * (whichdirection * 2 - 1);
7091 if (collided < 1 || animTarget != jumpupanim)
7093 if ((collided > .8 && jumppower >= 5))
7096 if ((!Tutorial::active || cananger) &&
7098 !Person::players[0]->dead &&
7099 distsq(&coords, &Person::players[0]->coords) < 400 &&
7101 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7102 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7103 !Game::editorenabled &&
7104 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7105 aitype = attacktypecutoff;
7106 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7107 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7108 !Game::editorenabled)
7109 aitype = attacktypecutoff;
7111 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7112 losupdatedelay = .2;
7113 for (unsigned j = 0; j < Person::players.size(); j++)
7114 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7115 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7116 if (distsq(&coords, &Person::players[j]->coords) < 400)
7117 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7118 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7119 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7120 DoRotation(jointPos(head), 0, yaw, 0)
7122 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7123 *Person::players[j]->scale + Person::players[j]->coords) ||
7124 (Person::players[j]->animTarget == hanganim &&
7125 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7126 aitype = searchtype;
7128 lastseen = Person::players[j]->coords;
7133 if (aitype == attacktypecutoff && Game::musictype != 2)
7134 if (creature != wolftype) {
7140 if (aitype != passivetype && Game::leveltime > .5)
7141 howactive = typeactive;
7143 if (aitype == passivetype) {
7144 aiupdatedelay -= multiplier;
7145 losupdatedelay -= multiplier;
7146 lastseentime += multiplier;
7147 pausetime -= multiplier;
7148 if (lastseentime > 1)
7151 if (aiupdatedelay < 0) {
7152 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7153 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7154 lookyaw = targetyaw;
7155 aiupdatedelay = .05;
7157 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7158 if (waypointtype[waypoint] == wppause)
7161 if (waypoint > numwaypoints - 1)
7167 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7178 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7179 if (!avoidsomething)
7180 targetyaw += 90 * (whichdirection * 2 - 1);
7182 XYZ leftpos, rightpos;
7183 float leftdist, rightdist;
7184 leftpos = coords + DoRotation(facing, 0, 90, 0);
7185 rightpos = coords - DoRotation(facing, 0, 90, 0);
7186 leftdist = distsq(&leftpos, &avoidwhere);
7187 rightdist = distsq(&rightpos, &avoidwhere);
7188 if (leftdist < rightdist)
7195 if (collided < 1 || animTarget != jumpupanim)
7197 if ((collided > .8 && jumppower >= 5))
7202 if (!Game::editorenabled) {
7203 if (howactive <= typesleeping)
7204 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7205 for (int j = 0; j < numenvsounds; j++) {
7206 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7207 if (vol > 0 && distsq(&coords, &envsound[j]) <
7208 2 * (vol + vol * (creature == rabbittype) * 3))
7209 aitype = attacktypecutoff;
7212 if (aitype != passivetype) {
7213 if (howactive == typesleeping)
7214 setAnimation(getupfromfrontanim);
7215 howactive = typeactive;
7219 if (howactive < typesleeping &&
7220 ((!Tutorial::active || cananger) && hostile) &&
7221 !Person::players[0]->dead &&
7222 distsq(&coords, &Person::players[0]->coords) < 400 &&
7224 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7225 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7226 aitype = attacktypecutoff;
7227 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7228 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7229 aitype = attacktypecutoff;
7232 if (creature == wolftype) {
7234 for (unsigned j = 0; j < Person::players.size(); j++) {
7235 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7236 float smelldistance = 50;
7237 if (j == 0 && Person::players[j]->num_weapons > 0) {
7238 if (weapons[Person::players[j]->weaponids[0]].bloody)
7239 smelldistance = 100;
7240 if (Person::players[j]->num_weapons == 2)
7241 if (weapons[Person::players[j]->weaponids[1]].bloody)
7242 smelldistance = 100;
7245 smelldistance = 100;
7246 windsmell = windvector;
7247 Normalise(&windsmell);
7248 windsmell = windsmell * 2 + Person::players[j]->coords;
7249 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7250 aitype = attacktypecutoff;
7255 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7256 losupdatedelay = .2;
7257 for (unsigned j = 0; j < Person::players.size(); j++) {
7258 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7259 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7260 if (distsq(&coords, &Person::players[j]->coords) < 400)
7261 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7262 if ((-1 == Object::checkcollide(
7263 DoRotation(jointPos(head), 0, yaw, 0)*
7265 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7266 Person::players[j]->scale + Person::players[j]->coords) &&
7267 !Person::players[j]->isWallJump()) ||
7268 (Person::players[j]->animTarget == hanganim &&
7269 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7271 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7276 if (lastseentime <= 0) {
7277 aitype = searchtype;
7279 lastseen = Person::players[j]->coords;
7287 if (aitype == attacktypecutoff && Game::musictype != 2) {
7288 if (creature != wolftype) {
7292 if (creature == wolftype) {
7302 if (aitype == searchtype) {
7303 aiupdatedelay -= multiplier;
7304 losupdatedelay -= multiplier;
7306 lastseentime -= multiplier;
7307 lastchecktime -= multiplier;
7309 if (isRun() && !onground) {
7310 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7311 XYZ test2 = coords + facing;
7313 XYZ test = coords + facing;
7315 j = Object::checkcollide(test2, test, laststanding);
7317 j = Object::checkcollide(test2, test);
7320 setAnimation(getStop());
7323 //aitype=passivetype;
7324 aitype = pathfindtype;
7325 finalfinaltarget = waypoints[waypoint];
7326 finalpathfindpoint = -1;
7327 targetpathfindpoint = -1;
7328 lastpathfindpoint = -1;
7329 lastpathfindpoint2 = -1;
7330 lastpathfindpoint3 = -1;
7331 lastpathfindpoint4 = -1;
7336 //check out last seen location
7337 if (aiupdatedelay < 0) {
7338 targetyaw = roughDirectionTo(coords, lastseen);
7339 lookyaw = targetyaw;
7340 aiupdatedelay = .05;
7343 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7346 lastseen.x += (float(Random() % 100) - 50) / 25;
7347 lastseen.z += (float(Random() % 100) - 50) / 25;
7358 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7359 if (!avoidsomething)
7360 targetyaw += 90 * (whichdirection * 2 - 1);
7362 XYZ leftpos, rightpos;
7363 float leftdist, rightdist;
7364 leftpos = coords + DoRotation(facing, 0, 90, 0);
7365 rightpos = coords - DoRotation(facing, 0, 90, 0);
7366 leftdist = distsq(&leftpos, &avoidwhere);
7367 rightdist = distsq(&rightpos, &avoidwhere);
7368 if (leftdist < rightdist)
7375 if (collided < 1 || animTarget != jumpupanim)
7377 if ((collided > .8 && jumppower >= 5))
7380 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7381 for (int k = 0; k < numenvsounds; k++) {
7382 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7383 aitype = attacktypecutoff;
7387 if (!Person::players[0]->dead &&
7388 losupdatedelay < 0 &&
7389 !Game::editorenabled &&
7391 ((!Tutorial::active || cananger) && hostile)) {
7392 losupdatedelay = .2;
7393 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7394 aitype = attacktypecutoff;
7397 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7398 //TODO: factor out canSeePlayer()
7399 if (distsq(&coords, &Person::players[0]->coords) < 400)
7400 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7401 if ((Object::checkcollide(
7402 DoRotation(jointPos(head), 0, yaw, 0)*
7404 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7405 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7406 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7407 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7408 /* //TODO: changed j to 0 on a whim, make sure this is correct
7409 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7410 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7412 aitype = attacktypecutoff;
7417 if (lastseentime < 0) {
7418 //aitype=passivetype;
7420 aitype = pathfindtype;
7421 finalfinaltarget = waypoints[waypoint];
7422 finalpathfindpoint = -1;
7423 targetpathfindpoint = -1;
7424 lastpathfindpoint = -1;
7425 lastpathfindpoint2 = -1;
7426 lastpathfindpoint3 = -1;
7427 lastpathfindpoint4 = -1;
7431 if (aitype != gethelptype)
7434 //get help from buddies
7435 if (aitype == gethelptype) {
7436 runninghowlong += multiplier;
7437 aiupdatedelay -= multiplier;
7439 if (aiupdatedelay < 0 || ally == 0) {
7443 //TODO: factor out closest search somehow
7446 float closestdist = -1;
7447 for (unsigned k = 0; k < Person::players.size(); k++) {
7448 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7449 (Person::players[k]->howactive < typedead1) &&
7450 !Person::players[k]->skeleton.free &&
7451 (Person::players[k]->aitype == passivetype)) {
7452 float distance = distsq(&coords, &Person::players[k]->coords);
7453 if (closestdist == -1 || distance < closestdist) {
7454 closestdist = distance;
7460 if (closest != -1) {
7465 lastseen = Person::players[0]->coords;
7472 XYZ facing = coords;
7473 XYZ flatfacing = Person::players[ally]->coords;
7474 facing.y += jointPos(head).y * scale;
7475 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7476 if (-1 != Object::checkcollide(facing, flatfacing))
7479 //no available ally, run back to player
7481 Person::players[ally]->skeleton.free ||
7482 Person::players[ally]->aitype != passivetype ||
7483 lastseentime <= 0) {
7484 aitype = searchtype;
7490 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7491 lookyaw = targetyaw;
7492 aiupdatedelay = .05;
7495 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7496 aitype = searchtype;
7498 Person::players[ally]->aitype = searchtype;
7499 if (Person::players[ally]->lastseentime < lastseentime) {
7500 Person::players[ally]->lastseen = lastseen;
7501 Person::players[ally]->lastseentime = lastseentime;
7502 Person::players[ally]->lastchecktime = lastchecktime;
7506 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7507 if (!avoidsomething)
7508 targetyaw += 90 * (whichdirection * 2 - 1);
7510 XYZ leftpos, rightpos;
7511 float leftdist, rightdist;
7512 leftpos = coords + DoRotation(facing, 0, 90, 0);
7513 rightpos = coords - DoRotation(facing, 0, 90, 0);
7514 leftdist = distsq(&leftpos, &avoidwhere);
7515 rightdist = distsq(&rightpos, &avoidwhere);
7516 if (leftdist < rightdist)
7530 if (collided < 1 || animTarget != jumpupanim)
7532 if (collided > .8 && jumppower >= 5)
7536 //retreiving a weapon on the ground
7537 if (aitype == getweapontype) {
7538 aiupdatedelay -= multiplier;
7539 lastchecktime -= multiplier;
7541 if (aiupdatedelay < 0) {
7547 float closestdist = -1;
7548 for (unsigned k = 0; k < weapons.size(); k++)
7549 if (weapons[k].owner == -1) {
7550 float distance = distsq(&coords, &weapons[k].position);
7551 if (closestdist == -1 || distance < closestdist) {
7552 closestdist = distance;
7565 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7566 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7567 aitype = attacktypecutoff;
7570 if (!Person::players[0]->dead)
7572 if (weapons[ally].owner != -1 ||
7573 distsq(&coords, &weapons[ally].position) > 16) {
7574 aitype = attacktypecutoff;
7577 //TODO: factor these out as moveToward()
7578 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7579 lookyaw = targetyaw;
7580 aiupdatedelay = .05;
7584 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7585 if (!avoidsomething)
7586 targetyaw += 90 * (whichdirection * 2 - 1);
7588 XYZ leftpos, rightpos;
7589 float leftdist, rightdist;
7590 leftpos = coords + DoRotation(facing, 0, 90, 0);
7591 rightpos = coords - DoRotation(facing, 0, 90, 0);
7592 leftdist = distsq(&leftpos, &avoidwhere);
7593 rightdist = distsq(&rightpos, &avoidwhere);
7594 if (leftdist < rightdist)
7608 if (animTarget != crouchremoveknifeanim &&
7609 animTarget != removeknifeanim)
7610 throwtogglekeydown = 0;
7613 if (collided < 1 || animTarget != jumpupanim)
7615 if ((collided > .8 && jumppower >= 5))
7619 if (aitype == attacktypecutoff) {
7620 aiupdatedelay -= multiplier;
7621 //dodge or reverse rabbit kicks, knife throws, flips
7622 if (damage < damagetolerance * 2 / 3)
7623 if ((Person::players[0]->animTarget == rabbitkickanim ||
7624 Person::players[0]->animTarget == knifethrowanim ||
7625 (Person::players[0]->isFlip() &&
7626 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7627 !Person::players[0]->skeleton.free &&
7628 (aiupdatedelay < .1)) {
7632 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7633 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7634 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7635 if (abs(Random() % 2) == 0)
7636 setAnimation(backhandspringanim);
7638 setAnimation(rollanim);
7639 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7642 if (animTarget == jumpupanim || animTarget == jumpdownanim)
7643 setAnimation(flipanim);
7647 aiupdatedelay = .02;
7649 //get confused by flips
7650 if (Person::players[0]->isFlip() &&
7651 !Person::players[0]->skeleton.free &&
7652 Person::players[0]->animTarget != walljumprightkickanim &&
7653 Person::players[0]->animTarget != walljumpleftkickanim) {
7654 if (distsq(&Person::players[0]->coords, &coords) < 25)
7655 if ((1 - damage / damagetolerance) > .5)
7658 //go for weapon on the ground
7659 if (wentforweapon < 3)
7660 for (unsigned k = 0; k < weapons.size(); k++)
7661 if (creature != wolftype)
7662 if (num_weapons == 0 &&
7663 weapons[k].owner == -1 &&
7664 weapons[k].velocity.x == 0 &&
7665 weapons[k].velocity.z == 0 &&
7666 weapons[k].velocity.y == 0) {
7667 if (distsq(&coords, &weapons[k].position) < 16) {
7670 aitype = getweapontype;
7674 //dodge/reverse walljump kicks
7675 if (damage < damagetolerance / 2)
7676 if (Animation::animations[animTarget].height != highheight)
7677 if (damage < damagetolerance * .5 &&
7678 ((Person::players[0]->animTarget == walljumprightkickanim ||
7679 Person::players[0]->animTarget == walljumpleftkickanim) &&
7680 ((aiupdatedelay < .15 &&
7682 (aiupdatedelay < .08 &&
7683 difficulty != 2)))) {
7686 //walked off a ledge (?)
7687 if (isRun() && !onground)
7688 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7689 XYZ test2 = coords + facing;
7691 XYZ test = coords + facing;
7693 j = Object::checkcollide(test2, test, laststanding);
7695 j = Object::checkcollide(test2, test);
7698 setAnimation(getStop());
7701 aitype = pathfindtype;
7702 finalfinaltarget = waypoints[waypoint];
7703 finalpathfindpoint = -1;
7704 targetpathfindpoint = -1;
7705 lastpathfindpoint = -1;
7706 lastpathfindpoint2 = -1;
7707 lastpathfindpoint3 = -1;
7708 lastpathfindpoint4 = -1;
7712 //lose sight of player in the air (?)
7713 if (Person::players[0]->coords.y > coords.y + 5 &&
7714 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7715 !Person::players[0]->onterrain) {
7716 aitype = pathfindtype;
7717 finalfinaltarget = waypoints[waypoint];
7718 finalpathfindpoint = -1;
7719 targetpathfindpoint = -1;
7720 lastpathfindpoint = -1;
7721 lastpathfindpoint2 = -1;
7722 lastpathfindpoint3 = -1;
7723 lastpathfindpoint4 = -1;
7725 //it's time to think (?)
7726 if (aiupdatedelay < 0 &&
7727 !Animation::animations[animTarget].attack &&
7728 animTarget != staggerbackhighanim &&
7729 animTarget != staggerbackhardanim &&
7730 animTarget != backhandspringanim &&
7731 animTarget != dodgebackanim) {
7733 if (weaponactive == -1 && num_weapons > 0)
7734 drawkeydown = Random() % 2;
7737 rabbitkickenabled = Random() % 2;
7739 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7740 XYZ targetpoint = Person::players[0]->coords;
7741 if (distsq(&Person::players[0]->coords, &coords) <
7742 distsq(&rotatetarget, &coords))
7743 targetpoint += Person::players[0]->velocity *
7744 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7745 targetyaw = roughDirectionTo(coords, targetpoint);
7746 lookyaw = targetyaw;
7747 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7749 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7751 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7752 distsq(&coords, &Person::players[0]->coords) < 9) &&
7753 Person::players[0]->weaponactive != -1)
7755 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7759 //chill out around the corpse
7760 if (Person::players[0]->dead) {
7762 if (Random() % 10 == 0)
7764 if (Random() % 100 == 0) {
7765 aitype = pathfindtype;
7766 finalfinaltarget = waypoints[waypoint];
7767 finalpathfindpoint = -1;
7768 targetpathfindpoint = -1;
7769 lastpathfindpoint = -1;
7770 lastpathfindpoint2 = -1;
7771 lastpathfindpoint3 = -1;
7772 lastpathfindpoint4 = -1;
7781 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7782 targetyaw += 90 * (whichdirection * 2 - 1);
7784 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7788 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7792 if (aitype != playercontrolled &&
7797 for (unsigned j = 0; j < Person::players.size(); j++)
7798 if (j != id && !Person::players[j]->skeleton.free &&
7799 Person::players[j]->hasvictim &&
7800 (Tutorial::active && reversaltrain ||
7801 Random() % 2 == 0 && difficulty == 2 ||
7802 Random() % 4 == 0 && difficulty == 1 ||
7803 Random() % 8 == 0 && difficulty == 0 ||
7804 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7805 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7806 (Random() % 2 == 0 || difficulty == 2) ||
7807 (isIdle() || isRun()) &&
7808 Person::players[j]->weaponactive != -1 ||
7809 Person::players[j]->animTarget == swordslashanim &&
7810 weaponactive != -1 ||
7811 Person::players[j]->animTarget == staffhitanim ||
7812 Person::players[j]->animTarget == staffspinhitanim))
7813 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7814 Person::players[j]->victim == Person::players[id] &&
7815 (Person::players[j]->animTarget == sweepanim ||
7816 Person::players[j]->animTarget == spinkickanim ||
7817 Person::players[j]->animTarget == staffhitanim ||
7818 Person::players[j]->animTarget == staffspinhitanim ||
7819 Person::players[j]->animTarget == winduppunchanim ||
7820 Person::players[j]->animTarget == upunchanim ||
7821 Person::players[j]->animTarget == wolfslapanim ||
7822 Person::players[j]->animTarget == knifeslashstartanim ||
7823 Person::players[j]->animTarget == swordslashanim &&
7824 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7825 weaponactive != -1))) {
7833 Person::players[target]->Reverse();
7838 if (collided > .8 && jumppower >= 5 ||
7839 distsq(&coords, &Person::players[0]->coords) > 400 &&
7841 creature == rabbittype)
7843 //TODO: why are we controlling the human?
7844 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7845 Person::players[0]->jumpkeydown = 0;
7846 if (Person::players[0]->animTarget == jumpdownanim &&
7847 distsq(&Person::players[0]->coords, &coords) < 40)
7852 if (Tutorial::active)
7857 XYZ facing = coords;
7858 XYZ flatfacing = Person::players[0]->coords;
7859 facing.y += jointPos(head).y * scale;
7860 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7862 if (-1 != Object::checkcollide(facing, flatfacing)) {
7865 if (lastseentime <= 0 &&
7866 (creature != wolftype ||
7867 weaponstuck == -1)) {
7868 aitype = searchtype;
7870 lastseen = Person::players[0]->coords;
7877 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7878 (aitype == attacktypecutoff ||
7879 aitype == searchtype))
7880 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7881 XYZ test = Person::players[0]->coords;
7883 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7887 if (aitype == passivetype && !(numwaypoints > 1) ||
7889 pause && damage > superpermanentdamage) {
7908 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7909 facing = flatfacing;
7911 if (aitype == attacktypecutoff) {
7912 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7913 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7914 } else if (howactive >= typesleeping) {
7915 targetheadyaw = targetyaw;
7916 targetheadpitch = 0;
7918 if (interestdelay <= 0) {
7919 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7920 headtarget = coords;
7921 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7922 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7923 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7924 headtarget += facing * 1.5;
7926 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7927 targetheadpitch = pitchTo(coords, headtarget);