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);
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);
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 (int 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;
4813 if (dead == 1 || howactive == typesleeping) {
4814 unconscioustime += multiplier;
4815 //If unconscious, close eyes and mouth
4816 if (righthandmorphend != 0)
4817 righthandmorphness = 0;
4818 righthandmorphend = 0;
4819 targetrighthandmorphness = 1;
4821 if (lefthandmorphend != 0)
4822 lefthandmorphness = 0;
4823 lefthandmorphend = 0;
4824 targetlefthandmorphness = 1;
4826 if (headmorphend != 3 && headmorphend != 5)
4829 targetheadmorphness = 1;
4833 if (howactive > typesleeping) {
4836 if (bloodtoggle && !bled) {
4837 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4839 if (bloodtoggle && !bled)
4840 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4841 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4842 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4846 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4851 if (dead == 2 || howactive > typesleeping) {
4852 //If dead, open mouth and hands
4853 if (righthandmorphend != 0)
4854 righthandmorphness = 0;
4855 righthandmorphend = 0;
4856 targetrighthandmorphness = 1;
4858 if (lefthandmorphend != 0)
4859 lefthandmorphness = 0;
4860 lefthandmorphend = 0;
4861 targetlefthandmorphness = 1;
4863 if (headmorphend != 2)
4866 targetheadmorphness = 1;
4869 if (stunned > 0 && !dead && headmorphend != 2) {
4870 if (headmorphend != 4)
4873 targetheadmorphness = 1;
4876 if (damage > damagetolerance && !dead) {
4879 unconscioustime = 0;
4881 if (creature == wolftype) {
4882 award_bonus(0, Wolfbonus);
4887 if (weaponactive != -1) {
4888 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4889 weapons[weaponids[0]].velocity.x += .01;
4892 weaponids[0] = weaponids[num_weapons];
4893 if (weaponstuck == num_weapons)
4897 for (unsigned i = 0; i < Person::players.size(); i++) {
4898 Person::players[i]->wentforweapon = 0;
4904 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4913 damage -= multiplier * 13;
4914 permanentdamage -= multiplier * 4;
4915 if (isIdle() || isCrouch()) {
4916 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 (unsigned int 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 (unsigned int 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 if (speechdelay <= 0) {
5437 unsigned int i = abs(Random() % 4);
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 ||
5554 animTarget == staffspinhitreversalanim ||
5555 animTarget == staffspinhitreversedanim ||
5556 animTarget == staffhitreversalanim ||
5557 animTarget == staffhitreversedanim ||
5558 animTarget == hurtidleanim ||
5559 animTarget == winduppunchanim ||
5560 animTarget == swordslashreversalanim ||
5561 animTarget == swordslashreversedanim ||
5562 animTarget == knifeslashreversalanim ||
5563 animTarget == knifeslashreversedanim ||
5564 animTarget == knifethrowanim ||
5565 animTarget == knifefollowanim ||
5566 animTarget == knifefollowedanim ||
5567 animTarget == killanim ||
5568 animTarget == dropkickanim ||
5569 animTarget == upunchanim ||
5570 animTarget == knifeslashstartanim ||
5571 animTarget == swordslashanim ||
5572 animTarget == staffhitanim ||
5573 animTarget == staffspinhitanim ||
5574 animTarget == staffgroundsmashanim ||
5575 animTarget == spinkickreversalanim ||
5576 animTarget == sweepreversalanim ||
5577 animTarget == lowkickanim ||
5578 animTarget == sweepreversedanim ||
5579 animTarget == rabbitkickreversalanim ||
5580 animTarget == rabbitkickreversedanim ||
5581 animTarget == jumpreversalanim ||
5582 animTarget == jumpreversedanim) {
5583 //close hands and yell
5584 if (righthandmorphend != 1 &&
5585 righthandmorphness == targetrighthandmorphness) {
5586 righthandmorphness = 0;
5587 righthandmorphend = 1;
5588 targetrighthandmorphness = 1;
5591 if (lefthandmorphend != 1 &&
5592 lefthandmorphness == targetlefthandmorphness) {
5593 lefthandmorphness = 0;
5594 lefthandmorphend = 1;
5595 targetlefthandmorphness = 1;
5598 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5601 targetheadmorphness = 1;
5608 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5609 (victim->aitype != searchtype) && (aitype != passivetype) &&
5610 (aitype != searchtype) && (victim->id < Person::players.size())) {
5611 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5615 if (!dead && animTarget != hurtidleanim)
5616 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5617 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5620 targetheadmorphness = 1;
5624 if (weaponactive != -1) {
5625 if (weapons[weaponids[weaponactive]].getType() != staff) {
5626 righthandmorphstart = 1;
5627 righthandmorphend = 1;
5629 if (weapons[weaponids[weaponactive]].getType() == staff) {
5630 righthandmorphstart = 2;
5631 righthandmorphend = 2;
5633 targetrighthandmorphness = 1;
5636 terrainnormal = terrain.getNormal(coords.x, coords.z);
5638 if (Animation::animations[animTarget].attack != reversal) {
5639 if (!isnormal(coords.x))
5647 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5648 facing = flatfacing;
5649 ReflectVector(&facing, terrainnormal);
5653 animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5655 targettilt2 = -facing.y * 20;
5660 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5662 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5663 flatvelocity = velocity;
5665 flatvelspeed = findLength(&flatvelocity);
5666 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5667 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5672 if (targettilt > 25)
5674 if (targettilt < -25)
5678 if (targettilt2 > 45)
5680 if (targettilt2 < -45)
5682 if (abs(tilt2 - targettilt2) < multiplier * 400)
5683 tilt2 = targettilt2;
5684 else if (tilt2 > targettilt2) {
5685 tilt2 -= multiplier * 400;
5686 } else if (tilt2 < targettilt2) {
5687 tilt2 += multiplier * 400;
5689 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5696 if (!isnormal(targettilt) && targettilt) {
5699 if (!isnormal(targettilt2) && targettilt2) {
5704 if (animTarget == rabbittackleanim) {
5705 velocity += facing * multiplier * speed * 700 * scale;
5706 velspeed = findLength(&velocity);
5707 if (velspeed > speed * 65 * scale) {
5708 velocity /= velspeed;
5709 velspeed = speed * 65 * scale;
5710 velocity *= velspeed;
5712 velocity.y += gravity * multiplier * 20;
5713 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5714 velspeed = findLength(&velocity);
5715 velocity = flatfacing * velspeed;
5717 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5718 if (isRun() || animTarget == rabbitkickanim) {
5719 velocity += facing * multiplier * speed * 700 * scale;
5720 velspeed = findLength(&velocity);
5721 if (velspeed > speed * 45 * scale) {
5722 velocity /= velspeed;
5723 velspeed = speed * 45 * scale;
5724 velocity *= velspeed;
5726 velocity.y += gravity * multiplier * 20;
5727 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5728 velspeed = findLength(&velocity);
5729 if (velspeed < speed * 30 * scale)
5730 velspeed = speed * 30 * scale;
5731 velocity = flatfacing * velspeed;
5733 } else if (isRun()) {
5734 velocity += facing * multiplier * speed * 700 * scale;
5735 velspeed = findLength(&velocity);
5736 if (creature == rabbittype) {
5737 if (velspeed > speed * 55 * scale) {
5738 velocity /= velspeed;
5739 velspeed = speed * 55 * scale;
5740 velocity *= velspeed;
5743 if (creature == wolftype) {
5744 if (velspeed > speed * 75 * scale) {
5745 velocity /= velspeed;
5746 velspeed = speed * 75 * scale;
5747 velocity *= velspeed;
5750 velocity.y += gravity * multiplier * 20;
5751 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5752 velspeed = findLength(&velocity);
5753 velocity = flatfacing * velspeed;
5756 if (animTarget == rollanim && targetFrame().label != 6) {
5757 velocity += facing * multiplier * speed * 700 * scale;
5758 velspeed = findLength(&velocity);
5759 if (velspeed > speed * 45 * scale) {
5760 velocity /= velspeed;
5761 velspeed = speed * 45 * scale;
5762 velocity *= velspeed;
5764 velocity.y += gravity * multiplier * 20;
5765 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5766 velspeed = findLength(&velocity);
5767 velocity = flatfacing * velspeed;
5770 if (animTarget == sneakanim || animTarget == walkanim) {
5771 velocity += facing * multiplier * speed * 700 * scale;
5772 velspeed = findLength(&velocity);
5773 if (velspeed > speed * 12 * scale) {
5774 velocity /= velspeed;
5775 velspeed = speed * 12 * scale;
5776 velocity *= velspeed;
5778 velocity.y += gravity * multiplier * 20;
5779 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5780 velspeed = findLength(&velocity);
5781 velocity = flatfacing * velspeed;
5784 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5785 velocity += facing * multiplier * speed * 700 * scale;
5786 velspeed = findLength(&velocity);
5787 if (velspeed > speed * 2 * scale) {
5788 velocity /= velspeed;
5789 velspeed = speed * 2 * scale;
5790 velocity *= velspeed;
5792 velocity.y += gravity * multiplier * 20;
5793 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5794 velspeed = findLength(&velocity);
5795 velocity = flatfacing * velspeed;
5799 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5800 velocity -= facing * multiplier * speed * 700 * scale;
5801 velspeed = findLength(&velocity);
5802 if (velspeed > speed * 2 * scale) {
5803 velocity /= velspeed;
5804 velspeed = speed * 2 * scale;
5805 velocity *= velspeed;
5807 velocity.y += gravity * multiplier * 20;
5808 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5809 velspeed = findLength(&velocity);
5810 velocity = flatfacing * velspeed * -1;
5813 if (animTarget == fightsidestep) {
5814 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5815 velspeed = findLength(&velocity);
5816 if (velspeed > speed * 12 * scale) {
5817 velocity /= velspeed;
5818 velspeed = speed * 12 * scale;
5819 velocity *= velspeed;
5821 velocity.y += gravity * multiplier * 20;
5822 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5823 velspeed = findLength(&velocity);
5824 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5827 if (animTarget == staggerbackhighanim) {
5828 coords -= facing * multiplier * speed * 16 * scale;
5831 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5832 coords -= facing * multiplier * speed * 20 * scale;
5836 if (animTarget == backhandspringanim) {
5837 //coords-=facing*multiplier*50*scale;
5838 velocity += facing * multiplier * speed * 700 * scale * -1;
5839 velspeed = findLength(&velocity);
5840 if (velspeed > speed * 50 * scale) {
5841 velocity /= velspeed;
5842 velspeed = speed * 50 * scale;
5843 velocity *= velspeed;
5845 velocity.y += gravity * multiplier * 20;
5846 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5847 velspeed = findLength(&velocity);
5848 velocity = flatfacing * velspeed * -1;
5850 if (animTarget == dodgebackanim) {
5851 //coords-=facing*multiplier*50*scale;
5852 velocity += facing * multiplier * speed * 700 * scale * -1;
5853 velspeed = findLength(&velocity);
5854 if (velspeed > speed * 60 * scale) {
5855 velocity /= velspeed;
5856 velspeed = speed * 60 * scale;
5857 velocity *= velspeed;
5859 velocity.y += gravity * multiplier * 20;
5860 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5861 velspeed = findLength(&velocity);
5862 velocity = flatfacing * velspeed * -1;
5865 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5866 velspeed = findLength(&velocity);
5870 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5871 velocity.y += gravity * multiplier;
5874 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5875 coords += velocity * multiplier;
5877 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5878 if (isFlip() && targetFrame().label == 7)
5881 if (animTarget == jumpupanim) {
5883 animTarget = getIdle();
5890 pause_sound(whooshsound);
5891 OPENAL_SetVolume(channels[whooshsound], 0);
5894 if (animTarget == jumpdownanim || isFlip()) {
5895 if (isFlip())jumppower = -4;
5896 animTarget = getLanding();
5897 emit_sound_at(landsound, coords, 128.);
5900 addEnvSound(coords);
5905 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5906 coords.y += gravity * multiplier * 2;
5907 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5908 coords.y = terrain.getHeight(coords.x, coords.z);
5913 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)) {
5914 velspeed = findLength(&velocity);
5916 if (velspeed < multiplier * 300 * scale) {
5919 velocity -= velocity / velspeed * multiplier * 300 * scale;
5920 if (velspeed > 5 && (isLanding() || isLandhard())) {
5921 skiddingdelay += multiplier;
5922 if (skiddelay <= 0) {
5923 FootLand(leftfoot, .5);
5924 FootLand(rightfoot, .5);
5932 velspeed = findLength(&velocity);
5934 if (velspeed < multiplier * 600 * scale) {
5937 velocity -= velocity / velspeed * multiplier * 600 * scale;
5939 if (velspeed > 5 && (isLanding() || isLandhard())) {
5940 skiddingdelay += multiplier;
5941 if (skiddelay <= 0) {
5942 FootLand(leftfoot, .5);
5943 FootLand(rightfoot, .5);
5950 if (skiddingdelay < 0)
5951 skiddingdelay += multiplier;
5952 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5954 if (!onterrain || environment == grassyenvironment) {
5955 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5957 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5961 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5962 terrainnormal = victim->coords - coords;
5963 Normalise(&terrainnormal);
5964 targetyaw = -asin(0 - terrainnormal.x);
5965 targetyaw *= 360 / 6.28;
5966 if (terrainnormal.z < 0)
5967 targetyaw = 180 - targetyaw;
5968 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5971 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5972 targetyaw = victim->targetyaw;
5974 if (animTarget == rabbittacklinganim) {
5975 coords = victim->coords;
5978 skeleton.oldfree = skeleton.free;
5982 midterrain.x = terrain.size * terrain.scale / 2;
5983 midterrain.z = terrain.size * terrain.scale / 2;
5984 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5986 tempposit = coords - midterrain;
5988 Normalise(&tempposit);
5989 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5990 coords.x = tempposit.x + midterrain.x;
5991 coords.z = tempposit.z + midterrain.z;
5997 * inverse kinematics helper function
5999 void IKHelper(Person *p, float interp)
6001 XYZ point, change, change2;
6002 float heightleft, heightright;
6004 // TODO: implement localToWorld and worldToLocal
6005 // but keep in mind it won't be the same math if player is ragdolled or something
6006 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
6007 // then comb through code for places where to use it
6009 // point = localToWorld(jointPos(leftfoot))
6010 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
6011 // adjust height of foot
6012 heightleft = terrain.getHeight(point.x, point.z) + .04;
6013 point.y = heightleft;
6014 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
6015 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
6016 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
6017 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
6018 // move ankle along with foot
6019 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
6020 // average knee pos between old and new pos
6021 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
6023 // do same as above for right leg
6024 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
6025 heightright = terrain.getHeight(point.x, point.z) + .04;
6026 point.y = heightright;
6027 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
6028 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
6029 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
6030 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
6031 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
6033 // fix up skeleton now that we've moved body parts?
6034 p->skeleton.DoConstraints(&p->coords, &p->scale);
6041 int Person::DrawSkeleton()
6043 int oldplayerdetail;
6044 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6045 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6055 glAlphaFunc(GL_GREATER, 0.0001);
6057 float terrainheight;
6061 if (!isnormal(tilt))
6063 if (!isnormal(tilt2))
6065 oldplayerdetail = playerdetail;
6067 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6070 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6073 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6078 if (playerdetail != oldplayerdetail) {
6080 normalsupdatedelay = 0;
6082 static float updatedelaychange;
6083 static float morphness;
6084 static float framemult;
6086 skeleton.FindForwards();
6087 if (howactive == typesittingwall) {
6088 skeleton.specialforward[1] = 0;
6089 skeleton.specialforward[1].z = 1;
6095 static int weaponattachmuscle;
6096 static int weaponrotatemuscle;
6097 static XYZ weaponpoint;
6098 static int start, endthing;
6099 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6100 if (!isSleeping() && !isSitting()) {
6101 // TODO: give these meaningful names
6102 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6103 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6104 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6105 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6107 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6109 if (creature == wolftype)
6113 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6114 IKHelper(this, target);
6115 if (creature == wolftype)
6116 IKHelper(this, target);
6119 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6120 IKHelper(this, 1 - target);
6121 if (creature == wolftype)
6122 IKHelper(this, 1 - target);
6126 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()))
6129 targetheadyaw = -targetyaw;
6130 targetheadpitch = 0;
6131 if (Animation::animations[animTarget].attack == 3)
6132 targetheadyaw += 180;
6134 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6135 skeleton.drawmodel.vertex[i] = 0;
6136 skeleton.drawmodel.vertex[i].y = 999;
6138 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6139 skeleton.drawmodellow.vertex[i] = 0;
6140 skeleton.drawmodellow.vertex[i].y = 999;
6142 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6143 skeleton.drawmodelclothes.vertex[i] = 0;
6144 skeleton.drawmodelclothes.vertex[i].y = 999;
6146 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6147 // convenience renames
6148 const int p1 = skeleton.muscles[i].parent1->label;
6149 const int p2 = skeleton.muscles[i].parent2->label;
6151 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6156 if (p1 == righthand || p2 == righthand) {
6157 morphness = righthandmorphness;
6158 start = righthandmorphstart;
6159 endthing = righthandmorphend;
6161 if (p1 == lefthand || p2 == lefthand) {
6162 morphness = lefthandmorphness;
6163 start = lefthandmorphstart;
6164 endthing = lefthandmorphend;
6166 if (p1 == head || p2 == head) {
6167 morphness = headmorphness;
6168 start = headmorphstart;
6169 endthing = headmorphend;
6171 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6172 morphness = chestmorphness;
6173 start = chestmorphstart;
6174 endthing = chestmorphend;
6176 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6177 morphness = tailmorphness;
6178 start = tailmorphstart;
6179 endthing = tailmorphend;
6182 skeleton.FindRotationMuscle(i, animTarget);
6183 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6184 glMatrixMode(GL_MODELVIEW);
6188 glRotatef(tilt2, 1, 0, 0);
6190 glRotatef(tilt, 0, 0, 1);
6193 glTranslatef(mid.x, mid.y, mid.z);
6195 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6196 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6198 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6199 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6201 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6202 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6204 if (playerdetail || skeleton.free == 3) {
6205 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6206 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6207 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6208 glMatrixMode(GL_MODELVIEW);
6210 if (p1 == abdomen || p2 == abdomen)
6211 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6212 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6213 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6214 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6215 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6216 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6217 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6218 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6219 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6220 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6221 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6222 if (p1 == head || p2 == head)
6223 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6224 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6225 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6226 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6227 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6228 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6229 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6233 if (!playerdetail || skeleton.free == 3) {
6234 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6235 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6236 glMatrixMode(GL_MODELVIEW);
6238 if (p1 == abdomen || p2 == abdomen)
6239 glTranslatef(v0.x * proportionbody.x,
6240 v0.y * proportionbody.y,
6241 v0.z * proportionbody.z);
6242 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6243 glTranslatef(v0.x * proportionarms.x,
6244 v0.y * proportionarms.y,
6245 v0.z * proportionarms.z);
6246 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6247 glTranslatef(v0.x * proportionlegs.x,
6248 v0.y * proportionlegs.y,
6249 v0.z * proportionlegs.z);
6250 if (p1 == head || p2 == head)
6251 glTranslatef(v0.x * proportionhead.x,
6252 v0.y * proportionhead.y,
6253 v0.z * proportionhead.z);
6255 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6256 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6257 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6258 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6264 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6265 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6267 glMatrixMode(GL_MODELVIEW);
6271 glRotatef(tilt2, 1, 0, 0);
6273 glRotatef(tilt, 0, 0, 1);
6274 glTranslatef(mid.x, mid.y, mid.z);
6275 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6276 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6278 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6279 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6281 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6282 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6284 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6285 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6286 glMatrixMode(GL_MODELVIEW);
6288 if (p1 == abdomen || p2 == abdomen)
6289 glTranslatef(v0.x * proportionbody.x,
6290 v0.y * proportionbody.y,
6291 v0.z * proportionbody.z);
6292 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6293 glTranslatef(v0.x * proportionarms.x,
6294 v0.y * proportionarms.y,
6295 v0.z * proportionarms.z);
6296 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6297 glTranslatef(v0.x * proportionlegs.x,
6298 v0.y * proportionlegs.y,
6299 v0.z * proportionlegs.z);
6300 if (p1 == head || p2 == head)
6301 glTranslatef(v0.x * proportionhead.x,
6302 v0.y * proportionhead.y,
6303 v0.z * proportionhead.z);
6304 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6305 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6306 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6307 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6312 updatedelay = 1 + (float)(Random() % 100) / 1000;
6314 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6315 normalsupdatedelay = 1;
6316 if (playerdetail || skeleton.free == 3)
6317 skeleton.drawmodel.CalculateNormals(0);
6318 if (!playerdetail || skeleton.free == 3)
6319 skeleton.drawmodellow.CalculateNormals(0);
6320 if (skeleton.clothes)
6321 skeleton.drawmodelclothes.CalculateNormals(0);
6323 if (playerdetail || skeleton.free == 3)
6324 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6325 if (!playerdetail || skeleton.free == 3)
6326 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6327 if (skeleton.clothes) {
6328 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6333 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6334 if (updatedelaychange > -realmultiplier * 30)
6335 updatedelaychange = -realmultiplier * 30;
6336 if (updatedelaychange > -framemult * 4)
6337 updatedelaychange = -framemult * 4;
6338 if (skeleton.free == 1)
6339 updatedelaychange *= 6;
6341 updatedelaychange *= 8;
6342 updatedelay += updatedelaychange;
6344 glMatrixMode(GL_MODELVIEW);
6346 glTranslatef(coords.x, coords.y - .02, coords.z);
6347 if (!skeleton.free) {
6348 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6349 glRotatef(yaw, 0, 1, 0);
6353 glColor4f(.4, 1, .4, 1);
6354 glDisable(GL_LIGHTING);
6355 glDisable(GL_TEXTURE_2D);
6358 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6359 XYZ &v0 = skeleton.drawmodel.vertex[i];
6360 glVertex3f(v0.x, v0.y, v0.z);
6366 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6367 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6368 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6369 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6370 glVertex3f(v0.x, v0.y, v0.z);
6371 glVertex3f(v1.x, v1.y, v1.z);
6372 glVertex3f(v1.x, v1.y, v1.z);
6373 glVertex3f(v2.x, v2.y, v2.z);
6374 glVertex3f(v2.x, v2.y, v2.z);
6375 glVertex3f(v0.x, v0.y, v0.z);
6381 terrainlight = terrain.getLighting(coords.x, coords.z);
6382 distance = distsq(&viewer, &coords);
6383 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6387 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6388 if (terrainheight < 1)
6390 if (terrainheight > 1.7)
6391 terrainheight = 1.7;
6393 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6394 glDisable(GL_BLEND);
6395 glAlphaFunc(GL_GREATER, 0.0001);
6396 glEnable(GL_TEXTURE_2D);
6398 glDisable(GL_TEXTURE_2D);
6399 glColor4f(.7, .35, 0, .5);
6401 glEnable(GL_LIGHTING);
6404 if (Tutorial::active && id != 0) {
6405 glColor4f(.7, .7, .7, 0.6);
6407 glEnable(GL_LIGHTING);
6409 if (canattack && cananger)
6410 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6411 glDisable(GL_TEXTURE_2D);
6412 glColor4f(1, 0, 0, 0.8);
6414 glMatrixMode(GL_TEXTURE);
6416 glTranslatef(0, -smoketex, 0);
6417 glTranslatef(-smoketex, 0, 0);
6421 if (Tutorial::active && (id != 0))
6422 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6424 skeleton.drawmodel.draw();
6427 if (!playerdetail) {
6428 if (Tutorial::active && (id != 0))
6429 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6431 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6434 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6435 if (Tutorial::active && id != 0) {
6437 glMatrixMode(GL_MODELVIEW);
6438 glEnable(GL_TEXTURE_2D);
6439 glColor4f(.7, .7, .7, 0.6);
6441 glEnable(GL_LIGHTING);
6443 if (canattack && cananger)
6444 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6445 glDisable(GL_TEXTURE_2D);
6446 glColor4f(1, 0, 0, 0.8);
6448 glMatrixMode(GL_TEXTURE);
6450 glTranslatef(0, -smoketex * .6, 0);
6451 glTranslatef(smoketex * .6, 0, 0);
6454 if (Tutorial::active && (id != 0))
6455 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6457 skeleton.drawmodel.draw();
6460 if (!playerdetail) {
6461 if (Tutorial::active && (id != 0))
6462 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6464 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6469 if (Tutorial::active && id != 0) {
6471 glMatrixMode(GL_MODELVIEW);
6472 glEnable(GL_TEXTURE_2D);
6474 if (skeleton.clothes) {
6478 skeleton.drawmodelclothes.draw();
6480 skeleton.drawmodelclothes.drawimmediate();
6486 if (num_weapons > 0) {
6487 for (k = 0; k < num_weapons; k++) {
6489 if (weaponactive == k) {
6490 if (weapons[i].getType() != staff) {
6491 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6492 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6493 weaponattachmuscle = j;
6496 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6497 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) {
6498 weaponrotatemuscle = j;
6501 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6502 if (creature == wolftype)
6503 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6505 if (weapons[i].getType() == staff) {
6506 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6507 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6508 weaponattachmuscle = j;
6511 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6512 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) {
6513 weaponrotatemuscle = j;
6516 //weaponpoint=jointPos(rightwrist);
6517 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6518 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6519 XYZ tempnormthing, vec1, vec2;
6520 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6521 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6522 CrossProduct(&vec1, &vec2, &tempnormthing);
6523 Normalise(&tempnormthing);
6524 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6525 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6528 if (weaponactive != k && weaponstuck != k) {
6529 if (weapons[i].getType() == knife)
6530 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6531 if (weapons[i].getType() == sword)
6532 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6533 if (weapons[i].getType() == staff)
6534 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6535 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6536 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) {
6537 weaponrotatemuscle = j;
6541 if (weaponstuck == k) {
6542 if (weaponstuckwhere == 0)
6543 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6545 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6546 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6547 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) {
6548 weaponrotatemuscle = j;
6552 if (skeleton.free) {
6553 weapons[i].position = weaponpoint * scale + coords;
6554 weapons[i].bigrotation = 0;
6555 weapons[i].bigtilt = 0;
6556 weapons[i].bigtilt2 = 0;
6558 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;
6559 weapons[i].bigrotation = yaw;
6560 weapons[i].bigtilt = tilt;
6561 weapons[i].bigtilt2 = tilt2;
6563 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6564 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6565 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6566 if (weaponactive == k) {
6567 if (weapons[i].getType() == knife) {
6568 weapons[i].smallrotation = 180;
6569 weapons[i].smallrotation2 = 0;
6570 if (isCrouch() || wasCrouch()) {
6571 weapons[i].smallrotation2 = 20;
6573 if (animTarget == hurtidleanim) {
6574 weapons[i].smallrotation2 = 50;
6576 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6577 XYZ temppoint1, temppoint2;
6580 temppoint1 = jointPos(righthand);
6581 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6582 distance = findDistance(&temppoint1, &temppoint2);
6583 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6584 weapons[i].rotation2 *= 360 / 6.28;
6587 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6588 weapons[i].rotation1 *= 360 / 6.28;
6589 weapons[i].rotation3 = 0;
6590 weapons[i].smallrotation = -90;
6591 weapons[i].smallrotation2 = 0;
6592 if (temppoint1.x > temppoint2.x)
6593 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6595 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6596 XYZ temppoint1, temppoint2;
6599 temppoint1 = jointPos(righthand);
6600 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6601 distance = findDistance(&temppoint1, &temppoint2);
6602 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6603 weapons[i].rotation2 *= 360 / 6.28;
6606 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6607 weapons[i].rotation1 *= 360 / 6.28;
6608 weapons[i].rotation3 = 0;
6609 weapons[i].smallrotation = 90;
6610 weapons[i].smallrotation2 = 0;
6611 if (temppoint1.x > temppoint2.x)
6612 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6614 if (animTarget == knifethrowanim) {
6615 weapons[i].smallrotation = 90;
6616 //weapons[i].smallrotation2=-90;
6617 weapons[i].smallrotation2 = 0;
6618 weapons[i].rotation1 = 0;
6619 weapons[i].rotation2 = 0;
6620 weapons[i].rotation3 = 0;
6622 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6623 weapons[i].smallrotation = -90;
6624 weapons[i].rotation1 = 0;
6625 weapons[i].rotation2 = 0;
6626 weapons[i].rotation3 = 0;
6629 if (weapons[i].getType() == sword) {
6630 weapons[i].smallrotation = 0;
6631 weapons[i].smallrotation2 = 0;
6632 if (animTarget == knifethrowanim) {
6633 weapons[i].smallrotation = -90;
6634 weapons[i].smallrotation2 = 0;
6635 weapons[i].rotation1 = 0;
6636 weapons[i].rotation2 = 0;
6637 weapons[i].rotation3 = 0;
6639 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)) {
6640 XYZ temppoint1, temppoint2;
6643 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6644 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6645 distance = findDistance(&temppoint1, &temppoint2);
6646 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6647 weapons[i].rotation2 *= 360 / 6.28;
6650 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6651 weapons[i].rotation1 *= 360 / 6.28;
6652 weapons[i].rotation3 = 0;
6653 weapons[i].smallrotation = 90;
6654 weapons[i].smallrotation2 = 0;
6655 if (temppoint1.x > temppoint2.x)
6656 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6659 if (weapons[i].getType() == staff) {
6660 weapons[i].smallrotation = 100;
6661 weapons[i].smallrotation2 = 0;
6662 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6663 XYZ temppoint1, temppoint2;
6666 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6667 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6668 distance = findDistance(&temppoint1, &temppoint2);
6669 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6670 weapons[i].rotation2 *= 360 / 6.28;
6673 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6674 weapons[i].rotation1 *= 360 / 6.28;
6675 weapons[i].rotation3 = 0;
6676 weapons[i].smallrotation = 90;
6677 weapons[i].smallrotation2 = 0;
6678 if (temppoint1.x > temppoint2.x)
6679 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6683 if (weaponactive != k && weaponstuck != k) {
6684 if (weapons[i].getType() == knife) {
6685 weapons[i].smallrotation = -70;
6686 weapons[i].smallrotation2 = 10;
6688 if (weapons[i].getType() == sword) {
6689 weapons[i].smallrotation = -100;
6690 weapons[i].smallrotation2 = -8;
6692 if (weapons[i].getType() == staff) {
6693 weapons[i].smallrotation = -100;
6694 weapons[i].smallrotation2 = -8;
6697 if (weaponstuck == k) {
6698 if (weaponstuckwhere == 0)
6699 weapons[i].smallrotation = 180;
6701 weapons[i].smallrotation = 0;
6702 weapons[i].smallrotation2 = 10;
6711 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6713 if (animCurrent != animTarget)
6715 if (skeleton.free == 2)
6724 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6727 static float distance;
6728 static float olddistance;
6729 static int intersecting;
6730 static int firstintersecting;
6733 static XYZ start, end;
6734 static float slopethreshold = -.4;
6736 firstintersecting = -1;
6740 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6743 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6744 for (i = 0; i < 4; i++) {
6745 for (j = 0; j < model->TriangleNum; j++) {
6746 if (model->facenormals[j].y <= slopethreshold) {
6748 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)));
6749 if (distance < radius) {
6750 point = *p1 - model->facenormals[j] * distance;
6751 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]]))
6754 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6755 &model->vertex[model->Triangles[j].vertex[1]],
6758 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6759 &model->vertex[model->Triangles[j].vertex[2]],
6762 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6763 &model->vertex[model->Triangles[j].vertex[2]],
6766 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6770 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)) {
6771 p1->y = point.y + radius;
6772 if ((animTarget == jumpdownanim || isFlip())) {
6773 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6776 if (animTarget == jumpupanim) {
6778 animTarget = getIdle();
6785 pause_sound(whooshsound);
6786 OPENAL_SetVolume(channels[whooshsound], 0);
6789 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6792 animTarget = getLanding();
6793 emit_sound_at(landsound, coords, 128.);
6796 addEnvSound(coords);
6803 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6804 olddistance = distance;
6805 firstintersecting = j;
6810 for (j = 0; j < model->TriangleNum; j++) {
6811 if (model->facenormals[j].y > slopethreshold) {
6814 start.y -= radius / 4;
6815 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6816 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6817 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6818 distance = abs((model->facenormals[j].x * start.x)
6819 + (model->facenormals[j].y * start.y)
6820 + (model->facenormals[j].z * start.z)
6821 - ((model->facenormals[j].x * v0.x)
6822 + (model->facenormals[j].y * v0.y)
6823 + (model->facenormals[j].z * v0.z)));
6824 if (distance < radius * .5) {
6825 point = start - model->facenormals[j] * distance;
6826 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6829 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6831 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6833 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6835 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6836 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6838 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6839 if (findLengthfast(&start) < findLengthfast(&velocity))
6842 *p1 += model->facenormals[j] * (distance - radius * .5);
6845 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6846 olddistance = distance;
6847 firstintersecting = j;
6854 *p = DoRotation(*p, 0, *rotate, 0);
6857 *p1 = DoRotation(*p1, 0, *rotate, 0);
6859 return firstintersecting;
6862 int findPathDist(int start, int end)
6867 unsigned int smallestcount = 1000;
6868 for (char i = 0; i < 50; i++) {
6869 unsigned int count = 0;
6874 while (last != end && count < 30) {
6876 for (int j = 0; j < Game::numpathpoints; j++) {
6877 if (j != last && j != last2 && j != last3 && j != last4) {
6879 if (Game::numpathpointconnect[j])
6880 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
6881 if (Game::pathpointconnect[j][k] == last)connected = 1;
6884 if (Game::numpathpointconnect[last])
6885 for (int k = 0; k < Game::numpathpointconnect[last]; k++) {
6886 if (Game::pathpointconnect[last][k] == j)connected = 1;
6889 if (closest == -1 || Random() % 2 == 0) {
6900 if (count < smallestcount) {
6901 smallestcount = count;
6904 return smallestcount;
6907 void Person::takeWeapon(int weaponId)
6910 weapons[weaponId].owner = id;
6911 if (num_weapons > 0) {
6912 weaponids[num_weapons] = weaponids[0];
6915 weaponids[0] = weaponId;
6918 void Person::addClothes()
6920 if (numclothes > 0) {
6921 for (int i = 0; i < numclothes; i++) {
6928 bool Person::addClothes(const int& clothesId)
6931 const std::string fileName = clothes[clothesId];
6933 GLubyte* array = &skeleton.skinText[0];
6937 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6942 float tintr = clothestintr[clothesId];
6943 float tintg = clothestintg[clothesId];
6944 float tintb = clothestintb[clothesId];
6946 if (tintr > 1) tintr = 1;
6947 if (tintg > 1) tintg = 1;
6948 if (tintb > 1) tintb = 1;
6950 if (tintr < 0) tintr = 0;
6951 if (tintg < 0) tintg = 0;
6952 if (tintb < 0) tintb = 0;
6954 int bytesPerPixel = texture.bpp / 8;
6958 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6959 if (bytesPerPixel == 3)
6961 else if ((i + 1) % 4 == 0)
6962 alphanum = texture.data[i];
6963 if ((i + 1) % 4 || bytesPerPixel == 3) {
6965 texture.data[i] *= tintr;
6967 texture.data[i] *= tintg;
6969 texture.data[i] *= tintb;
6970 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);
6982 if (aitype != playercontrolled && !Dialog::inDialog()) {
6984 //disable movement in editor
6985 if (Game::editorenabled)
6989 if (distsqflat(&Person::players[0]->coords, &coords) < 30 &&
6990 Person::players[0]->coords.y > coords.y + 2 &&
6991 !Person::players[0]->onterrain)
6995 if (aitype == pathfindtype) {
6996 if (finalpathfindpoint == -1) {
6997 float closestdistance;
7002 closestdistance = -1;
7003 for (int j = 0; j < Game::numpathpoints; j++) {
7004 if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) {
7005 closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]);
7007 finaltarget = Game::pathpoint[j];
7010 finalpathfindpoint = closest;
7011 for (int j = 0; j < Game::numpathpoints; j++) {
7012 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7013 DistancePointLine(&finalfinaltarget, &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);
7019 finaltarget = colpoint;
7023 finalpathfindpoint = closest;
7026 if (targetpathfindpoint == -1) {
7027 float closestdistance;
7032 closestdistance = -1;
7033 if (lastpathfindpoint == -1) {
7034 for (int j = 0; j < Game::numpathpoints; j++) {
7035 if (j != lastpathfindpoint)
7036 if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) {
7037 closestdistance = distsq(&coords, &Game::pathpoint[j]);
7041 targetpathfindpoint = closest;
7042 for (int j = 0; j < Game::numpathpoints; j++)
7043 if (j != lastpathfindpoint)
7044 for (int k = 0; k < Game::numpathpointconnect[j]; k++) {
7045 DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint );
7046 if (sq(tempdist) < closestdistance) {
7047 if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) <
7048 findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) {
7049 closestdistance = sq(tempdist);
7054 targetpathfindpoint = closest;
7056 for (int j = 0; j < Game::numpathpoints; j++)
7057 if (j != lastpathfindpoint &&
7058 j != lastpathfindpoint2 &&
7059 j != lastpathfindpoint3 &&
7060 j != lastpathfindpoint4) {
7062 if (Game::numpathpointconnect[j])
7063 for (int k = 0; k < Game::numpathpointconnect[j]; k++)
7064 if (Game::pathpointconnect[j][k] == lastpathfindpoint)
7067 if (Game::numpathpointconnect[lastpathfindpoint])
7068 for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++)
7069 if (Game::pathpointconnect[lastpathfindpoint][k] == j)
7072 tempdist = findPathDist(j, finalpathfindpoint);
7073 if (closest == -1 || tempdist < closestdistance) {
7074 closestdistance = tempdist;
7079 targetpathfindpoint = closest;
7082 losupdatedelay -= multiplier;
7084 targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]);
7085 lookyaw = targetyaw;
7087 //reached target point
7088 if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) {
7089 lastpathfindpoint4 = lastpathfindpoint3;
7090 lastpathfindpoint3 = lastpathfindpoint2;
7091 lastpathfindpoint2 = lastpathfindpoint;
7092 lastpathfindpoint = targetpathfindpoint;
7093 if (lastpathfindpoint2 == -1)
7094 lastpathfindpoint2 = lastpathfindpoint;
7095 if (lastpathfindpoint3 == -1)
7096 lastpathfindpoint3 = lastpathfindpoint2;
7097 if (lastpathfindpoint4 == -1)
7098 lastpathfindpoint4 = lastpathfindpoint3;
7099 targetpathfindpoint = -1;
7101 if ( distsqflat(&coords, &finalfinaltarget) <
7102 distsqflat(&coords, &finaltarget) ||
7103 distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) ||
7104 lastpathfindpoint == finalpathfindpoint) {
7105 aitype = passivetype;
7116 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7117 targetyaw += 90 * (whichdirection * 2 - 1);
7119 if (collided < 1 || animTarget != jumpupanim)
7121 if ((collided > .8 && jumppower >= 5))
7124 if ((!Tutorial::active || cananger) &&
7126 !Person::players[0]->dead &&
7127 distsq(&coords, &Person::players[0]->coords) < 400 &&
7129 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7130 Animation::animations[Person::players[0]->animTarget].height != lowheight &&
7131 !Game::editorenabled &&
7132 (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain))
7133 aitype = attacktypecutoff;
7134 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7135 Animation::animations[Person::players[0]->animTarget].height == highheight &&
7136 !Game::editorenabled)
7137 aitype = attacktypecutoff;
7139 if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7140 losupdatedelay = .2;
7141 for (unsigned j = 0; j < Person::players.size(); j++)
7142 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype)
7143 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7144 if (distsq(&coords, &Person::players[j]->coords) < 400)
7145 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7146 if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain)
7147 if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(
7148 DoRotation(jointPos(head), 0, yaw, 0)
7150 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)
7151 *Person::players[j]->scale + Person::players[j]->coords) ||
7152 (Person::players[j]->animTarget == hanganim &&
7153 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7154 aitype = searchtype;
7156 lastseen = Person::players[j]->coords;
7161 if (aitype == attacktypecutoff && Game::musictype != 2)
7162 if (creature != wolftype) {
7168 if (aitype != passivetype && Game::leveltime > .5)
7169 howactive = typeactive;
7171 if (aitype == passivetype) {
7172 aiupdatedelay -= multiplier;
7173 losupdatedelay -= multiplier;
7174 lastseentime += multiplier;
7175 pausetime -= multiplier;
7176 if (lastseentime > 1)
7179 if (aiupdatedelay < 0) {
7180 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) {
7181 targetyaw = roughDirectionTo(coords, waypoints[waypoint]);
7182 lookyaw = targetyaw;
7183 aiupdatedelay = .05;
7185 if (distsqflat(&coords, &waypoints[waypoint]) < 1) {
7186 if (waypointtype[waypoint] == wppause)
7189 if (waypoint > numwaypoints - 1)
7195 if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0)
7206 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7207 if (!avoidsomething)
7208 targetyaw += 90 * (whichdirection * 2 - 1);
7210 XYZ leftpos, rightpos;
7211 float leftdist, rightdist;
7212 leftpos = coords + DoRotation(facing, 0, 90, 0);
7213 rightpos = coords - DoRotation(facing, 0, 90, 0);
7214 leftdist = distsq(&leftpos, &avoidwhere);
7215 rightdist = distsq(&rightpos, &avoidwhere);
7216 if (leftdist < rightdist)
7223 if (collided < 1 || animTarget != jumpupanim)
7225 if ((collided > .8 && jumppower >= 5))
7230 if (!Game::editorenabled) {
7231 if (howactive <= typesleeping)
7232 if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile)
7233 for (int j = 0; j < numenvsounds; j++) {
7234 float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j];
7235 if (vol > 0 && distsq(&coords, &envsound[j]) <
7236 2 * (vol + vol * (creature == rabbittype) * 3))
7237 aitype = attacktypecutoff;
7240 if (aitype != passivetype) {
7241 if (howactive == typesleeping)
7242 setAnimation(getupfromfrontanim);
7243 howactive = typeactive;
7247 if (howactive < typesleeping &&
7248 ((!Tutorial::active || cananger) && hostile) &&
7249 !Person::players[0]->dead &&
7250 distsq(&coords, &Person::players[0]->coords) < 400 &&
7252 if (distsq(&coords, &Person::players[0]->coords) < 12 &&
7253 Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled)
7254 aitype = attacktypecutoff;
7255 if (distsq(&coords, &Person::players[0]->coords) < 30 &&
7256 Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled)
7257 aitype = attacktypecutoff;
7260 if (creature == wolftype) {
7262 for (unsigned j = 0; j < Person::players.size(); j++) {
7263 if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) {
7264 float smelldistance = 50;
7265 if (j == 0 && Person::players[j]->num_weapons > 0) {
7266 if (weapons[Person::players[j]->weaponids[0]].bloody)
7267 smelldistance = 100;
7268 if (Person::players[j]->num_weapons == 2)
7269 if (weapons[Person::players[j]->weaponids[1]].bloody)
7270 smelldistance = 100;
7273 smelldistance = 100;
7274 windsmell = windvector;
7275 Normalise(&windsmell);
7276 windsmell = windsmell * 2 + Person::players[j]->coords;
7277 if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled)
7278 aitype = attacktypecutoff;
7283 if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) {
7284 losupdatedelay = .2;
7285 for (unsigned j = 0; j < Person::players.size(); j++) {
7286 if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) {
7287 if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0)
7288 if (distsq(&coords, &Person::players[j]->coords) < 400)
7289 if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0)
7290 if ((-1 == Object::checkcollide(
7291 DoRotation(jointPos(head), 0, yaw, 0)*
7293 DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0)*
7294 Person::players[j]->scale + Person::players[j]->coords) &&
7295 !Person::players[j]->isWallJump()) ||
7296 (Person::players[j]->animTarget == hanganim &&
7297 normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) {
7299 if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight)
7304 if (lastseentime <= 0) {
7305 aitype = searchtype;
7307 lastseen = Person::players[j]->coords;
7315 if (aitype == attacktypecutoff && Game::musictype != 2) {
7316 if (creature != wolftype) {
7320 if (creature == wolftype) {
7330 if (aitype == searchtype) {
7331 aiupdatedelay -= multiplier;
7332 losupdatedelay -= multiplier;
7334 lastseentime -= multiplier;
7335 lastchecktime -= multiplier;
7337 if (isRun() && !onground) {
7338 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7339 XYZ test2 = coords + facing;
7341 XYZ test = coords + facing;
7343 j = Object::checkcollide(test2, test, laststanding);
7345 j = Object::checkcollide(test2, test);
7348 setAnimation(getStop());
7351 //aitype=passivetype;
7352 aitype = pathfindtype;
7353 finalfinaltarget = waypoints[waypoint];
7354 finalpathfindpoint = -1;
7355 targetpathfindpoint = -1;
7356 lastpathfindpoint = -1;
7357 lastpathfindpoint2 = -1;
7358 lastpathfindpoint3 = -1;
7359 lastpathfindpoint4 = -1;
7364 //check out last seen location
7365 if (aiupdatedelay < 0) {
7366 targetyaw = roughDirectionTo(coords, lastseen);
7367 lookyaw = targetyaw;
7368 aiupdatedelay = .05;
7371 if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) {
7374 lastseen.x += (float(Random() % 100) - 50) / 25;
7375 lastseen.z += (float(Random() % 100) - 50) / 25;
7386 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7387 if (!avoidsomething)
7388 targetyaw += 90 * (whichdirection * 2 - 1);
7390 XYZ leftpos, rightpos;
7391 float leftdist, rightdist;
7392 leftpos = coords + DoRotation(facing, 0, 90, 0);
7393 rightpos = coords - DoRotation(facing, 0, 90, 0);
7394 leftdist = distsq(&leftpos, &avoidwhere);
7395 rightdist = distsq(&rightpos, &avoidwhere);
7396 if (leftdist < rightdist)
7403 if (collided < 1 || animTarget != jumpupanim)
7405 if ((collided > .8 && jumppower >= 5))
7408 if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile))
7409 for (int k = 0; k < numenvsounds; k++) {
7410 if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) {
7411 aitype = attacktypecutoff;
7415 if (!Person::players[0]->dead &&
7416 losupdatedelay < 0 &&
7417 !Game::editorenabled &&
7419 ((!Tutorial::active || cananger) && hostile)) {
7420 losupdatedelay = .2;
7421 if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) {
7422 aitype = attacktypecutoff;
7425 if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight)
7426 //TODO: factor out canSeePlayer()
7427 if (distsq(&coords, &Person::players[0]->coords) < 400)
7428 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7429 if ((Object::checkcollide(
7430 DoRotation(jointPos(head), 0, yaw, 0)*
7432 DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0)*
7433 Person::players[0]->scale + Person::players[0]->coords) == -1) ||
7434 (Person::players[0]->animTarget == hanganim && normaldotproduct(
7435 Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) {
7436 /* //TODO: changed j to 0 on a whim, make sure this is correct
7437 (Person::players[j]->animTarget==hanganim&&normaldotproduct(
7438 Person::players[j]->facing,coords-Person::players[j]->coords)<0)
7440 aitype = attacktypecutoff;
7445 if (lastseentime < 0) {
7446 //aitype=passivetype;
7448 aitype = pathfindtype;
7449 finalfinaltarget = waypoints[waypoint];
7450 finalpathfindpoint = -1;
7451 targetpathfindpoint = -1;
7452 lastpathfindpoint = -1;
7453 lastpathfindpoint2 = -1;
7454 lastpathfindpoint3 = -1;
7455 lastpathfindpoint4 = -1;
7459 if (aitype != gethelptype)
7462 //get help from buddies
7463 if (aitype == gethelptype) {
7464 runninghowlong += multiplier;
7465 aiupdatedelay -= multiplier;
7467 if (aiupdatedelay < 0 || ally == 0) {
7471 //TODO: factor out closest search somehow
7474 float closestdist = -1;
7475 for (unsigned k = 0; k < Person::players.size(); k++) {
7476 if ((k != id) && (k != 0) && !Person::players[k]->dead &&
7477 (Person::players[k]->howactive < typedead1) &&
7478 !Person::players[k]->skeleton.free &&
7479 (Person::players[k]->aitype == passivetype)) {
7480 float distance = distsq(&coords, &Person::players[k]->coords);
7481 if (closestdist == -1 || distance < closestdist) {
7482 closestdist = distance;
7488 if (closest != -1) {
7493 lastseen = Person::players[0]->coords;
7500 XYZ facing = coords;
7501 XYZ flatfacing = Person::players[ally]->coords;
7502 facing.y += jointPos(head).y * scale;
7503 flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale;
7504 if (-1 != Object::checkcollide(facing, flatfacing))
7507 //no available ally, run back to player
7509 Person::players[ally]->skeleton.free ||
7510 Person::players[ally]->aitype != passivetype ||
7511 lastseentime <= 0) {
7512 aitype = searchtype;
7518 targetyaw = roughDirectionTo(coords, Person::players[ally]->coords);
7519 lookyaw = targetyaw;
7520 aiupdatedelay = .05;
7523 if (distsqflat(&coords, &Person::players[ally]->coords) < 3) {
7524 aitype = searchtype;
7526 Person::players[ally]->aitype = searchtype;
7527 if (Person::players[ally]->lastseentime < lastseentime) {
7528 Person::players[ally]->lastseen = lastseen;
7529 Person::players[ally]->lastseentime = lastseentime;
7530 Person::players[ally]->lastchecktime = lastchecktime;
7534 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7535 if (!avoidsomething)
7536 targetyaw += 90 * (whichdirection * 2 - 1);
7538 XYZ leftpos, rightpos;
7539 float leftdist, rightdist;
7540 leftpos = coords + DoRotation(facing, 0, 90, 0);
7541 rightpos = coords - DoRotation(facing, 0, 90, 0);
7542 leftdist = distsq(&leftpos, &avoidwhere);
7543 rightdist = distsq(&rightpos, &avoidwhere);
7544 if (leftdist < rightdist)
7558 if (collided < 1 || animTarget != jumpupanim)
7560 if (collided > .8 && jumppower >= 5)
7564 //retreiving a weapon on the ground
7565 if (aitype == getweapontype) {
7566 aiupdatedelay -= multiplier;
7567 lastchecktime -= multiplier;
7569 if (aiupdatedelay < 0) {
7575 float closestdist = -1;
7576 for (unsigned k = 0; k < weapons.size(); k++)
7577 if (weapons[k].owner == -1) {
7578 float distance = distsq(&coords, &weapons[k].position);
7579 if (closestdist == -1 || distance < closestdist) {
7580 closestdist = distance;
7593 if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile))
7594 if (ally < 0 || weaponactive != -1 || lastchecktime <= 0) {
7595 aitype = attacktypecutoff;
7598 if (!Person::players[0]->dead)
7600 if (weapons[ally].owner != -1 ||
7601 distsq(&coords, &weapons[ally].position) > 16) {
7602 aitype = attacktypecutoff;
7605 //TODO: factor these out as moveToward()
7606 targetyaw = roughDirectionTo(coords, weapons[ally].position);
7607 lookyaw = targetyaw;
7608 aiupdatedelay = .05;
7612 if (avoidcollided > .8 && !jumpkeydown && collided < .8) {
7613 if (!avoidsomething)
7614 targetyaw += 90 * (whichdirection * 2 - 1);
7616 XYZ leftpos, rightpos;
7617 float leftdist, rightdist;
7618 leftpos = coords + DoRotation(facing, 0, 90, 0);
7619 rightpos = coords - DoRotation(facing, 0, 90, 0);
7620 leftdist = distsq(&leftpos, &avoidwhere);
7621 rightdist = distsq(&rightpos, &avoidwhere);
7622 if (leftdist < rightdist)
7636 if (animTarget != crouchremoveknifeanim &&
7637 animTarget != removeknifeanim)
7638 throwtogglekeydown = 0;
7641 if (collided < 1 || animTarget != jumpupanim)
7643 if ((collided > .8 && jumppower >= 5))
7647 if (aitype == attacktypecutoff) {
7648 aiupdatedelay -= multiplier;
7649 //dodge or reverse rabbit kicks, knife throws, flips
7650 if (damage < damagetolerance * 2 / 3)
7651 if ((Person::players[0]->animTarget == rabbitkickanim ||
7652 Person::players[0]->animTarget == knifethrowanim ||
7653 (Person::players[0]->isFlip() &&
7654 normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) &&
7655 !Person::players[0]->skeleton.free &&
7656 (aiupdatedelay < .1)) {
7660 if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->weaponactive != -1) {
7661 if (weapons[Person::players[0]->weaponids[0]].getType() == knife) {
7662 if (isIdle() || isCrouch() || isRun() || isFlip()) {
7663 if (abs(Random() % 2) == 0)
7664 setAnimation(backhandspringanim);
7666 setAnimation(rollanim);
7667 targetyaw += 90 * (abs(Random() % 2) * 2 - 1);
7670 if (animTarget == jumpupanim || animTarget == jumpdownanim)
7671 setAnimation(flipanim);
7675 aiupdatedelay = .02;
7677 //get confused by flips
7678 if (Person::players[0]->isFlip() &&
7679 !Person::players[0]->skeleton.free &&
7680 Person::players[0]->animTarget != walljumprightkickanim &&
7681 Person::players[0]->animTarget != walljumpleftkickanim) {
7682 if (distsq(&Person::players[0]->coords, &coords) < 25)
7683 if ((1 - damage / damagetolerance) > .5)
7686 //go for weapon on the ground
7687 if (wentforweapon < 3)
7688 for (unsigned k = 0; k < weapons.size(); k++)
7689 if (creature != wolftype)
7690 if (num_weapons == 0 &&
7691 weapons[k].owner == -1 &&
7692 weapons[k].velocity.x == 0 &&
7693 weapons[k].velocity.z == 0 &&
7694 weapons[k].velocity.y == 0) {
7695 if (distsq(&coords, &weapons[k].position) < 16) {
7698 aitype = getweapontype;
7702 //dodge/reverse walljump kicks
7703 if (damage < damagetolerance / 2)
7704 if (Animation::animations[animTarget].height != highheight)
7705 if (damage < damagetolerance * .5 &&
7706 ((Person::players[0]->animTarget == walljumprightkickanim ||
7707 Person::players[0]->animTarget == walljumpleftkickanim) &&
7708 ((aiupdatedelay < .15 &&
7710 (aiupdatedelay < .08 &&
7711 difficulty != 2)))) {
7714 //walked off a ledge (?)
7715 if (isRun() && !onground)
7716 if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) {
7717 XYZ test2 = coords + facing;
7719 XYZ test = coords + facing;
7721 j = Object::checkcollide(test2, test, laststanding);
7723 j = Object::checkcollide(test2, test);
7726 setAnimation(getStop());
7729 aitype = pathfindtype;
7730 finalfinaltarget = waypoints[waypoint];
7731 finalpathfindpoint = -1;
7732 targetpathfindpoint = -1;
7733 lastpathfindpoint = -1;
7734 lastpathfindpoint2 = -1;
7735 lastpathfindpoint3 = -1;
7736 lastpathfindpoint4 = -1;
7740 //lose sight of player in the air (?)
7741 if (Person::players[0]->coords.y > coords.y + 5 &&
7742 Animation::animations[Person::players[0]->animTarget].height != highheight &&
7743 !Person::players[0]->onterrain) {
7744 aitype = pathfindtype;
7745 finalfinaltarget = waypoints[waypoint];
7746 finalpathfindpoint = -1;
7747 targetpathfindpoint = -1;
7748 lastpathfindpoint = -1;
7749 lastpathfindpoint2 = -1;
7750 lastpathfindpoint3 = -1;
7751 lastpathfindpoint4 = -1;
7753 //it's time to think (?)
7754 if (aiupdatedelay < 0 &&
7755 !Animation::animations[animTarget].attack &&
7756 animTarget != staggerbackhighanim &&
7757 animTarget != staggerbackhardanim &&
7758 animTarget != backhandspringanim &&
7759 animTarget != dodgebackanim) {
7761 if (weaponactive == -1 && num_weapons > 0)
7762 drawkeydown = Random() % 2;
7765 rabbitkickenabled = Random() % 2;
7767 XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity;
7768 XYZ targetpoint = Person::players[0]->coords;
7769 if (distsq(&Person::players[0]->coords, &coords) <
7770 distsq(&rotatetarget, &coords))
7771 targetpoint += Person::players[0]->velocity *
7772 findDistance(&Person::players[0]->coords, &coords) / findLength(&velocity);
7773 targetyaw = roughDirectionTo(coords, targetpoint);
7774 lookyaw = targetyaw;
7775 aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000);
7777 if (distsq(&coords, &Person::players[0]->coords) > 5 && (Person::players[0]->weaponactive == -1 || weaponactive != -1))
7779 else if ((distsq(&coords, &Person::players[0]->coords) > 16 ||
7780 distsq(&coords, &Person::players[0]->coords) < 9) &&
7781 Person::players[0]->weaponactive != -1)
7783 else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0))
7787 //chill out around the corpse
7788 if (Person::players[0]->dead) {
7790 if (Random() % 10 == 0)
7792 if (Random() % 100 == 0) {
7793 aitype = pathfindtype;
7794 finalfinaltarget = waypoints[waypoint];
7795 finalpathfindpoint = -1;
7796 targetpathfindpoint = -1;
7797 lastpathfindpoint = -1;
7798 lastpathfindpoint2 = -1;
7799 lastpathfindpoint3 = -1;
7800 lastpathfindpoint4 = -1;
7809 if (avoidcollided > .8 && !jumpkeydown && collided < .8)
7810 targetyaw += 90 * (whichdirection * 2 - 1);
7812 if (Random() % 2 == 0 || weaponactive != -1 || creature == wolftype)
7816 if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7)
7820 if (aitype != playercontrolled &&
7825 for (unsigned j = 0; j < Person::players.size(); j++)
7826 if (j != id && !Person::players[j]->skeleton.free &&
7827 Person::players[j]->hasvictim &&
7828 (Tutorial::active && reversaltrain ||
7829 Random() % 2 == 0 && difficulty == 2 ||
7830 Random() % 4 == 0 && difficulty == 1 ||
7831 Random() % 8 == 0 && difficulty == 0 ||
7832 Person::players[j]->lastattack2 == Person::players[j]->animTarget &&
7833 Person::players[j]->lastattack3 == Person::players[j]->animTarget &&
7834 (Random() % 2 == 0 || difficulty == 2) ||
7835 (isIdle() || isRun()) &&
7836 Person::players[j]->weaponactive != -1 ||
7837 Person::players[j]->animTarget == swordslashanim &&
7838 weaponactive != -1 ||
7839 Person::players[j]->animTarget == staffhitanim ||
7840 Person::players[j]->animTarget == staffspinhitanim))
7841 if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 &&
7842 Person::players[j]->victim == Person::players[id] &&
7843 (Person::players[j]->animTarget == sweepanim ||
7844 Person::players[j]->animTarget == spinkickanim ||
7845 Person::players[j]->animTarget == staffhitanim ||
7846 Person::players[j]->animTarget == staffspinhitanim ||
7847 Person::players[j]->animTarget == winduppunchanim ||
7848 Person::players[j]->animTarget == upunchanim ||
7849 Person::players[j]->animTarget == wolfslapanim ||
7850 Person::players[j]->animTarget == knifeslashstartanim ||
7851 Person::players[j]->animTarget == swordslashanim &&
7852 (distsq(&Person::players[j]->coords, &coords) < 2 ||
7853 weaponactive != -1))) {
7861 Person::players[target]->Reverse();
7866 if (collided > .8 && jumppower >= 5 ||
7867 distsq(&coords, &Person::players[0]->coords) > 400 &&
7869 creature == rabbittype)
7871 //TODO: why are we controlling the human?
7872 if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0)
7873 Person::players[0]->jumpkeydown = 0;
7874 if (Person::players[0]->animTarget == jumpdownanim &&
7875 distsq(&Person::players[0]->coords, &coords) < 40)
7880 if (Tutorial::active)
7885 XYZ facing = coords;
7886 XYZ flatfacing = Person::players[0]->coords;
7887 facing.y += jointPos(head).y * scale;
7888 flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale;
7890 if (-1 != Object::checkcollide(facing, flatfacing)) {
7893 if (lastseentime <= 0 &&
7894 (creature != wolftype ||
7895 weaponstuck == -1)) {
7896 aitype = searchtype;
7898 lastseen = Person::players[0]->coords;
7905 if (Animation::animations[Person::players[0]->animTarget].height == highheight &&
7906 (aitype == attacktypecutoff ||
7907 aitype == searchtype))
7908 if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) {
7909 XYZ test = Person::players[0]->coords;
7911 if (-1 == Object::checkcollide(Person::players[0]->coords, test))
7915 if (aitype == passivetype && !(numwaypoints > 1) ||
7917 pause && damage > superpermanentdamage) {
7936 XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0);
7937 facing = flatfacing;
7939 if (aitype == attacktypecutoff) {
7940 targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords);
7941 targetheadpitch = pitchTo(coords, Person::players[0]->coords);
7942 } else if (howactive >= typesleeping) {
7943 targetheadyaw = targetyaw;
7944 targetheadpitch = 0;
7946 if (interestdelay <= 0) {
7947 interestdelay = .7 + (float)(abs(Random() % 100)) / 100;
7948 headtarget = coords;
7949 headtarget.x += (float)(abs(Random() % 200) - 100) / 100;
7950 headtarget.z += (float)(abs(Random() % 200) - 100) / 100;
7951 headtarget.y += (float)(abs(Random() % 200) - 100) / 300;
7952 headtarget += facing * 1.5;
7954 targetheadyaw = 180 - roughDirectionTo(coords, headtarget);
7955 targetheadpitch = pitchTo(coords, headtarget);