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"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern float realtexdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern GLubyte wolfbloodText[512 * 512 * 3];
46 extern int bloodtoggle;
47 extern Objects objects;
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 int tutoriallevel;
61 extern float smoketex;
62 extern int tutorialstage;
63 extern bool reversaltrain;
64 extern bool canattack;
66 extern float damagedealt;
68 extern float hostiletime;
70 extern bool gamestarted;
72 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
77 animCurrent(bounceidleanim),
78 animTarget(bounceidleanim),
85 howactive(typeactive),
87 superruntoggle(false),
88 lastattack(0), lastattack2(0), lastattack3(0),
89 currentoffset(), targetoffset(), offset(),
121 rabbitkickenabled(false),
130 damagetolerance(200),
133 superpermanentdamage(0),
147 bleedx(0), bleedy(0),
151 headyaw(0), headpitch(0),
152 targetheadyaw(0), targetheadpitch(0),
163 normalsupdatedelay(0),
166 forwardkeydown(false),
167 forwardstogglekeydown(false),
172 jumptogglekeydown(false),
173 crouchkeydown(false),
174 crouchtogglekeydown(false),
176 drawtogglekeydown(false),
178 throwtogglekeydown(false),
179 attackkeydown(false),
184 crouchkeydowntime(0),
198 whichdirection(false),
199 whichdirectiondelay(0),
200 avoidsomething(false),
209 lefthandmorphness(0),
210 righthandmorphness(0),
214 targetlefthandmorphness(0),
215 targetrighthandmorphness(0),
216 targetheadmorphness(1),
217 targetchestmorphness(0),
218 targettailmorphness(0),
219 lefthandmorphstart(0), lefthandmorphend(0),
220 righthandmorphstart(0), righthandmorphend(0),
221 headmorphstart(0), headmorphend(0),
222 chestmorphstart(0), chestmorphend(0),
223 tailmorphstart(0), tailmorphend(0),
226 highreversaldelay(0),
229 creature(rabbittype),
276 finalpathfindpoint(0),
277 targetpathfindpoint(0),
278 lastpathfindpoint(0),
279 lastpathfindpoint2(0),
280 lastpathfindpoint3(0),
281 lastpathfindpoint4(0),
298 neckspurtparticledelay(0),
302 rabbitkickragdoll(false),
310 /* Read a person in tfile. Throws an error if it’s not valid */
311 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
314 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
316 funpackf(tfile, "Bi", &howactive);
318 howactive = typeactive;
321 funpackf(tfile, "Bf", &scale);
326 funpackf(tfile, "Bb", &immobile);
331 funpackf(tfile, "Bf", &yaw);
336 if (num_weapons < 0 || num_weapons > 5) {
337 throw InvalidPersonException();
339 if (num_weapons > 0 && num_weapons < 5) {
340 for (int j = 0; j < num_weapons; j++) {
341 weaponids[j] = weapons.size();
343 funpackf(tfile, "Bi", &type);
344 weapons.push_back(Weapon(type, id));
347 funpackf(tfile, "Bi", &numwaypoints);
348 for (int j = 0; j < numwaypoints; j++) {
349 funpackf(tfile, "Bf", &waypoints[j].x);
350 funpackf(tfile, "Bf", &waypoints[j].y);
351 funpackf(tfile, "Bf", &waypoints[j].z);
353 funpackf(tfile, "Bi", &waypointtype[j]);
355 waypointtype[j] = wpkeepwalking;
359 funpackf(tfile, "Bi", &waypoint);
360 if (waypoint > (numwaypoints - 1)) {
364 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
365 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
366 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
367 funpackf(tfile, "Bf Bf", &power, &speedmult);
369 float headprop, legprop, armprop, bodyprop;
372 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
380 if (creature == wolftype) {
381 proportionhead = 1.1 * headprop;
382 proportionbody = 1.1 * bodyprop;
383 proportionarms = 1.1 * armprop;
384 proportionlegs = 1.1 * legprop;
385 } else if (creature == rabbittype) {
386 proportionhead = 1.2 * headprop;
387 proportionbody = 1.05 * bodyprop;
388 proportionarms = 1.00 * armprop;
389 proportionlegs = 1.1 * legprop;
390 proportionlegs.y = 1.05 * legprop;
393 funpackf(tfile, "Bi", &numclothes);
394 for (int k = 0; k < numclothes; k++) {
396 funpackf(tfile, "Bi", &templength);
397 for (int l = 0; l < templength; l++)
398 funpackf(tfile, "Bb", &clothes[k][l]);
399 clothes[k][templength] = '\0';
400 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
406 if (creature == wolftype) {
408 damagetolerance = 300;
415 realoldcoords = coords;
418 void Person::skeletonLoad(bool clothes)
421 if (creature != wolftype) {
423 "Skeleton/BasicFigure",
424 "Skeleton/BasicFigureLow",
425 "Skeleton/RabbitBelt",
427 "Models/Body2.solid",
428 "Models/Body3.solid",
429 "Models/Body4.solid",
430 "Models/Body5.solid",
431 "Models/Body6.solid",
432 "Models/Body7.solid",
433 "Models/BodyLow.solid",
439 "Skeleton/BasicFigureWolf",
440 "Skeleton/BasicFigureWolfLow",
441 "Skeleton/RabbitBelt",
443 "Models/Wolf2.solid",
444 "Models/Wolf3.solid",
445 "Models/Wolf4.solid",
446 "Models/Wolf5.solid",
447 "Models/Wolf6.solid",
448 "Models/Wolf7.solid",
449 "Models/WolfLow.solid",
455 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
461 * GameTick/doPlayerCollisions
463 void Person::CheckKick()
466 && (animTarget == rabbitkickanim
468 && victim != this->shared_from_this()
470 && animCurrent == rabbitkickanim)
471 && distsq(&coords, &victim->coords) < 1.2
472 && !victim->skeleton.free))
475 if (Animation::animations[victim->animTarget].height != lowheight) {
476 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
477 XYZ relative = velocity;
479 Normalise(&relative);
483 if (tutoriallevel != 1)
484 emit_sound_at(heavyimpactsound, victim->coords);
486 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
487 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
490 victim->DoDamage(100 * damagemult / victim->protectionhigh);
496 animTarget = backflipanim;
498 velocity = facing * -10;
502 resume_stream(whooshsound);
504 award_bonus(id, cannon);
505 } else if (victim->isCrouch()) {
506 animTarget = rabbitkickreversedanim;
507 animCurrent = rabbitkickreversedanim;
508 victim->animCurrent = rabbitkickreversalanim;
509 victim->animTarget = rabbitkickreversalanim;
515 victim->oldcoords = victim->coords;
516 coords = victim->coords;
517 victim->targetyaw = targetyaw;
518 victim->victim = this->shared_from_this();
525 * GameTick/doPlayerCollisions - spread fire between players
526 * GameTick/doDevKeys - press f to ignite
527 * Person::DoStuff - spread fire from lit campfires and bushes
529 void Person::CatchFire()
531 XYZ flatfacing, flatvelocity;
533 for (int i = 0; i < 10; i++) {
534 howmany = fabs(Random() % (skeleton.joints.size()));
536 flatvelocity = skeleton.joints[howmany].velocity;
537 flatfacing = skeleton.joints[howmany].position * scale + coords;
539 flatvelocity = velocity;
540 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
542 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
547 emit_sound_at(firestartsound, coords);
549 emit_stream_at(stream_firesound, coords);
557 * idle animation for this creature (depending on status)
559 int Person::getIdle()
561 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
563 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
564 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
565 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
566 victim->id < Person::players.size())) {
567 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
568 if (creature == rabbittype)
569 return fightidleanim;
570 if (creature == wolftype)
573 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
574 if (weapons[weaponids[weaponactive]].getType() == knife)
575 return knifefightidleanim;
576 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
577 return swordfightidlebothanim;
578 if (weapons[weaponids[weaponactive]].getType() == sword)
579 return swordfightidleanim;
580 if (weapons[weaponids[weaponactive]].getType() == staff)
581 return swordfightidleanim;
583 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
584 return fightsidestep;
586 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
588 if (howactive == typesitting) return sitanim;
589 if (howactive == typesittingwall) return sitwallanim;
590 if (howactive == typesleeping) return sleepanim;
591 if (howactive == typedead1) return dead1anim;
592 if (howactive == typedead2) return dead2anim;
593 if (howactive == typedead3) return dead3anim;
594 if (howactive == typedead4) return dead4anim;
595 if (creature == rabbittype) return bounceidleanim;
596 if (creature == wolftype) return wolfidle;
601 * crouch animation for this creature
603 int Person::getCrouch()
605 if (creature == rabbittype)
607 if (creature == wolftype)
608 return wolfcrouchanim;
613 * running animation for this creature (can be upright or all fours)
617 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
619 if (creature == wolftype && (!superruntoggle))
622 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
623 return rabbitrunninganim;
624 if (creature == wolftype && (superruntoggle))
625 return wolfrunninganim;
631 int Person::getStop()
633 if (creature == rabbittype)
635 if (creature == wolftype)
642 int Person::getLanding()
644 if (creature == rabbittype)
646 if (creature == wolftype)
653 int Person::getLandhard()
655 if (creature == rabbittype)
657 if (creature == wolftype)
658 return wolflandhardanim;
665 * Person::DoAnimations
668 SolidHitBonus(int playerid)
670 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
671 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
673 award_bonus(playerid, solidhit);
677 * spawns blood effects
679 void Person::DoBlood(float howmuch, int which)
681 // FIXME: should abstract out inputs
682 static int bleedxint, bleedyint;
684 if (bloodtoggle && tutoriallevel != 1) {
685 if (bleeding <= 0 && spurt) {
687 for (int i = 0; i < 3; i++) {
688 // emit blood particles
691 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
692 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
693 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
694 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
697 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
698 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
699 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
700 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
703 if (Random() % 2 == 0) // 50% chance
704 for (int i = 0; i < 3; i++) {
705 if (Random() % 2 != 0) {
706 // emit teeth particles
709 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
710 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
713 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
714 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
718 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
720 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
722 Sprite::setLastSpriteSpecial(3); // sets it to teeth
727 // FIXME: manipulating attributes
728 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
731 if (creature == rabbittype)
732 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) {
733 bleedxint = abs(Random() % 512);
734 bleedyint = abs(Random() % 512);
736 if (creature == wolftype)
737 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) {
738 bleedxint = abs(Random() % 512);
739 bleedyint = abs(Random() % 512);
743 bleedy /= realtexdetail;
744 bleedx /= realtexdetail;
745 direction = abs(Random() % 2) * 2 - 1;
754 * spawns big blood effects and ???
755 * modifies character's skin texture
757 void Person::DoBloodBig(float howmuch, int which)
759 static int bleedxint, bleedyint, i, j;
761 if (howmuch && id == 0)
764 if (tutoriallevel != 1 || id == 0)
765 if (aitype != playercontrolled && howmuch > 0) {
769 if (creature == wolftype) {
770 int i = abs(Random() % 2);
772 whichsound = snarlsound;
774 whichsound = snarl2sound;
776 if (creature == rabbittype) {
777 int i = abs(Random() % 2);
779 whichsound = rabbitpainsound;
780 if (i == 1 && howmuch >= 2)
781 whichsound = rabbitpain1sound;
784 if (whichsound != -1) {
785 emit_sound_at(whichsound, coords);
790 if (id == 0 && howmuch > 0) {
794 if (bloodtoggle && decals && tutoriallevel != 1) {
795 if (bleeding <= 0 && spurt) {
797 for (int i = 0; i < 3; i++) {
798 // emit blood particles
799 // FIXME: copypaste from above
802 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
803 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
804 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
805 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
808 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
809 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
810 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
811 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
816 // weird texture manipulation code follows.
817 // looks like this is painting blood onto the character's skin texture
818 // FIXME: surely there's a better way
820 int offsetx = 0, offsety = 0;
822 offsety = Random() % 40;
823 offsetx = abs(Random() % 60);
825 if (which == 190 || which == 185) {
826 offsety = Random() % 40;
827 offsetx = abs(Random() % 100) - 20;
830 offsety = Random() % 10;
831 offsetx = Random() % 10;
834 offsety = Random() % 20;
835 offsetx = Random() % 20;
837 if (which == 220 || which == 215) {
847 if (creature == rabbittype)
848 for (i = 0; i < 512; i++) {
849 for (j = 0; j < 512; j++) {
850 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
851 if (i < startx) startx = i;
852 if (j < starty) starty = j;
853 if (i > endx) endx = i;
854 if (j > endy) endy = j;
858 if (creature == wolftype)
859 for (i = 0; i < 512; i++) {
860 for (j = 0; j < 512; j++) {
861 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
862 if (i < startx) startx = i;
863 if (j < starty) starty = j;
864 if (i > endx) endx = i;
865 if (j > endy) endy = j;
875 if (startx < 0) startx = 0;
876 if (starty < 0) starty = 0;
877 if (endx > 512 - 1) endx = 512 - 1;
878 if (endy > 512 - 1) endy = 512 - 1;
879 if (endx < startx) endx = startx;
880 if (endy < starty) endy = starty;
882 startx /= realtexdetail;
883 starty /= realtexdetail;
884 endx /= realtexdetail;
885 endy /= realtexdetail;
887 int texdetailint = realtexdetail;
889 if (creature == rabbittype)
890 for (i = startx; i < endx; i++) {
891 for (j = starty; j < endy; j++) {
892 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) {
893 color = Random() % 85 + 170;
894 where = i * skeleton.skinsize * 3 + j * 3;
895 if (skeleton.skinText[where + 0] > color / 2)
896 skeleton.skinText[where + 0] = color / 2;
897 skeleton.skinText[where + 1] = 0;
898 skeleton.skinText[where + 2] = 0;
902 if (creature == wolftype)
903 for (i = startx; i < endx; i++) {
904 for (j = starty; j < endy; j++) {
905 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) {
906 color = Random() % 85 + 170;
907 where = i * skeleton.skinsize * 3 + j * 3;
908 if (skeleton.skinText[where + 0] > color / 2)
909 skeleton.skinText[where + 0] = color / 2;
910 skeleton.skinText[where + 1] = 0;
911 skeleton.skinText[where + 2] = 0;
915 skeleton.drawmodel.textureptr.bind();
920 if (creature == rabbittype)
921 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) {
922 bleedxint = abs(Random() % 512);
923 bleedyint = abs(Random() % 512);
925 if (creature == wolftype)
926 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) {
927 bleedxint = abs(Random() % 512);
928 bleedyint = abs(Random() % 512);
930 bleedy = bleedxint + offsetx;
931 bleedx = bleedyint + offsety;
932 bleedy /= realtexdetail;
933 bleedx /= realtexdetail;
938 if (bleedx > skeleton.skinsize - 1)
939 bleedx = skeleton.skinsize - 1;
940 if (bleedy > skeleton.skinsize - 1)
941 bleedy = skeleton.skinsize - 1;
942 direction = abs(Random() % 2) * 2 - 1;
945 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
946 deathbleeding += bleeding;
947 bloodloss += bleeding * 3;
949 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
950 if (abs(Random() % 2) == 0) {
951 aitype = gethelptype;
954 aitype = attacktypecutoff;
962 * similar to DoBloodBig
964 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
968 static XYZ startpoint, endpoint, colpoint, movepoint;
969 static float rotationpoint;
971 static XYZ p1, p2, p3, p0;
974 float coordsx, coordsy;
977 if (bloodtoggle && decals && tutoriallevel != 1) {
980 where = DoRotation(where, 0, -yaw, 0);
988 // ray testing for a tri in the character model
989 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
990 if (whichtri != -1) {
991 // low level geometry math
993 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
994 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
995 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
997 bary.x = distsq(&p0, &p1);
998 bary.y = distsq(&p0, &p2);
999 bary.z = distsq(&p0, &p3);
1001 total = bary.x + bary.y + bary.z;
1006 bary.x = 1 - bary.x;
1007 bary.y = 1 - bary.y;
1008 bary.z = 1 - bary.z;
1010 total = bary.x + bary.y + bary.z;
1016 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1017 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1018 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1019 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1020 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1021 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1022 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;
1023 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;
1025 if (bleeding <= 0 && spurt) {
1027 for (int i = 0; i < 3; i++) {
1028 // emit blood particles
1029 // FIXME: more copypaste code
1031 if (skeleton.free) {
1032 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1033 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1034 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1035 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1038 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1039 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1040 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1041 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1046 // texture manipulation follows
1048 int offsetx = 0, offsety = 0;
1049 offsetx = (1 + coordsy) * 512 - 291;
1050 offsety = coordsx * 512 - 437;
1057 if (creature == rabbittype)
1058 for (i = 0; i < 512; i++) {
1059 for (j = 0; j < 512; j++) {
1060 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1061 if (i < startx) startx = i;
1062 if (j < starty) starty = j;
1063 if (i > endx) endx = i;
1064 if (j > endy) endy = j;
1068 if (creature == wolftype)
1069 for (i = 0; i < 512; i++) {
1070 for (j = 0; j < 512; j++) {
1071 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1072 if (i < startx) startx = i;
1073 if (j < starty) starty = j;
1074 if (i > endx) endx = i;
1075 if (j > endy) endy = j;
1084 if (startx < 0) startx = 0;
1085 if (starty < 0) starty = 0;
1086 if (endx > 512 - 1) endx = 512 - 1;
1087 if (endy > 512 - 1) endy = 512 - 1;
1088 if (endx < startx) endx = startx;
1089 if (endy < starty) endy = starty;
1091 startx /= realtexdetail;
1092 starty /= realtexdetail;
1093 endx /= realtexdetail;
1094 endy /= realtexdetail;
1096 int texdetailint = realtexdetail;
1098 if (creature == rabbittype)
1099 for (i = startx; i < endx; i++) {
1100 for (j = starty; j < endy; j++) {
1101 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) {
1102 color = Random() % 85 + 170;
1103 where = i * skeleton.skinsize * 3 + j * 3;
1104 if (skeleton.skinText[where + 0] > color / 2)
1105 skeleton.skinText[where + 0] = color / 2;
1106 skeleton.skinText[where + 1] = 0;
1107 skeleton.skinText[where + 2] = 0;
1108 } 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) {
1109 color = Random() % 85 + 170;
1110 where = i * skeleton.skinsize * 3 + j * 3;
1111 if (skeleton.skinText[where + 0] > color / 2)
1112 skeleton.skinText[where + 0] = color / 2;
1113 skeleton.skinText[where + 1] = 0;
1114 skeleton.skinText[where + 2] = 0;
1118 if (creature == wolftype)
1119 for (i = startx; i < endx; i++) {
1120 for (j = starty; j < endy; j++) {
1121 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) {
1122 color = Random() % 85 + 170;
1123 where = i * skeleton.skinsize * 3 + j * 3;
1124 if (skeleton.skinText[where + 0] > color / 2)
1125 skeleton.skinText[where + 0] = color / 2;
1126 skeleton.skinText[where + 1] = 0;
1127 skeleton.skinText[where + 2] = 0;
1128 } 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) {
1129 color = Random() % 85 + 170;
1130 where = i * skeleton.skinsize * 3 + j * 3;
1131 if (skeleton.skinText[where + 0] > color / 2)
1132 skeleton.skinText[where + 0] = color / 2;
1133 skeleton.skinText[where + 1] = 0;
1134 skeleton.skinText[where + 2] = 0;
1138 skeleton.drawmodel.textureptr.bind();
1141 bleedy = (1 + coordsy) * 512;
1142 bleedx = coordsx * 512;
1143 bleedy /= realtexdetail;
1144 bleedx /= realtexdetail;
1149 if (bleedx > skeleton.skinsize - 1)
1150 bleedx = skeleton.skinsize - 1;
1151 if (bleedy > skeleton.skinsize - 1)
1152 bleedy = skeleton.skinsize - 1;
1153 direction = abs(Random() % 2) * 2 - 1;
1158 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1159 deathbleeding += bleeding;
1160 bloodloss += bleeding * 3;
1162 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1163 if (abs(Random() % 2) == 0) {
1164 aitype = gethelptype;
1167 aitype = attacktypecutoff;
1178 * guessing this performs a reversal
1180 void Person::Reverse()
1182 if (!((victim->aitype == playercontrolled
1184 || staggerdelay <= 0)
1185 && victim->animTarget != jumpupanim
1186 && victim->animTarget != jumpdownanim
1187 && (tutoriallevel != 1 || cananger)
1191 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1192 && (victim->id != 0 || difficulty >= 2)
1193 && (creature != wolftype || victim->creature == wolftype))
1196 if (animTarget == sweepanim) {
1197 animTarget = sweepreversedanim;
1198 animCurrent = sweepreversedanim;
1199 victim->animCurrent = sweepreversalanim;
1200 victim->animTarget = sweepreversalanim;
1202 if (animTarget == spinkickanim) {
1203 animTarget = spinkickreversedanim;
1204 animCurrent = spinkickreversedanim;
1205 victim->animCurrent = spinkickreversalanim;
1206 victim->animTarget = spinkickreversalanim;
1208 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1209 if (animTarget == rabbittacklinganim) {
1212 victim->frameCurrent = 6;
1213 victim->frameTarget = 7;
1215 animTarget = upunchreversedanim;
1216 animCurrent = upunchreversedanim;
1217 victim->animCurrent = upunchreversalanim;
1218 victim->animTarget = upunchreversalanim;
1220 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1221 if (victim->weaponactive != -1) {
1222 victim->throwtogglekeydown = 1;
1223 XYZ tempVelocity = victim->velocity * .2;
1224 if (tempVelocity.x == 0)
1225 tempVelocity.x = .1;
1226 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1227 victim->num_weapons--;
1228 if (victim->num_weapons) {
1229 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1230 if (victim->weaponstuck == victim->num_weapons)
1231 victim->weaponstuck = 0;
1234 victim->weaponactive = -1;
1235 for (unsigned j = 0; j < Person::players.size(); j++) {
1236 Person::players[j]->wentforweapon = 0;
1240 animTarget = staffhitreversedanim;
1241 animCurrent = staffhitreversedanim;
1242 victim->animCurrent = staffhitreversalanim;
1243 victim->animTarget = staffhitreversalanim;
1245 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1246 if (victim->weaponactive != -1) {
1247 victim->throwtogglekeydown = 1;
1248 XYZ tempVelocity = victim->velocity * .2;
1249 if (tempVelocity.x == 0)
1250 tempVelocity.x = .1;
1251 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1252 victim->num_weapons--;
1253 if (victim->num_weapons) {
1254 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1255 if (victim->weaponstuck == victim->num_weapons)
1256 victim->weaponstuck = 0;
1259 victim->weaponactive = -1;
1260 for (unsigned j = 0; j < Person::players.size(); j++) {
1261 Person::players[j]->wentforweapon = 0;
1264 animTarget = staffspinhitreversedanim;
1265 animCurrent = staffspinhitreversedanim;
1266 victim->animCurrent = staffspinhitreversalanim;
1267 victim->animTarget = staffspinhitreversalanim;
1269 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1270 if (victim->weaponactive != -1) {
1271 victim->throwtogglekeydown = 1;
1272 XYZ tempVelocity = victim->velocity * .2;
1273 if (tempVelocity.x == 0)
1274 tempVelocity.x = .1;
1275 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1276 victim->num_weapons--;
1277 if (victim->num_weapons) {
1278 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1279 if (victim->weaponstuck == victim->num_weapons)
1280 victim->weaponstuck = 0;
1283 victim->weaponactive = -1;
1284 for (unsigned j = 0; j < Person::players.size(); j++) {
1285 Person::players[j]->wentforweapon = 0;
1288 animTarget = swordslashreversedanim;
1289 animCurrent = swordslashreversedanim;
1290 victim->animCurrent = swordslashreversalanim;
1291 victim->animTarget = swordslashreversalanim;
1293 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1294 if (victim->weaponactive != -1) {
1295 victim->throwtogglekeydown = 1;
1296 XYZ tempVelocity = victim->velocity * .2;
1297 if (tempVelocity.x == 0)
1298 tempVelocity.x = .1;
1299 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1300 victim->num_weapons--;
1301 if (victim->num_weapons) {
1302 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1303 if (victim->weaponstuck == victim->num_weapons)
1304 victim->weaponstuck = 0;
1307 victim->weaponactive = -1;
1308 for (unsigned j = 0; j < Person::players.size(); j++) {
1309 Person::players[j]->wentforweapon = 0;
1312 animTarget = knifeslashreversedanim;
1313 animCurrent = knifeslashreversedanim;
1314 victim->animCurrent = knifeslashreversalanim;
1315 victim->animTarget = knifeslashreversalanim;
1317 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1318 victim->targettilt2 = targettilt2;
1319 victim->frameCurrent = frameCurrent;
1320 victim->frameTarget = frameTarget;
1321 victim->target = target;
1322 victim->velocity = 0;
1323 victim->oldcoords = victim->coords;
1324 victim->coords = coords;
1325 victim->targetyaw = targetyaw;
1326 victim->yaw = targetyaw;
1327 victim->victim = this->shared_from_this();
1329 if (animTarget == winduppunchanim) {
1330 animTarget = winduppunchblockedanim;
1331 victim->animTarget = blockhighleftanim;
1332 victim->frameTarget = 1;
1333 victim->target = .5;
1334 victim->victim = this->shared_from_this();
1335 victim->targetyaw = targetyaw + 180;
1337 if (animTarget == wolfslapanim) {
1338 animTarget = winduppunchblockedanim;
1339 victim->animTarget = blockhighleftanim;
1340 victim->frameTarget = 1;
1341 victim->target = .5;
1342 victim->victim = this->shared_from_this();
1343 victim->targetyaw = targetyaw + 180;
1345 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1346 animTarget = swordslashparriedanim;
1347 parriedrecently = .4;
1348 victim->parriedrecently = 0;
1349 victim->animTarget = swordslashparryanim;
1350 victim->frameTarget = 1;
1351 victim->target = .5;
1352 victim->victim = this->shared_from_this();
1353 victim->targetyaw = targetyaw + 180;
1355 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1356 if (victim->weaponactive != -1) {
1357 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1358 if (weapons[victim->weaponids[0]].getType() == staff)
1359 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1360 if (weapons[weaponids[0]].getType() == staff)
1361 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1362 emit_sound_at(swordstaffsound, victim->coords);
1364 emit_sound_at(metalhitsound, victim->coords);
1368 victim->Puff(righthand);
1370 victim->frameTarget = 0;
1371 victim->animTarget = staggerbackhighanim;
1372 victim->targetyaw = targetyaw + 180;
1374 aim = DoRotation(facing, 0, 90, 0) * 21;
1376 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1377 victim->num_weapons--;
1378 if (victim->num_weapons) {
1379 victim->weaponids[0] = victim->weaponids[num_weapons];
1380 if (victim->weaponstuck == victim->num_weapons)
1381 victim->weaponstuck = 0;
1383 victim->weaponactive = -1;
1384 for (unsigned i = 0; i < Person::players.size(); i++) {
1385 Person::players[i]->wentforweapon = 0;
1389 if (abs(Random() % 20) == 0) {
1390 if (weaponactive != -1) {
1391 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1392 if (weapons[victim->weaponids[0]].getType() == staff)
1393 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1394 if (weapons[weaponids[0]].getType() == staff)
1395 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1397 emit_sound_at(swordstaffsound, coords);
1399 emit_sound_at(metalhitsound, coords);
1407 animTarget = staggerbackhighanim;
1408 targetyaw = targetyaw + 180;
1410 aim = DoRotation(facing, 0, 90, 0) * 21;
1412 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1415 weaponids[0] = weaponids[num_weapons];
1416 if (weaponstuck == num_weapons)
1420 for (unsigned i = 0; i < Person::players.size(); i++) {
1421 Person::players[i]->wentforweapon = 0;
1428 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1429 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1430 victim->animTarget = dodgebackanim;
1431 victim->frameTarget = 0;
1435 rotatetarget = coords - victim->coords;
1436 Normalise(&rotatetarget);
1437 victim->targetyaw = -asin(0 - rotatetarget.x);
1438 victim->targetyaw *= 360 / 6.28;
1439 if (rotatetarget.z < 0)
1440 victim->targetyaw = 180 - victim->targetyaw;
1442 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1444 victim->lastattack3 = victim->lastattack2;
1445 victim->lastattack2 = victim->lastattack;
1446 victim->lastattack = victim->animTarget;
1448 victim->animTarget = sweepanim;
1449 victim->frameTarget = 0;
1453 rotatetarget = coords - victim->coords;
1454 Normalise(&rotatetarget);
1455 victim->targetyaw = -asin(0 - rotatetarget.x);
1456 victim->targetyaw *= 360 / 6.28;
1457 if (rotatetarget.z < 0)
1458 victim->targetyaw = 180 - victim->targetyaw;
1460 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1462 victim->lastattack3 = victim->lastattack2;
1463 victim->lastattack2 = victim->lastattack;
1464 victim->lastattack = victim->animTarget;
1469 victim->velocity = 0;
1471 if (aitype != playercontrolled) {
1473 if (escapednum < 2) {
1474 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1475 if ((Random() % chances) == 0) {
1481 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1488 void Person::DoDamage(float howmuch)
1490 // subtract health (temporary?)
1491 if (tutoriallevel != 1)
1492 damage += howmuch / power;
1495 damagedealt += howmuch / power;
1497 damagetaken += howmuch / power;
1500 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1503 if (tutoriallevel != 1)
1504 permanentdamage += howmuch / 2 / power;
1505 if (tutoriallevel != 1)
1506 superpermanentdamage += howmuch / 4 / power;
1508 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1510 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1514 camerashake += howmuch / 100;
1515 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1516 blackout = damage / damagetolerance;
1521 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1522 aitype = attacktypecutoff;
1523 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1524 if (abs(Random() % 2) == 0) {
1525 aitype = gethelptype;
1528 aitype = attacktypecutoff;
1532 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1535 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1536 if (skeleton.free) {
1537 flatvelocity2 = skeleton.joints[i].velocity;
1538 flatfacing2 = skeleton.joints[i].position * scale + coords;
1540 flatvelocity2 = velocity;
1541 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1543 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1544 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1545 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1546 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1547 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1548 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1551 emit_sound_at(splattersound, coords);
1556 if (!dead && creature == wolftype) {
1557 award_bonus(0, Wolfbonus);
1564 if (tutoriallevel != 1 || id == 0)
1565 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1566 int whichsound = -1;
1568 if (creature == wolftype) {
1569 int i = abs(Random() % 2);
1571 whichsound = snarlsound;
1573 whichsound = snarl2sound;
1575 if (creature == rabbittype) {
1576 int i = abs(Random() % 2);
1578 whichsound = rabbitpainsound;
1579 if (i == 1 && damage > damagetolerance)
1580 whichsound = rabbitpain1sound;
1583 if (whichsound != -1) {
1584 emit_sound_at(whichsound, coords);
1585 addEnvSound(coords);
1592 * calculate/animate head facing direction?
1594 void Person::DoHead()
1596 static XYZ rotatearound;
1598 static float lookspeed = 500;
1600 if (!freeze && !winfreeze) {
1603 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1604 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1606 while (targetheadyaw > 180)targetheadyaw -= 360;
1607 while (targetheadyaw < -180)targetheadyaw += 360;
1609 if (targetheadyaw > 160)
1610 targetheadpitch = targetheadpitch * -1;
1611 if (targetheadyaw < -160)
1612 targetheadpitch = targetheadpitch * -1;
1613 if (targetheadyaw > 160)
1614 targetheadyaw = targetheadyaw - 180;
1615 if (targetheadyaw < -160)
1616 targetheadyaw = targetheadyaw + 180;
1618 if (targetheadpitch > 120)
1619 targetheadpitch = 120;
1620 if (targetheadpitch < -120)
1621 targetheadpitch = -120;
1622 if (targetheadyaw > 120)
1623 targetheadyaw = 120;
1624 if (targetheadyaw < -120)
1625 targetheadyaw = -120;
1628 targetheadpitch = 0;
1630 if (targetheadyaw > 80)
1632 if (targetheadyaw < -80)
1633 targetheadyaw = -80;
1634 if (targetheadpitch > 50)
1635 targetheadpitch = 50;
1636 if (targetheadpitch < -50)
1637 targetheadpitch = -50;
1640 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1641 headyaw = targetheadyaw;
1642 else if (headyaw > targetheadyaw) {
1643 headyaw -= multiplier * lookspeed;
1644 } else if (headyaw < targetheadyaw) {
1645 headyaw += multiplier * lookspeed;
1648 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1649 headpitch = targetheadpitch;
1650 else if (headpitch > targetheadpitch) {
1651 headpitch -= multiplier * lookspeed / 2;
1652 } else if (headpitch < targetheadpitch) {
1653 headpitch += multiplier * lookspeed / 2;
1656 rotatearound = jointPos(neck);
1657 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1661 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1662 facing = DoRotation(facing, headpitch * .4, 0, 0);
1663 facing = DoRotation(facing, 0, headyaw * .4, 0);
1666 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1667 facing = DoRotation(facing, headpitch * .8, 0, 0);
1668 facing = DoRotation(facing, 0, headyaw * .8, 0);
1671 if (animTarget == walkanim) {
1672 facing = DoRotation(facing, headpitch * .6, 0, 0);
1673 facing = DoRotation(facing, 0, headyaw * .6, 0);
1676 skeleton.specialforward[0] = facing;
1677 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1678 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1679 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1680 skeleton.FindRotationMuscle(i, animTarget);
1687 * ragdolls character?
1689 void Person::RagDoll(bool checkcollision)
1694 if (!skeleton.free) {
1697 if (id == 0 && isFlip())
1704 facing = DoRotation(facing, 0, yaw, 0);
1706 skeleton.freetime = 0;
1708 skeleton.longdead = 0;
1711 skeleton.broken = 0;
1712 skeleton.spinny = 1;
1714 skeleton.freefall = 1;
1716 if (!isnormal(velocity.x)) velocity.x = 0;
1717 if (!isnormal(velocity.y)) velocity.y = 0;
1718 if (!isnormal(velocity.z)) velocity.z = 0;
1719 if (!isnormal(yaw)) yaw = 0;
1720 if (!isnormal(coords.x)) coords = 0;
1721 if (!isnormal(tilt)) tilt = 0;
1722 if (!isnormal(tilt2)) tilt2 = 0;
1724 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1725 skeleton.joints[i].delay = 0;
1726 skeleton.joints[i].locked = 0;
1727 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1728 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1729 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1730 skeleton.joints[i].position.y += .1;
1731 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1732 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1735 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1736 skeleton.joints[i].velocity = 0;
1737 skeleton.joints[i].velchange = 0;
1739 skeleton.DoConstraints(&coords, &scale);
1740 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1741 skeleton.DoConstraints(&coords, &scale);
1742 skeleton.DoConstraints(&coords, &scale);
1743 skeleton.DoConstraints(&coords, &scale);
1744 skeleton.DoConstraints(&coords, &scale);
1747 speed = targetFrame().speed * 2;
1748 if (currentFrame().speed > targetFrame().speed) {
1749 speed = currentFrame().speed * 2;
1752 speed = transspeed * 2;
1756 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1757 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1758 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);
1760 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1761 change.x = (float)(Random() % 100) / 100;
1762 change.y = (float)(Random() % 100) / 100;
1763 change.z = (float)(Random() % 100) / 100;
1764 skeleton.joints[i].velocity += change;
1765 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1767 change.x = (float)(Random() % 100) / 100;
1768 change.y = (float)(Random() % 100) / 100;
1769 change.z = (float)(Random() % 100) / 100;
1770 skeleton.joints[i].velchange += change;
1771 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1774 if (checkcollision) {
1777 if (!skeleton.joints.empty()) {
1780 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1781 average += skeleton.joints[j].position;
1783 average /= skeleton.joints.size();
1784 coords += average * scale;
1785 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1786 skeleton.joints[j].position -= average;
1790 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1791 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1792 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1793 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1794 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1797 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1798 coords.x = lowpoint.x;
1799 coords.z = lowpoint.z;
1808 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1809 velocity += skeleton.joints[i].velocity * scale;
1811 velocity /= skeleton.joints.size();
1814 if (Random() % 2 == 0) {
1815 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1816 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1817 weapons[weaponids[0]].velocity.x += .01;
1820 weaponids[0] = weaponids[num_weapons];
1821 if (weaponstuck == num_weapons)
1825 for (unsigned i = 0; i < Person::players.size(); i++) {
1826 Person::players[i]->wentforweapon = 0;
1831 animTarget = bounceidleanim;
1832 animCurrent = bounceidleanim;
1842 void Person::FootLand(bodypart whichfoot, float opacity)
1844 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1845 cerr << "FootLand called on wrong bodypart" << endl;
1848 static XYZ terrainlight;
1849 static XYZ footvel, footpoint;
1850 if (opacity >= 1 || skiddelay <= 0) {
1853 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1854 if (distsq(&footpoint, &viewer))
1855 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1856 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1857 footvel = velocity / 5;
1860 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1861 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1862 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1863 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1864 if (environment == snowyenvironment) {
1865 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1867 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1869 } else if (environment == grassyenvironment) {
1870 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1871 } else if (environment == desertenvironment) {
1872 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1874 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1878 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1879 footvel = velocity / 5;
1882 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1883 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1884 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1891 * make a puff effect at a body part (dust effect?)
1893 void Person::Puff(int whichlabel)
1895 static XYZ footvel, footpoint;
1898 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1899 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1903 * I think I added this in an attempt to clean up code
1905 void Person::setAnimation(int animation)
1907 animTarget = animation;
1916 void Person::DoAnimations()
1918 if (!skeleton.free) {
1919 static float oldtarget;
1921 if (isIdle() && animCurrent != getIdle())
1922 normalsupdatedelay = 0;
1924 if (animTarget == tempanim || animCurrent == tempanim) {
1925 Animation::animations[tempanim] = tempanimation;
1927 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1933 vel[0] = velocity.x;
1934 vel[1] = velocity.y;
1935 vel[2] = velocity.z;
1938 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1939 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1941 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1943 if (!crouchkeydown && velocity.y >= -15)
1946 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1951 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1953 if (normaldotproduct(targfacing, velocity) >= -.3)
1954 animTarget = flipanim;
1956 animTarget = backflipanim;
1957 crouchtogglekeydown = 1;
1965 if (Animation::animations[animTarget].attack != reversed)
1967 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1968 crouchtogglekeydown = 0;
1969 if (aitype == playercontrolled)
1972 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1975 crouchtogglekeydown = 1;
1979 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1981 normalsupdatedelay = 0;
1985 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1987 emit_sound_at(fireendsound, coords);
1988 pause_sound(stream_firesound);
1992 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1993 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1995 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1996 if (normaldotproduct(victim->facing, facing) > 0)
1997 victim->animTarget = rabbittackledbackanim;
1999 victim->animTarget = rabbittackledfrontanim;
2000 victim->frameTarget = 2;
2003 victim->targetyaw = yaw;
2004 if (victim->aitype == gethelptype)
2005 victim->DoDamage(victim->damagetolerance - victim->damage);
2006 //victim->DoDamage(30);
2007 if (creature == wolftype) {
2009 emit_sound_at(clawslicesound, victim->coords);
2011 victim->DoBloodBig(1 / victim->armorhead, 210);
2013 award_bonus(id, TackleBonus,
2014 victim->aitype == gethelptype ? 50 : 0);
2018 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2019 if (weapons[weaponids[0]].getType() == knife) {
2020 if (weaponactive == -1)
2022 else if (weaponactive == 0)
2025 if (weaponactive == -1) {
2026 emit_sound_at(knifesheathesound, coords);
2028 if (weaponactive != -1) {
2029 emit_sound_at(knifedrawsound, coords, 128);
2032 drawtogglekeydown = 1;
2035 if (tutoriallevel != 1 || id == 0)
2036 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2037 int whichsound = -1;
2039 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2040 if (targetFrame().label == 1)
2041 whichsound = footstepsound;
2043 whichsound = footstepsound2;
2044 if (targetFrame().label == 1)
2045 FootLand(leftfoot, 1);
2046 if (targetFrame().label == 2)
2047 FootLand(rightfoot, 1);
2048 if (targetFrame().label == 3 && isRun()) {
2049 FootLand(rightfoot, 1);
2050 FootLand(leftfoot, 1);
2054 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2055 if (targetFrame().label == 1)
2056 whichsound = footstepsound3;
2058 whichsound = footstepsound4;
2062 if (targetFrame().label == 1)
2063 whichsound = footstepsound3;
2065 whichsound = footstepsound4;
2067 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2068 if (Animation::animations[animTarget].attack != neutral) {
2069 unsigned r = abs(Random() % 3);
2071 whichsound = lowwhooshsound;
2073 whichsound = midwhooshsound;
2075 whichsound = highwhooshsound;
2077 if (Animation::animations[animTarget].attack == neutral) {
2078 whichsound = movewhooshsound;
2080 } else if (targetFrame().label == 4) {
2081 whichsound = knifeswishsound;
2083 if (targetFrame().label == 8 && tutoriallevel != 1) {
2084 whichsound = landsound2;
2087 if (whichsound != -1) {
2088 emit_sound_at(whichsound, coords, 256.);
2091 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2092 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2093 addEnvSound(coords, 15);
2095 addEnvSound(coords, 6);
2100 if (targetFrame().label == 3) {
2102 emit_sound_at(whichsound, coords, 128.);
2108 if (tutoriallevel != 1 || id == 0)
2109 if (speechdelay <= 0)
2110 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2111 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2112 int whichsound = -1;
2113 if (targetFrame().label == 4 && aitype != playercontrolled) {
2114 if (Animation::animations[animTarget].attack != neutral) {
2115 unsigned r = abs(Random() % 4);
2116 if (creature == rabbittype) {
2117 if (r == 0) whichsound = rabbitattacksound;
2118 if (r == 1) whichsound = rabbitattack2sound;
2119 if (r == 2) whichsound = rabbitattack3sound;
2120 if (r == 3) whichsound = rabbitattack4sound;
2122 if (creature == wolftype) {
2123 if (r == 0) whichsound = barksound;
2124 if (r == 1) whichsound = bark2sound;
2125 if (r == 2) whichsound = bark3sound;
2126 if (r == 3) whichsound = barkgrowlsound;
2132 if (whichsound != -1) {
2133 emit_sound_at(whichsound, coords);
2139 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2140 FootLand(leftfoot, 1);
2141 FootLand(rightfoot, 1);
2145 currentoffset = targetoffset;
2146 frameTarget = frameCurrent;
2147 animCurrent = animTarget;
2150 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2151 for (unsigned i = 0; i < weapons.size(); i++) {
2152 if (weapons[i].owner == -1)
2153 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2154 if (distsq(&coords, &weapons[i].position) >= 1) {
2155 if (weapons[i].getType() != staff) {
2156 emit_sound_at(knifedrawsound, coords, 128.);
2165 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2166 for (unsigned i = 0; i < weapons.size(); i++) {
2167 bool willwork = true;
2168 if (weapons[i].owner != -1)
2169 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2170 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2171 if (Person::players[weapons[i].owner]->num_weapons > 1)
2173 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2174 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2175 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2176 bool fleshstuck = false;
2177 if (weapons[i].owner != -1)
2178 if (victim->weaponstuck != -1) {
2179 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2184 emit_sound_at(fleshstabremovesound, coords, 128.);
2186 if (weapons[i].getType() != staff) {
2187 emit_sound_at(knifedrawsound, coords, 128.);
2190 if (weapons[i].owner != -1) {
2191 victim = Person::players[weapons[i].owner];
2192 if (victim->num_weapons == 1)
2193 victim->num_weapons = 0;
2195 victim->num_weapons = 1;
2197 //victim->weaponactive=-1;
2198 victim->skeleton.longdead = 0;
2199 victim->skeleton.free = 1;
2200 victim->skeleton.broken = 0;
2202 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2203 victim->skeleton.joints[j].velchange = 0;
2204 victim->skeleton.joints[j].locked = 0;
2210 Normalise(&relative);
2211 XYZ footvel, footpoint;
2213 footpoint = weapons[i].position;
2214 if (victim->weaponstuck != -1) {
2215 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2217 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2218 weapons[i].bloody = 2;
2219 weapons[i].blooddrip = 5;
2220 victim->weaponstuck = -1;
2223 if (victim->num_weapons > 0) {
2224 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2225 victim->weaponstuck = 0;
2226 if (victim->weaponids[0] == int(i))
2227 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2230 victim->jointVel(abdomen) += relative * 6;
2231 victim->jointVel(neck) += relative * 6;
2232 victim->jointVel(rightshoulder) += relative * 6;
2233 victim->jointVel(leftshoulder) += relative * 6;
2241 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2242 if (weaponactive == -1)
2244 else if (weaponactive == 0) {
2246 if (num_weapons == 2) {
2248 buffer = weaponids[0];
2249 weaponids[0] = weaponids[1];
2250 weaponids[1] = buffer;
2253 if (weaponactive == -1) {
2254 emit_sound_at(knifesheathesound, coords, 128.);
2256 if (weaponactive != -1) {
2257 emit_sound_at(knifedrawsound, coords, 128.);
2262 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2263 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2264 Normalise(&rotatetarget);
2265 targetyaw = -asin(0 - rotatetarget.x);
2266 targetyaw *= 360 / 6.28;
2267 if (rotatetarget.z < 0)
2268 targetyaw = 180 - targetyaw;
2270 if (animTarget == walljumprightkickanim)
2272 if (animTarget == walljumpleftkickanim)
2278 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2281 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2286 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2287 animTarget = rabbittackleanim;
2289 emit_sound_at(jumpsound, coords);
2297 targetloc = velocity;
2298 Normalise(&targetloc);
2299 targetloc += coords;
2300 for (unsigned i = 0; i < Person::players.size(); i++) {
2302 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2303 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2307 if (closestid != -1)
2308 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2310 victim = Person::players[closestid];
2311 coords = victim->coords;
2312 animCurrent = rabbittacklinganim;
2313 animTarget = rabbittacklinganim;
2317 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2318 rotatetarget = coords - victim->coords;
2319 Normalise(&rotatetarget);
2320 targetyaw = -asin(0 - rotatetarget.x);
2321 targetyaw *= 360 / 6.28;
2322 if (rotatetarget.z < 0)
2323 targetyaw = 180 - targetyaw;
2325 if (animTarget != rabbitrunninganim) {
2326 emit_sound_at(jumpsound, coords, 128.);
2332 float damagemult = 1 * power;
2333 if (creature == wolftype)
2334 damagemult = 2.5 * power;
2336 damagemult /= victim->damagetolerance / 200;
2338 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)) {
2339 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2340 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2344 if (Random() % 2 || creature == wolftype) {
2347 if (creature == wolftype)
2350 if (tutoriallevel != 1) {
2351 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2353 if (creature == wolftype) {
2354 emit_sound_at(clawslicesound, victim->coords, 128.);
2356 victim->DoBloodBig(2 / victim->armorhead, 175);
2360 relative = victim->coords - coords;
2362 Normalise(&relative);
2363 relative = DoRotation(relative, 0, -90, 0);
2364 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2365 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2367 victim->jointVel(head) += relative * damagemult * 200;
2369 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2375 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2376 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2380 if (Random() % 2 || creature == wolftype) {
2382 if (creature == wolftype)
2385 emit_sound_at(whooshhitsound, victim->coords);
2386 if (creature == wolftype) {
2387 emit_sound_at(clawslicesound, victim->coords, 128.);
2389 victim->DoBloodBig(2, 175);
2393 relative = victim->coords - coords;
2395 Normalise(&relative);
2397 Normalise(&relative);
2398 relative = DoRotation(relative, 0, 90, 0);
2399 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2400 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2402 victim->jointVel(head) += relative * damagemult * 100;
2404 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2408 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2409 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2415 if (tutoriallevel != 1) {
2416 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2418 if (creature == wolftype) {
2419 emit_sound_at(clawslicesound, victim->coords, 128.);
2421 victim->DoBloodBig(2 / victim->armorhead, 175);
2427 Normalise(&relative);
2428 relative = DoRotation(relative, 0, -90, 0);
2429 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2430 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2432 victim->jointVel(head) += relative * damagemult * 200;
2434 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2436 if (victim->damage > victim->damagetolerance)
2437 award_bonus(id, style);
2443 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2444 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2450 if (tutoriallevel != 1) {
2451 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2453 if (creature == wolftype) {
2454 emit_sound_at(clawslicesound, victim->coords, 128.);
2456 victim->DoBloodBig(2 / victim->armorhead, 175);
2462 Normalise(&relative);
2463 relative = DoRotation(relative, 0, 90, 0);
2464 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2465 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2467 victim->jointVel(head) += relative * damagemult * 200;
2469 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2471 if (victim->damage > victim->damagetolerance)
2472 award_bonus(id, style);
2478 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2479 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2487 emit_sound_at(whooshhitsound, victim->coords);
2490 relative = victim->coords - coords;
2492 Normalise(&relative);
2493 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2494 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2496 victim->jointVel(head) += relative * damagemult * 100;
2498 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2502 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2503 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2507 emit_sound_at(whooshhitsound, victim->coords, 128.);
2509 victim->skeleton.longdead = 0;
2510 victim->skeleton.free = 1;
2511 victim->skeleton.broken = 0;
2512 victim->skeleton.spinny = 1;
2514 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2515 victim->skeleton.joints[i].velchange = 0;
2516 victim->skeleton.joints[i].delay = 0;
2517 victim->skeleton.joints[i].locked = 0;
2518 //victim->skeleton.joints[i].velocity=0;
2524 Normalise(&relative);
2525 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2526 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2527 victim->skeleton.joints[i].position.y += relative.y * .3;
2528 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2529 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2531 victim->Puff(abdomen);
2532 victim->jointVel(abdomen).y = relative.y * 400;
2536 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2537 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2541 if (tutoriallevel != 1) {
2542 emit_sound_at(heavyimpactsound, coords, 128.);
2545 relative = victim->coords - coords;
2547 Normalise(&relative);
2548 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2549 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2551 victim->Puff(abdomen);
2552 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2556 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2557 victim->jointVel(abdomen) += relative * damagemult * 300;
2561 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2562 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2566 if (tutoriallevel != 1) {
2567 emit_sound_at(thudsound, coords);
2570 victim->skeleton.longdead = 0;
2571 victim->skeleton.free = 1;
2572 victim->skeleton.broken = 0;
2573 victim->skeleton.spinny = 1;
2575 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2576 victim->skeleton.joints[i].velchange = 0;
2577 //victim->skeleton.joints[i].delay=0;
2578 victim->skeleton.joints[i].locked = 0;
2581 relative = victim->coords - coords;
2582 Normalise(&relative);
2584 Normalise(&relative);
2585 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2586 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2591 victim->Puff(abdomen);
2592 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2593 victim->jointVel(abdomen) += relative * damagemult * 200;
2602 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2605 if (!victim->skeleton.free)
2609 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2610 emit_sound_at(knifesheathesound, coords, 128.);
2613 if (victim && hasvictim) {
2614 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2616 XYZ where, startpoint, endpoint, movepoint, colpoint;
2617 float rotationpoint;
2619 if (weapons[weaponids[weaponactive]].getType() == knife) {
2620 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2621 where -= victim->coords;
2622 if (!victim->skeleton.free)
2623 where = DoRotation(where, 0, -victim->yaw, 0);
2626 startpoint.y += 100;
2630 if (weapons[weaponids[weaponactive]].getType() == sword) {
2631 where = weapons[weaponids[weaponactive]].position;
2632 where -= victim->coords;
2633 if (!victim->skeleton.free)
2634 where = DoRotation(where, 0, -victim->yaw, 0);
2636 where = weapons[weaponids[weaponactive]].tippoint;
2637 where -= victim->coords;
2638 if (!victim->skeleton.free)
2639 where = DoRotation(where, 0, -victim->yaw, 0);
2642 if (weapons[weaponids[weaponactive]].getType() == staff) {
2643 where = weapons[weaponids[weaponactive]].position;
2644 where -= victim->coords;
2645 if (!victim->skeleton.free)
2646 where = DoRotation(where, 0, -victim->yaw, 0);
2648 where = weapons[weaponids[weaponactive]].tippoint;
2649 where -= victim->coords;
2650 if (!victim->skeleton.free)
2651 where = DoRotation(where, 0, -victim->yaw, 0);
2656 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2658 if (whichtri != -1) {
2659 if (victim->dead != 2) {
2660 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2662 award_bonus(id, FinishedBonus);
2665 weapons[weaponids[weaponactive]].bloody = 2;
2667 victim->skeleton.longdead = 0;
2668 victim->skeleton.free = 1;
2669 victim->skeleton.broken = 0;
2671 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2672 victim->skeleton.joints[i].velchange = 0;
2673 victim->skeleton.joints[i].locked = 0;
2674 //victim->skeleton.joints[i].velocity=0;
2676 emit_sound_at(fleshstabsound, coords, 128);
2679 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2680 weapons[weaponids[weaponactive]].blooddrip += 5;
2681 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2683 if (whichtri == -1) {
2685 emit_sound_at(knifesheathesound, coords, 128.);
2691 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2693 emit_sound_at(knifedrawsound, coords, 128);
2696 if (victim && hasvictim) {
2697 XYZ footvel, footpoint;
2699 emit_sound_at(fleshstabremovesound, coords, 128.);
2702 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2704 if (weapons[weaponids[weaponactive]].getType() == sword) {
2705 XYZ where, startpoint, endpoint, movepoint;
2706 float rotationpoint;
2709 where = weapons[weaponids[weaponactive]].position;
2710 where -= victim->coords;
2711 if (!victim->skeleton.free)
2712 where = DoRotation(where, 0, -victim->yaw, 0);
2714 where = weapons[weaponids[weaponactive]].tippoint;
2715 where -= victim->coords;
2716 if (!victim->skeleton.free)
2717 where = DoRotation(where, 0, -victim->yaw, 0);
2722 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2723 footpoint += victim->coords;
2725 if (whichtri == -1) {
2726 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2729 if (weapons[weaponids[weaponactive]].getType() == staff) {
2730 XYZ where, startpoint, endpoint, movepoint;
2731 float rotationpoint;
2734 where = weapons[weaponids[weaponactive]].position;
2735 where -= victim->coords;
2736 if (!victim->skeleton.free)
2737 where = DoRotation(where, 0, -victim->yaw, 0);
2739 where = weapons[weaponids[weaponactive]].tippoint;
2740 where -= victim->coords;
2741 if (!victim->skeleton.free)
2742 where = DoRotation(where, 0, -victim->yaw, 0);
2747 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2748 footpoint += victim->coords;
2750 if (whichtri == -1) {
2751 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2754 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2756 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2757 victim->skeleton.longdead = 0;
2758 victim->skeleton.free = 1;
2759 victim->skeleton.broken = 0;
2761 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2762 victim->skeleton.joints[i].velchange = 0;
2763 victim->skeleton.joints[i].locked = 0;
2764 //victim->skeleton.joints[i].velocity=0;
2770 Normalise(&relative);
2771 //victim->Puff(abdomen);
2773 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2775 if (victim->bloodloss < victim->damagetolerance) {
2776 victim->bloodloss += 1000;
2780 victim->jointVel(abdomen) += relative * damagemult * 20;
2784 if (!hasvictim && onterrain) {
2785 weapons[weaponids[weaponactive]].bloody = 0;
2786 weapons[weaponids[weaponactive]].blooddrip = 0;
2790 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2791 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2799 if (tutoriallevel != 1) {
2800 emit_sound_at(heavyimpactsound, victim->coords, 128);
2805 relative = victim->coords - coords;
2807 Normalise(&relative);
2808 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2809 victim->skeleton.joints[i].velocity = relative * 30;
2811 victim->jointVel(head) += relative * damagemult * 150;
2813 victim->frameTarget = 0;
2814 victim->animTarget = staggerbackhardanim;
2815 victim->targetyaw = targetyaw + 180;
2817 victim->stunned = 1;
2820 victim->Puff(abdomen);
2821 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2828 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2829 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2833 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2834 if (tutoriallevel != 1) {
2835 emit_sound_at(thudsound, victim->coords);
2837 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2838 if (tutoriallevel != 1) {
2839 emit_sound_at(whooshhitsound, victim->coords);
2842 if (tutoriallevel != 1) {
2843 emit_sound_at(heavyimpactsound, victim->coords);
2847 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2850 relative = victim->coords - coords;
2852 Normalise(&relative);
2854 Normalise(&relative);
2855 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2856 victim->skeleton.joints[i].velocity = relative * 5;
2858 victim->jointVel(abdomen) += relative * damagemult * 400;
2860 victim->frameTarget = 0;
2861 victim->animTarget = staggerbackhardanim;
2862 victim->targetyaw = targetyaw + 180;
2864 victim->stunned = 1;
2866 victim->Puff(abdomen);
2867 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2873 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2874 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2875 if (victim->id == 0)
2877 emit_sound_at(landsound2, victim->coords);
2883 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2884 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2885 if (victim->id == 0)
2888 if (weaponactive != -1) {
2889 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2890 if (weapons[victim->weaponids[0]].getType() == staff)
2891 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2892 if (weapons[weaponids[0]].getType() == staff)
2893 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2895 emit_sound_at(swordstaffsound, victim->coords);
2897 emit_sound_at(metalhitsound, victim->coords);
2905 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2906 if (weaponactive != -1) {
2909 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);
2911 weapons[weaponids[0]].thrown(aim * 50);
2914 weaponids[0] = weaponids[num_weapons];
2920 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2922 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2924 if (tutoriallevel != 1)
2925 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2927 award_bonus(id, Slicebonus);
2928 if (tutoriallevel != 1) {
2929 emit_sound_at(knifeslicesound, victim->coords);
2931 //victim->jointVel(abdomen)+=relative*damagemult*200;
2932 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2933 if (victim->id != 0 || difficulty == 2) {
2934 victim->frameTarget = 0;
2935 victim->animTarget = staggerbackhardanim;
2936 victim->targetyaw = targetyaw + 180;
2940 victim->lowreversaldelay = 0;
2941 victim->highreversaldelay = 0;
2942 if (aitype != playercontrolled)
2943 weaponmissdelay = .6;
2945 if (tutoriallevel != 1)
2946 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2947 weapons[weaponids[weaponactive]].bloody = 1;
2948 if (tutoriallevel != 1)
2949 weapons[weaponids[weaponactive]].blooddrip += 3;
2951 XYZ footvel, footpoint;
2953 if (skeleton.free) {
2954 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2956 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2958 if (tutoriallevel != 1) {
2960 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2961 footvel = DoRotation(facing, 0, 90, 0) * .8;
2963 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2964 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2965 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2966 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2968 if (tutoriallevel == 1) {
2969 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2971 victim->DoDamage(damagemult * 0);
2974 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2975 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2976 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2977 award_bonus(id, Slashbonus);
2979 if (tutoriallevel != 1) {
2980 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2981 victim->DoBloodBig(2 / victim->armorhigh, 190);
2983 victim->DoBloodBig(2 / victim->armorhigh, 185);
2984 victim->deathbleeding = 1;
2985 emit_sound_at(swordslicesound, victim->coords);
2987 //victim->jointVel(abdomen)+=relative*damagemult*200;
2988 if (tutoriallevel != 1) {
2989 victim->frameTarget = 0;
2990 victim->animTarget = staggerbackhardanim;
2991 victim->targetyaw = targetyaw + 180;
2995 if (tutoriallevel != 1) {
2996 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2997 weapons[weaponids[weaponactive]].bloody = 1;
2998 weapons[weaponids[weaponactive]].blooddrip += 3;
3000 float bloodlossamount;
3001 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3002 victim->bloodloss += bloodlossamount / victim->armorhigh;
3003 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
3004 victim->DoDamage(damagemult * 0);
3006 XYZ footvel, footpoint;
3008 if (skeleton.free) {
3009 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3011 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3014 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3015 footvel = DoRotation(facing, 0, 90, 0) * .8;
3017 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3018 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3019 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3020 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3023 if (victim->weaponactive != -1) {
3024 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3025 if (weapons[victim->weaponids[0]].getType() == staff)
3026 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3027 if (weapons[weaponids[0]].getType() == staff)
3028 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3030 emit_sound_at(swordstaffsound, victim->coords);
3032 emit_sound_at(metalhitsound, victim->coords);
3038 victim->Puff(righthand);
3040 victim->frameTarget = 0;
3041 victim->animTarget = staggerbackhighanim;
3042 victim->targetyaw = targetyaw + 180;
3044 aim = DoRotation(facing, 0, 90, 0) * 21;
3046 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3047 victim->num_weapons--;
3048 if (victim->num_weapons) {
3049 victim->weaponids[0] = victim->weaponids[num_weapons];
3050 if (victim->weaponstuck == victim->num_weapons)
3051 victim->weaponstuck = 0;
3053 victim->weaponactive = -1;
3054 for (unsigned i = 0; i < Person::players.size(); i++) {
3055 Person::players[i]->wentforweapon = 0;
3062 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3063 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3064 if (tutoriallevel != 1) {
3065 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3069 if (Random() % 2 || creature == wolftype) {
3072 emit_sound_at(staffheadsound, victim->coords);
3076 relative = victim->coords - coords;
3078 Normalise(&relative);
3079 relative = DoRotation(relative, 0, 90, 0);
3081 Normalise(&relative);
3082 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3083 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3085 victim->jointVel(head) += relative * damagemult * 230;
3086 victim->jointVel(neck) += relative * damagemult * 230;
3088 if (tutoriallevel != 1) {
3089 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3091 award_bonus(id, solidhit, 30);
3096 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3097 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3098 if (tutoriallevel != 1) {
3099 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3103 if (Random() % 2 || creature == wolftype) {
3106 emit_sound_at(staffheadsound, victim->coords);
3110 relative = victim->coords - coords;
3112 Normalise(&relative);
3113 relative = DoRotation(relative, 0, -90, 0);
3114 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3115 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3117 victim->jointVel(head) += relative * damagemult * 220;
3118 victim->jointVel(neck) += relative * damagemult * 220;
3120 if (tutoriallevel != 1) {
3121 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3123 award_bonus(id, solidhit, 60);
3128 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3129 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3131 if (tutoriallevel != 1) {
3133 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3136 if (Random() % 2 || creature == wolftype) {
3139 emit_sound_at(staffbodysound, victim->coords);
3141 victim->skeleton.longdead = 0;
3142 victim->skeleton.free = 1;
3143 victim->skeleton.broken = 0;
3145 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3146 victim->skeleton.joints[i].velchange = 0;
3147 victim->skeleton.joints[i].locked = 0;
3148 //victim->skeleton.joints[i].velocity=0;
3155 Normalise(&relative);
3156 if (!victim->dead) {
3157 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3158 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3160 victim->jointVel(abdomen) += relative * damagemult * 40;
3163 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3164 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3167 victim->Puff(abdomen);
3168 if (tutoriallevel != 1) {
3169 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3171 if (!victim->dead) {
3172 award_bonus(id, solidhit, 40);
3178 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3179 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3184 relative = victim->coords - coords;
3186 Normalise(&relative);
3190 if (Animation::animations[victim->animTarget].height == lowheight) {
3196 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3197 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3199 victim->jointVel(head) += relative * damagemult * 200;
3200 if (tutoriallevel != 1) {
3201 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3204 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3205 if (victim->howactive == typesleeping)
3206 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3207 if (creature == wolftype) {
3208 emit_sound_at(clawslicesound, victim->coords, 128.);
3210 victim->DoBloodBig(2 / victim->armorhead, 175);
3213 if (victim->damage >= victim->damagetolerance)
3215 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3216 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3218 victim->jointVel(abdomen) += relative * damagemult * 200;
3219 victim->frameTarget = 0;
3220 victim->animTarget = staggerbackhighanim;
3221 victim->targetyaw = targetyaw + 180;
3223 if (tutoriallevel != 1) {
3224 emit_sound_at(landsound2, victim->coords, 128.);
3226 victim->Puff(abdomen);
3227 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3228 if (creature == wolftype) {
3229 emit_sound_at(clawslicesound, victim->coords, 128.);
3231 victim->DoBloodBig(2 / victim->armorhigh, 170);
3238 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3239 if ((victim->animTarget != jumpupanim) &&
3240 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3241 (victim != this->shared_from_this())) {
3245 if (tutoriallevel != 1) {
3246 emit_sound_at(landsound2, victim->coords, 128.);
3249 relative = victim->coords - coords;
3251 Normalise(&relative);
3253 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3256 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3257 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3259 relative = DoRotation(relative, 0, -90, 0);
3261 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3262 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)
3263 victim->skeleton.joints[i].velocity = relative * 80;
3265 victim->Puff(rightankle);
3266 victim->Puff(leftankle);
3267 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3269 if (victim->damage >= victim->damagetolerance)
3271 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3272 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3274 relative = DoRotation(relative, 0, -90, 0);
3275 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3276 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)
3277 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3279 victim->jointVel(abdomen) += relative * damagemult * 200;
3280 victim->frameTarget = 0;
3281 victim->animTarget = staggerbackhighanim;
3282 victim->targetyaw = targetyaw + 180;
3284 if (tutoriallevel != 1) {
3285 emit_sound_at(landsound2, victim->coords, 128.);
3287 victim->Puff(abdomen);
3288 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3296 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3297 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3305 if (tutoriallevel != 1) {
3306 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3308 if (creature == wolftype) {
3309 emit_sound_at(clawslicesound, victim->coords, 128);
3311 victim->DoBloodBig(2 / victim->armorhigh, 170);
3315 relative = victim->coords - oldcoords;
3317 Normalise(&relative);
3318 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3319 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3321 victim->jointVel(abdomen) += relative * damagemult * 200;
3322 victim->Puff(abdomen);
3323 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3325 award_bonus(id, Reversal);
3328 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3329 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3330 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3331 takeWeapon(victim->weaponids[victim->weaponactive]);
3332 victim->num_weapons--;
3333 if (victim->num_weapons > 0) {
3334 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3336 victim->weaponactive = -1;
3341 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3349 emit_sound_at(whooshhitsound, victim->coords, 128.);
3352 relative = victim->coords - oldcoords;
3354 Normalise(&relative);
3355 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3356 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3358 victim->jointVel(abdomen) += relative * damagemult * 200;
3360 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3363 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3372 award_bonus(id, staffreversebonus);
3374 if (tutoriallevel != 1) {
3375 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3378 award_bonus(id, staffreversebonus); // Huh, again?
3381 relative = victim->coords - oldcoords;
3383 Normalise(&relative);
3384 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3385 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3387 victim->jointVel(abdomen) += relative * damagemult * 200;
3389 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3392 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3398 Normalise(&relative);
3400 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3401 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3403 victim->jointVel(lefthand) *= .1;
3404 victim->jointVel(leftwrist) *= .2;
3405 victim->jointVel(leftelbow) *= .5;
3406 victim->jointVel(leftshoulder) *= .7;
3407 victim->jointVel(righthand) *= .1;
3408 victim->jointVel(rightwrist) *= .2;
3409 victim->jointVel(rightelbow) *= .5;
3410 victim->jointVel(rightshoulder) *= .7;
3412 victim->Puff(abdomen);
3413 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3415 award_bonus(id, Reversal);
3419 if (weaponactive != -1 || creature == wolftype)
3421 if (creature == rabbittype && weaponactive != -1)
3422 if (weapons[weaponids[0]].getType() == staff)
3425 if (weaponactive != -1) {
3426 victim->DoBloodBig(2 / victim->armorhigh, 225);
3427 emit_sound_at(knifeslicesound, victim->coords);
3428 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3429 weapons[weaponids[weaponactive]].bloody = 1;
3430 weapons[weaponids[weaponactive]].blooddrip += 3;
3432 if (weaponactive == -1 && creature == wolftype) {
3433 emit_sound_at(clawslicesound, victim->coords, 128.);
3435 victim->DoBloodBig(2 / victim->armorhigh, 175);
3442 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3448 Normalise(&relative);
3450 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3451 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3453 victim->jointVel(lefthand) *= .1 - 1;
3454 victim->jointVel(leftwrist) *= .2 - 1;
3455 victim->jointVel(leftelbow) *= .5 - 1;
3456 victim->jointVel(leftshoulder) *= .7 - 1;
3457 victim->jointVel(righthand) *= .1 - 1;
3458 victim->jointVel(rightwrist) *= .2 - 1;
3459 victim->jointVel(rightelbow) *= .5 - 1;
3460 victim->jointVel(rightshoulder) *= .7 - 1;
3462 award_bonus(id, swordreversebonus);
3465 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3473 if (tutoriallevel != 1) {
3474 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3478 relative = victim->coords - oldcoords;
3480 Normalise(&relative);
3481 relative = DoRotation(relative, 0, -90, 0);
3482 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3483 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3485 victim->jointVel(abdomen) += relative * damagemult * 200;
3486 victim->Puff(abdomen);
3487 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3489 award_bonus(id, Reversal);
3492 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3495 victim->skeleton.spinny = 0;
3497 relative = facing * -1;
3499 Normalise(&relative);
3500 if (victim->id == 0)
3502 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3503 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3505 victim->damage = victim->damagetolerance;
3506 victim->permanentdamage = victim->damagetolerance - 1;
3509 if (weaponactive != -1 || creature == wolftype)
3511 if (creature == rabbittype && weaponactive != -1)
3512 if (weapons[weaponids[0]].getType() == staff)
3515 if (weaponactive != -1) {
3516 victim->DoBloodBig(200, 225);
3517 emit_sound_at(knifeslicesound, victim->coords);
3519 weapons[weaponids[weaponactive]].bloody = 2;
3520 weapons[weaponids[weaponactive]].blooddrip += 5;
3523 if (creature == wolftype && weaponactive == -1) {
3524 emit_sound_at(clawslicesound, victim->coords, 128.);
3526 victim->DoBloodBig(2, 175);
3529 award_bonus(id, spinecrusher);
3532 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3533 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3535 if (animTarget == knifefollowanim)
3536 victim->DoBloodBig(200, 210);
3537 if (animTarget == knifesneakattackanim) {
3538 XYZ footvel, footpoint;
3540 footpoint = weapons[weaponids[0]].tippoint;
3542 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3543 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3544 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3545 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3546 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3547 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3548 victim->DoBloodBig(200, 195);
3549 award_bonus(id, tracheotomy);
3551 if (animTarget == knifefollowanim) {
3552 award_bonus(id, Stabbonus);
3553 XYZ footvel, footpoint;
3555 footpoint = weapons[weaponids[0]].tippoint;
3557 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3558 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3559 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3560 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3561 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3562 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3565 victim->bloodloss += 10000;
3566 victim->velocity = 0;
3567 emit_sound_at(fleshstabsound, victim->coords);
3569 weapons[weaponids[weaponactive]].bloody = 2;
3570 weapons[weaponids[weaponactive]].blooddrip += 5;
3574 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3576 victim->velocity = 0;
3577 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3578 victim->skeleton.joints[i].velocity = 0;
3580 if (animTarget == knifefollowanim) {
3582 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3583 victim->skeleton.joints[i].velocity = 0;
3586 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3587 emit_sound_at(fleshstabremovesound, victim->coords);
3589 weapons[weaponids[weaponactive]].bloody = 2;
3590 weapons[weaponids[weaponactive]].blooddrip += 5;
3592 XYZ footvel, footpoint;
3594 footpoint = weapons[weaponids[0]].tippoint;
3596 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3597 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3598 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3599 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3600 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3601 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3605 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3606 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3607 award_bonus(id, backstab);
3611 XYZ footvel, footpoint;
3613 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3615 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3616 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3617 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3618 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3619 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3620 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3621 victim->DoBloodBig(200, 180);
3622 victim->DoBloodBig(200, 215);
3623 victim->bloodloss += 10000;
3624 victim->velocity = 0;
3625 emit_sound_at(fleshstabsound, victim->coords);
3627 weapons[weaponids[weaponactive]].bloody = 2;
3628 weapons[weaponids[weaponactive]].blooddrip += 5;
3632 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3634 victim->velocity = 0;
3635 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3636 victim->skeleton.joints[i].velocity = 0;
3638 if (weaponactive != -1) {
3639 emit_sound_at(fleshstabremovesound, victim->coords);
3641 weapons[weaponids[weaponactive]].bloody = 2;
3642 weapons[weaponids[weaponactive]].blooddrip += 5;
3644 XYZ footvel, footpoint;
3646 footpoint = weapons[weaponids[0]].tippoint;
3648 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3649 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3650 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3651 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3652 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3653 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3657 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3665 if (weaponactive == -1) {
3666 if (tutoriallevel != 1) {
3667 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3672 if (weaponactive != -1 || creature == wolftype)
3674 if (creature == rabbittype && weaponactive != -1)
3675 if (weapons[weaponids[0]].getType() == staff)
3678 if (weaponactive != -1) {
3679 victim->DoBloodBig(2 / victim->armorhead, 225);
3680 emit_sound_at(knifeslicesound, victim->coords);
3681 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3682 weapons[weaponids[weaponactive]].bloody = 1;
3683 weapons[weaponids[weaponactive]].blooddrip += 3;
3685 if (weaponactive == -1 && creature == wolftype) {
3686 emit_sound_at(clawslicesound, victim->coords, 128.);
3688 victim->DoBloodBig(2 / victim->armorhead, 175);
3692 award_bonus(id, Reversal);
3697 relative = facing * -1;
3699 Normalise(&relative);
3700 relative = DoRotation(relative, 0, 90, 0);
3702 Normalise(&relative);
3703 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3704 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3706 victim->jointVel(head) += relative * damagemult * 200;
3707 if (victim->damage < victim->damagetolerance - 100)
3708 victim->velocity = relative * 200;
3709 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3710 victim->velocity = 0;
3713 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))) {
3717 relative = facing * -1;
3719 Normalise(&relative);
3720 relative = DoRotation(relative, 0, 90, 0);
3722 Normalise(&relative);
3723 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3724 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3726 victim->jointVel(head) += relative * damagemult * 200;
3729 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3730 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3731 award_bonus(id, reverseko);
3737 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3740 animTarget = getIdle();
3741 FootLand(leftfoot, 1);
3742 FootLand(rightfoot, 1);
3744 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3745 animTarget = rollanim;
3747 emit_sound_at(movewhooshsound, coords, 128.);
3749 if (animCurrent == staggerbackhighanim) {
3750 animTarget = getIdle();
3752 if (animCurrent == staggerbackhardanim) {
3753 animTarget = getIdle();
3755 if (animCurrent == removeknifeanim) {
3756 animTarget = getIdle();
3758 if (animCurrent == crouchremoveknifeanim) {
3759 animTarget = getCrouch();
3761 if (animCurrent == backhandspringanim) {
3762 animTarget = getIdle();
3764 if (animCurrent == dodgebackanim) {
3765 animTarget = getIdle();
3767 if (animCurrent == drawleftanim) {
3768 animTarget = getIdle();
3770 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3771 animTarget = getIdle();
3772 if (animCurrent == crouchdrawrightanim) {
3773 animTarget = getCrouch();
3775 if (weaponactive == -1)
3777 else if (weaponactive == 0) {
3779 if (num_weapons == 2) {
3781 buffer = weaponids[0];
3782 weaponids[0] = weaponids[1];
3783 weaponids[1] = buffer;
3787 if (weaponactive == -1) {
3788 emit_sound_at(knifesheathesound, coords, 128.);
3790 if (weaponactive != -1) {
3791 emit_sound_at(knifedrawsound, coords, 128.);
3794 if (animCurrent == rollanim) {
3795 animTarget = getCrouch();
3796 FootLand(leftfoot, 1);
3797 FootLand(rightfoot, 1);
3800 if (animTarget == walljumprightkickanim) {
3803 if (animTarget == walljumpleftkickanim) {
3806 animTarget = jumpdownanim;
3808 if (animCurrent == climbanim) {
3809 animTarget = getCrouch();
3811 coords += facing * .1;
3812 if (!isnormal(coords.x))
3823 if (animTarget == rabbitkickreversalanim) {
3824 animTarget = getCrouch();
3827 if (animTarget == jumpreversalanim) {
3828 animTarget = getCrouch();
3831 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3832 if (attackkeydown && animTarget != walljumpfrontanim) {
3834 float closestdist = -1;
3836 if (Person::players.size() > 1)
3837 for (unsigned i = 0; i < Person::players.size(); i++) {
3838 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3839 distance = distsq(&Person::players[i]->coords, &coords);
3840 if (closestdist == -1 || distance < closestdist) {
3841 closestdist = distance;
3846 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3847 victim = Person::players[closest];
3848 animTarget = walljumprightkickanim;
3850 XYZ rotatetarget = victim->coords - coords;
3851 Normalise(&rotatetarget);
3852 yaw = -asin(0 - rotatetarget.x);
3854 if (rotatetarget.z < 0)
3856 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3857 velocity = (victim->coords - coords) * 4;
3862 if (animTarget == walljumpbackanim) {
3863 animTarget = backflipanim;
3865 velocity = facing * -8;
3868 resume_stream(whooshsound);
3870 if (animTarget == walljumprightanim) {
3871 animTarget = rightflipanim;
3875 velocity = DoRotation(facing, 0, 30, 0) * -8;
3878 if (animTarget == walljumpfrontanim) {
3879 animTarget = frontflipanim;
3883 velocity = facing * 8;
3887 resume_stream(whooshsound);
3889 if (animTarget == walljumpleftanim) {
3890 if (attackkeydown) {
3892 float closestdist = -1;
3894 if (Person::players.size() > 1)
3895 for (unsigned i = 0; i < Person::players.size(); i++) {
3896 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3897 distance = distsq(&Person::players[i]->coords, &coords);
3898 if (closestdist == -1 || distance < closestdist) {
3899 closestdist = distance;
3904 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3905 victim = Person::players[closest];
3906 animTarget = walljumpleftkickanim;
3908 XYZ rotatetarget = victim->coords - coords;
3909 Normalise(&rotatetarget);
3910 yaw = -asin(0 - rotatetarget.x);
3912 if (rotatetarget.z < 0)
3914 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3915 velocity = (victim->coords - coords) * 4;
3920 if (animTarget != walljumpleftkickanim) {
3921 animTarget = leftflipanim;
3925 velocity = DoRotation(facing, 0, -30, 0) * -8;
3929 resume_stream(whooshsound);
3931 if (animTarget == sneakattackanim) {
3932 animCurrent = getCrouch();
3933 animTarget = getCrouch();
3940 transspeed = 1000000;
3941 targetheadyaw += 180;
3942 coords -= facing * .7;
3944 coords.y = terrain.getHeight(coords.x, coords.z);
3948 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3949 animTarget = getIdle();
3952 coords.y = terrain.getHeight(coords.x, coords.z);
3956 if (animCurrent == knifefollowanim) {
3957 animTarget = getIdle();
3960 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3961 float ycoords = oldcoords.y;
3962 animTarget = getStop();
3967 transspeed = 1000000;
3968 targetheadyaw += 180;
3969 if (!isnormal(coords.x))
3971 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3972 oldcoords = coords + facing * .5;
3973 else if (animCurrent == sweepreversalanim)
3974 oldcoords = coords + facing * 1.1;
3975 else if (animCurrent == upunchreversalanim) {
3976 oldcoords = coords + facing * 1.5;
3979 targetheadyaw += 180;
3982 } else if (animCurrent == knifeslashreversalanim) {
3983 oldcoords = coords + facing * .5;
3986 targetheadyaw += 90;
3989 } else if (animCurrent == staffspinhitreversalanim) {
3992 targetheadyaw += 180;
3997 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3999 oldcoords.y = ycoords;
4000 currentoffset = coords - oldcoords;
4006 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4011 if (Animation::animations[animTarget].attack == reversed) {
4013 if (animTarget == sweepreversedanim)
4015 animTarget = backhandspringanim;
4017 emit_sound_at(landsound, coords, 128);
4019 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4020 animTarget = rollanim;
4023 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4024 coords.y = oldcoords.y;
4026 if (animCurrent == knifeslashreversedanim) {
4027 animTarget = rollanim;
4032 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4033 coords.y = oldcoords.y;
4037 animTarget = jumpdownanim;
4040 animTarget = getIdle();
4042 animTarget = getIdle();
4043 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4044 animTarget = getIdle();
4046 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4047 coords.y = oldcoords.y;
4048 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4049 targetoffset.y = coords.y;
4051 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4052 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4053 currentoffset.y -= (coords.y - targetoffset.y);
4054 coords.y = targetoffset.y;
4056 normalsupdatedelay = 0;
4058 if (animCurrent == upunchanim) {
4059 animTarget = getStop();
4060 normalsupdatedelay = 0;
4063 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4067 if (num_weapons > 0)
4068 if (weapons[0].getType() == staff)
4074 rabbitkickragdoll = 1;
4076 if (animCurrent == rabbitkickreversedanim) {
4082 skeleton.spinny = 0;
4083 SolidHitBonus(!id); // FIXME: tricky id
4087 animTarget = rollanim;
4090 pause_sound(whooshsound);
4094 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4098 skeleton.spinny = 0;
4100 if (animCurrent == jumpreversedanim) {
4106 skeleton.spinny = 0;
4107 SolidHitBonus(!id); // FIXME: tricky id
4111 animTarget = rollanim;
4112 coords += facing * 2;
4114 pause_sound(whooshsound);
4119 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) {
4120 animTarget = getupfromfrontanim;
4122 } else if (Animation::animations[animCurrent].attack == normalattack) {
4123 animTarget = getIdle();
4126 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4127 animTarget = blockhighleftstrikeanim;
4129 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4130 animTarget = getIdle();
4133 if (animCurrent == spinkickanim && victim->skeleton.free) {
4134 if (creature == rabbittype)
4135 animTarget = fightidleanim;
4140 if (isIdle() && !wasIdle())
4141 normalsupdatedelay = 0;
4143 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4144 animTarget = jumpdownanim;
4147 if (!skeleton.free) {
4149 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4150 if (!isRun() || !wasRun()) {
4151 if (targetFrame().speed > currentFrame().speed)
4152 target += multiplier * targetFrame().speed * speed * 2;
4153 if (targetFrame().speed <= currentFrame().speed)
4154 target += multiplier * currentFrame().speed * speed * 2;
4156 if (isRun() && wasRun()) {
4158 tempspeed = velspeed;
4159 if (tempspeed < 10 * speedmult)
4160 tempspeed = 10 * speedmult;
4161 /* FIXME - mixed of target and current here, is that intended? */
4162 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4164 } else if (transspeed)
4165 target += multiplier * transspeed * speed * 2;
4167 if (!isRun() || !wasRun()) {
4168 if (targetFrame().speed > currentFrame().speed)
4169 target += multiplier * targetFrame().speed * 2;
4170 if (targetFrame().speed <= currentFrame().speed)
4171 target += multiplier * currentFrame().speed * 2;
4175 if (animCurrent != animTarget)
4176 target = (target + oldtarget) / 2;
4179 frameCurrent = frameTarget;
4183 rot = targetrot * target;
4184 yaw += rot - oldrot;
4190 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4191 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4193 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4195 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4196 skeleton.joints[i].position = currentFrame().joints[i].position;
4199 skeleton.FindForwards();
4201 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4202 if (skeleton.muscles[i].visible) {
4203 skeleton.FindRotationMuscle(i, animTarget);
4206 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4207 if (skeleton.muscles[i].visible) {
4208 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4209 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4210 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4211 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4212 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4213 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4218 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4219 skeleton.joints[i].position = targetFrame().joints[i].position;
4222 skeleton.FindForwards();
4224 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4225 if (skeleton.muscles[i].visible) {
4226 skeleton.FindRotationMuscle(i, animTarget);
4229 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4230 if (skeleton.muscles[i].visible) {
4231 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4232 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4233 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4234 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4235 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4236 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4237 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4238 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4239 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4240 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4241 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4242 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4247 oldanimCurrent = animCurrent;
4248 oldanimTarget = animTarget;
4249 oldframeTarget = frameTarget;
4250 oldframeCurrent = frameCurrent;
4252 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4253 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4254 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4256 offset = currentoffset * (1 - target) + targetoffset * target;
4257 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4258 if (skeleton.muscles[i].visible) {
4259 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4260 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4261 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4266 if (isLanding() && landhard) {
4269 animTarget = getLandhard();
4282 void Person::DoStuff()
4284 static XYZ terrainnormal;
4285 static XYZ flatfacing;
4286 static XYZ flatvelocity;
4287 static float flatvelspeed;
4289 static int bloodsize;
4290 static int startx, starty, endx, endy;
4291 static GLubyte color;
4292 static XYZ bloodvel;
4294 onfiredelay -= multiplier;
4295 if (onfiredelay < 0 && onfire) {
4296 if (Random() % 2 == 0) {
4302 crouchkeydowntime += multiplier;
4304 crouchkeydowntime = 0;
4305 jumpkeydowntime += multiplier;
4306 if (!jumpkeydown && skeleton.free)
4307 jumpkeydowntime = 0;
4309 if (hostile || damage > 0 || bloodloss > 0)
4312 if (isIdle() || isRun())
4315 if (num_weapons == 1 && weaponactive != -1)
4319 blooddimamount -= multiplier * .3;
4320 speechdelay -= multiplier;
4321 texupdatedelay -= multiplier;
4322 interestdelay -= multiplier;
4323 flamedelay -= multiplier;
4324 parriedrecently -= multiplier;
4326 victim = this->shared_from_this();
4331 speed = 1.1 * speedmult;
4333 speed = 1.0 * speedmult;
4335 rabbitkickragdoll = 0;
4339 if (id != 0 && (creature == rabbittype || difficulty != 2))
4341 if (id != 0 && creature == wolftype && difficulty == 2) {
4343 if (aitype != passivetype) {
4345 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) {
4351 if (animTarget == wolfrunninganim && !superruntoggle) {
4352 animTarget = getRun();
4356 if (weaponactive == -1 && num_weapons > 0) {
4357 if (weapons[weaponids[0]].getType() == staff) {
4363 burnt += multiplier;
4367 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4369 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4375 vel[0] = velocity.x;
4376 vel[1] = velocity.y;
4377 vel[2] = velocity.z;
4380 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4381 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4385 while (flamedelay < 0 && onfire) {
4387 int howmany = fabs(Random() % (skeleton.joints.size()));
4388 if (skeleton.free) {
4389 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4390 flatfacing = skeleton.joints[howmany].position * scale + coords;
4392 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4393 flatvelocity = (coords - oldcoords) / multiplier / 2;
4395 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4398 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4400 int howmany = fabs(Random() % (skeleton.joints.size()));
4401 if (skeleton.free) {
4402 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4403 flatfacing = skeleton.joints[howmany].position * scale + coords;
4405 flatvelocity = (coords - oldcoords) / multiplier / 2;
4406 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4408 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4412 bleeding -= multiplier * .3;
4413 if (bloodtoggle == 2) {
4414 skeleton.drawmodel.textureptr.bind();
4415 if ((bleeding <= 0) && (detail != 2))
4420 if (neckspurtamount > 0) {
4421 neckspurtamount -= multiplier;
4422 neckspurtdelay -= multiplier * 3;
4423 neckspurtparticledelay -= multiplier * 3;
4424 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4427 if (skeleton.free) {
4428 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4429 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4430 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4432 bloodvel.z = 5 * neckspurtamount;
4433 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4434 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4435 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4437 neckspurtparticledelay = .05;
4439 if (neckspurtdelay < 0) {
4444 if (deathbleeding > 0 && dead != 2) {
4445 if (deathbleeding < 5)
4446 bleeddelay -= deathbleeding * multiplier / 4;
4448 bleeddelay -= 5 * multiplier / 4;
4449 if (bleeddelay < 0 && bloodtoggle) {
4454 if (skeleton.free) {
4455 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4456 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4458 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4459 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4463 bloodloss += deathbleeding * multiplier * 80;
4464 deathbleeding -= multiplier * 1.6;
4465 if (deathbleeding < 0)
4467 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4468 if (weaponactive != -1) {
4469 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4470 weapons[weaponids[0]].velocity.x += .01;
4473 weaponids[0] = weaponids[num_weapons];
4474 if (weaponstuck == num_weapons)
4478 for (unsigned i = 0; i < Person::players.size(); i++) {
4479 Person::players[i]->wentforweapon = 0;
4487 if (!dead && creature == wolftype) {
4488 award_bonus(0, Wolfbonus);
4491 if (animTarget == knifefollowedanim && !skeleton.free) {
4492 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4493 skeleton.joints[i].velocity = 0;
4494 skeleton.joints[i].velocity.y = -2;
4497 if (id != 0 && unconscioustime > .1) {
4505 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4506 texupdatedelay = .12;
4508 bloodsize = 5 - realtexdetail;
4512 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4513 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4514 endx = startx + bloodsize;
4515 endy = starty + bloodsize;
4525 if (endx > skeleton.skinsize - 1) {
4526 endx = skeleton.skinsize - 1;
4529 if (endy > skeleton.skinsize - 1) {
4530 endy = skeleton.skinsize - 1;
4538 for (i = startx; i < endx; i++) {
4539 for (int j = starty; j < endy; j++) {
4540 if (Random() % 2 == 0) {
4541 color = Random() % 85 + 170;
4542 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4543 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4544 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4545 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4550 skeleton.drawmodel.textureptr.bind();
4554 if (skeleton.free) {
4555 bleedx += 4 * direction / realtexdetail;
4557 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4559 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4561 bleedy -= 4 / realtexdetail;
4563 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4565 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4569 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4570 righthandmorphness = targetrighthandmorphness;
4571 righthandmorphstart = righthandmorphend;
4572 } else if (righthandmorphness > targetrighthandmorphness) {
4573 righthandmorphness -= multiplier * 4;
4574 } else if (righthandmorphness < targetrighthandmorphness) {
4575 righthandmorphness += multiplier * 4;
4578 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4579 lefthandmorphness = targetlefthandmorphness;
4580 lefthandmorphstart = lefthandmorphend;
4581 } else if (lefthandmorphness > targetlefthandmorphness) {
4582 lefthandmorphness -= multiplier * 4;
4583 } else if (lefthandmorphness < targetlefthandmorphness) {
4584 lefthandmorphness += multiplier * 4;
4587 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4588 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4589 tailmorphness = targettailmorphness;
4590 tailmorphstart = tailmorphend;
4591 } else if (tailmorphness > targettailmorphness) {
4592 tailmorphness -= multiplier * 10;
4593 } else if (tailmorphness < targettailmorphness) {
4594 tailmorphness += multiplier * 10;
4598 if (creature == wolftype) {
4599 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4600 tailmorphness = targettailmorphness;
4601 tailmorphstart = tailmorphend;
4602 } else if (tailmorphness > targettailmorphness) {
4603 tailmorphness -= multiplier * 2;
4604 } else if (tailmorphness < targettailmorphness) {
4605 tailmorphness += multiplier * 2;
4609 if (headmorphend == 3 || headmorphstart == 3) {
4610 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4611 headmorphness = targetheadmorphness;
4612 headmorphstart = headmorphend;
4613 } else if (headmorphness > targetheadmorphness) {
4614 headmorphness -= multiplier * 7;
4615 } else if (headmorphness < targetheadmorphness) {
4616 headmorphness += multiplier * 7;
4618 } else if (headmorphend == 5 || headmorphstart == 5) {
4619 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4620 headmorphness = targetheadmorphness;
4621 headmorphstart = headmorphend;
4622 } else if (headmorphness > targetheadmorphness) {
4623 headmorphness -= multiplier * 10;
4624 } else if (headmorphness < targetheadmorphness) {
4625 headmorphness += multiplier * 10;
4628 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4629 headmorphness = targetheadmorphness;
4630 headmorphstart = headmorphend;
4631 } else if (headmorphness > targetheadmorphness) {
4632 headmorphness -= multiplier * 4;
4633 } else if (headmorphness < targetheadmorphness) {
4634 headmorphness += multiplier * 4;
4638 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4639 chestmorphness = targetchestmorphness;
4640 chestmorphstart = chestmorphend;
4641 } else if (chestmorphness > targetchestmorphness) {
4642 chestmorphness -= multiplier;
4643 } else if (chestmorphness < targetchestmorphness) {
4644 chestmorphness += multiplier;
4647 if (dead != 2 && howactive <= typesleeping) {
4648 if (chestmorphstart == 0 && chestmorphend == 0) {
4650 targetchestmorphness = 1;
4653 if (chestmorphstart != 0 && chestmorphend != 0) {
4655 targetchestmorphness = 1;
4657 if (environment == snowyenvironment) {
4660 if (skeleton.free) {
4661 footvel = skeleton.specialforward[0] * -1;
4662 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4664 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4665 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4667 if (animTarget == sleepanim)
4668 footvel = DoRotation(footvel, 0, 90, 0);
4669 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4673 if (!dead && howactive < typesleeping) {
4674 blinkdelay -= multiplier * 2;
4675 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4677 targetheadmorphness = 1;
4679 blinkdelay = (float)(abs(Random() % 40)) / 5;
4681 if (headmorphstart == 3 && headmorphend == 3) {
4683 targetheadmorphness = 1;
4688 twitchdelay -= multiplier * 1.5;
4689 if (animTarget != hurtidleanim) {
4690 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4692 targetheadmorphness = 1;
4694 twitchdelay = (float)(abs(Random() % 40)) / 5;
4696 if (headmorphstart == 5 && headmorphend == 5) {
4698 targetheadmorphness = 1;
4702 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4703 twitchdelay3 -= multiplier * 1;
4704 if (Random() % 2 == 0) {
4705 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4706 righthandmorphness = 0;
4707 targetrighthandmorphness = 1;
4708 righthandmorphend = 1;
4709 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4711 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4712 righthandmorphness = 0;
4713 targetrighthandmorphness = 1;
4714 righthandmorphend = 0;
4717 if (Random() % 2 == 0) {
4718 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4719 lefthandmorphness = 0;
4720 targetlefthandmorphness = 1;
4721 lefthandmorphend = 1;
4722 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4724 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4725 lefthandmorphness = 0;
4726 targetlefthandmorphness = 1;
4727 lefthandmorphend = 0;
4733 if (creature == rabbittype) {
4734 if (howactive < typesleeping)
4735 twitchdelay2 -= multiplier * 1.5;
4737 twitchdelay2 -= multiplier * 0.5;
4738 if (howactive <= typesleeping) {
4739 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4741 targettailmorphness = 1;
4743 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4745 if (tailmorphstart == 1 && tailmorphend == 1) {
4747 targettailmorphness = 1;
4750 if (tailmorphstart == 2 && tailmorphend == 2) {
4752 targettailmorphness = 1;
4759 if (creature == wolftype) {
4760 twitchdelay2 -= multiplier * 1.5;
4761 if (tailmorphend != 0)
4762 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4764 targettailmorphness = 1;
4768 if (tailmorphend != 5)
4769 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4771 targettailmorphness = 1;
4775 if (twitchdelay2 <= 0) {
4776 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4778 targettailmorphness = 1;
4781 if (tailmorphstart == 1 && tailmorphend == 1) {
4783 targettailmorphness = 1;
4786 if (tailmorphstart == 2 && tailmorphend == 2) {
4788 targettailmorphness = 1;
4791 if (tailmorphstart == 3 && tailmorphend == 3) {
4793 targettailmorphness = 1;
4796 if (tailmorphstart == 4 && tailmorphend == 4) {
4798 targettailmorphness = 1;
4805 unconscioustime = 0;
4807 if (dead == 1 || howactive == typesleeping) {
4808 unconscioustime += multiplier;
4809 //If unconscious, close eyes and mouth
4810 if (righthandmorphend != 0)
4811 righthandmorphness = 0;
4812 righthandmorphend = 0;
4813 targetrighthandmorphness = 1;
4815 if (lefthandmorphend != 0)
4816 lefthandmorphness = 0;
4817 lefthandmorphend = 0;
4818 targetlefthandmorphness = 1;
4820 if (headmorphend != 3 && headmorphend != 5)
4823 targetheadmorphness = 1;
4827 if (howactive > typesleeping) {
4830 if (bloodtoggle && !bled) {
4831 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4833 if (bloodtoggle && !bled)
4834 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4835 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4836 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4840 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4845 if (dead == 2 || howactive > typesleeping) {
4846 //If dead, open mouth and hands
4847 if (righthandmorphend != 0)
4848 righthandmorphness = 0;
4849 righthandmorphend = 0;
4850 targetrighthandmorphness = 1;
4852 if (lefthandmorphend != 0)
4853 lefthandmorphness = 0;
4854 lefthandmorphend = 0;
4855 targetlefthandmorphness = 1;
4857 if (headmorphend != 2)
4860 targetheadmorphness = 1;
4863 if (stunned > 0 && !dead && headmorphend != 2) {
4864 if (headmorphend != 4)
4867 targetheadmorphness = 1;
4870 if (damage > damagetolerance && !dead) {
4873 unconscioustime = 0;
4875 if (creature == wolftype) {
4876 award_bonus(0, Wolfbonus);
4881 if (weaponactive != -1) {
4882 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4883 weapons[weaponids[0]].velocity.x += .01;
4886 weaponids[0] = weaponids[num_weapons];
4887 if (weaponstuck == num_weapons)
4891 for (unsigned i = 0; i < Person::players.size(); i++) {
4892 Person::players[i]->wentforweapon = 0;
4898 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4907 damage -= multiplier * 13;
4909 permanentdamage -= multiplier * 4;
4910 if (isIdle() || isCrouch()) {
4912 permanentdamage -= multiplier * 4;
4916 if (permanentdamage < 0)
4917 permanentdamage = 0;
4918 if (superpermanentdamage < 0)
4919 superpermanentdamage = 0;
4920 if (permanentdamage < superpermanentdamage) {
4921 permanentdamage = superpermanentdamage;
4923 if (damage < permanentdamage) {
4924 damage = permanentdamage;
4926 if (dead == 1 && damage < damagetolerance) {
4930 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4931 skeleton.joints[i].velocity = 0;
4934 if (permanentdamage > damagetolerance && dead != 2) {
4937 if (weaponactive != -1) {
4938 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4939 weapons[weaponids[0]].velocity.x += .01;
4942 weaponids[0] = weaponids[num_weapons];
4943 if (weaponstuck == num_weapons)
4947 for (unsigned i = 0; i < Person::players.size(); i++) {
4948 Person::players[i]->wentforweapon = 0;
4954 if (!dead && creature == wolftype) {
4955 award_bonus(0, Wolfbonus);
4958 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4959 award_bonus(id, touchofdeath);
4960 if (id != 0 && unconscioustime > .1) {
4968 emit_sound_at(breaksound, coords);
4971 if (skeleton.free == 1) {
4973 pause_sound(whooshsound);
4976 //If knocked over, open hands and close mouth
4977 if (righthandmorphend != 0)
4978 righthandmorphness = 0;
4979 righthandmorphend = 0;
4980 targetrighthandmorphness = 1;
4982 if (lefthandmorphend != 0)
4983 lefthandmorphness = 0;
4984 lefthandmorphend = 0;
4985 targetlefthandmorphness = 1;
4987 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4988 if (headmorphend != 0)
4991 targetheadmorphness = 1;
4995 skeleton.DoGravity(&scale);
4997 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4998 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4999 award_bonus(id, deepimpact);
5000 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5004 if (!skeleton.joints.empty()) {
5005 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5006 average += skeleton.joints[j].position;
5008 average /= skeleton.joints.size();
5009 coords += average * scale;
5010 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5011 skeleton.joints[j].position -= average;
5013 average /= multiplier;
5017 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5018 velocity += skeleton.joints[i].velocity * scale;
5020 velocity /= skeleton.joints.size();
5022 if (!isnormal(velocity.x) && velocity.x) {
5026 if (findLength(&average) < 10 && dead && skeleton.free) {
5027 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5028 if (skeleton.longdead > 2000) {
5029 if (skeleton.longdead > 6000) {
5031 pause_sound(whooshsound);
5036 if (dead == 2 && bloodloss < damagetolerance) {
5038 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5040 if (bloodtoggle && !bled) {
5041 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5043 if (bloodtoggle && !bled)
5044 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5045 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5046 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5047 float size = .2 * 1.2;
5050 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5054 if (dead == 2 && bloodloss >= damagetolerance) {
5056 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5059 if (bloodtoggle && !bled) {
5060 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5062 if (bloodtoggle && !bled)
5063 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5064 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5065 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5069 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5076 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5077 bool canrecover = 1;
5078 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5079 startpoint = coords;
5082 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5084 if (velocity.y < -30)
5086 for (i = 0; i < objects.numobjects; i++) {
5087 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5088 colviewer = startpoint;
5089 coltarget = endpoint;
5090 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5099 terrainnormal = jointPos(groin) - jointPos(abdomen);
5100 if (joint(groin).locked && joint(abdomen).locked) {
5101 terrainnormal = jointPos(groin) - jointPos(abdomen);
5102 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5104 if (joint(abdomen).locked && joint(neck).locked) {
5105 terrainnormal = jointPos(abdomen) - jointPos(neck);
5106 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5108 if (joint(groin).locked && joint(neck).locked) {
5109 terrainnormal = jointPos(groin) - jointPos(neck);
5110 middle = (jointPos(groin) + jointPos(neck)) / 2;
5112 Normalise(&terrainnormal);
5114 targetyaw = -asin(0 - terrainnormal.x);
5115 targetyaw *= 360 / 6.28;
5116 if (terrainnormal.z < 0)
5117 targetyaw = 180 - targetyaw;
5121 animTarget = flipanim;
5122 crouchtogglekeydown = 1;
5127 animCurrent = tempanim;
5131 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5132 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5133 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5138 if (findLength(&average) < 10 && !dead && skeleton.free) {
5139 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5140 if (skeleton.longdead > (damage + 500) * 1.5) {
5142 pause_sound(whooshsound);
5148 terrainnormal = jointPos(groin) - jointPos(abdomen);
5149 if (joint(groin).locked && joint(abdomen).locked) {
5150 terrainnormal = jointPos(groin) - jointPos(abdomen);
5151 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5153 if (joint(abdomen).locked && joint(neck).locked) {
5154 terrainnormal = jointPos(abdomen) - jointPos(neck);
5155 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5157 if (joint(groin).locked && joint(neck).locked) {
5158 terrainnormal = jointPos(groin) - jointPos(neck);
5159 middle = (jointPos(groin) + jointPos(neck)) / 2;
5161 Normalise(&terrainnormal);
5163 targetyaw = -asin(0 - terrainnormal.x);
5164 targetyaw *= 360 / 6.28;
5165 if (terrainnormal.z < 0)
5166 targetyaw = 180 - targetyaw;
5169 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5172 if (skeleton.forward.y < 0) {
5173 animTarget = getupfrombackanim;
5177 if (skeleton.forward.y > -.3) {
5178 animTarget = getupfromfrontanim;
5186 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5187 animTarget = rollanim;
5188 targetyaw = lookyaw;
5205 if ( !leftkeydown && !rightkeydown)
5212 if (abs(targettilt2) > 50)
5214 animCurrent = tempanim;
5217 tilt2 = targettilt2;
5219 if (middle.y > 0 && animTarget != rollanim)
5220 targetoffset.y = middle.y + 1;
5222 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5223 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5224 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5231 if (num_weapons > 0)
5232 if (weapons[0].getType() == staff)
5234 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5235 if (velocity.y > -30) {
5237 tempvelocity = velocity;
5238 Normalise(&tempvelocity);
5239 targetyaw = -asin(0 - tempvelocity.x);
5240 targetyaw *= 360 / 6.28;
5242 targetyaw = 180 - targetyaw;
5246 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5247 animTarget = rollanim;
5250 animTarget = backhandspringanim;
5256 emit_sound_at(movewhooshsound, coords, 128.);
5258 animCurrent = animTarget;
5259 frameCurrent = frameTarget - 1;
5271 if (skeleton.freefall == 0)
5276 if (aitype != passivetype || skeleton.free == 1)
5277 if (findLengthfast(&velocity) > .1)
5278 for (i = 0; i < objects.numobjects; i++) {
5279 if (objects.type[i] == firetype)
5280 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5282 if (!objects.onfire[i]) {
5283 emit_sound_at(firestartsound, objects.position[i]);
5285 objects.onfire[i] = 1;
5288 if (objects.onfire[i]) {
5293 if (objects.type[i] == bushtype)
5294 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5296 if (!objects.onfire[i]) {
5297 emit_sound_at(firestartsound, objects.position[i]);
5299 objects.onfire[i] = 1;
5303 if (objects.onfire[i]) {
5307 if (objects.messedwith[i] <= 0) {
5311 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5314 addEnvSound(coords, 4 * findLength(&velocity));
5318 if (environment == grassyenvironment)
5319 howmany = findLength(&velocity) * 4;
5320 if (environment == snowyenvironment)
5321 howmany = findLength(&velocity) * 2;
5323 if (environment != desertenvironment)
5324 for (int j = 0; j < howmany; j++) {
5325 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5326 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5327 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5330 pos.x += float(abs(Random() % 100) - 50) / 200;
5331 pos.y += float(abs(Random() % 100) - 50) / 200;
5332 pos.z += float(abs(Random() % 100) - 50) / 200;
5333 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);
5334 Sprite::setLastSpriteSpecial(1);
5336 howmany = findLength(&velocity) * 4;
5338 if (environment == snowyenvironment)
5339 for (int j = 0; j < howmany; j++) {
5340 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5341 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5342 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5345 pos.x += float(abs(Random() % 100) - 50) / 200;
5346 pos.y += float(abs(Random() % 100) - 50) / 200;
5347 pos.z += float(abs(Random() % 100) - 50) / 200;
5348 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5349 Sprite::setLastSpriteSpecial(2);
5352 objects.rotx[i] += velocity.x * multiplier * 6;
5353 objects.roty[i] += velocity.z * multiplier * 6;
5354 objects.messedwith[i] = .5;
5357 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5358 if (objects.pitch[i] == 0)
5361 tempcoord = coords - objects.position[i];
5362 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5363 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5364 tempcoord += objects.position[i];
5366 if (distsqflat(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 8 && distsq(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 300 && tempcoord.y > objects.position[i].y + 3 * objects.scale[i]) {
5367 if (objects.messedwith[i] <= 0) {
5371 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5374 addEnvSound(coords, 4 * findLength(&velocity));
5378 if (environment == grassyenvironment)
5379 howmany = findLength(&velocity) * 4;
5380 if (environment == snowyenvironment)
5381 howmany = findLength(&velocity) * 2;
5383 if (environment != desertenvironment)
5384 for (int j = 0; j < howmany; j++) {
5385 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5386 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5387 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5389 pos += velocity * .1;
5391 pos.x += float(abs(Random() % 100) - 50) / 150;
5392 pos.y += float(abs(Random() % 100) - 50) / 150;
5393 pos.z += float(abs(Random() % 100) - 50) / 150;
5394 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);
5395 Sprite::setLastSpriteSpecial(1);
5397 howmany = findLength(&velocity) * 4;
5399 if (environment == snowyenvironment)
5400 for (int j = 0; j < howmany; j++) {
5401 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5402 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5403 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5405 pos += velocity * .1;
5407 pos.x += float(abs(Random() % 100) - 50) / 150;
5408 pos.y += float(abs(Random() % 100) - 50) / 150;
5409 pos.z += float(abs(Random() % 100) - 50) / 150;
5410 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5411 Sprite::setLastSpriteSpecial(2);
5414 objects.messedwith[i] = .5;
5419 if (!skeleton.free) {
5422 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5425 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5427 if (tutoriallevel == 1 && id != 0)
5429 if (play && aitype != playercontrolled) {
5430 int whichsound = -1;
5431 i = abs(Random() % 4);
5432 if (speechdelay <= 0) {
5433 if (creature == rabbittype) {
5435 whichsound = rabbitchitter;
5437 whichsound = rabbitchitter2;
5439 if (creature == wolftype) {
5441 whichsound = growlsound;
5443 whichsound = growl2sound;
5448 if (whichsound != -1) {
5449 emit_sound_at(whichsound, coords);
5453 if (animTarget == staggerbackhighanim)
5455 if (animTarget == staggerbackhardanim)
5457 staggerdelay -= multiplier;
5458 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5460 if (velocity.y < -30 && animTarget == jumpdownanim)
5462 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5463 animTarget = getIdle();
5467 weaponmissdelay -= multiplier;
5468 highreversaldelay -= multiplier;
5469 lowreversaldelay -= multiplier;
5470 lastcollide -= multiplier;
5471 skiddelay -= multiplier;
5472 if (!isnormal(velocity.x) && velocity.x) {
5475 if (!isnormal(targettilt) && targettilt) {
5478 if (!isnormal(targettilt2) && targettilt2) {
5481 if (!isnormal(targetyaw) && targetyaw) {
5485 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5486 //open hands and close mouth
5487 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5488 righthandmorphness = 0;
5489 righthandmorphend = 0;
5490 targetrighthandmorphness = 1;
5493 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5494 lefthandmorphness = 0;
5495 lefthandmorphend = 0;
5496 targetlefthandmorphness = 1;
5499 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5502 targetheadmorphness = 1;
5506 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) {
5507 //open hands and mouth
5508 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5509 righthandmorphness = 0;
5510 righthandmorphend = 0;
5511 targetrighthandmorphness = 1;
5514 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5515 lefthandmorphness = 0;
5516 lefthandmorphend = 0;
5517 targetlefthandmorphness = 1;
5520 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5523 targetheadmorphness = 1;
5527 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5528 //close hands and mouth
5529 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5530 righthandmorphness = 0;
5531 righthandmorphend = 1;
5532 targetrighthandmorphness = 1;
5535 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5536 lefthandmorphness = 0;
5537 lefthandmorphend = 1;
5538 targetlefthandmorphness = 1;
5541 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5544 targetheadmorphness = 1;
5548 if (animTarget == spinkickanim || animTarget == staffspinhitreversalanim || animTarget == staffspinhitreversedanim || animTarget == staffhitreversalanim || animTarget == staffhitreversedanim || animTarget == hurtidleanim || animTarget == winduppunchanim || animTarget == swordslashreversalanim || animTarget == swordslashreversedanim || animTarget == knifeslashreversalanim || animTarget == knifeslashreversedanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == knifefollowedanim || animTarget == killanim || animTarget == dropkickanim || animTarget == upunchanim || animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim || animTarget == staffgroundsmashanim || animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == lowkickanim || animTarget == sweepreversedanim || animTarget == rabbitkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversalanim || animTarget == jumpreversedanim) {
5549 //close hands and yell
5550 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5551 righthandmorphness = 0;
5552 righthandmorphend = 1;
5553 targetrighthandmorphness = 1;
5556 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5557 lefthandmorphness = 0;
5558 lefthandmorphend = 1;
5559 targetlefthandmorphness = 1;
5562 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5565 targetheadmorphness = 1;
5572 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5573 (victim->aitype != searchtype) && (aitype != passivetype) &&
5574 (aitype != searchtype) && (victim->id < Person::players.size())) {
5575 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5579 if (!dead && animTarget != hurtidleanim)
5580 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5581 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5584 targetheadmorphness = 1;
5588 if (weaponactive != -1) {
5589 if (weapons[weaponids[weaponactive]].getType() != staff) {
5590 righthandmorphstart = 1;
5591 righthandmorphend = 1;
5593 if (weapons[weaponids[weaponactive]].getType() == staff) {
5594 righthandmorphstart = 2;
5595 righthandmorphend = 2;
5597 targetrighthandmorphness = 1;
5600 terrainnormal = terrain.getNormal(coords.x, coords.z);
5602 if (Animation::animations[animTarget].attack != reversal) {
5603 if (!isnormal(coords.x))
5611 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5612 facing = flatfacing;
5613 ReflectVector(&facing, terrainnormal);
5616 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5618 targettilt2 = -facing.y * 20;
5623 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5625 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5626 flatvelocity = velocity;
5628 flatvelspeed = findLength(&flatvelocity);
5629 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5630 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5635 if (targettilt > 25)
5637 if (targettilt < -25)
5641 if (targettilt2 > 45)
5643 if (targettilt2 < -45)
5645 if (abs(tilt2 - targettilt2) < multiplier * 400)
5646 tilt2 = targettilt2;
5647 else if (tilt2 > targettilt2) {
5648 tilt2 -= multiplier * 400;
5649 } else if (tilt2 < targettilt2) {
5650 tilt2 += multiplier * 400;
5652 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5659 if (!isnormal(targettilt) && targettilt) {
5662 if (!isnormal(targettilt2) && targettilt2) {
5667 if (animTarget == rabbittackleanim) {
5668 velocity += facing * multiplier * speed * 700 * scale;
5669 velspeed = findLength(&velocity);
5670 if (velspeed > speed * 65 * scale) {
5671 velocity /= velspeed;
5672 velspeed = speed * 65 * scale;
5673 velocity *= velspeed;
5675 velocity.y += gravity * multiplier * 20;
5676 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5677 velspeed = findLength(&velocity);
5678 velocity = flatfacing * velspeed;
5680 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5681 if (isRun() || animTarget == rabbitkickanim) {
5682 velocity += facing * multiplier * speed * 700 * scale;
5683 velspeed = findLength(&velocity);
5684 if (velspeed > speed * 45 * scale) {
5685 velocity /= velspeed;
5686 velspeed = speed * 45 * scale;
5687 velocity *= velspeed;
5689 velocity.y += gravity * multiplier * 20;
5690 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5691 velspeed = findLength(&velocity);
5692 if (velspeed < speed * 30 * scale)
5693 velspeed = speed * 30 * scale;
5694 velocity = flatfacing * velspeed;
5696 } else if (isRun()) {
5697 velocity += facing * multiplier * speed * 700 * scale;
5698 velspeed = findLength(&velocity);
5699 if (creature == rabbittype) {
5700 if (velspeed > speed * 55 * scale) {
5701 velocity /= velspeed;
5702 velspeed = speed * 55 * scale;
5703 velocity *= velspeed;
5706 if (creature == wolftype) {
5707 if (velspeed > speed * 75 * scale) {
5708 velocity /= velspeed;
5709 velspeed = speed * 75 * scale;
5710 velocity *= velspeed;
5713 velocity.y += gravity * multiplier * 20;
5714 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5715 velspeed = findLength(&velocity);
5716 velocity = flatfacing * velspeed;
5719 if (animTarget == rollanim && targetFrame().label != 6) {
5720 velocity += facing * multiplier * speed * 700 * scale;
5721 velspeed = findLength(&velocity);
5722 if (velspeed > speed * 45 * scale) {
5723 velocity /= velspeed;
5724 velspeed = speed * 45 * scale;
5725 velocity *= velspeed;
5727 velocity.y += gravity * multiplier * 20;
5728 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5729 velspeed = findLength(&velocity);
5730 velocity = flatfacing * velspeed;
5733 if (animTarget == sneakanim || animTarget == walkanim) {
5734 velocity += facing * multiplier * speed * 700 * scale;
5735 velspeed = findLength(&velocity);
5736 if (velspeed > speed * 12 * scale) {
5737 velocity /= velspeed;
5738 velspeed = speed * 12 * scale;
5739 velocity *= velspeed;
5741 velocity.y += gravity * multiplier * 20;
5742 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5743 velspeed = findLength(&velocity);
5744 velocity = flatfacing * velspeed;
5747 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5748 velocity += facing * multiplier * speed * 700 * scale;
5749 velspeed = findLength(&velocity);
5750 if (velspeed > speed * 2 * scale) {
5751 velocity /= velspeed;
5752 velspeed = speed * 2 * scale;
5753 velocity *= velspeed;
5755 velocity.y += gravity * multiplier * 20;
5756 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5757 velspeed = findLength(&velocity);
5758 velocity = flatfacing * velspeed;
5762 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5763 velocity -= facing * multiplier * speed * 700 * scale;
5764 velspeed = findLength(&velocity);
5765 if (velspeed > speed * 2 * scale) {
5766 velocity /= velspeed;
5767 velspeed = speed * 2 * scale;
5768 velocity *= velspeed;
5770 velocity.y += gravity * multiplier * 20;
5771 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5772 velspeed = findLength(&velocity);
5773 velocity = flatfacing * velspeed * -1;
5776 if (animTarget == fightsidestep) {
5777 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5778 velspeed = findLength(&velocity);
5779 if (velspeed > speed * 12 * scale) {
5780 velocity /= velspeed;
5781 velspeed = speed * 12 * scale;
5782 velocity *= velspeed;
5784 velocity.y += gravity * multiplier * 20;
5785 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5786 velspeed = findLength(&velocity);
5787 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5790 if (animTarget == staggerbackhighanim) {
5791 coords -= facing * multiplier * speed * 16 * scale;
5794 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5795 coords -= facing * multiplier * speed * 20 * scale;
5799 if (animTarget == backhandspringanim) {
5800 //coords-=facing*multiplier*50*scale;
5801 velocity += facing * multiplier * speed * 700 * scale * -1;
5802 velspeed = findLength(&velocity);
5803 if (velspeed > speed * 50 * scale) {
5804 velocity /= velspeed;
5805 velspeed = speed * 50 * scale;
5806 velocity *= velspeed;
5808 velocity.y += gravity * multiplier * 20;
5809 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5810 velspeed = findLength(&velocity);
5811 velocity = flatfacing * velspeed * -1;
5813 if (animTarget == dodgebackanim) {
5814 //coords-=facing*multiplier*50*scale;
5815 velocity += facing * multiplier * speed * 700 * scale * -1;
5816 velspeed = findLength(&velocity);
5817 if (velspeed > speed * 60 * scale) {
5818 velocity /= velspeed;
5819 velspeed = speed * 60 * scale;
5820 velocity *= velspeed;
5822 velocity.y += gravity * multiplier * 20;
5823 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5824 velspeed = findLength(&velocity);
5825 velocity = flatfacing * velspeed * -1;
5828 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5829 velspeed = findLength(&velocity);
5833 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5834 velocity.y += gravity * multiplier;
5837 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5838 coords += velocity * multiplier;
5840 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5841 if (isFlip() && targetFrame().label == 7)
5844 if (animTarget == jumpupanim) {
5846 animTarget = getIdle();
5853 pause_sound(whooshsound);
5854 OPENAL_SetVolume(channels[whooshsound], 0);
5857 if (animTarget == jumpdownanim || isFlip()) {
5858 if (isFlip())jumppower = -4;
5859 animTarget = getLanding();
5860 emit_sound_at(landsound, coords, 128.);
5863 addEnvSound(coords);
5868 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5869 coords.y += gravity * multiplier * 2;
5870 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5871 coords.y = terrain.getHeight(coords.x, coords.z);
5876 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)) {
5877 velspeed = findLength(&velocity);
5879 if (velspeed < multiplier * 300 * scale) {
5882 velocity -= velocity / velspeed * multiplier * 300 * scale;
5883 if (velspeed > 5 && (isLanding() || isLandhard())) {
5884 skiddingdelay += multiplier;
5885 if (skiddelay <= 0) {
5886 FootLand(leftfoot, .5);
5887 FootLand(rightfoot, .5);
5895 velspeed = findLength(&velocity);
5897 if (velspeed < multiplier * 600 * scale) {
5900 velocity -= velocity / velspeed * multiplier * 600 * scale;
5902 if (velspeed > 5 && (isLanding() || isLandhard())) {
5903 skiddingdelay += multiplier;
5904 if (skiddelay <= 0) {
5905 FootLand(leftfoot, .5);
5906 FootLand(rightfoot, .5);
5913 if (skiddingdelay < 0)
5914 skiddingdelay += multiplier;
5915 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5917 if (!onterrain || environment == grassyenvironment) {
5918 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5920 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5924 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5925 terrainnormal = victim->coords - coords;
5926 Normalise(&terrainnormal);
5927 targetyaw = -asin(0 - terrainnormal.x);
5928 targetyaw *= 360 / 6.28;
5929 if (terrainnormal.z < 0)
5930 targetyaw = 180 - targetyaw;
5931 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5934 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5935 targetyaw = victim->targetyaw;
5937 if (animTarget == rabbittacklinganim) {
5938 coords = victim->coords;
5941 skeleton.oldfree = skeleton.free;
5945 midterrain.x = terrain.size * terrain.scale / 2;
5946 midterrain.z = terrain.size * terrain.scale / 2;
5947 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5949 tempposit = coords - midterrain;
5951 Normalise(&tempposit);
5952 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5953 coords.x = tempposit.x + midterrain.x;
5954 coords.z = tempposit.z + midterrain.z;
5960 * inverse kinematics helper function
5962 void IKHelper(Person *p, float interp)
5964 XYZ point, change, change2;
5965 float heightleft, heightright;
5967 // TODO: implement localToWorld and worldToLocal
5968 // but keep in mind it won't be the same math if player is ragdolled or something
5969 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5970 // then comb through code for places where to use it
5972 // point = localToWorld(jointPos(leftfoot))
5973 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5974 // adjust height of foot
5975 heightleft = terrain.getHeight(point.x, point.z) + .04;
5976 point.y = heightleft;
5977 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5978 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5979 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5980 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5981 // move ankle along with foot
5982 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5983 // average knee pos between old and new pos
5984 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5986 // do same as above for right leg
5987 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5988 heightright = terrain.getHeight(point.x, point.z) + .04;
5989 point.y = heightright;
5990 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5991 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5992 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5993 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5994 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5996 // fix up skeleton now that we've moved body parts?
5997 p->skeleton.DoConstraints(&p->coords, &p->scale);
6004 int Person::DrawSkeleton()
6006 int oldplayerdetail;
6007 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6008 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6018 glAlphaFunc(GL_GREATER, 0.0001);
6020 float terrainheight;
6024 if (!isnormal(tilt))
6026 if (!isnormal(tilt2))
6028 oldplayerdetail = playerdetail;
6030 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6033 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6036 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6041 if (playerdetail != oldplayerdetail) {
6043 normalsupdatedelay = 0;
6045 static float updatedelaychange;
6046 static float morphness;
6047 static float framemult;
6049 skeleton.FindForwards();
6050 if (howactive == typesittingwall) {
6051 skeleton.specialforward[1] = 0;
6052 skeleton.specialforward[1].z = 1;
6058 static int weaponattachmuscle;
6059 static int weaponrotatemuscle;
6060 static XYZ weaponpoint;
6061 static int start, endthing;
6062 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6063 if (!isSleeping() && !isSitting()) {
6064 // TODO: give these meaningful names
6065 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6066 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6067 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6068 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6070 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6072 if (creature == wolftype)
6076 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6077 IKHelper(this, target);
6078 if (creature == wolftype)
6079 IKHelper(this, target);
6082 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6083 IKHelper(this, 1 - target);
6084 if (creature == wolftype)
6085 IKHelper(this, 1 - target);
6089 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()))
6092 targetheadyaw = -targetyaw;
6093 targetheadpitch = 0;
6094 if (Animation::animations[animTarget].attack == 3)
6095 targetheadyaw += 180;
6097 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6098 skeleton.drawmodel.vertex[i] = 0;
6099 skeleton.drawmodel.vertex[i].y = 999;
6101 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6102 skeleton.drawmodellow.vertex[i] = 0;
6103 skeleton.drawmodellow.vertex[i].y = 999;
6105 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6106 skeleton.drawmodelclothes.vertex[i] = 0;
6107 skeleton.drawmodelclothes.vertex[i].y = 999;
6109 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6110 // convenience renames
6111 const int p1 = skeleton.muscles[i].parent1->label;
6112 const int p2 = skeleton.muscles[i].parent2->label;
6114 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6119 if (p1 == righthand || p2 == righthand) {
6120 morphness = righthandmorphness;
6121 start = righthandmorphstart;
6122 endthing = righthandmorphend;
6124 if (p1 == lefthand || p2 == lefthand) {
6125 morphness = lefthandmorphness;
6126 start = lefthandmorphstart;
6127 endthing = lefthandmorphend;
6129 if (p1 == head || p2 == head) {
6130 morphness = headmorphness;
6131 start = headmorphstart;
6132 endthing = headmorphend;
6134 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6135 morphness = chestmorphness;
6136 start = chestmorphstart;
6137 endthing = chestmorphend;
6139 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6140 morphness = tailmorphness;
6141 start = tailmorphstart;
6142 endthing = tailmorphend;
6145 skeleton.FindRotationMuscle(i, animTarget);
6146 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6147 glMatrixMode(GL_MODELVIEW);
6151 glRotatef(tilt2, 1, 0, 0);
6153 glRotatef(tilt, 0, 0, 1);
6156 glTranslatef(mid.x, mid.y, mid.z);
6158 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6159 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6161 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6162 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6164 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6165 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6167 if (playerdetail || skeleton.free == 3) {
6168 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6169 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6170 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6171 glMatrixMode(GL_MODELVIEW);
6173 if (p1 == abdomen || p2 == abdomen)
6174 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6175 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6176 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6177 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6178 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6179 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6180 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6181 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6182 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6183 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6184 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6185 if (p1 == head || p2 == head)
6186 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6187 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6188 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6189 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6190 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6191 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6192 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6196 if (!playerdetail || skeleton.free == 3) {
6197 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6198 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6199 glMatrixMode(GL_MODELVIEW);
6201 if (p1 == abdomen || p2 == abdomen)
6202 glTranslatef(v0.x * proportionbody.x,
6203 v0.y * proportionbody.y,
6204 v0.z * proportionbody.z);
6205 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6206 glTranslatef(v0.x * proportionarms.x,
6207 v0.y * proportionarms.y,
6208 v0.z * proportionarms.z);
6209 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6210 glTranslatef(v0.x * proportionlegs.x,
6211 v0.y * proportionlegs.y,
6212 v0.z * proportionlegs.z);
6213 if (p1 == head || p2 == head)
6214 glTranslatef(v0.x * proportionhead.x,
6215 v0.y * proportionhead.y,
6216 v0.z * proportionhead.z);
6218 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6219 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6220 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6221 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6227 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6228 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6230 glMatrixMode(GL_MODELVIEW);
6234 glRotatef(tilt2, 1, 0, 0);
6236 glRotatef(tilt, 0, 0, 1);
6237 glTranslatef(mid.x, mid.y, mid.z);
6238 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6239 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6241 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6242 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6244 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6245 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6247 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6248 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6249 glMatrixMode(GL_MODELVIEW);
6251 if (p1 == abdomen || p2 == abdomen)
6252 glTranslatef(v0.x * proportionbody.x,
6253 v0.y * proportionbody.y,
6254 v0.z * proportionbody.z);
6255 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6256 glTranslatef(v0.x * proportionarms.x,
6257 v0.y * proportionarms.y,
6258 v0.z * proportionarms.z);
6259 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6260 glTranslatef(v0.x * proportionlegs.x,
6261 v0.y * proportionlegs.y,
6262 v0.z * proportionlegs.z);
6263 if (p1 == head || p2 == head)
6264 glTranslatef(v0.x * proportionhead.x,
6265 v0.y * proportionhead.y,
6266 v0.z * proportionhead.z);
6267 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6268 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6269 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6270 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6275 updatedelay = 1 + (float)(Random() % 100) / 1000;
6277 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6278 normalsupdatedelay = 1;
6279 if (playerdetail || skeleton.free == 3)
6280 skeleton.drawmodel.CalculateNormals(0);
6281 if (!playerdetail || skeleton.free == 3)
6282 skeleton.drawmodellow.CalculateNormals(0);
6283 if (skeleton.clothes)
6284 skeleton.drawmodelclothes.CalculateNormals(0);
6286 if (playerdetail || skeleton.free == 3)
6287 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6288 if (!playerdetail || skeleton.free == 3)
6289 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6290 if (skeleton.clothes) {
6291 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6296 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6297 if (updatedelaychange > -realmultiplier * 30)
6298 updatedelaychange = -realmultiplier * 30;
6299 if (updatedelaychange > -framemult * 4)
6300 updatedelaychange = -framemult * 4;
6301 if (skeleton.free == 1)
6302 updatedelaychange *= 6;
6304 updatedelaychange *= 8;
6305 updatedelay += updatedelaychange;
6307 glMatrixMode(GL_MODELVIEW);
6309 glTranslatef(coords.x, coords.y - .02, coords.z);
6310 if (!skeleton.free) {
6311 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6312 glRotatef(yaw, 0, 1, 0);
6316 glColor4f(.4, 1, .4, 1);
6317 glDisable(GL_LIGHTING);
6318 glDisable(GL_TEXTURE_2D);
6321 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6322 XYZ &v0 = skeleton.drawmodel.vertex[i];
6323 glVertex3f(v0.x, v0.y, v0.z);
6329 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6330 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6331 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6332 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6333 glVertex3f(v0.x, v0.y, v0.z);
6334 glVertex3f(v1.x, v1.y, v1.z);
6335 glVertex3f(v1.x, v1.y, v1.z);
6336 glVertex3f(v2.x, v2.y, v2.z);
6337 glVertex3f(v2.x, v2.y, v2.z);
6338 glVertex3f(v0.x, v0.y, v0.z);
6344 terrainlight = terrain.getLighting(coords.x, coords.z);
6345 distance = distsq(&viewer, &coords);
6346 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6350 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6351 if (terrainheight < 1)
6353 if (terrainheight > 1.7)
6354 terrainheight = 1.7;
6356 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6357 glDisable(GL_BLEND);
6358 glAlphaFunc(GL_GREATER, 0.0001);
6359 glEnable(GL_TEXTURE_2D);
6361 glDisable(GL_TEXTURE_2D);
6362 glColor4f(.7, .35, 0, .5);
6364 glEnable(GL_LIGHTING);
6367 if (tutoriallevel && id != 0) {
6368 glColor4f(.7, .7, .7, 0.6);
6370 glEnable(GL_LIGHTING);
6372 if (canattack && cananger)
6373 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6374 glDisable(GL_TEXTURE_2D);
6375 glColor4f(1, 0, 0, 0.8);
6377 glMatrixMode(GL_TEXTURE);
6379 glTranslatef(0, -smoketex, 0);
6380 glTranslatef(-smoketex, 0, 0);
6384 if ((tutoriallevel && id != 0))
6385 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6387 skeleton.drawmodel.draw();
6390 if (!playerdetail) {
6391 if ((tutoriallevel && id != 0))
6392 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6394 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6397 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6398 if (tutoriallevel && id != 0) {
6400 glMatrixMode(GL_MODELVIEW);
6401 glEnable(GL_TEXTURE_2D);
6402 glColor4f(.7, .7, .7, 0.6);
6404 glEnable(GL_LIGHTING);
6406 if (canattack && cananger)
6407 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6408 glDisable(GL_TEXTURE_2D);
6409 glColor4f(1, 0, 0, 0.8);
6411 glMatrixMode(GL_TEXTURE);
6413 glTranslatef(0, -smoketex * .6, 0);
6414 glTranslatef(smoketex * .6, 0, 0);
6417 if ((tutoriallevel && id != 0))
6418 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6420 skeleton.drawmodel.draw();
6423 if (!playerdetail) {
6424 if ((tutoriallevel && id != 0))
6425 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6427 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6432 if (tutoriallevel && id != 0) {
6434 glMatrixMode(GL_MODELVIEW);
6435 glEnable(GL_TEXTURE_2D);
6437 if (skeleton.clothes) {
6441 skeleton.drawmodelclothes.draw();
6443 skeleton.drawmodelclothes.drawimmediate();
6449 if (num_weapons > 0) {
6450 for (k = 0; k < num_weapons; k++) {
6452 if (weaponactive == k) {
6453 if (weapons[i].getType() != staff) {
6454 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6455 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6456 weaponattachmuscle = j;
6459 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6460 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) {
6461 weaponrotatemuscle = j;
6464 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6465 if (creature == wolftype)
6466 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6468 if (weapons[i].getType() == staff) {
6469 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6470 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6471 weaponattachmuscle = j;
6474 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6475 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) {
6476 weaponrotatemuscle = j;
6479 //weaponpoint=jointPos(rightwrist);
6480 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6481 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6482 XYZ tempnormthing, vec1, vec2;
6483 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6484 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6485 CrossProduct(&vec1, &vec2, &tempnormthing);
6486 Normalise(&tempnormthing);
6487 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6488 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6491 if (weaponactive != k && weaponstuck != k) {
6492 if (weapons[i].getType() == knife)
6493 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6494 if (weapons[i].getType() == sword)
6495 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6496 if (weapons[i].getType() == staff)
6497 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6498 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6499 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) {
6500 weaponrotatemuscle = j;
6504 if (weaponstuck == k) {
6505 if (weaponstuckwhere == 0)
6506 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6508 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6509 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6510 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) {
6511 weaponrotatemuscle = j;
6515 if (skeleton.free) {
6516 weapons[i].position = weaponpoint * scale + coords;
6517 weapons[i].bigrotation = 0;
6518 weapons[i].bigtilt = 0;
6519 weapons[i].bigtilt2 = 0;
6521 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;
6522 weapons[i].bigrotation = yaw;
6523 weapons[i].bigtilt = tilt;
6524 weapons[i].bigtilt2 = tilt2;
6526 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6527 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6528 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6529 if (weaponactive == k) {
6530 if (weapons[i].getType() == knife) {
6531 weapons[i].smallrotation = 180;
6532 weapons[i].smallrotation2 = 0;
6533 if (isCrouch() || wasCrouch()) {
6534 weapons[i].smallrotation2 = 20;
6536 if (animTarget == hurtidleanim) {
6537 weapons[i].smallrotation2 = 50;
6539 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6540 XYZ temppoint1, temppoint2;
6543 temppoint1 = jointPos(righthand);
6544 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6545 distance = findDistance(&temppoint1, &temppoint2);
6546 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6547 weapons[i].rotation2 *= 360 / 6.28;
6550 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6551 weapons[i].rotation1 *= 360 / 6.28;
6552 weapons[i].rotation3 = 0;
6553 weapons[i].smallrotation = -90;
6554 weapons[i].smallrotation2 = 0;
6555 if (temppoint1.x > temppoint2.x)
6556 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6558 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6559 XYZ temppoint1, temppoint2;
6562 temppoint1 = jointPos(righthand);
6563 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6564 distance = findDistance(&temppoint1, &temppoint2);
6565 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6566 weapons[i].rotation2 *= 360 / 6.28;
6569 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6570 weapons[i].rotation1 *= 360 / 6.28;
6571 weapons[i].rotation3 = 0;
6572 weapons[i].smallrotation = 90;
6573 weapons[i].smallrotation2 = 0;
6574 if (temppoint1.x > temppoint2.x)
6575 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6577 if (animTarget == knifethrowanim) {
6578 weapons[i].smallrotation = 90;
6579 //weapons[i].smallrotation2=-90;
6580 weapons[i].smallrotation2 = 0;
6581 weapons[i].rotation1 = 0;
6582 weapons[i].rotation2 = 0;
6583 weapons[i].rotation3 = 0;
6585 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6586 weapons[i].smallrotation = -90;
6587 weapons[i].rotation1 = 0;
6588 weapons[i].rotation2 = 0;
6589 weapons[i].rotation3 = 0;
6592 if (weapons[i].getType() == sword) {
6593 weapons[i].smallrotation = 0;
6594 weapons[i].smallrotation2 = 0;
6595 if (animTarget == knifethrowanim) {
6596 weapons[i].smallrotation = -90;
6597 weapons[i].smallrotation2 = 0;
6598 weapons[i].rotation1 = 0;
6599 weapons[i].rotation2 = 0;
6600 weapons[i].rotation3 = 0;
6602 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)) {
6603 XYZ temppoint1, temppoint2;
6606 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6607 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6608 distance = findDistance(&temppoint1, &temppoint2);
6609 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6610 weapons[i].rotation2 *= 360 / 6.28;
6613 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6614 weapons[i].rotation1 *= 360 / 6.28;
6615 weapons[i].rotation3 = 0;
6616 weapons[i].smallrotation = 90;
6617 weapons[i].smallrotation2 = 0;
6618 if (temppoint1.x > temppoint2.x)
6619 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6622 if (weapons[i].getType() == staff) {
6623 weapons[i].smallrotation = 100;
6624 weapons[i].smallrotation2 = 0;
6625 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6626 XYZ temppoint1, temppoint2;
6629 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6630 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6631 distance = findDistance(&temppoint1, &temppoint2);
6632 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6633 weapons[i].rotation2 *= 360 / 6.28;
6636 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6637 weapons[i].rotation1 *= 360 / 6.28;
6638 weapons[i].rotation3 = 0;
6639 weapons[i].smallrotation = 90;
6640 weapons[i].smallrotation2 = 0;
6641 if (temppoint1.x > temppoint2.x)
6642 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6646 if (weaponactive != k && weaponstuck != k) {
6647 if (weapons[i].getType() == knife) {
6648 weapons[i].smallrotation = -70;
6649 weapons[i].smallrotation2 = 10;
6651 if (weapons[i].getType() == sword) {
6652 weapons[i].smallrotation = -100;
6653 weapons[i].smallrotation2 = -8;
6655 if (weapons[i].getType() == staff) {
6656 weapons[i].smallrotation = -100;
6657 weapons[i].smallrotation2 = -8;
6660 if (weaponstuck == k) {
6661 if (weaponstuckwhere == 0)
6662 weapons[i].smallrotation = 180;
6664 weapons[i].smallrotation = 0;
6665 weapons[i].smallrotation2 = 10;
6674 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6676 if (animCurrent != animTarget)
6678 if (skeleton.free == 2)
6687 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6690 static float distance;
6691 static float olddistance;
6692 static int intersecting;
6693 static int firstintersecting;
6696 static XYZ start, end;
6697 static float slopethreshold = -.4;
6699 firstintersecting = -1;
6703 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6706 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6707 for (i = 0; i < 4; i++) {
6708 for (j = 0; j < model->TriangleNum; j++) {
6709 if (model->facenormals[j].y <= slopethreshold) {
6711 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)));
6712 if (distance < radius) {
6713 point = *p1 - model->facenormals[j] * distance;
6714 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]]))
6717 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6718 &model->vertex[model->Triangles[j].vertex[1]],
6721 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6722 &model->vertex[model->Triangles[j].vertex[2]],
6725 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6726 &model->vertex[model->Triangles[j].vertex[2]],
6729 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6733 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)) {
6734 p1->y = point.y + radius;
6735 if ((animTarget == jumpdownanim || isFlip())) {
6736 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6739 if (animTarget == jumpupanim) {
6741 animTarget = getIdle();
6748 pause_sound(whooshsound);
6749 OPENAL_SetVolume(channels[whooshsound], 0);
6752 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6755 animTarget = getLanding();
6756 emit_sound_at(landsound, coords, 128.);
6759 addEnvSound(coords);
6766 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6767 olddistance = distance;
6768 firstintersecting = j;
6773 for (j = 0; j < model->TriangleNum; j++) {
6774 if (model->facenormals[j].y > slopethreshold) {
6777 start.y -= radius / 4;
6778 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6779 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6780 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6781 distance = abs((model->facenormals[j].x * start.x)
6782 + (model->facenormals[j].y * start.y)
6783 + (model->facenormals[j].z * start.z)
6784 - ((model->facenormals[j].x * v0.x)
6785 + (model->facenormals[j].y * v0.y)
6786 + (model->facenormals[j].z * v0.z)));
6787 if (distance < radius * .5) {
6788 point = start - model->facenormals[j] * distance;
6789 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6792 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6794 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6796 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6798 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6799 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6801 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6802 if (findLengthfast(&start) < findLengthfast(&velocity))
6805 *p1 += model->facenormals[j] * (distance - radius * .5);
6808 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6809 olddistance = distance;
6810 firstintersecting = j;
6817 *p = DoRotation(*p, 0, *rotate, 0);
6820 *p1 = DoRotation(*p1, 0, *rotate, 0);
6822 return firstintersecting;
6825 void Person::takeWeapon(int weaponId)
6828 weapons[weaponId].owner = id;
6829 if (num_weapons > 0) {
6830 weaponids[num_weapons] = weaponids[0];
6833 weaponids[0] = weaponId;
6836 void Person::addClothes()
6838 if (numclothes > 0) {
6839 for (int i = 0; i < numclothes; i++) {
6846 bool Person::addClothes(const int& clothesId)
6849 const std::string fileName = clothes[clothesId];
6851 GLubyte* array = &skeleton.skinText[0];
6855 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6860 float tintr = clothestintr[clothesId];
6861 float tintg = clothestintg[clothesId];
6862 float tintb = clothestintb[clothesId];
6864 if (tintr > 1) tintr = 1;
6865 if (tintg > 1) tintg = 1;
6866 if (tintb > 1) tintb = 1;
6868 if (tintr < 0) tintr = 0;
6869 if (tintg < 0) tintg = 0;
6870 if (tintb < 0) tintb = 0;
6872 int bytesPerPixel = texture.bpp / 8;
6876 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6877 if (bytesPerPixel == 3)
6879 else if ((i + 1) % 4 == 0)
6880 alphanum = texture.data[i];
6881 if ((i + 1) % 4 || bytesPerPixel == 3) {
6883 texture.data[i] *= tintr;
6885 texture.data[i] *= tintg;
6887 texture.data[i] *= tintb;
6888 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);