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)
1497 damagetaken += howmuch / power;
1499 damagedealt += howmuch / power;
1503 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) {
1508 if (!Tutorial::active) {
1509 damage += howmuch / power;
1510 permanentdamage += howmuch / 2 / power;
1511 superpermanentdamage += howmuch / 4 / power;
1514 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1516 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1520 camerashake += howmuch / 100;
1521 if ((howmuch > 50 && damage > damagetolerance / 2)) {
1522 blackout = damage / damagetolerance;
1530 if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile))
1531 aitype = attacktypecutoff;
1532 if (!Tutorial::active && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1533 if (abs(Random() % 2) == 0) {
1534 aitype = gethelptype;
1537 aitype = attacktypecutoff;
1541 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1544 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1545 if (skeleton.free) {
1546 flatvelocity2 = skeleton.joints[i].velocity;
1547 flatfacing2 = skeleton.joints[i].position * scale + coords;
1549 flatvelocity2 = velocity;
1550 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1552 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1553 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1554 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1555 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1556 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1557 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1560 emit_sound_at(splattersound, coords);
1565 if (!dead && creature == wolftype) {
1566 award_bonus(0, Wolfbonus);
1573 if (!Tutorial::active || id == 0) {
1574 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1575 int whichsound = -1;
1577 if (creature == wolftype) {
1578 int i = abs(Random() % 2);
1580 whichsound = snarlsound;
1582 whichsound = snarl2sound;
1584 if (creature == rabbittype) {
1585 int i = abs(Random() % 2);
1587 whichsound = rabbitpainsound;
1588 if (i == 1 && damage > damagetolerance)
1589 whichsound = rabbitpain1sound;
1592 if (whichsound != -1) {
1593 emit_sound_at(whichsound, coords);
1594 addEnvSound(coords);
1602 * calculate/animate head facing direction?
1604 void Person::DoHead()
1606 static XYZ rotatearound;
1608 static float lookspeed = 500;
1610 if (!freeze && !winfreeze) {
1613 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1614 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1616 while (targetheadyaw > 180)targetheadyaw -= 360;
1617 while (targetheadyaw < -180)targetheadyaw += 360;
1619 if (targetheadyaw > 160)
1620 targetheadpitch = targetheadpitch * -1;
1621 if (targetheadyaw < -160)
1622 targetheadpitch = targetheadpitch * -1;
1623 if (targetheadyaw > 160)
1624 targetheadyaw = targetheadyaw - 180;
1625 if (targetheadyaw < -160)
1626 targetheadyaw = targetheadyaw + 180;
1628 if (targetheadpitch > 120)
1629 targetheadpitch = 120;
1630 if (targetheadpitch < -120)
1631 targetheadpitch = -120;
1632 if (targetheadyaw > 120)
1633 targetheadyaw = 120;
1634 if (targetheadyaw < -120)
1635 targetheadyaw = -120;
1638 targetheadpitch = 0;
1640 if (targetheadyaw > 80)
1642 if (targetheadyaw < -80)
1643 targetheadyaw = -80;
1644 if (targetheadpitch > 50)
1645 targetheadpitch = 50;
1646 if (targetheadpitch < -50)
1647 targetheadpitch = -50;
1650 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1651 headyaw = targetheadyaw;
1652 else if (headyaw > targetheadyaw) {
1653 headyaw -= multiplier * lookspeed;
1654 } else if (headyaw < targetheadyaw) {
1655 headyaw += multiplier * lookspeed;
1658 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1659 headpitch = targetheadpitch;
1660 else if (headpitch > targetheadpitch) {
1661 headpitch -= multiplier * lookspeed / 2;
1662 } else if (headpitch < targetheadpitch) {
1663 headpitch += multiplier * lookspeed / 2;
1666 rotatearound = jointPos(neck);
1667 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1671 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1672 facing = DoRotation(facing, headpitch * .4, 0, 0);
1673 facing = DoRotation(facing, 0, headyaw * .4, 0);
1676 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1677 facing = DoRotation(facing, headpitch * .8, 0, 0);
1678 facing = DoRotation(facing, 0, headyaw * .8, 0);
1681 if (animTarget == walkanim) {
1682 facing = DoRotation(facing, headpitch * .6, 0, 0);
1683 facing = DoRotation(facing, 0, headyaw * .6, 0);
1686 skeleton.specialforward[0] = facing;
1687 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1688 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1689 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1690 skeleton.FindRotationMuscle(i, animTarget);
1697 * ragdolls character?
1699 void Person::RagDoll(bool checkcollision)
1704 if (!skeleton.free) {
1707 if (id == 0 && isFlip())
1714 facing = DoRotation(facing, 0, yaw, 0);
1716 skeleton.freetime = 0;
1718 skeleton.longdead = 0;
1721 skeleton.broken = 0;
1722 skeleton.spinny = 1;
1724 skeleton.freefall = 1;
1726 if (!isnormal(velocity.x)) velocity.x = 0;
1727 if (!isnormal(velocity.y)) velocity.y = 0;
1728 if (!isnormal(velocity.z)) velocity.z = 0;
1729 if (!isnormal(yaw)) yaw = 0;
1730 if (!isnormal(coords.x)) coords = 0;
1731 if (!isnormal(tilt)) tilt = 0;
1732 if (!isnormal(tilt2)) tilt2 = 0;
1734 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1735 skeleton.joints[i].delay = 0;
1736 skeleton.joints[i].locked = 0;
1737 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1738 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1739 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1740 skeleton.joints[i].position.y += .1;
1741 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1742 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1745 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1746 skeleton.joints[i].velocity = 0;
1747 skeleton.joints[i].velchange = 0;
1749 skeleton.DoConstraints(&coords, &scale);
1750 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1751 skeleton.DoConstraints(&coords, &scale);
1752 skeleton.DoConstraints(&coords, &scale);
1753 skeleton.DoConstraints(&coords, &scale);
1754 skeleton.DoConstraints(&coords, &scale);
1757 speed = targetFrame().speed * 2;
1758 if (currentFrame().speed > targetFrame().speed) {
1759 speed = currentFrame().speed * 2;
1762 speed = transspeed * 2;
1766 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1767 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1768 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);
1770 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1771 change.x = (float)(Random() % 100) / 100;
1772 change.y = (float)(Random() % 100) / 100;
1773 change.z = (float)(Random() % 100) / 100;
1774 skeleton.joints[i].velocity += change;
1775 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1777 change.x = (float)(Random() % 100) / 100;
1778 change.y = (float)(Random() % 100) / 100;
1779 change.z = (float)(Random() % 100) / 100;
1780 skeleton.joints[i].velchange += change;
1781 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1784 if (checkcollision) {
1787 if (!skeleton.joints.empty()) {
1790 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1791 average += skeleton.joints[j].position;
1793 average /= skeleton.joints.size();
1794 coords += average * scale;
1795 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1796 skeleton.joints[j].position -= average;
1800 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1801 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1802 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1803 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1804 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1807 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1808 coords.x = lowpoint.x;
1809 coords.z = lowpoint.z;
1818 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1819 velocity += skeleton.joints[i].velocity * scale;
1821 velocity /= skeleton.joints.size();
1824 if (Random() % 2 == 0) {
1825 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1826 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1827 weapons[weaponids[0]].velocity.x += .01;
1830 weaponids[0] = weaponids[num_weapons];
1831 if (weaponstuck == num_weapons)
1835 for (unsigned i = 0; i < Person::players.size(); i++) {
1836 Person::players[i]->wentforweapon = 0;
1841 animTarget = bounceidleanim;
1842 animCurrent = bounceidleanim;
1852 void Person::FootLand(bodypart whichfoot, float opacity)
1854 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1855 cerr << "FootLand called on wrong bodypart" << endl;
1858 static XYZ terrainlight;
1859 static XYZ footvel, footpoint;
1860 if (opacity >= 1 || skiddelay <= 0) {
1863 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1864 if (distsq(&footpoint, &viewer))
1865 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1866 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1867 footvel = velocity / 5;
1870 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1871 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1872 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1873 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1874 if (environment == snowyenvironment) {
1875 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1877 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1879 } else if (environment == grassyenvironment) {
1880 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1881 } else if (environment == desertenvironment) {
1882 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1884 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1888 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1889 footvel = velocity / 5;
1892 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1893 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1894 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1901 * make a puff effect at a body part (dust effect?)
1903 void Person::Puff(int whichlabel)
1905 static XYZ footvel, footpoint;
1908 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1909 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1913 * I think I added this in an attempt to clean up code
1915 void Person::setAnimation(int animation)
1917 animTarget = animation;
1926 void Person::DoAnimations()
1928 if (!skeleton.free) {
1929 static float oldtarget;
1931 if (isIdle() && animCurrent != getIdle())
1932 normalsupdatedelay = 0;
1934 if (animTarget == tempanim || animCurrent == tempanim) {
1935 Animation::animations[tempanim] = tempanimation;
1937 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1943 vel[0] = velocity.x;
1944 vel[1] = velocity.y;
1945 vel[2] = velocity.z;
1948 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1949 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1951 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1953 if (!crouchkeydown && velocity.y >= -15)
1956 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1961 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1963 if (normaldotproduct(targfacing, velocity) >= -.3)
1964 animTarget = flipanim;
1966 animTarget = backflipanim;
1967 crouchtogglekeydown = 1;
1975 if (Animation::animations[animTarget].attack != reversed)
1977 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1978 crouchtogglekeydown = 0;
1979 if (aitype == playercontrolled)
1982 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1985 crouchtogglekeydown = 1;
1989 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1991 normalsupdatedelay = 0;
1995 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1997 emit_sound_at(fireendsound, coords);
1998 pause_sound(stream_firesound);
2002 if (animTarget == rabbittacklinganim && frameTarget == 1) {
2003 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
2005 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
2006 if (normaldotproduct(victim->facing, facing) > 0)
2007 victim->animTarget = rabbittackledbackanim;
2009 victim->animTarget = rabbittackledfrontanim;
2010 victim->frameTarget = 2;
2013 victim->targetyaw = yaw;
2014 if (victim->aitype == gethelptype)
2015 victim->DoDamage(victim->damagetolerance - victim->damage);
2016 //victim->DoDamage(30);
2017 if (creature == wolftype) {
2019 emit_sound_at(clawslicesound, victim->coords);
2021 victim->DoBloodBig(1 / victim->armorhead, 210);
2023 award_bonus(id, TackleBonus,
2024 victim->aitype == gethelptype ? 50 : 0);
2028 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2029 if (weapons[weaponids[0]].getType() == knife) {
2030 if (weaponactive == -1)
2032 else if (weaponactive == 0)
2035 if (weaponactive == -1) {
2036 emit_sound_at(knifesheathesound, coords);
2038 if (weaponactive != -1) {
2039 emit_sound_at(knifedrawsound, coords, 128);
2042 drawtogglekeydown = 1;
2045 if (!Tutorial::active || id == 0)
2046 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2047 int whichsound = -1;
2049 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2050 if (targetFrame().label == 1)
2051 whichsound = footstepsound;
2053 whichsound = footstepsound2;
2054 if (targetFrame().label == 1)
2055 FootLand(leftfoot, 1);
2056 if (targetFrame().label == 2)
2057 FootLand(rightfoot, 1);
2058 if (targetFrame().label == 3 && isRun()) {
2059 FootLand(rightfoot, 1);
2060 FootLand(leftfoot, 1);
2064 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2065 if (targetFrame().label == 1)
2066 whichsound = footstepsound3;
2068 whichsound = footstepsound4;
2072 if (targetFrame().label == 1)
2073 whichsound = footstepsound3;
2075 whichsound = footstepsound4;
2077 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2078 if (Animation::animations[animTarget].attack != neutral) {
2079 unsigned r = abs(Random() % 3);
2081 whichsound = lowwhooshsound;
2083 whichsound = midwhooshsound;
2085 whichsound = highwhooshsound;
2087 if (Animation::animations[animTarget].attack == neutral) {
2088 whichsound = movewhooshsound;
2090 } else if (targetFrame().label == 4) {
2091 whichsound = knifeswishsound;
2093 if (targetFrame().label == 8 && !Tutorial::active) {
2094 whichsound = landsound2;
2097 if (whichsound != -1) {
2098 emit_sound_at(whichsound, coords, 256.);
2101 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2102 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2103 addEnvSound(coords, 15);
2105 addEnvSound(coords, 6);
2110 if (targetFrame().label == 3) {
2112 emit_sound_at(whichsound, coords, 128.);
2118 if (!Tutorial::active || id == 0)
2119 if (speechdelay <= 0)
2120 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2121 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2122 int whichsound = -1;
2123 if (targetFrame().label == 4 && aitype != playercontrolled) {
2124 if (Animation::animations[animTarget].attack != neutral) {
2125 unsigned r = abs(Random() % 4);
2126 if (creature == rabbittype) {
2127 if (r == 0) whichsound = rabbitattacksound;
2128 if (r == 1) whichsound = rabbitattack2sound;
2129 if (r == 2) whichsound = rabbitattack3sound;
2130 if (r == 3) whichsound = rabbitattack4sound;
2132 if (creature == wolftype) {
2133 if (r == 0) whichsound = barksound;
2134 if (r == 1) whichsound = bark2sound;
2135 if (r == 2) whichsound = bark3sound;
2136 if (r == 3) whichsound = barkgrowlsound;
2142 if (whichsound != -1) {
2143 emit_sound_at(whichsound, coords);
2149 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2150 FootLand(leftfoot, 1);
2151 FootLand(rightfoot, 1);
2155 currentoffset = targetoffset;
2156 frameTarget = frameCurrent;
2157 animCurrent = animTarget;
2160 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2161 for (unsigned i = 0; i < weapons.size(); i++) {
2162 if (weapons[i].owner == -1)
2163 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2164 if (distsq(&coords, &weapons[i].position) >= 1) {
2165 if (weapons[i].getType() != staff) {
2166 emit_sound_at(knifedrawsound, coords, 128.);
2175 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2176 for (unsigned i = 0; i < weapons.size(); i++) {
2177 bool willwork = true;
2178 if (weapons[i].owner != -1)
2179 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2180 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2181 if (Person::players[weapons[i].owner]->num_weapons > 1)
2183 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2184 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2185 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2186 bool fleshstuck = false;
2187 if (weapons[i].owner != -1)
2188 if (victim->weaponstuck != -1) {
2189 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2194 emit_sound_at(fleshstabremovesound, coords, 128.);
2196 if (weapons[i].getType() != staff) {
2197 emit_sound_at(knifedrawsound, coords, 128.);
2200 if (weapons[i].owner != -1) {
2201 victim = Person::players[weapons[i].owner];
2202 if (victim->num_weapons == 1)
2203 victim->num_weapons = 0;
2205 victim->num_weapons = 1;
2207 //victim->weaponactive=-1;
2208 victim->skeleton.longdead = 0;
2209 victim->skeleton.free = 1;
2210 victim->skeleton.broken = 0;
2212 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2213 victim->skeleton.joints[j].velchange = 0;
2214 victim->skeleton.joints[j].locked = 0;
2220 Normalise(&relative);
2221 XYZ footvel, footpoint;
2223 footpoint = weapons[i].position;
2224 if (victim->weaponstuck != -1) {
2225 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2227 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2228 weapons[i].bloody = 2;
2229 weapons[i].blooddrip = 5;
2230 victim->weaponstuck = -1;
2233 if (victim->num_weapons > 0) {
2234 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2235 victim->weaponstuck = 0;
2236 if (victim->weaponids[0] == int(i))
2237 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2240 victim->jointVel(abdomen) += relative * 6;
2241 victim->jointVel(neck) += relative * 6;
2242 victim->jointVel(rightshoulder) += relative * 6;
2243 victim->jointVel(leftshoulder) += relative * 6;
2251 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2252 if (weaponactive == -1)
2254 else if (weaponactive == 0) {
2256 if (num_weapons == 2) {
2258 buffer = weaponids[0];
2259 weaponids[0] = weaponids[1];
2260 weaponids[1] = buffer;
2263 if (weaponactive == -1) {
2264 emit_sound_at(knifesheathesound, coords, 128.);
2266 if (weaponactive != -1) {
2267 emit_sound_at(knifedrawsound, coords, 128.);
2272 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2273 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2274 Normalise(&rotatetarget);
2275 targetyaw = -asin(0 - rotatetarget.x);
2276 targetyaw *= 360 / 6.28;
2277 if (rotatetarget.z < 0)
2278 targetyaw = 180 - targetyaw;
2280 if (animTarget == walljumprightkickanim)
2282 if (animTarget == walljumpleftkickanim)
2288 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2291 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2296 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2297 animTarget = rabbittackleanim;
2299 emit_sound_at(jumpsound, coords);
2307 targetloc = velocity;
2308 Normalise(&targetloc);
2309 targetloc += coords;
2310 for (unsigned i = 0; i < Person::players.size(); i++) {
2312 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2313 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2317 if (closestid != -1)
2318 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2320 victim = Person::players[closestid];
2321 coords = victim->coords;
2322 animCurrent = rabbittacklinganim;
2323 animTarget = rabbittacklinganim;
2327 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2328 rotatetarget = coords - victim->coords;
2329 Normalise(&rotatetarget);
2330 targetyaw = -asin(0 - rotatetarget.x);
2331 targetyaw *= 360 / 6.28;
2332 if (rotatetarget.z < 0)
2333 targetyaw = 180 - targetyaw;
2335 if (animTarget != rabbitrunninganim) {
2336 emit_sound_at(jumpsound, coords, 128.);
2342 float damagemult = 1 * power;
2343 if (creature == wolftype)
2344 damagemult = 2.5 * power;
2346 damagemult /= victim->damagetolerance / 200;
2348 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)) {
2349 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2350 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2354 if (Random() % 2 || creature == wolftype) {
2357 if (creature == wolftype)
2360 if (!Tutorial::active) {
2361 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2363 if (creature == wolftype) {
2364 emit_sound_at(clawslicesound, victim->coords, 128.);
2366 victim->DoBloodBig(2 / victim->armorhead, 175);
2370 relative = victim->coords - coords;
2372 Normalise(&relative);
2373 relative = DoRotation(relative, 0, -90, 0);
2374 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2375 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2377 victim->jointVel(head) += relative * damagemult * 200;
2379 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2385 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2386 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2390 if (Random() % 2 || creature == wolftype) {
2392 if (creature == wolftype)
2395 emit_sound_at(whooshhitsound, victim->coords);
2396 if (creature == wolftype) {
2397 emit_sound_at(clawslicesound, victim->coords, 128.);
2399 victim->DoBloodBig(2, 175);
2403 relative = victim->coords - coords;
2405 Normalise(&relative);
2407 Normalise(&relative);
2408 relative = DoRotation(relative, 0, 90, 0);
2409 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2410 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2412 victim->jointVel(head) += relative * damagemult * 100;
2414 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2418 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2419 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2425 if (!Tutorial::active) {
2426 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2428 if (creature == wolftype) {
2429 emit_sound_at(clawslicesound, victim->coords, 128.);
2431 victim->DoBloodBig(2 / victim->armorhead, 175);
2437 Normalise(&relative);
2438 relative = DoRotation(relative, 0, -90, 0);
2439 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2440 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2442 victim->jointVel(head) += relative * damagemult * 200;
2444 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2446 if (victim->damage > victim->damagetolerance)
2447 award_bonus(id, style);
2453 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2454 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2460 if (!Tutorial::active) {
2461 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2463 if (creature == wolftype) {
2464 emit_sound_at(clawslicesound, victim->coords, 128.);
2466 victim->DoBloodBig(2 / victim->armorhead, 175);
2472 Normalise(&relative);
2473 relative = DoRotation(relative, 0, 90, 0);
2474 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2475 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2477 victim->jointVel(head) += relative * damagemult * 200;
2479 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2481 if (victim->damage > victim->damagetolerance)
2482 award_bonus(id, style);
2488 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2489 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2497 emit_sound_at(whooshhitsound, victim->coords);
2500 relative = victim->coords - coords;
2502 Normalise(&relative);
2503 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2504 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2506 victim->jointVel(head) += relative * damagemult * 100;
2508 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2512 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2513 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2517 emit_sound_at(whooshhitsound, victim->coords, 128.);
2519 victim->skeleton.longdead = 0;
2520 victim->skeleton.free = 1;
2521 victim->skeleton.broken = 0;
2522 victim->skeleton.spinny = 1;
2524 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2525 victim->skeleton.joints[i].velchange = 0;
2526 victim->skeleton.joints[i].delay = 0;
2527 victim->skeleton.joints[i].locked = 0;
2528 //victim->skeleton.joints[i].velocity=0;
2534 Normalise(&relative);
2535 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2536 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2537 victim->skeleton.joints[i].position.y += relative.y * .3;
2538 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2539 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2541 victim->Puff(abdomen);
2542 victim->jointVel(abdomen).y = relative.y * 400;
2546 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2547 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2551 if (!Tutorial::active) {
2552 emit_sound_at(heavyimpactsound, coords, 128.);
2555 relative = victim->coords - coords;
2557 Normalise(&relative);
2558 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2559 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2561 victim->Puff(abdomen);
2562 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2566 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2567 victim->jointVel(abdomen) += relative * damagemult * 300;
2571 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2572 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2576 if (!Tutorial::active) {
2577 emit_sound_at(thudsound, coords);
2580 victim->skeleton.longdead = 0;
2581 victim->skeleton.free = 1;
2582 victim->skeleton.broken = 0;
2583 victim->skeleton.spinny = 1;
2585 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2586 victim->skeleton.joints[i].velchange = 0;
2587 //victim->skeleton.joints[i].delay=0;
2588 victim->skeleton.joints[i].locked = 0;
2591 relative = victim->coords - coords;
2592 Normalise(&relative);
2594 Normalise(&relative);
2595 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2596 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2601 victim->Puff(abdomen);
2602 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2603 victim->jointVel(abdomen) += relative * damagemult * 200;
2612 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2615 if (!victim->skeleton.free)
2619 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2620 emit_sound_at(knifesheathesound, coords, 128.);
2623 if (victim && hasvictim) {
2624 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2626 XYZ where, startpoint, endpoint, movepoint, colpoint;
2627 float rotationpoint;
2629 if (weapons[weaponids[weaponactive]].getType() == knife) {
2630 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2631 where -= victim->coords;
2632 if (!victim->skeleton.free)
2633 where = DoRotation(where, 0, -victim->yaw, 0);
2636 startpoint.y += 100;
2640 if (weapons[weaponids[weaponactive]].getType() == sword) {
2641 where = weapons[weaponids[weaponactive]].position;
2642 where -= victim->coords;
2643 if (!victim->skeleton.free)
2644 where = DoRotation(where, 0, -victim->yaw, 0);
2646 where = weapons[weaponids[weaponactive]].tippoint;
2647 where -= victim->coords;
2648 if (!victim->skeleton.free)
2649 where = DoRotation(where, 0, -victim->yaw, 0);
2652 if (weapons[weaponids[weaponactive]].getType() == staff) {
2653 where = weapons[weaponids[weaponactive]].position;
2654 where -= victim->coords;
2655 if (!victim->skeleton.free)
2656 where = DoRotation(where, 0, -victim->yaw, 0);
2658 where = weapons[weaponids[weaponactive]].tippoint;
2659 where -= victim->coords;
2660 if (!victim->skeleton.free)
2661 where = DoRotation(where, 0, -victim->yaw, 0);
2666 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2668 if (whichtri != -1) {
2669 if (victim->dead != 2) {
2670 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2672 award_bonus(id, FinishedBonus);
2675 weapons[weaponids[weaponactive]].bloody = 2;
2677 victim->skeleton.longdead = 0;
2678 victim->skeleton.free = 1;
2679 victim->skeleton.broken = 0;
2681 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2682 victim->skeleton.joints[i].velchange = 0;
2683 victim->skeleton.joints[i].locked = 0;
2684 //victim->skeleton.joints[i].velocity=0;
2686 emit_sound_at(fleshstabsound, coords, 128);
2689 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2690 weapons[weaponids[weaponactive]].blooddrip += 5;
2691 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2693 if (whichtri == -1) {
2695 emit_sound_at(knifesheathesound, coords, 128.);
2701 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2703 emit_sound_at(knifedrawsound, coords, 128);
2706 if (victim && hasvictim) {
2707 XYZ footvel, footpoint;
2709 emit_sound_at(fleshstabremovesound, coords, 128.);
2712 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2714 if (weapons[weaponids[weaponactive]].getType() == sword) {
2715 XYZ where, startpoint, endpoint, movepoint;
2716 float rotationpoint;
2719 where = weapons[weaponids[weaponactive]].position;
2720 where -= victim->coords;
2721 if (!victim->skeleton.free)
2722 where = DoRotation(where, 0, -victim->yaw, 0);
2724 where = weapons[weaponids[weaponactive]].tippoint;
2725 where -= victim->coords;
2726 if (!victim->skeleton.free)
2727 where = DoRotation(where, 0, -victim->yaw, 0);
2732 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2733 footpoint += victim->coords;
2735 if (whichtri == -1) {
2736 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2739 if (weapons[weaponids[weaponactive]].getType() == staff) {
2740 XYZ where, startpoint, endpoint, movepoint;
2741 float rotationpoint;
2744 where = weapons[weaponids[weaponactive]].position;
2745 where -= victim->coords;
2746 if (!victim->skeleton.free)
2747 where = DoRotation(where, 0, -victim->yaw, 0);
2749 where = weapons[weaponids[weaponactive]].tippoint;
2750 where -= victim->coords;
2751 if (!victim->skeleton.free)
2752 where = DoRotation(where, 0, -victim->yaw, 0);
2757 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2758 footpoint += victim->coords;
2760 if (whichtri == -1) {
2761 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2764 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2766 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2767 victim->skeleton.longdead = 0;
2768 victim->skeleton.free = 1;
2769 victim->skeleton.broken = 0;
2771 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2772 victim->skeleton.joints[i].velchange = 0;
2773 victim->skeleton.joints[i].locked = 0;
2774 //victim->skeleton.joints[i].velocity=0;
2780 Normalise(&relative);
2781 //victim->Puff(abdomen);
2783 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2785 if (victim->bloodloss < victim->damagetolerance) {
2786 victim->bloodloss += 1000;
2790 victim->jointVel(abdomen) += relative * damagemult * 20;
2794 if (!hasvictim && onterrain) {
2795 weapons[weaponids[weaponactive]].bloody = 0;
2796 weapons[weaponids[weaponactive]].blooddrip = 0;
2800 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2801 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2809 if (!Tutorial::active) {
2810 emit_sound_at(heavyimpactsound, victim->coords, 128);
2815 relative = victim->coords - coords;
2817 Normalise(&relative);
2818 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2819 victim->skeleton.joints[i].velocity = relative * 30;
2821 victim->jointVel(head) += relative * damagemult * 150;
2823 victim->frameTarget = 0;
2824 victim->animTarget = staggerbackhardanim;
2825 victim->targetyaw = targetyaw + 180;
2827 victim->stunned = 1;
2830 victim->Puff(abdomen);
2831 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2838 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2839 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2843 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2844 if (!Tutorial::active) {
2845 emit_sound_at(thudsound, victim->coords);
2847 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2848 if (!Tutorial::active) {
2849 emit_sound_at(whooshhitsound, victim->coords);
2852 if (!Tutorial::active) {
2853 emit_sound_at(heavyimpactsound, victim->coords);
2857 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2860 relative = victim->coords - coords;
2862 Normalise(&relative);
2864 Normalise(&relative);
2865 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2866 victim->skeleton.joints[i].velocity = relative * 5;
2868 victim->jointVel(abdomen) += relative * damagemult * 400;
2870 victim->frameTarget = 0;
2871 victim->animTarget = staggerbackhardanim;
2872 victim->targetyaw = targetyaw + 180;
2874 victim->stunned = 1;
2876 victim->Puff(abdomen);
2877 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2883 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2884 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2885 if (victim->id == 0)
2887 emit_sound_at(landsound2, victim->coords);
2893 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2894 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2895 if (victim->id == 0)
2898 if (weaponactive != -1) {
2899 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2900 if (weapons[victim->weaponids[0]].getType() == staff)
2901 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2902 if (weapons[weaponids[0]].getType() == staff)
2903 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2905 emit_sound_at(swordstaffsound, victim->coords);
2907 emit_sound_at(metalhitsound, victim->coords);
2915 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2916 if (weaponactive != -1) {
2919 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);
2921 weapons[weaponids[0]].thrown(aim * 50);
2924 weaponids[0] = weaponids[num_weapons];
2930 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2932 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2934 if (!Tutorial::active) {
2935 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2938 award_bonus(id, Slicebonus);
2939 if (!Tutorial::active) {
2940 emit_sound_at(knifeslicesound, victim->coords);
2942 //victim->jointVel(abdomen)+=relative*damagemult*200;
2943 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2944 if (victim->id != 0 || difficulty == 2) {
2945 victim->frameTarget = 0;
2946 victim->animTarget = staggerbackhardanim;
2947 victim->targetyaw = targetyaw + 180;
2951 victim->lowreversaldelay = 0;
2952 victim->highreversaldelay = 0;
2953 if (aitype != playercontrolled)
2954 weaponmissdelay = .6;
2956 if (!Tutorial::active) {
2957 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
2958 weapons[weaponids[weaponactive]].bloody = 1;
2960 weapons[weaponids[weaponactive]].blooddrip += 3;
2963 XYZ footvel, footpoint;
2965 if (skeleton.free) {
2966 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2968 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2970 if (Tutorial::active) {
2971 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2974 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2976 footvel = DoRotation(facing, 0, 90, 0) * .8;
2977 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2978 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2979 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2980 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2982 victim->DoDamage(damagemult * 0);
2985 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2986 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2987 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2988 award_bonus(id, Slashbonus);
2990 if (!Tutorial::active) {
2991 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2992 victim->DoBloodBig(2 / victim->armorhigh, 190);
2994 victim->DoBloodBig(2 / victim->armorhigh, 185);
2995 victim->deathbleeding = 1;
2996 emit_sound_at(swordslicesound, victim->coords);
2997 victim->frameTarget = 0;
2998 victim->animTarget = staggerbackhardanim;
2999 victim->targetyaw = targetyaw + 180;
3001 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) {
3002 weapons[weaponids[weaponactive]].bloody = 1;
3004 weapons[weaponids[weaponactive]].blooddrip += 3;
3006 float bloodlossamount;
3007 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3008 victim->bloodloss += bloodlossamount / victim->armorhigh;
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);
3021 footvel = DoRotation(facing, 0, 90, 0) * .8;
3023 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3024 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3025 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3026 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3029 if (victim->weaponactive != -1) {
3030 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3031 if (weapons[victim->weaponids[0]].getType() == staff)
3032 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3033 if (weapons[weaponids[0]].getType() == staff)
3034 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3036 emit_sound_at(swordstaffsound, victim->coords);
3038 emit_sound_at(metalhitsound, victim->coords);
3044 victim->Puff(righthand);
3046 victim->frameTarget = 0;
3047 victim->animTarget = staggerbackhighanim;
3048 victim->targetyaw = targetyaw + 180;
3050 aim = DoRotation(facing, 0, 90, 0) * 21;
3052 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3053 victim->num_weapons--;
3054 if (victim->num_weapons) {
3055 victim->weaponids[0] = victim->weaponids[num_weapons];
3056 if (victim->weaponstuck == victim->num_weapons)
3057 victim->weaponstuck = 0;
3059 victim->weaponactive = -1;
3060 for (unsigned i = 0; i < Person::players.size(); i++) {
3061 Person::players[i]->wentforweapon = 0;
3068 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3069 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3070 if (!Tutorial::active) {
3071 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3075 if (Random() % 2 || creature == wolftype) {
3078 emit_sound_at(staffheadsound, victim->coords);
3082 relative = victim->coords - coords;
3084 Normalise(&relative);
3085 relative = DoRotation(relative, 0, 90, 0);
3087 Normalise(&relative);
3088 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3089 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3091 victim->jointVel(head) += relative * damagemult * 230;
3092 victim->jointVel(neck) += relative * damagemult * 230;
3094 if (!Tutorial::active) {
3095 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3097 award_bonus(id, solidhit, 30);
3102 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3103 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3104 if (!Tutorial::active) {
3105 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3109 if (Random() % 2 || creature == wolftype) {
3112 emit_sound_at(staffheadsound, victim->coords);
3116 relative = victim->coords - coords;
3118 Normalise(&relative);
3119 relative = DoRotation(relative, 0, -90, 0);
3120 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3121 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3123 victim->jointVel(head) += relative * damagemult * 220;
3124 victim->jointVel(neck) += relative * damagemult * 220;
3126 if (!Tutorial::active) {
3127 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3129 award_bonus(id, solidhit, 60);
3134 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3135 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3137 if (!Tutorial::active) {
3139 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3142 if (Random() % 2 || creature == wolftype) {
3145 emit_sound_at(staffbodysound, victim->coords);
3147 victim->skeleton.longdead = 0;
3148 victim->skeleton.free = 1;
3149 victim->skeleton.broken = 0;
3151 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3152 victim->skeleton.joints[i].velchange = 0;
3153 victim->skeleton.joints[i].locked = 0;
3154 //victim->skeleton.joints[i].velocity=0;
3161 Normalise(&relative);
3162 if (!victim->dead) {
3163 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3164 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3166 victim->jointVel(abdomen) += relative * damagemult * 40;
3169 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3170 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3173 victim->Puff(abdomen);
3174 if (!Tutorial::active) {
3175 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3177 if (!victim->dead) {
3178 award_bonus(id, solidhit, 40);
3184 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3185 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3190 relative = victim->coords - coords;
3192 Normalise(&relative);
3196 if (Animation::animations[victim->animTarget].height == lowheight) {
3202 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3203 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3205 victim->jointVel(head) += relative * damagemult * 200;
3206 if (!Tutorial::active) {
3207 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3210 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3211 if (victim->howactive == typesleeping)
3212 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3213 if (creature == wolftype) {
3214 emit_sound_at(clawslicesound, victim->coords, 128.);
3216 victim->DoBloodBig(2 / victim->armorhead, 175);
3219 if (victim->damage >= victim->damagetolerance)
3221 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3222 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3224 victim->jointVel(abdomen) += relative * damagemult * 200;
3225 victim->frameTarget = 0;
3226 victim->animTarget = staggerbackhighanim;
3227 victim->targetyaw = targetyaw + 180;
3229 if (!Tutorial::active) {
3230 emit_sound_at(landsound2, victim->coords, 128.);
3232 victim->Puff(abdomen);
3233 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3234 if (creature == wolftype) {
3235 emit_sound_at(clawslicesound, victim->coords, 128.);
3237 victim->DoBloodBig(2 / victim->armorhigh, 170);
3244 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3245 if ((victim->animTarget != jumpupanim) &&
3246 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3247 (victim != this->shared_from_this())) {
3251 if (!Tutorial::active) {
3252 emit_sound_at(landsound2, victim->coords, 128.);
3255 relative = victim->coords - coords;
3257 Normalise(&relative);
3259 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3262 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3263 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3265 relative = DoRotation(relative, 0, -90, 0);
3267 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3268 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)
3269 victim->skeleton.joints[i].velocity = relative * 80;
3271 victim->Puff(rightankle);
3272 victim->Puff(leftankle);
3273 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3275 if (victim->damage >= victim->damagetolerance)
3277 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3278 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3280 relative = DoRotation(relative, 0, -90, 0);
3281 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3282 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)
3283 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3285 victim->jointVel(abdomen) += relative * damagemult * 200;
3286 victim->frameTarget = 0;
3287 victim->animTarget = staggerbackhighanim;
3288 victim->targetyaw = targetyaw + 180;
3290 if (!Tutorial::active) {
3291 emit_sound_at(landsound2, victim->coords, 128.);
3293 victim->Puff(abdomen);
3294 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3302 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3303 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3311 if (!Tutorial::active) {
3312 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3314 if (creature == wolftype) {
3315 emit_sound_at(clawslicesound, victim->coords, 128);
3317 victim->DoBloodBig(2 / victim->armorhigh, 170);
3321 relative = victim->coords - oldcoords;
3323 Normalise(&relative);
3324 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3325 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3327 victim->jointVel(abdomen) += relative * damagemult * 200;
3328 victim->Puff(abdomen);
3329 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3331 award_bonus(id, Reversal);
3334 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3335 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3336 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3337 takeWeapon(victim->weaponids[victim->weaponactive]);
3338 victim->num_weapons--;
3339 if (victim->num_weapons > 0) {
3340 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3342 victim->weaponactive = -1;
3347 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3355 emit_sound_at(whooshhitsound, victim->coords, 128.);
3358 relative = victim->coords - oldcoords;
3360 Normalise(&relative);
3361 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3362 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3364 victim->jointVel(abdomen) += relative * damagemult * 200;
3366 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3369 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3378 award_bonus(id, staffreversebonus);
3380 if (!Tutorial::active) {
3381 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3384 award_bonus(id, staffreversebonus); // Huh, again?
3387 relative = victim->coords - oldcoords;
3389 Normalise(&relative);
3390 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3391 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3393 victim->jointVel(abdomen) += relative * damagemult * 200;
3395 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3398 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3404 Normalise(&relative);
3406 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3407 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3409 victim->jointVel(lefthand) *= .1;
3410 victim->jointVel(leftwrist) *= .2;
3411 victim->jointVel(leftelbow) *= .5;
3412 victim->jointVel(leftshoulder) *= .7;
3413 victim->jointVel(righthand) *= .1;
3414 victim->jointVel(rightwrist) *= .2;
3415 victim->jointVel(rightelbow) *= .5;
3416 victim->jointVel(rightshoulder) *= .7;
3418 victim->Puff(abdomen);
3419 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3421 award_bonus(id, Reversal);
3425 if (weaponactive != -1 || creature == wolftype)
3427 if (creature == rabbittype && weaponactive != -1)
3428 if (weapons[weaponids[0]].getType() == staff)
3431 if (weaponactive != -1) {
3432 victim->DoBloodBig(2 / victim->armorhigh, 225);
3433 emit_sound_at(knifeslicesound, victim->coords);
3434 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3435 weapons[weaponids[weaponactive]].bloody = 1;
3436 weapons[weaponids[weaponactive]].blooddrip += 3;
3438 if (weaponactive == -1 && creature == wolftype) {
3439 emit_sound_at(clawslicesound, victim->coords, 128.);
3441 victim->DoBloodBig(2 / victim->armorhigh, 175);
3448 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3454 Normalise(&relative);
3456 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3457 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3459 victim->jointVel(lefthand) *= .1 - 1;
3460 victim->jointVel(leftwrist) *= .2 - 1;
3461 victim->jointVel(leftelbow) *= .5 - 1;
3462 victim->jointVel(leftshoulder) *= .7 - 1;
3463 victim->jointVel(righthand) *= .1 - 1;
3464 victim->jointVel(rightwrist) *= .2 - 1;
3465 victim->jointVel(rightelbow) *= .5 - 1;
3466 victim->jointVel(rightshoulder) *= .7 - 1;
3468 award_bonus(id, swordreversebonus);
3471 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3479 if (!Tutorial::active) {
3480 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3484 relative = victim->coords - oldcoords;
3486 Normalise(&relative);
3487 relative = DoRotation(relative, 0, -90, 0);
3488 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3489 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3491 victim->jointVel(abdomen) += relative * damagemult * 200;
3492 victim->Puff(abdomen);
3493 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3495 award_bonus(id, Reversal);
3498 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3501 victim->skeleton.spinny = 0;
3503 relative = facing * -1;
3505 Normalise(&relative);
3506 if (victim->id == 0)
3508 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3509 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3511 victim->damage = victim->damagetolerance;
3512 victim->permanentdamage = victim->damagetolerance - 1;
3515 if (weaponactive != -1 || creature == wolftype)
3517 if (creature == rabbittype && weaponactive != -1)
3518 if (weapons[weaponids[0]].getType() == staff)
3521 if (weaponactive != -1) {
3522 victim->DoBloodBig(200, 225);
3523 emit_sound_at(knifeslicesound, victim->coords);
3525 weapons[weaponids[weaponactive]].bloody = 2;
3526 weapons[weaponids[weaponactive]].blooddrip += 5;
3529 if (creature == wolftype && weaponactive == -1) {
3530 emit_sound_at(clawslicesound, victim->coords, 128.);
3532 victim->DoBloodBig(2, 175);
3535 award_bonus(id, spinecrusher);
3538 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3539 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3541 if (animTarget == knifefollowanim)
3542 victim->DoBloodBig(200, 210);
3543 if (animTarget == knifesneakattackanim) {
3544 XYZ footvel, footpoint;
3546 footpoint = weapons[weaponids[0]].tippoint;
3548 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3549 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3550 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3551 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3552 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3553 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3554 victim->DoBloodBig(200, 195);
3555 award_bonus(id, tracheotomy);
3557 if (animTarget == knifefollowanim) {
3558 award_bonus(id, Stabbonus);
3559 XYZ footvel, footpoint;
3561 footpoint = weapons[weaponids[0]].tippoint;
3563 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3564 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3565 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3566 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3567 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3568 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3571 victim->bloodloss += 10000;
3572 victim->velocity = 0;
3573 emit_sound_at(fleshstabsound, victim->coords);
3575 weapons[weaponids[weaponactive]].bloody = 2;
3576 weapons[weaponids[weaponactive]].blooddrip += 5;
3580 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3582 victim->velocity = 0;
3583 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3584 victim->skeleton.joints[i].velocity = 0;
3586 if (animTarget == knifefollowanim) {
3588 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3589 victim->skeleton.joints[i].velocity = 0;
3592 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3593 emit_sound_at(fleshstabremovesound, victim->coords);
3595 weapons[weaponids[weaponactive]].bloody = 2;
3596 weapons[weaponids[weaponactive]].blooddrip += 5;
3598 XYZ footvel, footpoint;
3600 footpoint = weapons[weaponids[0]].tippoint;
3602 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3603 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3604 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3605 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3606 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3607 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3611 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3612 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3613 award_bonus(id, backstab);
3617 XYZ footvel, footpoint;
3619 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3621 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3622 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3623 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3624 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3625 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3626 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3627 victim->DoBloodBig(200, 180);
3628 victim->DoBloodBig(200, 215);
3629 victim->bloodloss += 10000;
3630 victim->velocity = 0;
3631 emit_sound_at(fleshstabsound, victim->coords);
3633 weapons[weaponids[weaponactive]].bloody = 2;
3634 weapons[weaponids[weaponactive]].blooddrip += 5;
3638 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3640 victim->velocity = 0;
3641 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3642 victim->skeleton.joints[i].velocity = 0;
3644 if (weaponactive != -1) {
3645 emit_sound_at(fleshstabremovesound, victim->coords);
3647 weapons[weaponids[weaponactive]].bloody = 2;
3648 weapons[weaponids[weaponactive]].blooddrip += 5;
3650 XYZ footvel, footpoint;
3652 footpoint = weapons[weaponids[0]].tippoint;
3654 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3655 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3656 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3657 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3658 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3659 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3663 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3671 if (weaponactive == -1) {
3672 if (!Tutorial::active) {
3673 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3678 if (weaponactive != -1 || creature == wolftype)
3680 if (creature == rabbittype && weaponactive != -1)
3681 if (weapons[weaponids[0]].getType() == staff)
3684 if (weaponactive != -1) {
3685 victim->DoBloodBig(2 / victim->armorhead, 225);
3686 emit_sound_at(knifeslicesound, victim->coords);
3687 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3688 weapons[weaponids[weaponactive]].bloody = 1;
3689 weapons[weaponids[weaponactive]].blooddrip += 3;
3691 if (weaponactive == -1 && creature == wolftype) {
3692 emit_sound_at(clawslicesound, victim->coords, 128.);
3694 victim->DoBloodBig(2 / victim->armorhead, 175);
3698 award_bonus(id, Reversal);
3703 relative = facing * -1;
3705 Normalise(&relative);
3706 relative = DoRotation(relative, 0, 90, 0);
3708 Normalise(&relative);
3709 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3710 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3712 victim->jointVel(head) += relative * damagemult * 200;
3713 if (victim->damage < victim->damagetolerance - 100)
3714 victim->velocity = relative * 200;
3715 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3716 victim->velocity = 0;
3719 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))) {
3723 relative = facing * -1;
3725 Normalise(&relative);
3726 relative = DoRotation(relative, 0, 90, 0);
3728 Normalise(&relative);
3729 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3730 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3732 victim->jointVel(head) += relative * damagemult * 200;
3735 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3736 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3737 award_bonus(id, reverseko);
3743 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3746 animTarget = getIdle();
3747 FootLand(leftfoot, 1);
3748 FootLand(rightfoot, 1);
3750 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3751 animTarget = rollanim;
3753 emit_sound_at(movewhooshsound, coords, 128.);
3755 if (animCurrent == staggerbackhighanim) {
3756 animTarget = getIdle();
3758 if (animCurrent == staggerbackhardanim) {
3759 animTarget = getIdle();
3761 if (animCurrent == removeknifeanim) {
3762 animTarget = getIdle();
3764 if (animCurrent == crouchremoveknifeanim) {
3765 animTarget = getCrouch();
3767 if (animCurrent == backhandspringanim) {
3768 animTarget = getIdle();
3770 if (animCurrent == dodgebackanim) {
3771 animTarget = getIdle();
3773 if (animCurrent == drawleftanim) {
3774 animTarget = getIdle();
3776 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3777 animTarget = getIdle();
3778 if (animCurrent == crouchdrawrightanim) {
3779 animTarget = getCrouch();
3781 if (weaponactive == -1)
3783 else if (weaponactive == 0) {
3785 if (num_weapons == 2) {
3787 buffer = weaponids[0];
3788 weaponids[0] = weaponids[1];
3789 weaponids[1] = buffer;
3793 if (weaponactive == -1) {
3794 emit_sound_at(knifesheathesound, coords, 128.);
3796 if (weaponactive != -1) {
3797 emit_sound_at(knifedrawsound, coords, 128.);
3800 if (animCurrent == rollanim) {
3801 animTarget = getCrouch();
3802 FootLand(leftfoot, 1);
3803 FootLand(rightfoot, 1);
3806 if (animTarget == walljumprightkickanim) {
3809 if (animTarget == walljumpleftkickanim) {
3812 animTarget = jumpdownanim;
3814 if (animCurrent == climbanim) {
3815 animTarget = getCrouch();
3817 coords += facing * .1;
3818 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);
6950 if (aitype != playercontrolled && !Dialog::inDialog()) {
6952 //disable movement in editor
6953 if (Game::editorenabled)
6957 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6958 Person::players[0]->coords.y > coords.y + 2 &&
6959 !Person::players[0]->onterrain)
6963 if (aitype == pathfindtype) {
6964 if (finalpathfindpoint == -1) {
6965 float closestdistance;
6970 closestdistance = -1;
6971 for (int j = 0; j < Game::numpathpoints; j++) {
6972 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
6973 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
6975 finaltarget = Game::pathpoint[j];
6978 finalpathfindpoint = closest;
6979 for (int j = 0; j < Game::numpathpoints; j++) {
6980 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6981 DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint);
6982 if (sq(tempdist) < closestdistance)
6983 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
6984 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
6985 closestdistance = sq(tempdist);
6987 finaltarget = colpoint;
6991 finalpathfindpoint = closest;
6994 if (targetpathfindpoint == -1) {
6995 float closestdistance;
7000 closestdistance = -1;
7001 if (lastpathfindpoint == -1) {
7002 for (int j = 0; j < Game::numpathpoints; j++) {
7003 if (j != lastpathfindpoint)
7004 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7005 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7009 targetpathfindpoint = closest;
7010 for (int j = 0; j < Game::numpathpoints; j++)
7011 if (j != lastpathfindpoint)
7012 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7013 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7014 if (sq(tempdist) < closestdistance) {
7015 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7016 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7017 closestdistance = sq(tempdist);
7022 targetpathfindpoint = closest;
7024 for (int j = 0; j < Game::numpathpoints; j++)
7025 if (j != lastpathfindpoint &&
7026 j != lastpathfindpoint2 &&
7027 j != lastpathfindpoint3 &&
7028 j != lastpathfindpoint4) {
7030 if (Game::numpathpointconnect[j])
7031 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7032 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7035 if (Game::numpathpointconnect[lastpathfindpoint])
7036 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7037 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7040 tempdist = findPathDist(j, finalpathfindpoint);
7041 if (closest == -1 || tempdist < closestdistance) {
7042 closestdistance = tempdist;
7047 targetpathfindpoint = closest;
7050 losupdatedelay -= multiplier;
7052 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7053 lookyaw = targetyaw;
7055 //reached target point
7056 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7057 lastpathfindpoint4 = lastpathfindpoint3;
7058 lastpathfindpoint3 = lastpathfindpoint2;
7059 lastpathfindpoint2 = lastpathfindpoint;
7060 lastpathfindpoint = targetpathfindpoint;
7061 if (lastpathfindpoint2 == -1)
7062 lastpathfindpoint2 = lastpathfindpoint;
7063 if (lastpathfindpoint3 == -1)
7064 lastpathfindpoint3 = lastpathfindpoint2;
7065 if (lastpathfindpoint4 == -1)
7066 lastpathfindpoint4 = lastpathfindpoint3;
7067 targetpathfindpoint = -1;
7069 if ( distsqflat(&coords, &finalfinaltarget) <
7070 distsqflat(&coords, &finaltarget) ||
7071 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7072 lastpathfindpoint == finalpathfindpoint) {
7073 aitype = passivetype;
7084 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7085 targetyaw += 90 * (whichdirection * 2 - 1);
7087 if (collided < 1 || animTarget != jumpupanim)
7089 if ((collided > .8 && jumppower >= 5))
7092 if ((!Tutorial::active || cananger) &&
7094 !Person::players[0]->dead &&
7095 distsq(&coords, &Person::players[0]->coords) < 400 &&
7097 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7098 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7099 !Game::editorenabled &&
7100 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7101 aitype = attacktypecutoff;
7102 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7103 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7104 !Game::editorenabled)
7105 aitype = attacktypecutoff;
7107 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7108 losupdatedelay = .2;
7109 for (unsigned j = 0; j < Person::players.size(); j++)
7110 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7111 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7112 if (distsq(&coords, &Person::players[j]->coords) < 400)
7113 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7114 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7115 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7116 DoRotation(jointPos(head), 0, yaw, 0)
7118 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7119 *Person::players[j]->scale + Person::players[j]->coords) ||
7120 (Person::players[j]->animTarget == hanganim &&
7121 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7122 aitype = searchtype;
7124 lastseen = Person::players[j]->coords;
7129 if (aitype == attacktypecutoff && Game::musictype != 2)
7130 if (creature != wolftype) {
7136 if (aitype != passivetype && Game::leveltime > .5)
7137 howactive = typeactive;
7139 if (aitype == passivetype) {
7140 aiupdatedelay -= multiplier;
7141 losupdatedelay -= multiplier;
7142 lastseentime += multiplier;
7143 pausetime -= multiplier;
7144 if (lastseentime > 1)
7147 if (aiupdatedelay < 0) {
7148 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7149 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7150 lookyaw = targetyaw;
7151 aiupdatedelay = .05;
7153 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7154 if (waypointtype[waypoint] == wppause)
7157 if (waypoint > numwaypoints - 1)
7163 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7174 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7175 if (!avoidsomething)
7176 targetyaw += 90 * (whichdirection * 2 - 1);
7178 XYZ leftpos, rightpos;
7179 float leftdist, rightdist;
7180 leftpos = coords + DoRotation(facing, 0, 90, 0);
7181 rightpos = coords - DoRotation(facing, 0, 90, 0);
7182 leftdist = distsq(&leftpos, &avoidwhere);
7183 rightdist = distsq(&rightpos, &avoidwhere);
7184 if (leftdist < rightdist)
7191 if (collided < 1 || animTarget != jumpupanim)
7193 if ((collided > .8 && jumppower >= 5))
7198 if (!Game::editorenabled) {
7199 if (howactive <= typesleeping)
7200 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7201 for (int j = 0; j < numenvsounds; j++) {
7202 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7203 if (vol > 0 && distsq(&coords, &envsound[j]) <
7204 2 * (vol + vol * (creature == rabbittype) * 3))
7205 aitype = attacktypecutoff;
7208 if (aitype != passivetype) {
7209 if (howactive == typesleeping)
7210 setAnimation(getupfromfrontanim);
7211 howactive = typeactive;
7215 if (howactive < typesleeping &&
7216 ((!Tutorial::active || cananger) && hostile) &&
7217 !Person::players[0]->dead &&
7218 distsq(&coords, &Person::players[0]->coords) < 400 &&
7220 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7221 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7222 aitype = attacktypecutoff;
7223 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7224 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7225 aitype = attacktypecutoff;
7228 if (creature == wolftype) {
7230 for (unsigned j = 0; j < Person::players.size(); j++) {
7231 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7232 float smelldistance = 50;
7233 if (j == 0 && Person::players[j]->num_weapons > 0) {
7234 if (weapons[Person::players[j]->weaponids[0]].bloody)
7235 smelldistance = 100;
7236 if (Person::players[j]->num_weapons == 2)
7237 if (weapons[Person::players[j]->weaponids[1]].bloody)
7238 smelldistance = 100;
7241 smelldistance = 100;
7242 windsmell = windvector;
7243 Normalise(&windsmell);
7244 windsmell = windsmell * 2 + Person::players[j]->coords;
7245 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7246 aitype = attacktypecutoff;
7251 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7252 losupdatedelay = .2;
7253 for (unsigned j = 0; j < Person::players.size(); j++) {
7254 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7255 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7256 if (distsq(&coords, &Person::players[j]->coords) < 400)
7257 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7258 if ((-1 == Object::checkcollide(
7259 DoRotation(jointPos(head), 0, yaw, 0)*
7261 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7262 Person::players[j]->scale + Person::players[j]->coords) &&
7263 !Person::players[j]->isWallJump()) ||
7264 (Person::players[j]->animTarget == hanganim &&
7265 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7267 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7272 if (lastseentime <= 0) {
7273 aitype = searchtype;
7275 lastseen = Person::players[j]->coords;
7283 if (aitype == attacktypecutoff && Game::musictype != 2) {
7284 if (creature != wolftype) {
7288 if (creature == wolftype) {
7298 if (aitype == searchtype) {
7299 aiupdatedelay -= multiplier;
7300 losupdatedelay -= multiplier;
7302 lastseentime -= multiplier;
7303 lastchecktime -= multiplier;
7305 if (isRun() && !onground) {
7306 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7307 XYZ test2 = coords + facing;
7309 XYZ test = coords + facing;
7311 j = Object::checkcollide(test2, test, laststanding);
7313 j = Object::checkcollide(test2, test);
7316 setAnimation(getStop());
7319 //aitype=passivetype;
7320 aitype = pathfindtype;
7321 finalfinaltarget = waypoints[waypoint];
7322 finalpathfindpoint = -1;
7323 targetpathfindpoint = -1;
7324 lastpathfindpoint = -1;
7325 lastpathfindpoint2 = -1;
7326 lastpathfindpoint3 = -1;
7327 lastpathfindpoint4 = -1;
7332 //check out last seen location
7333 if (aiupdatedelay < 0) {
7334 targetyaw = roughDirectionTo(coords, lastseen);
7335 lookyaw = targetyaw;
7336 aiupdatedelay = .05;
7339 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7342 lastseen.x += (float(Random() % 100) - 50) / 25;
7343 lastseen.z += (float(Random() % 100) - 50) / 25;
7354 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7355 if (!avoidsomething)
7356 targetyaw += 90 * (whichdirection * 2 - 1);
7358 XYZ leftpos, rightpos;
7359 float leftdist, rightdist;
7360 leftpos = coords + DoRotation(facing, 0, 90, 0);
7361 rightpos = coords - DoRotation(facing, 0, 90, 0);
7362 leftdist = distsq(&leftpos, &avoidwhere);
7363 rightdist = distsq(&rightpos, &avoidwhere);
7364 if (leftdist < rightdist)
7371 if (collided < 1 || animTarget != jumpupanim)
7373 if ((collided > .8 && jumppower >= 5))
7376 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7377 for (int k = 0; k < numenvsounds; k++) {
7378 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7379 aitype = attacktypecutoff;
7383 if (!Person::players[0]->dead &&
7384 losupdatedelay < 0 &&
7385 !Game::editorenabled &&
7387 ((!Tutorial::active || cananger) && hostile)) {
7388 losupdatedelay = .2;
7389 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7390 aitype = attacktypecutoff;
7393 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7394 //TODO: factor out canSeePlayer()
7395 if (distsq(&coords, &Person::players[0]->coords) < 400)
7396 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7397 if ((Object::checkcollide(
7398 DoRotation(jointPos(head), 0, yaw, 0)*
7400 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7401 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7402 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7403 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7404 /* //TODO: changed j to 0 on a whim, make sure this is correct
7405 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7406 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7408 aitype = attacktypecutoff;
7413 if (lastseentime < 0) {
7414 //aitype=passivetype;
7416 aitype = pathfindtype;
7417 finalfinaltarget = waypoints[waypoint];
7418 finalpathfindpoint = -1;
7419 targetpathfindpoint = -1;
7420 lastpathfindpoint = -1;
7421 lastpathfindpoint2 = -1;
7422 lastpathfindpoint3 = -1;
7423 lastpathfindpoint4 = -1;
7427 if (aitype != gethelptype)
7430 //get help from buddies
7431 if (aitype == gethelptype) {
7432 runninghowlong += multiplier;
7433 aiupdatedelay -= multiplier;
7435 if (aiupdatedelay < 0 || ally == 0) {
7439 //TODO: factor out closest search somehow
7442 float closestdist = -1;
7443 for (unsigned k = 0; k < Person::players.size(); k++) {
7444 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7445 (Person::players[k]->howactive < typedead1) &&
7446 !Person::players[k]->skeleton.free &&
7447 (Person::players[k]->aitype == passivetype)) {
7448 float distance = distsq(&coords, &Person::players[k]->coords);
7449 if (closestdist == -1 || distance < closestdist) {
7450 closestdist = distance;
7456 if (closest != -1) {
7461 lastseen = Person::players[0]->coords;
7468 XYZ facing = coords;
7469 XYZ flatfacing = Person::players[ally]->coords;
7470 facing.y += jointPos(head).y * scale;
7471 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7472 if (-1 != Object::checkcollide(facing, flatfacing))
7475 //no available ally, run back to player
7477 Person::players[ally]->skeleton.free ||
7478 Person::players[ally]->aitype != passivetype ||
7479 lastseentime <= 0) {
7480 aitype = searchtype;
7486 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7487 lookyaw = targetyaw;
7488 aiupdatedelay = .05;
7491 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7492 aitype = searchtype;
7494 Person::players[ally]->aitype = searchtype;
7495 if (Person::players[ally]->lastseentime < lastseentime) {
7496 Person::players[ally]->lastseen = lastseen;
7497 Person::players[ally]->lastseentime = lastseentime;
7498 Person::players[ally]->lastchecktime = lastchecktime;
7502 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7503 if (!avoidsomething)
7504 targetyaw += 90 * (whichdirection * 2 - 1);
7506 XYZ leftpos, rightpos;
7507 float leftdist, rightdist;
7508 leftpos = coords + DoRotation(facing, 0, 90, 0);
7509 rightpos = coords - DoRotation(facing, 0, 90, 0);
7510 leftdist = distsq(&leftpos, &avoidwhere);
7511 rightdist = distsq(&rightpos, &avoidwhere);
7512 if (leftdist < rightdist)
7526 if (collided < 1 || animTarget != jumpupanim)
7528 if (collided > .8 && jumppower >= 5)
7532 //retreiving a weapon on the ground
7533 if (aitype == getweapontype) {
7534 aiupdatedelay -= multiplier;
7535 lastchecktime -= multiplier;
7537 if (aiupdatedelay < 0) {
7543 float closestdist = -1;
7544 for (unsigned k = 0; k < weapons.size(); k++)
7545 if (weapons[k].owner == -1) {
7546 float distance = distsq(&coords, &weapons[k].position);
7547 if (closestdist == -1 || distance < closestdist) {
7548 closestdist = distance;
7561 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7562 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7563 aitype = attacktypecutoff;
7566 if (!Person::players[0]->dead)
7568 if (weapons[ally].owner != -1 ||
7569 distsq(&coords, &weapons[ally].position) > 16) {
7570 aitype = attacktypecutoff;
7573 //TODO: factor these out as moveToward()
7574 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7575 lookyaw = targetyaw;
7576 aiupdatedelay = .05;
7580 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7581 if (!avoidsomething)
7582 targetyaw += 90 * (whichdirection * 2 - 1);
7584 XYZ leftpos, rightpos;
7585 float leftdist, rightdist;
7586 leftpos = coords + DoRotation(facing, 0, 90, 0);
7587 rightpos = coords - DoRotation(facing, 0, 90, 0);
7588 leftdist = distsq(&leftpos, &avoidwhere);
7589 rightdist = distsq(&rightpos, &avoidwhere);
7590 if (leftdist < rightdist)
7604 if (animTarget != crouchremoveknifeanim &&
7605 animTarget != removeknifeanim)
7606 throwtogglekeydown = 0;
7609 if (collided < 1 || animTarget != jumpupanim)
7611 if ((collided > .8 && jumppower >= 5))
7615 if (aitype == attacktypecutoff) {
7616 aiupdatedelay -= multiplier;
7617 //dodge or reverse rabbit kicks, knife throws, flips
7618 if (damage < damagetolerance * 2 / 3)
7619 if ((Person::players[0]->animTarget == rabbitkickanim ||
7620 Person::players[0]->animTarget == knifethrowanim ||
7621 (Person::players[0]->isFlip() &&
7622 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7623 !Person::players[0]->skeleton.free &&
7624 (aiupdatedelay < .1)) {
7628 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7629 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7630 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7631 if (abs(Random() % 2) == 0)
7632 setAnimation(backhandspringanim);
7634 setAnimation(rollanim);
7635 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7638 if (animTarget == jumpupanim || animTarget == jumpdownanim)
7639 setAnimation(flipanim);
7643 aiupdatedelay = .02;
7645 //get confused by flips
7646 if (Person::players[0]->isFlip() &&
7647 !Person::players[0]->skeleton.free &&
7648 Person::players[0]->animTarget != walljumprightkickanim &&
7649 Person::players[0]->animTarget != walljumpleftkickanim) {
7650 if (distsq(&Person::players[0]->coords, &coords) < 25)
7651 if ((1 - damage / damagetolerance) > .5)
7654 //go for weapon on the ground
7655 if (wentforweapon < 3)
7656 for (unsigned k = 0; k < weapons.size(); k++)
7657 if (creature != wolftype)
7658 if (num_weapons == 0 &&
7659 weapons[k].owner == -1 &&
7660 weapons[k].velocity.x == 0 &&
7661 weapons[k].velocity.z == 0 &&
7662 weapons[k].velocity.y == 0) {
7663 if (distsq(&coords, &weapons[k].position) < 16) {
7666 aitype = getweapontype;
7670 //dodge/reverse walljump kicks
7671 if (damage < damagetolerance / 2)
7672 if (Animation::animations[animTarget].height != highheight)
7673 if (damage < damagetolerance * .5 &&
7674 ((Person::players[0]->animTarget == walljumprightkickanim ||
7675 Person::players[0]->animTarget == walljumpleftkickanim) &&
7676 ((aiupdatedelay < .15 &&
7678 (aiupdatedelay < .08 &&
7679 difficulty != 2)))) {
7682 //walked off a ledge (?)
7683 if (isRun() && !onground)
7684 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7685 XYZ test2 = coords + facing;
7687 XYZ test = coords + facing;
7689 j = Object::checkcollide(test2, test, laststanding);
7691 j = Object::checkcollide(test2, test);
7694 setAnimation(getStop());
7697 aitype = pathfindtype;
7698 finalfinaltarget = waypoints[waypoint];
7699 finalpathfindpoint = -1;
7700 targetpathfindpoint = -1;
7701 lastpathfindpoint = -1;
7702 lastpathfindpoint2 = -1;
7703 lastpathfindpoint3 = -1;
7704 lastpathfindpoint4 = -1;
7708 //lose sight of player in the air (?)
7709 if (Person::players[0]->coords.y > coords.y + 5 &&
7710 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7711 !Person::players[0]->onterrain) {
7712 aitype = pathfindtype;
7713 finalfinaltarget = waypoints[waypoint];
7714 finalpathfindpoint = -1;
7715 targetpathfindpoint = -1;
7716 lastpathfindpoint = -1;
7717 lastpathfindpoint2 = -1;
7718 lastpathfindpoint3 = -1;
7719 lastpathfindpoint4 = -1;
7721 //it's time to think (?)
7722 if (aiupdatedelay < 0 &&
7723 !Animation::animations[animTarget].attack &&
7724 animTarget != staggerbackhighanim &&
7725 animTarget != staggerbackhardanim &&
7726 animTarget != backhandspringanim &&
7727 animTarget != dodgebackanim) {
7729 if (weaponactive == -1 && num_weapons > 0)
7730 drawkeydown = Random() % 2;
7733 rabbitkickenabled = Random() % 2;
7735 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7736 XYZ targetpoint = Person::players[0]->coords;
7737 if (distsq(&Person::players[0]->coords, &coords) <
7738 distsq(&rotatetarget, &coords))
7739 targetpoint += Person::players[0]->velocity *
7740 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7741 targetyaw = roughDirectionTo(coords, targetpoint);
7742 lookyaw = targetyaw;
7743 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7745 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7747 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7748 distsq(&coords, &Person::players[0]->coords) < 9) &&
7749 Person::players[0]->weaponactive != -1)
7751 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7755 //chill out around the corpse
7756 if (Person::players[0]->dead) {
7758 if (Random() % 10 == 0)
7760 if (Random() % 100 == 0) {
7761 aitype = pathfindtype;
7762 finalfinaltarget = waypoints[waypoint];
7763 finalpathfindpoint = -1;
7764 targetpathfindpoint = -1;
7765 lastpathfindpoint = -1;
7766 lastpathfindpoint2 = -1;
7767 lastpathfindpoint3 = -1;
7768 lastpathfindpoint4 = -1;
7777 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7778 targetyaw += 90 * (whichdirection * 2 - 1);
7780 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7784 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7788 if (aitype != playercontrolled &&
7793 for (unsigned j = 0; j < Person::players.size(); j++)
7794 if (j != id && !Person::players[j]->skeleton.free &&
7795 Person::players[j]->hasvictim &&
7796 (Tutorial::active && reversaltrain ||
7797 Random() % 2 == 0 && difficulty == 2 ||
7798 Random() % 4 == 0 && difficulty == 1 ||
7799 Random() % 8 == 0 && difficulty == 0 ||
7800 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7801 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7802 (Random() % 2 == 0 || difficulty == 2) ||
7803 (isIdle() || isRun()) &&
7804 Person::players[j]->weaponactive != -1 ||
7805 Person::players[j]->animTarget == swordslashanim &&
7806 weaponactive != -1 ||
7807 Person::players[j]->animTarget == staffhitanim ||
7808 Person::players[j]->animTarget == staffspinhitanim))
7809 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7810 Person::players[j]->victim == Person::players[id] &&
7811 (Person::players[j]->animTarget == sweepanim ||
7812 Person::players[j]->animTarget == spinkickanim ||
7813 Person::players[j]->animTarget == staffhitanim ||
7814 Person::players[j]->animTarget == staffspinhitanim ||
7815 Person::players[j]->animTarget == winduppunchanim ||
7816 Person::players[j]->animTarget == upunchanim ||
7817 Person::players[j]->animTarget == wolfslapanim ||
7818 Person::players[j]->animTarget == knifeslashstartanim ||
7819 Person::players[j]->animTarget == swordslashanim &&
7820 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7821 weaponactive != -1))) {
7829 Person::players[target]->Reverse();
7834 if (collided > .8 && jumppower >= 5 ||
7835 distsq(&coords, &Person::players[0]->coords) > 400 &&
7837 creature == rabbittype)
7839 //TODO: why are we controlling the human?
7840 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7841 Person::players[0]->jumpkeydown = 0;
7842 if (Person::players[0]->animTarget == jumpdownanim &&
7843 distsq(&Person::players[0]->coords, &coords) < 40)
7848 if (Tutorial::active)
7853 XYZ facing = coords;
7854 XYZ flatfacing = Person::players[0]->coords;
7855 facing.y += jointPos(head).y * scale;
7856 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7858 if (-1 != Object::checkcollide(facing, flatfacing)) {
7861 if (lastseentime <= 0 &&
7862 (creature != wolftype ||
7863 weaponstuck == -1)) {
7864 aitype = searchtype;
7866 lastseen = Person::players[0]->coords;
7873 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7874 (aitype == attacktypecutoff ||
7875 aitype == searchtype))
7876 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7877 XYZ test = Person::players[0]->coords;
7879 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7883 if (aitype == passivetype && !(numwaypoints > 1) ||
7885 pause && damage > superpermanentdamage) {
7904 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7905 facing = flatfacing;
7907 if (aitype == attacktypecutoff) {
7908 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7909 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7910 } else if (howactive >= typesleeping) {
7911 targetheadyaw = targetyaw;
7912 targetheadpitch = 0;
7914 if (interestdelay <= 0) {
7915 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7916 headtarget = coords;
7917 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7918 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7919 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7920 headtarget += facing * 1.5;
7922 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7923 targetheadpitch = pitchTo(coords, headtarget);