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) {
1781 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1782 average += skeleton.joints[j].position;
1786 coords += average * scale;
1787 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1788 skeleton.joints[j].position -= average;
1791 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1792 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1793 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1794 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1795 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1798 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1799 coords.x = lowpoint.x;
1800 coords.z = lowpoint.z;
1809 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1810 velocity += skeleton.joints[i].velocity * scale;
1812 velocity /= skeleton.joints.size();
1815 if (Random() % 2 == 0) {
1816 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1817 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1818 weapons[weaponids[0]].velocity.x += .01;
1821 weaponids[0] = weaponids[num_weapons];
1822 if (weaponstuck == num_weapons)
1826 for (unsigned i = 0; i < Person::players.size(); i++) {
1827 Person::players[i]->wentforweapon = 0;
1832 animTarget = bounceidleanim;
1833 animCurrent = bounceidleanim;
1843 void Person::FootLand(bodypart whichfoot, float opacity)
1845 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1846 cerr << "FootLand called on wrong bodypart" << endl;
1849 static XYZ terrainlight;
1850 static XYZ footvel, footpoint;
1851 if (opacity >= 1 || skiddelay <= 0) {
1854 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1855 if (distsq(&footpoint, &viewer))
1856 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1857 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1858 footvel = velocity / 5;
1861 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1862 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1863 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1864 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1865 if (environment == snowyenvironment) {
1866 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1868 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1870 } else if (environment == grassyenvironment) {
1871 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1872 } else if (environment == desertenvironment) {
1873 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1875 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1879 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1880 footvel = velocity / 5;
1883 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1884 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1885 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1892 * make a puff effect at a body part (dust effect?)
1894 void Person::Puff(int whichlabel)
1896 static XYZ footvel, footpoint;
1899 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1900 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1904 * I think I added this in an attempt to clean up code
1906 void Person::setAnimation(int animation)
1908 animTarget = animation;
1917 void Person::DoAnimations()
1919 if (!skeleton.free) {
1920 static float oldtarget;
1922 if (isIdle() && animCurrent != getIdle())
1923 normalsupdatedelay = 0;
1925 if (animTarget == tempanim || animCurrent == tempanim) {
1926 Animation::animations[tempanim] = tempanimation;
1928 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1934 vel[0] = velocity.x;
1935 vel[1] = velocity.y;
1936 vel[2] = velocity.z;
1939 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1940 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1942 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1944 if (!crouchkeydown && velocity.y >= -15)
1947 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1952 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1954 if (normaldotproduct(targfacing, velocity) >= -.3)
1955 animTarget = flipanim;
1957 animTarget = backflipanim;
1958 crouchtogglekeydown = 1;
1966 if (Animation::animations[animTarget].attack != reversed)
1968 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1969 crouchtogglekeydown = 0;
1970 if (aitype == playercontrolled)
1973 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1976 crouchtogglekeydown = 1;
1980 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1982 normalsupdatedelay = 0;
1986 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1988 emit_sound_at(fireendsound, coords);
1989 pause_sound(stream_firesound);
1993 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1994 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1996 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1997 if (normaldotproduct(victim->facing, facing) > 0)
1998 victim->animTarget = rabbittackledbackanim;
2000 victim->animTarget = rabbittackledfrontanim;
2001 victim->frameTarget = 2;
2004 victim->targetyaw = yaw;
2005 if (victim->aitype == gethelptype)
2006 victim->DoDamage(victim->damagetolerance - victim->damage);
2007 //victim->DoDamage(30);
2008 if (creature == wolftype) {
2010 emit_sound_at(clawslicesound, victim->coords);
2012 victim->DoBloodBig(1 / victim->armorhead, 210);
2014 award_bonus(id, TackleBonus,
2015 victim->aitype == gethelptype ? 50 : 0);
2019 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2020 if (weapons[weaponids[0]].getType() == knife) {
2021 if (weaponactive == -1)
2023 else if (weaponactive == 0)
2026 if (weaponactive == -1) {
2027 emit_sound_at(knifesheathesound, coords);
2029 if (weaponactive != -1) {
2030 emit_sound_at(knifedrawsound, coords, 128);
2033 drawtogglekeydown = 1;
2036 if (tutoriallevel != 1 || id == 0)
2037 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2038 int whichsound = -1;
2040 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2041 if (targetFrame().label == 1)
2042 whichsound = footstepsound;
2044 whichsound = footstepsound2;
2045 if (targetFrame().label == 1)
2046 FootLand(leftfoot, 1);
2047 if (targetFrame().label == 2)
2048 FootLand(rightfoot, 1);
2049 if (targetFrame().label == 3 && isRun()) {
2050 FootLand(rightfoot, 1);
2051 FootLand(leftfoot, 1);
2055 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2056 if (targetFrame().label == 1)
2057 whichsound = footstepsound3;
2059 whichsound = footstepsound4;
2063 if (targetFrame().label == 1)
2064 whichsound = footstepsound3;
2066 whichsound = footstepsound4;
2068 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2069 if (Animation::animations[animTarget].attack != neutral) {
2070 unsigned r = abs(Random() % 3);
2072 whichsound = lowwhooshsound;
2074 whichsound = midwhooshsound;
2076 whichsound = highwhooshsound;
2078 if (Animation::animations[animTarget].attack == neutral) {
2079 whichsound = movewhooshsound;
2081 } else if (targetFrame().label == 4) {
2082 whichsound = knifeswishsound;
2084 if (targetFrame().label == 8 && tutoriallevel != 1) {
2085 whichsound = landsound2;
2088 if (whichsound != -1) {
2089 emit_sound_at(whichsound, coords, 256.);
2092 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2093 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2094 addEnvSound(coords, 15);
2096 addEnvSound(coords, 6);
2101 if (targetFrame().label == 3) {
2103 emit_sound_at(whichsound, coords, 128.);
2109 if (tutoriallevel != 1 || id == 0)
2110 if (speechdelay <= 0)
2111 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2112 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2113 int whichsound = -1;
2114 if (targetFrame().label == 4 && aitype != playercontrolled) {
2115 if (Animation::animations[animTarget].attack != neutral) {
2116 unsigned r = abs(Random() % 4);
2117 if (creature == rabbittype) {
2118 if (r == 0) whichsound = rabbitattacksound;
2119 if (r == 1) whichsound = rabbitattack2sound;
2120 if (r == 2) whichsound = rabbitattack3sound;
2121 if (r == 3) whichsound = rabbitattack4sound;
2123 if (creature == wolftype) {
2124 if (r == 0) whichsound = barksound;
2125 if (r == 1) whichsound = bark2sound;
2126 if (r == 2) whichsound = bark3sound;
2127 if (r == 3) whichsound = barkgrowlsound;
2133 if (whichsound != -1) {
2134 emit_sound_at(whichsound, coords);
2140 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2141 FootLand(leftfoot, 1);
2142 FootLand(rightfoot, 1);
2146 currentoffset = targetoffset;
2147 frameTarget = frameCurrent;
2148 animCurrent = animTarget;
2151 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2152 for (unsigned i = 0; i < weapons.size(); i++) {
2153 if (weapons[i].owner == -1)
2154 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2155 if (distsq(&coords, &weapons[i].position) >= 1) {
2156 if (weapons[i].getType() != staff) {
2157 emit_sound_at(knifedrawsound, coords, 128.);
2166 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2167 for (unsigned i = 0; i < weapons.size(); i++) {
2168 bool willwork = true;
2169 if (weapons[i].owner != -1)
2170 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2171 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2172 if (Person::players[weapons[i].owner]->num_weapons > 1)
2174 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2175 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2176 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2177 bool fleshstuck = false;
2178 if (weapons[i].owner != -1)
2179 if (victim->weaponstuck != -1) {
2180 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2185 emit_sound_at(fleshstabremovesound, coords, 128.);
2187 if (weapons[i].getType() != staff) {
2188 emit_sound_at(knifedrawsound, coords, 128.);
2191 if (weapons[i].owner != -1) {
2192 victim = Person::players[weapons[i].owner];
2193 if (victim->num_weapons == 1)
2194 victim->num_weapons = 0;
2196 victim->num_weapons = 1;
2198 //victim->weaponactive=-1;
2199 victim->skeleton.longdead = 0;
2200 victim->skeleton.free = 1;
2201 victim->skeleton.broken = 0;
2203 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2204 victim->skeleton.joints[j].velchange = 0;
2205 victim->skeleton.joints[j].locked = 0;
2211 Normalise(&relative);
2212 XYZ footvel, footpoint;
2214 footpoint = weapons[i].position;
2215 if (victim->weaponstuck != -1) {
2216 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2218 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2219 weapons[i].bloody = 2;
2220 weapons[i].blooddrip = 5;
2221 victim->weaponstuck = -1;
2224 if (victim->num_weapons > 0) {
2225 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2226 victim->weaponstuck = 0;
2227 if (victim->weaponids[0] == int(i))
2228 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2231 victim->jointVel(abdomen) += relative * 6;
2232 victim->jointVel(neck) += relative * 6;
2233 victim->jointVel(rightshoulder) += relative * 6;
2234 victim->jointVel(leftshoulder) += relative * 6;
2242 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2243 if (weaponactive == -1)
2245 else if (weaponactive == 0) {
2247 if (num_weapons == 2) {
2249 buffer = weaponids[0];
2250 weaponids[0] = weaponids[1];
2251 weaponids[1] = buffer;
2254 if (weaponactive == -1) {
2255 emit_sound_at(knifesheathesound, coords, 128.);
2257 if (weaponactive != -1) {
2258 emit_sound_at(knifedrawsound, coords, 128.);
2263 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2264 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2265 Normalise(&rotatetarget);
2266 targetyaw = -asin(0 - rotatetarget.x);
2267 targetyaw *= 360 / 6.28;
2268 if (rotatetarget.z < 0)
2269 targetyaw = 180 - targetyaw;
2271 if (animTarget == walljumprightkickanim)
2273 if (animTarget == walljumpleftkickanim)
2279 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2282 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2287 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2288 animTarget = rabbittackleanim;
2290 emit_sound_at(jumpsound, coords);
2298 targetloc = velocity;
2299 Normalise(&targetloc);
2300 targetloc += coords;
2301 for (unsigned i = 0; i < Person::players.size(); i++) {
2303 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2304 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2308 if (closestid != -1)
2309 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2311 victim = Person::players[closestid];
2312 coords = victim->coords;
2313 animCurrent = rabbittacklinganim;
2314 animTarget = rabbittacklinganim;
2318 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2319 rotatetarget = coords - victim->coords;
2320 Normalise(&rotatetarget);
2321 targetyaw = -asin(0 - rotatetarget.x);
2322 targetyaw *= 360 / 6.28;
2323 if (rotatetarget.z < 0)
2324 targetyaw = 180 - targetyaw;
2326 if (animTarget != rabbitrunninganim) {
2327 emit_sound_at(jumpsound, coords, 128.);
2333 float damagemult = 1 * power;
2334 if (creature == wolftype)
2335 damagemult = 2.5 * power;
2337 damagemult /= victim->damagetolerance / 200;
2339 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)) {
2340 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2341 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2345 if (Random() % 2 || creature == wolftype) {
2348 if (creature == wolftype)
2351 if (tutoriallevel != 1) {
2352 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2354 if (creature == wolftype) {
2355 emit_sound_at(clawslicesound, victim->coords, 128.);
2357 victim->DoBloodBig(2 / victim->armorhead, 175);
2361 relative = victim->coords - coords;
2363 Normalise(&relative);
2364 relative = DoRotation(relative, 0, -90, 0);
2365 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2366 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2368 victim->jointVel(head) += relative * damagemult * 200;
2370 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2376 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2377 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2381 if (Random() % 2 || creature == wolftype) {
2383 if (creature == wolftype)
2386 emit_sound_at(whooshhitsound, victim->coords);
2387 if (creature == wolftype) {
2388 emit_sound_at(clawslicesound, victim->coords, 128.);
2390 victim->DoBloodBig(2, 175);
2394 relative = victim->coords - coords;
2396 Normalise(&relative);
2398 Normalise(&relative);
2399 relative = DoRotation(relative, 0, 90, 0);
2400 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2401 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2403 victim->jointVel(head) += relative * damagemult * 100;
2405 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2409 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2410 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2416 if (tutoriallevel != 1) {
2417 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2419 if (creature == wolftype) {
2420 emit_sound_at(clawslicesound, victim->coords, 128.);
2422 victim->DoBloodBig(2 / victim->armorhead, 175);
2428 Normalise(&relative);
2429 relative = DoRotation(relative, 0, -90, 0);
2430 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2431 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2433 victim->jointVel(head) += relative * damagemult * 200;
2435 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2437 if (victim->damage > victim->damagetolerance)
2438 award_bonus(id, style);
2444 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2445 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2451 if (tutoriallevel != 1) {
2452 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2454 if (creature == wolftype) {
2455 emit_sound_at(clawslicesound, victim->coords, 128.);
2457 victim->DoBloodBig(2 / victim->armorhead, 175);
2463 Normalise(&relative);
2464 relative = DoRotation(relative, 0, 90, 0);
2465 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2466 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2468 victim->jointVel(head) += relative * damagemult * 200;
2470 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2472 if (victim->damage > victim->damagetolerance)
2473 award_bonus(id, style);
2479 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2480 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2488 emit_sound_at(whooshhitsound, victim->coords);
2491 relative = victim->coords - coords;
2493 Normalise(&relative);
2494 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2495 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2497 victim->jointVel(head) += relative * damagemult * 100;
2499 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2503 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2504 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2508 emit_sound_at(whooshhitsound, victim->coords, 128.);
2510 victim->skeleton.longdead = 0;
2511 victim->skeleton.free = 1;
2512 victim->skeleton.broken = 0;
2513 victim->skeleton.spinny = 1;
2515 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2516 victim->skeleton.joints[i].velchange = 0;
2517 victim->skeleton.joints[i].delay = 0;
2518 victim->skeleton.joints[i].locked = 0;
2519 //victim->skeleton.joints[i].velocity=0;
2525 Normalise(&relative);
2526 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2527 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2528 victim->skeleton.joints[i].position.y += relative.y * .3;
2529 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2530 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2532 victim->Puff(abdomen);
2533 victim->jointVel(abdomen).y = relative.y * 400;
2537 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2538 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2542 if (tutoriallevel != 1) {
2543 emit_sound_at(heavyimpactsound, coords, 128.);
2546 relative = victim->coords - coords;
2548 Normalise(&relative);
2549 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2550 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2552 victim->Puff(abdomen);
2553 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2557 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2558 victim->jointVel(abdomen) += relative * damagemult * 300;
2562 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2563 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2567 if (tutoriallevel != 1) {
2568 emit_sound_at(thudsound, coords);
2571 victim->skeleton.longdead = 0;
2572 victim->skeleton.free = 1;
2573 victim->skeleton.broken = 0;
2574 victim->skeleton.spinny = 1;
2576 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2577 victim->skeleton.joints[i].velchange = 0;
2578 //victim->skeleton.joints[i].delay=0;
2579 victim->skeleton.joints[i].locked = 0;
2582 relative = victim->coords - coords;
2583 Normalise(&relative);
2585 Normalise(&relative);
2586 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2587 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2592 victim->Puff(abdomen);
2593 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2594 victim->jointVel(abdomen) += relative * damagemult * 200;
2603 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2606 if (!victim->skeleton.free)
2610 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2611 emit_sound_at(knifesheathesound, coords, 128.);
2614 if (victim && hasvictim) {
2615 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2617 XYZ where, startpoint, endpoint, movepoint, colpoint;
2618 float rotationpoint;
2620 if (weapons[weaponids[weaponactive]].getType() == knife) {
2621 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2622 where -= victim->coords;
2623 if (!victim->skeleton.free)
2624 where = DoRotation(where, 0, -victim->yaw, 0);
2627 startpoint.y += 100;
2631 if (weapons[weaponids[weaponactive]].getType() == sword) {
2632 where = weapons[weaponids[weaponactive]].position;
2633 where -= victim->coords;
2634 if (!victim->skeleton.free)
2635 where = DoRotation(where, 0, -victim->yaw, 0);
2637 where = weapons[weaponids[weaponactive]].tippoint;
2638 where -= victim->coords;
2639 if (!victim->skeleton.free)
2640 where = DoRotation(where, 0, -victim->yaw, 0);
2643 if (weapons[weaponids[weaponactive]].getType() == staff) {
2644 where = weapons[weaponids[weaponactive]].position;
2645 where -= victim->coords;
2646 if (!victim->skeleton.free)
2647 where = DoRotation(where, 0, -victim->yaw, 0);
2649 where = weapons[weaponids[weaponactive]].tippoint;
2650 where -= victim->coords;
2651 if (!victim->skeleton.free)
2652 where = DoRotation(where, 0, -victim->yaw, 0);
2657 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2659 if (whichtri != -1) {
2660 if (victim->dead != 2) {
2661 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2663 award_bonus(id, FinishedBonus);
2666 weapons[weaponids[weaponactive]].bloody = 2;
2668 victim->skeleton.longdead = 0;
2669 victim->skeleton.free = 1;
2670 victim->skeleton.broken = 0;
2672 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2673 victim->skeleton.joints[i].velchange = 0;
2674 victim->skeleton.joints[i].locked = 0;
2675 //victim->skeleton.joints[i].velocity=0;
2677 emit_sound_at(fleshstabsound, coords, 128);
2680 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2681 weapons[weaponids[weaponactive]].blooddrip += 5;
2682 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2684 if (whichtri == -1) {
2686 emit_sound_at(knifesheathesound, coords, 128.);
2692 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2694 emit_sound_at(knifedrawsound, coords, 128);
2697 if (victim && hasvictim) {
2698 XYZ footvel, footpoint;
2700 emit_sound_at(fleshstabremovesound, coords, 128.);
2703 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2705 if (weapons[weaponids[weaponactive]].getType() == sword) {
2706 XYZ where, startpoint, endpoint, movepoint;
2707 float rotationpoint;
2710 where = weapons[weaponids[weaponactive]].position;
2711 where -= victim->coords;
2712 if (!victim->skeleton.free)
2713 where = DoRotation(where, 0, -victim->yaw, 0);
2715 where = weapons[weaponids[weaponactive]].tippoint;
2716 where -= victim->coords;
2717 if (!victim->skeleton.free)
2718 where = DoRotation(where, 0, -victim->yaw, 0);
2723 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2724 footpoint += victim->coords;
2726 if (whichtri == -1) {
2727 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2730 if (weapons[weaponids[weaponactive]].getType() == staff) {
2731 XYZ where, startpoint, endpoint, movepoint;
2732 float rotationpoint;
2735 where = weapons[weaponids[weaponactive]].position;
2736 where -= victim->coords;
2737 if (!victim->skeleton.free)
2738 where = DoRotation(where, 0, -victim->yaw, 0);
2740 where = weapons[weaponids[weaponactive]].tippoint;
2741 where -= victim->coords;
2742 if (!victim->skeleton.free)
2743 where = DoRotation(where, 0, -victim->yaw, 0);
2748 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2749 footpoint += victim->coords;
2751 if (whichtri == -1) {
2752 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2755 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2757 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2758 victim->skeleton.longdead = 0;
2759 victim->skeleton.free = 1;
2760 victim->skeleton.broken = 0;
2762 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2763 victim->skeleton.joints[i].velchange = 0;
2764 victim->skeleton.joints[i].locked = 0;
2765 //victim->skeleton.joints[i].velocity=0;
2771 Normalise(&relative);
2772 //victim->Puff(abdomen);
2774 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2776 if (victim->bloodloss < victim->damagetolerance) {
2777 victim->bloodloss += 1000;
2781 victim->jointVel(abdomen) += relative * damagemult * 20;
2785 if (!hasvictim && onterrain) {
2786 weapons[weaponids[weaponactive]].bloody = 0;
2787 weapons[weaponids[weaponactive]].blooddrip = 0;
2791 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2792 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2800 if (tutoriallevel != 1) {
2801 emit_sound_at(heavyimpactsound, victim->coords, 128);
2806 relative = victim->coords - coords;
2808 Normalise(&relative);
2809 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2810 victim->skeleton.joints[i].velocity = relative * 30;
2812 victim->jointVel(head) += relative * damagemult * 150;
2814 victim->frameTarget = 0;
2815 victim->animTarget = staggerbackhardanim;
2816 victim->targetyaw = targetyaw + 180;
2818 victim->stunned = 1;
2821 victim->Puff(abdomen);
2822 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2829 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2830 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2834 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2835 if (tutoriallevel != 1) {
2836 emit_sound_at(thudsound, victim->coords);
2838 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2839 if (tutoriallevel != 1) {
2840 emit_sound_at(whooshhitsound, victim->coords);
2843 if (tutoriallevel != 1) {
2844 emit_sound_at(heavyimpactsound, victim->coords);
2848 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2851 relative = victim->coords - coords;
2853 Normalise(&relative);
2855 Normalise(&relative);
2856 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2857 victim->skeleton.joints[i].velocity = relative * 5;
2859 victim->jointVel(abdomen) += relative * damagemult * 400;
2861 victim->frameTarget = 0;
2862 victim->animTarget = staggerbackhardanim;
2863 victim->targetyaw = targetyaw + 180;
2865 victim->stunned = 1;
2867 victim->Puff(abdomen);
2868 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2874 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2875 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2876 if (victim->id == 0)
2878 emit_sound_at(landsound2, victim->coords);
2884 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2885 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2886 if (victim->id == 0)
2889 if (weaponactive != -1) {
2890 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2891 if (weapons[victim->weaponids[0]].getType() == staff)
2892 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2893 if (weapons[weaponids[0]].getType() == staff)
2894 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2896 emit_sound_at(swordstaffsound, victim->coords);
2898 emit_sound_at(metalhitsound, victim->coords);
2906 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2907 if (weaponactive != -1) {
2910 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);
2912 weapons[weaponids[0]].thrown(aim * 50);
2915 weaponids[0] = weaponids[num_weapons];
2921 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2923 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2925 if (tutoriallevel != 1)
2926 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2928 award_bonus(id, Slicebonus);
2929 if (tutoriallevel != 1) {
2930 emit_sound_at(knifeslicesound, victim->coords);
2932 //victim->jointVel(abdomen)+=relative*damagemult*200;
2933 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2934 if (victim->id != 0 || difficulty == 2) {
2935 victim->frameTarget = 0;
2936 victim->animTarget = staggerbackhardanim;
2937 victim->targetyaw = targetyaw + 180;
2941 victim->lowreversaldelay = 0;
2942 victim->highreversaldelay = 0;
2943 if (aitype != playercontrolled)
2944 weaponmissdelay = .6;
2946 if (tutoriallevel != 1)
2947 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2948 weapons[weaponids[weaponactive]].bloody = 1;
2949 if (tutoriallevel != 1)
2950 weapons[weaponids[weaponactive]].blooddrip += 3;
2952 XYZ footvel, footpoint;
2954 if (skeleton.free) {
2955 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2957 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2959 if (tutoriallevel != 1) {
2961 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2962 footvel = DoRotation(facing, 0, 90, 0) * .8;
2964 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2965 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2966 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2967 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2969 if (tutoriallevel == 1) {
2970 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2972 victim->DoDamage(damagemult * 0);
2975 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2976 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2977 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2978 award_bonus(id, Slashbonus);
2980 if (tutoriallevel != 1) {
2981 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2982 victim->DoBloodBig(2 / victim->armorhigh, 190);
2984 victim->DoBloodBig(2 / victim->armorhigh, 185);
2985 victim->deathbleeding = 1;
2986 emit_sound_at(swordslicesound, victim->coords);
2988 //victim->jointVel(abdomen)+=relative*damagemult*200;
2989 if (tutoriallevel != 1) {
2990 victim->frameTarget = 0;
2991 victim->animTarget = staggerbackhardanim;
2992 victim->targetyaw = targetyaw + 180;
2996 if (tutoriallevel != 1) {
2997 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2998 weapons[weaponids[weaponactive]].bloody = 1;
2999 weapons[weaponids[weaponactive]].blooddrip += 3;
3001 float bloodlossamount;
3002 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3003 victim->bloodloss += bloodlossamount / victim->armorhigh;
3004 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
3005 victim->DoDamage(damagemult * 0);
3007 XYZ footvel, footpoint;
3009 if (skeleton.free) {
3010 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3012 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3015 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3016 footvel = DoRotation(facing, 0, 90, 0) * .8;
3018 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3019 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3020 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3021 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3024 if (victim->weaponactive != -1) {
3025 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3026 if (weapons[victim->weaponids[0]].getType() == staff)
3027 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3028 if (weapons[weaponids[0]].getType() == staff)
3029 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3031 emit_sound_at(swordstaffsound, victim->coords);
3033 emit_sound_at(metalhitsound, victim->coords);
3039 victim->Puff(righthand);
3041 victim->frameTarget = 0;
3042 victim->animTarget = staggerbackhighanim;
3043 victim->targetyaw = targetyaw + 180;
3045 aim = DoRotation(facing, 0, 90, 0) * 21;
3047 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3048 victim->num_weapons--;
3049 if (victim->num_weapons) {
3050 victim->weaponids[0] = victim->weaponids[num_weapons];
3051 if (victim->weaponstuck == victim->num_weapons)
3052 victim->weaponstuck = 0;
3054 victim->weaponactive = -1;
3055 for (unsigned i = 0; i < Person::players.size(); i++) {
3056 Person::players[i]->wentforweapon = 0;
3063 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3064 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3065 if (tutoriallevel != 1) {
3066 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3070 if (Random() % 2 || creature == wolftype) {
3073 emit_sound_at(staffheadsound, victim->coords);
3077 relative = victim->coords - coords;
3079 Normalise(&relative);
3080 relative = DoRotation(relative, 0, 90, 0);
3082 Normalise(&relative);
3083 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3084 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3086 victim->jointVel(head) += relative * damagemult * 230;
3087 victim->jointVel(neck) += relative * damagemult * 230;
3089 if (tutoriallevel != 1) {
3090 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3092 award_bonus(id, solidhit, 30);
3097 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3098 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3099 if (tutoriallevel != 1) {
3100 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3104 if (Random() % 2 || creature == wolftype) {
3107 emit_sound_at(staffheadsound, victim->coords);
3111 relative = victim->coords - coords;
3113 Normalise(&relative);
3114 relative = DoRotation(relative, 0, -90, 0);
3115 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3116 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3118 victim->jointVel(head) += relative * damagemult * 220;
3119 victim->jointVel(neck) += relative * damagemult * 220;
3121 if (tutoriallevel != 1) {
3122 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3124 award_bonus(id, solidhit, 60);
3129 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3130 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3132 if (tutoriallevel != 1) {
3134 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3137 if (Random() % 2 || creature == wolftype) {
3140 emit_sound_at(staffbodysound, victim->coords);
3142 victim->skeleton.longdead = 0;
3143 victim->skeleton.free = 1;
3144 victim->skeleton.broken = 0;
3146 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3147 victim->skeleton.joints[i].velchange = 0;
3148 victim->skeleton.joints[i].locked = 0;
3149 //victim->skeleton.joints[i].velocity=0;
3156 Normalise(&relative);
3157 if (!victim->dead) {
3158 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3159 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3161 victim->jointVel(abdomen) += relative * damagemult * 40;
3164 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3165 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3168 victim->Puff(abdomen);
3169 if (tutoriallevel != 1) {
3170 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3172 if (!victim->dead) {
3173 award_bonus(id, solidhit, 40);
3179 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3180 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3185 relative = victim->coords - coords;
3187 Normalise(&relative);
3191 if (Animation::animations[victim->animTarget].height == lowheight) {
3197 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3198 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3200 victim->jointVel(head) += relative * damagemult * 200;
3201 if (tutoriallevel != 1) {
3202 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3205 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3206 if (victim->howactive == typesleeping)
3207 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3208 if (creature == wolftype) {
3209 emit_sound_at(clawslicesound, victim->coords, 128.);
3211 victim->DoBloodBig(2 / victim->armorhead, 175);
3214 if (victim->damage >= victim->damagetolerance)
3216 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3217 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3219 victim->jointVel(abdomen) += relative * damagemult * 200;
3220 victim->frameTarget = 0;
3221 victim->animTarget = staggerbackhighanim;
3222 victim->targetyaw = targetyaw + 180;
3224 if (tutoriallevel != 1) {
3225 emit_sound_at(landsound2, victim->coords, 128.);
3227 victim->Puff(abdomen);
3228 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3229 if (creature == wolftype) {
3230 emit_sound_at(clawslicesound, victim->coords, 128.);
3232 victim->DoBloodBig(2 / victim->armorhigh, 170);
3239 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3240 if ((victim->animTarget != jumpupanim) &&
3241 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3242 (victim != this->shared_from_this())) {
3246 if (tutoriallevel != 1) {
3247 emit_sound_at(landsound2, victim->coords, 128.);
3250 relative = victim->coords - coords;
3252 Normalise(&relative);
3254 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3257 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3258 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3260 relative = DoRotation(relative, 0, -90, 0);
3262 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3263 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)
3264 victim->skeleton.joints[i].velocity = relative * 80;
3266 victim->Puff(rightankle);
3267 victim->Puff(leftankle);
3268 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3270 if (victim->damage >= victim->damagetolerance)
3272 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3273 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3275 relative = DoRotation(relative, 0, -90, 0);
3276 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3277 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)
3278 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3280 victim->jointVel(abdomen) += relative * damagemult * 200;
3281 victim->frameTarget = 0;
3282 victim->animTarget = staggerbackhighanim;
3283 victim->targetyaw = targetyaw + 180;
3285 if (tutoriallevel != 1) {
3286 emit_sound_at(landsound2, victim->coords, 128.);
3288 victim->Puff(abdomen);
3289 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3297 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3298 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3306 if (tutoriallevel != 1) {
3307 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3309 if (creature == wolftype) {
3310 emit_sound_at(clawslicesound, victim->coords, 128);
3312 victim->DoBloodBig(2 / victim->armorhigh, 170);
3316 relative = victim->coords - oldcoords;
3318 Normalise(&relative);
3319 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3320 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3322 victim->jointVel(abdomen) += relative * damagemult * 200;
3323 victim->Puff(abdomen);
3324 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3326 award_bonus(id, Reversal);
3329 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3330 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3331 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3332 takeWeapon(victim->weaponids[victim->weaponactive]);
3333 victim->num_weapons--;
3334 if (victim->num_weapons > 0) {
3335 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3337 victim->weaponactive = -1;
3342 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3350 emit_sound_at(whooshhitsound, victim->coords, 128.);
3353 relative = victim->coords - oldcoords;
3355 Normalise(&relative);
3356 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3357 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3359 victim->jointVel(abdomen) += relative * damagemult * 200;
3361 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3364 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3373 award_bonus(id, staffreversebonus);
3375 if (tutoriallevel != 1) {
3376 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3379 award_bonus(id, staffreversebonus); // Huh, again?
3382 relative = victim->coords - oldcoords;
3384 Normalise(&relative);
3385 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3386 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3388 victim->jointVel(abdomen) += relative * damagemult * 200;
3390 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3393 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3399 Normalise(&relative);
3401 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3402 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3404 victim->jointVel(lefthand) *= .1;
3405 victim->jointVel(leftwrist) *= .2;
3406 victim->jointVel(leftelbow) *= .5;
3407 victim->jointVel(leftshoulder) *= .7;
3408 victim->jointVel(righthand) *= .1;
3409 victim->jointVel(rightwrist) *= .2;
3410 victim->jointVel(rightelbow) *= .5;
3411 victim->jointVel(rightshoulder) *= .7;
3413 victim->Puff(abdomen);
3414 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3416 award_bonus(id, Reversal);
3420 if (weaponactive != -1 || creature == wolftype)
3422 if (creature == rabbittype && weaponactive != -1)
3423 if (weapons[weaponids[0]].getType() == staff)
3426 if (weaponactive != -1) {
3427 victim->DoBloodBig(2 / victim->armorhigh, 225);
3428 emit_sound_at(knifeslicesound, victim->coords);
3429 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3430 weapons[weaponids[weaponactive]].bloody = 1;
3431 weapons[weaponids[weaponactive]].blooddrip += 3;
3433 if (weaponactive == -1 && creature == wolftype) {
3434 emit_sound_at(clawslicesound, victim->coords, 128.);
3436 victim->DoBloodBig(2 / victim->armorhigh, 175);
3443 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3449 Normalise(&relative);
3451 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3452 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3454 victim->jointVel(lefthand) *= .1 - 1;
3455 victim->jointVel(leftwrist) *= .2 - 1;
3456 victim->jointVel(leftelbow) *= .5 - 1;
3457 victim->jointVel(leftshoulder) *= .7 - 1;
3458 victim->jointVel(righthand) *= .1 - 1;
3459 victim->jointVel(rightwrist) *= .2 - 1;
3460 victim->jointVel(rightelbow) *= .5 - 1;
3461 victim->jointVel(rightshoulder) *= .7 - 1;
3463 award_bonus(id, swordreversebonus);
3466 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3474 if (tutoriallevel != 1) {
3475 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3479 relative = victim->coords - oldcoords;
3481 Normalise(&relative);
3482 relative = DoRotation(relative, 0, -90, 0);
3483 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3484 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3486 victim->jointVel(abdomen) += relative * damagemult * 200;
3487 victim->Puff(abdomen);
3488 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3490 award_bonus(id, Reversal);
3493 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3496 victim->skeleton.spinny = 0;
3498 relative = facing * -1;
3500 Normalise(&relative);
3501 if (victim->id == 0)
3503 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3504 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3506 victim->damage = victim->damagetolerance;
3507 victim->permanentdamage = victim->damagetolerance - 1;
3510 if (weaponactive != -1 || creature == wolftype)
3512 if (creature == rabbittype && weaponactive != -1)
3513 if (weapons[weaponids[0]].getType() == staff)
3516 if (weaponactive != -1) {
3517 victim->DoBloodBig(200, 225);
3518 emit_sound_at(knifeslicesound, victim->coords);
3520 weapons[weaponids[weaponactive]].bloody = 2;
3521 weapons[weaponids[weaponactive]].blooddrip += 5;
3524 if (creature == wolftype && weaponactive == -1) {
3525 emit_sound_at(clawslicesound, victim->coords, 128.);
3527 victim->DoBloodBig(2, 175);
3530 award_bonus(id, spinecrusher);
3533 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3534 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3536 if (animTarget == knifefollowanim)
3537 victim->DoBloodBig(200, 210);
3538 if (animTarget == knifesneakattackanim) {
3539 XYZ footvel, footpoint;
3541 footpoint = weapons[weaponids[0]].tippoint;
3543 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3544 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3545 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3546 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3547 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3548 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3549 victim->DoBloodBig(200, 195);
3550 award_bonus(id, tracheotomy);
3552 if (animTarget == knifefollowanim) {
3553 award_bonus(id, Stabbonus);
3554 XYZ footvel, footpoint;
3556 footpoint = weapons[weaponids[0]].tippoint;
3558 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3559 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3560 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3561 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3562 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3563 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3566 victim->bloodloss += 10000;
3567 victim->velocity = 0;
3568 emit_sound_at(fleshstabsound, victim->coords);
3570 weapons[weaponids[weaponactive]].bloody = 2;
3571 weapons[weaponids[weaponactive]].blooddrip += 5;
3575 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3577 victim->velocity = 0;
3578 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3579 victim->skeleton.joints[i].velocity = 0;
3581 if (animTarget == knifefollowanim) {
3583 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3584 victim->skeleton.joints[i].velocity = 0;
3587 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3588 emit_sound_at(fleshstabremovesound, victim->coords);
3590 weapons[weaponids[weaponactive]].bloody = 2;
3591 weapons[weaponids[weaponactive]].blooddrip += 5;
3593 XYZ footvel, footpoint;
3595 footpoint = weapons[weaponids[0]].tippoint;
3597 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3598 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3599 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3600 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3601 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3602 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3606 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3607 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3608 award_bonus(id, backstab);
3612 XYZ footvel, footpoint;
3614 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3616 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3617 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3618 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3619 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3620 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3621 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3622 victim->DoBloodBig(200, 180);
3623 victim->DoBloodBig(200, 215);
3624 victim->bloodloss += 10000;
3625 victim->velocity = 0;
3626 emit_sound_at(fleshstabsound, victim->coords);
3628 weapons[weaponids[weaponactive]].bloody = 2;
3629 weapons[weaponids[weaponactive]].blooddrip += 5;
3633 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3635 victim->velocity = 0;
3636 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3637 victim->skeleton.joints[i].velocity = 0;
3639 if (weaponactive != -1) {
3640 emit_sound_at(fleshstabremovesound, victim->coords);
3642 weapons[weaponids[weaponactive]].bloody = 2;
3643 weapons[weaponids[weaponactive]].blooddrip += 5;
3645 XYZ footvel, footpoint;
3647 footpoint = weapons[weaponids[0]].tippoint;
3649 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3650 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3651 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3652 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3653 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3654 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3658 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3666 if (weaponactive == -1) {
3667 if (tutoriallevel != 1) {
3668 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3673 if (weaponactive != -1 || creature == wolftype)
3675 if (creature == rabbittype && weaponactive != -1)
3676 if (weapons[weaponids[0]].getType() == staff)
3679 if (weaponactive != -1) {
3680 victim->DoBloodBig(2 / victim->armorhead, 225);
3681 emit_sound_at(knifeslicesound, victim->coords);
3682 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3683 weapons[weaponids[weaponactive]].bloody = 1;
3684 weapons[weaponids[weaponactive]].blooddrip += 3;
3686 if (weaponactive == -1 && creature == wolftype) {
3687 emit_sound_at(clawslicesound, victim->coords, 128.);
3689 victim->DoBloodBig(2 / victim->armorhead, 175);
3693 award_bonus(id, Reversal);
3698 relative = facing * -1;
3700 Normalise(&relative);
3701 relative = DoRotation(relative, 0, 90, 0);
3703 Normalise(&relative);
3704 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3705 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3707 victim->jointVel(head) += relative * damagemult * 200;
3708 if (victim->damage < victim->damagetolerance - 100)
3709 victim->velocity = relative * 200;
3710 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3711 victim->velocity = 0;
3714 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))) {
3718 relative = facing * -1;
3720 Normalise(&relative);
3721 relative = DoRotation(relative, 0, 90, 0);
3723 Normalise(&relative);
3724 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3725 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3727 victim->jointVel(head) += relative * damagemult * 200;
3730 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3731 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3732 award_bonus(id, reverseko);
3738 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3741 animTarget = getIdle();
3742 FootLand(leftfoot, 1);
3743 FootLand(rightfoot, 1);
3745 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3746 animTarget = rollanim;
3748 emit_sound_at(movewhooshsound, coords, 128.);
3750 if (animCurrent == staggerbackhighanim) {
3751 animTarget = getIdle();
3753 if (animCurrent == staggerbackhardanim) {
3754 animTarget = getIdle();
3756 if (animCurrent == removeknifeanim) {
3757 animTarget = getIdle();
3759 if (animCurrent == crouchremoveknifeanim) {
3760 animTarget = getCrouch();
3762 if (animCurrent == backhandspringanim) {
3763 animTarget = getIdle();
3765 if (animCurrent == dodgebackanim) {
3766 animTarget = getIdle();
3768 if (animCurrent == drawleftanim) {
3769 animTarget = getIdle();
3771 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3772 animTarget = getIdle();
3773 if (animCurrent == crouchdrawrightanim) {
3774 animTarget = getCrouch();
3776 if (weaponactive == -1)
3778 else if (weaponactive == 0) {
3780 if (num_weapons == 2) {
3782 buffer = weaponids[0];
3783 weaponids[0] = weaponids[1];
3784 weaponids[1] = buffer;
3788 if (weaponactive == -1) {
3789 emit_sound_at(knifesheathesound, coords, 128.);
3791 if (weaponactive != -1) {
3792 emit_sound_at(knifedrawsound, coords, 128.);
3795 if (animCurrent == rollanim) {
3796 animTarget = getCrouch();
3797 FootLand(leftfoot, 1);
3798 FootLand(rightfoot, 1);
3801 if (animTarget == walljumprightkickanim) {
3804 if (animTarget == walljumpleftkickanim) {
3807 animTarget = jumpdownanim;
3809 if (animCurrent == climbanim) {
3810 animTarget = getCrouch();
3812 coords += facing * .1;
3813 if (!isnormal(coords.x))
3824 if (animTarget == rabbitkickreversalanim) {
3825 animTarget = getCrouch();
3828 if (animTarget == jumpreversalanim) {
3829 animTarget = getCrouch();
3832 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3833 if (attackkeydown && animTarget != walljumpfrontanim) {
3835 float closestdist = -1;
3837 if (Person::players.size() > 1)
3838 for (unsigned i = 0; i < Person::players.size(); i++) {
3839 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3840 distance = distsq(&Person::players[i]->coords, &coords);
3841 if (closestdist == -1 || distance < closestdist) {
3842 closestdist = distance;
3847 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3848 victim = Person::players[closest];
3849 animTarget = walljumprightkickanim;
3851 XYZ rotatetarget = victim->coords - coords;
3852 Normalise(&rotatetarget);
3853 yaw = -asin(0 - rotatetarget.x);
3855 if (rotatetarget.z < 0)
3857 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3858 velocity = (victim->coords - coords) * 4;
3863 if (animTarget == walljumpbackanim) {
3864 animTarget = backflipanim;
3866 velocity = facing * -8;
3869 resume_stream(whooshsound);
3871 if (animTarget == walljumprightanim) {
3872 animTarget = rightflipanim;
3876 velocity = DoRotation(facing, 0, 30, 0) * -8;
3879 if (animTarget == walljumpfrontanim) {
3880 animTarget = frontflipanim;
3884 velocity = facing * 8;
3888 resume_stream(whooshsound);
3890 if (animTarget == walljumpleftanim) {
3891 if (attackkeydown) {
3893 float closestdist = -1;
3895 if (Person::players.size() > 1)
3896 for (unsigned i = 0; i < Person::players.size(); i++) {
3897 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3898 distance = distsq(&Person::players[i]->coords, &coords);
3899 if (closestdist == -1 || distance < closestdist) {
3900 closestdist = distance;
3905 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3906 victim = Person::players[closest];
3907 animTarget = walljumpleftkickanim;
3909 XYZ rotatetarget = victim->coords - coords;
3910 Normalise(&rotatetarget);
3911 yaw = -asin(0 - rotatetarget.x);
3913 if (rotatetarget.z < 0)
3915 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3916 velocity = (victim->coords - coords) * 4;
3921 if (animTarget != walljumpleftkickanim) {
3922 animTarget = leftflipanim;
3926 velocity = DoRotation(facing, 0, -30, 0) * -8;
3930 resume_stream(whooshsound);
3932 if (animTarget == sneakattackanim) {
3933 animCurrent = getCrouch();
3934 animTarget = getCrouch();
3941 transspeed = 1000000;
3942 targetheadyaw += 180;
3943 coords -= facing * .7;
3945 coords.y = terrain.getHeight(coords.x, coords.z);
3949 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3950 animTarget = getIdle();
3953 coords.y = terrain.getHeight(coords.x, coords.z);
3957 if (animCurrent == knifefollowanim) {
3958 animTarget = getIdle();
3961 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3962 float ycoords = oldcoords.y;
3963 animTarget = getStop();
3968 transspeed = 1000000;
3969 targetheadyaw += 180;
3970 if (!isnormal(coords.x))
3972 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3973 oldcoords = coords + facing * .5;
3974 else if (animCurrent == sweepreversalanim)
3975 oldcoords = coords + facing * 1.1;
3976 else if (animCurrent == upunchreversalanim) {
3977 oldcoords = coords + facing * 1.5;
3980 targetheadyaw += 180;
3983 } else if (animCurrent == knifeslashreversalanim) {
3984 oldcoords = coords + facing * .5;
3987 targetheadyaw += 90;
3990 } else if (animCurrent == staffspinhitreversalanim) {
3993 targetheadyaw += 180;
3998 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
4000 oldcoords.y = ycoords;
4001 currentoffset = coords - oldcoords;
4007 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4012 if (Animation::animations[animTarget].attack == reversed) {
4014 if (animTarget == sweepreversedanim)
4016 animTarget = backhandspringanim;
4018 emit_sound_at(landsound, coords, 128);
4020 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4021 animTarget = rollanim;
4024 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4025 coords.y = oldcoords.y;
4027 if (animCurrent == knifeslashreversedanim) {
4028 animTarget = rollanim;
4033 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4034 coords.y = oldcoords.y;
4038 animTarget = jumpdownanim;
4041 animTarget = getIdle();
4043 animTarget = getIdle();
4044 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4045 animTarget = getIdle();
4047 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4048 coords.y = oldcoords.y;
4049 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4050 targetoffset.y = coords.y;
4052 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4053 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4054 currentoffset.y -= (coords.y - targetoffset.y);
4055 coords.y = targetoffset.y;
4057 normalsupdatedelay = 0;
4059 if (animCurrent == upunchanim) {
4060 animTarget = getStop();
4061 normalsupdatedelay = 0;
4064 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4068 if (num_weapons > 0)
4069 if (weapons[0].getType() == staff)
4075 rabbitkickragdoll = 1;
4077 if (animCurrent == rabbitkickreversedanim) {
4083 skeleton.spinny = 0;
4084 SolidHitBonus(!id); // FIXME: tricky id
4088 animTarget = rollanim;
4091 pause_sound(whooshsound);
4095 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4099 skeleton.spinny = 0;
4101 if (animCurrent == jumpreversedanim) {
4107 skeleton.spinny = 0;
4108 SolidHitBonus(!id); // FIXME: tricky id
4112 animTarget = rollanim;
4113 coords += facing * 2;
4115 pause_sound(whooshsound);
4120 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) {
4121 animTarget = getupfromfrontanim;
4123 } else if (Animation::animations[animCurrent].attack == normalattack) {
4124 animTarget = getIdle();
4127 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4128 animTarget = blockhighleftstrikeanim;
4130 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4131 animTarget = getIdle();
4134 if (animCurrent == spinkickanim && victim->skeleton.free) {
4135 if (creature == rabbittype)
4136 animTarget = fightidleanim;
4141 if (isIdle() && !wasIdle())
4142 normalsupdatedelay = 0;
4144 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4145 animTarget = jumpdownanim;
4148 if (!skeleton.free) {
4150 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4151 if (!isRun() || !wasRun()) {
4152 if (targetFrame().speed > currentFrame().speed)
4153 target += multiplier * targetFrame().speed * speed * 2;
4154 if (targetFrame().speed <= currentFrame().speed)
4155 target += multiplier * currentFrame().speed * speed * 2;
4157 if (isRun() && wasRun()) {
4159 tempspeed = velspeed;
4160 if (tempspeed < 10 * speedmult)
4161 tempspeed = 10 * speedmult;
4162 /* FIXME - mixed of target and current here, is that intended? */
4163 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4165 } else if (transspeed)
4166 target += multiplier * transspeed * speed * 2;
4168 if (!isRun() || !wasRun()) {
4169 if (targetFrame().speed > currentFrame().speed)
4170 target += multiplier * targetFrame().speed * 2;
4171 if (targetFrame().speed <= currentFrame().speed)
4172 target += multiplier * currentFrame().speed * 2;
4176 if (animCurrent != animTarget)
4177 target = (target + oldtarget) / 2;
4180 frameCurrent = frameTarget;
4184 rot = targetrot * target;
4185 yaw += rot - oldrot;
4191 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4192 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4194 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4196 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4197 skeleton.joints[i].position = currentFrame().joints[i].position;
4200 skeleton.FindForwards();
4202 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4203 if (skeleton.muscles[i].visible) {
4204 skeleton.FindRotationMuscle(i, animTarget);
4207 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4208 if (skeleton.muscles[i].visible) {
4209 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4210 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4211 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4212 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4213 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4214 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4219 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4220 skeleton.joints[i].position = targetFrame().joints[i].position;
4223 skeleton.FindForwards();
4225 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4226 if (skeleton.muscles[i].visible) {
4227 skeleton.FindRotationMuscle(i, animTarget);
4230 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4231 if (skeleton.muscles[i].visible) {
4232 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4233 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4234 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4235 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4236 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4237 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4238 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4239 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4240 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4241 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4242 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4243 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4248 oldanimCurrent = animCurrent;
4249 oldanimTarget = animTarget;
4250 oldframeTarget = frameTarget;
4251 oldframeCurrent = frameCurrent;
4253 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4254 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4255 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4257 offset = currentoffset * (1 - target) + targetoffset * target;
4258 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4259 if (skeleton.muscles[i].visible) {
4260 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4261 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4262 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4267 if (isLanding() && landhard) {
4270 animTarget = getLandhard();
4283 void Person::DoStuff()
4285 static XYZ terrainnormal;
4286 static XYZ flatfacing;
4287 static XYZ flatvelocity;
4288 static float flatvelspeed;
4292 static int bloodsize;
4293 static int startx, starty, endx, endy;
4294 static GLubyte color;
4295 static XYZ bloodvel;
4297 onfiredelay -= multiplier;
4298 if (onfiredelay < 0 && onfire) {
4299 if (Random() % 2 == 0) {
4305 crouchkeydowntime += multiplier;
4307 crouchkeydowntime = 0;
4308 jumpkeydowntime += multiplier;
4309 if (!jumpkeydown && skeleton.free)
4310 jumpkeydowntime = 0;
4312 if (hostile || damage > 0 || bloodloss > 0)
4315 if (isIdle() || isRun())
4318 if (num_weapons == 1 && weaponactive != -1)
4322 blooddimamount -= multiplier * .3;
4323 speechdelay -= multiplier;
4324 texupdatedelay -= multiplier;
4325 interestdelay -= multiplier;
4326 flamedelay -= multiplier;
4327 parriedrecently -= multiplier;
4329 victim = this->shared_from_this();
4334 speed = 1.1 * speedmult;
4336 speed = 1.0 * speedmult;
4338 rabbitkickragdoll = 0;
4342 if (id != 0 && (creature == rabbittype || difficulty != 2))
4344 if (id != 0 && creature == wolftype && difficulty == 2) {
4346 if (aitype != passivetype) {
4348 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) {
4354 if (animTarget == wolfrunninganim && !superruntoggle) {
4355 animTarget = getRun();
4359 if (weaponactive == -1 && num_weapons > 0) {
4360 if (weapons[weaponids[0]].getType() == staff) {
4366 burnt += multiplier;
4370 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4372 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4378 vel[0] = velocity.x;
4379 vel[1] = velocity.y;
4380 vel[2] = velocity.z;
4383 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4384 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4388 while (flamedelay < 0 && onfire) {
4390 howmany = fabs(Random() % (skeleton.joints.size()));
4391 if (skeleton.free) {
4392 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4393 flatfacing = skeleton.joints[howmany].position * scale + coords;
4395 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4396 flatvelocity = (coords - oldcoords) / multiplier / 2;
4398 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4401 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4403 howmany = fabs(Random() % (skeleton.joints.size()));
4404 if (skeleton.free) {
4405 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4406 flatfacing = skeleton.joints[howmany].position * scale + coords;
4408 flatvelocity = (coords - oldcoords) / multiplier / 2;
4409 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4411 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4415 bleeding -= multiplier * .3;
4416 if (bloodtoggle == 2) {
4417 skeleton.drawmodel.textureptr.bind();
4418 if ((bleeding <= 0) && (detail != 2))
4423 if (neckspurtamount > 0) {
4424 neckspurtamount -= multiplier;
4425 neckspurtdelay -= multiplier * 3;
4426 neckspurtparticledelay -= multiplier * 3;
4427 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4430 if (skeleton.free) {
4431 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4432 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4433 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4435 bloodvel.z = 5 * neckspurtamount;
4436 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4437 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4438 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4440 neckspurtparticledelay = .05;
4442 if (neckspurtdelay < 0) {
4447 if (deathbleeding > 0 && dead != 2) {
4448 if (deathbleeding < 5)
4449 bleeddelay -= deathbleeding * multiplier / 4;
4451 bleeddelay -= 5 * multiplier / 4;
4452 if (bleeddelay < 0 && bloodtoggle) {
4457 if (skeleton.free) {
4458 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4459 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4461 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4462 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4466 bloodloss += deathbleeding * multiplier * 80;
4467 deathbleeding -= multiplier * 1.6;
4468 if (deathbleeding < 0)
4470 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4471 if (weaponactive != -1) {
4472 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4473 weapons[weaponids[0]].velocity.x += .01;
4476 weaponids[0] = weaponids[num_weapons];
4477 if (weaponstuck == num_weapons)
4481 for (unsigned i = 0; i < Person::players.size(); i++) {
4482 Person::players[i]->wentforweapon = 0;
4490 if (!dead && creature == wolftype) {
4491 award_bonus(0, Wolfbonus);
4494 if (animTarget == knifefollowedanim && !skeleton.free) {
4495 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4496 skeleton.joints[i].velocity = 0;
4497 skeleton.joints[i].velocity.y = -2;
4500 if (id != 0 && unconscioustime > .1) {
4508 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4509 texupdatedelay = .12;
4511 bloodsize = 5 - realtexdetail;
4515 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4516 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4517 endx = startx + bloodsize;
4518 endy = starty + bloodsize;
4528 if (endx > skeleton.skinsize - 1) {
4529 endx = skeleton.skinsize - 1;
4532 if (endy > skeleton.skinsize - 1) {
4533 endy = skeleton.skinsize - 1;
4541 for (i = startx; i < endx; i++) {
4542 for (int j = starty; j < endy; j++) {
4543 if (Random() % 2 == 0) {
4544 color = Random() % 85 + 170;
4545 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4546 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4547 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4548 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4553 skeleton.drawmodel.textureptr.bind();
4557 if (skeleton.free) {
4558 bleedx += 4 * direction / realtexdetail;
4560 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4562 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4564 bleedy -= 4 / realtexdetail;
4566 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4568 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4572 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4573 righthandmorphness = targetrighthandmorphness;
4574 righthandmorphstart = righthandmorphend;
4575 } else if (righthandmorphness > targetrighthandmorphness) {
4576 righthandmorphness -= multiplier * 4;
4577 } else if (righthandmorphness < targetrighthandmorphness) {
4578 righthandmorphness += multiplier * 4;
4581 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4582 lefthandmorphness = targetlefthandmorphness;
4583 lefthandmorphstart = lefthandmorphend;
4584 } else if (lefthandmorphness > targetlefthandmorphness) {
4585 lefthandmorphness -= multiplier * 4;
4586 } else if (lefthandmorphness < targetlefthandmorphness) {
4587 lefthandmorphness += multiplier * 4;
4590 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4591 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4592 tailmorphness = targettailmorphness;
4593 tailmorphstart = tailmorphend;
4594 } else if (tailmorphness > targettailmorphness) {
4595 tailmorphness -= multiplier * 10;
4596 } else if (tailmorphness < targettailmorphness) {
4597 tailmorphness += multiplier * 10;
4601 if (creature == wolftype) {
4602 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4603 tailmorphness = targettailmorphness;
4604 tailmorphstart = tailmorphend;
4605 } else if (tailmorphness > targettailmorphness) {
4606 tailmorphness -= multiplier * 2;
4607 } else if (tailmorphness < targettailmorphness) {
4608 tailmorphness += multiplier * 2;
4612 if (headmorphend == 3 || headmorphstart == 3) {
4613 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4614 headmorphness = targetheadmorphness;
4615 headmorphstart = headmorphend;
4616 } else if (headmorphness > targetheadmorphness) {
4617 headmorphness -= multiplier * 7;
4618 } else if (headmorphness < targetheadmorphness) {
4619 headmorphness += multiplier * 7;
4621 } else if (headmorphend == 5 || headmorphstart == 5) {
4622 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4623 headmorphness = targetheadmorphness;
4624 headmorphstart = headmorphend;
4625 } else if (headmorphness > targetheadmorphness) {
4626 headmorphness -= multiplier * 10;
4627 } else if (headmorphness < targetheadmorphness) {
4628 headmorphness += multiplier * 10;
4631 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4632 headmorphness = targetheadmorphness;
4633 headmorphstart = headmorphend;
4634 } else if (headmorphness > targetheadmorphness) {
4635 headmorphness -= multiplier * 4;
4636 } else if (headmorphness < targetheadmorphness) {
4637 headmorphness += multiplier * 4;
4641 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4642 chestmorphness = targetchestmorphness;
4643 chestmorphstart = chestmorphend;
4644 } else if (chestmorphness > targetchestmorphness) {
4645 chestmorphness -= multiplier;
4646 } else if (chestmorphness < targetchestmorphness) {
4647 chestmorphness += multiplier;
4650 if (dead != 2 && howactive <= typesleeping) {
4651 if (chestmorphstart == 0 && chestmorphend == 0) {
4653 targetchestmorphness = 1;
4656 if (chestmorphstart != 0 && chestmorphend != 0) {
4658 targetchestmorphness = 1;
4660 if (environment == snowyenvironment) {
4663 if (skeleton.free) {
4664 footvel = skeleton.specialforward[0] * -1;
4665 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4667 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4668 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4670 if (animTarget == sleepanim)
4671 footvel = DoRotation(footvel, 0, 90, 0);
4672 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4676 if (!dead && howactive < typesleeping) {
4677 blinkdelay -= multiplier * 2;
4678 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4680 targetheadmorphness = 1;
4682 blinkdelay = (float)(abs(Random() % 40)) / 5;
4684 if (headmorphstart == 3 && headmorphend == 3) {
4686 targetheadmorphness = 1;
4691 twitchdelay -= multiplier * 1.5;
4692 if (animTarget != hurtidleanim) {
4693 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4695 targetheadmorphness = 1;
4697 twitchdelay = (float)(abs(Random() % 40)) / 5;
4699 if (headmorphstart == 5 && headmorphend == 5) {
4701 targetheadmorphness = 1;
4705 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4706 twitchdelay3 -= multiplier * 1;
4707 if (Random() % 2 == 0) {
4708 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4709 righthandmorphness = 0;
4710 targetrighthandmorphness = 1;
4711 righthandmorphend = 1;
4712 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4714 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4715 righthandmorphness = 0;
4716 targetrighthandmorphness = 1;
4717 righthandmorphend = 0;
4720 if (Random() % 2 == 0) {
4721 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4722 lefthandmorphness = 0;
4723 targetlefthandmorphness = 1;
4724 lefthandmorphend = 1;
4725 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4727 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4728 lefthandmorphness = 0;
4729 targetlefthandmorphness = 1;
4730 lefthandmorphend = 0;
4736 if (creature == rabbittype) {
4737 if (howactive < typesleeping)
4738 twitchdelay2 -= multiplier * 1.5;
4740 twitchdelay2 -= multiplier * 0.5;
4741 if (howactive <= typesleeping) {
4742 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4744 targettailmorphness = 1;
4746 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4748 if (tailmorphstart == 1 && tailmorphend == 1) {
4750 targettailmorphness = 1;
4753 if (tailmorphstart == 2 && tailmorphend == 2) {
4755 targettailmorphness = 1;
4762 if (creature == wolftype) {
4763 twitchdelay2 -= multiplier * 1.5;
4764 if (tailmorphend != 0)
4765 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4767 targettailmorphness = 1;
4771 if (tailmorphend != 5)
4772 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4774 targettailmorphness = 1;
4778 if (twitchdelay2 <= 0) {
4779 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4781 targettailmorphness = 1;
4784 if (tailmorphstart == 1 && tailmorphend == 1) {
4786 targettailmorphness = 1;
4789 if (tailmorphstart == 2 && tailmorphend == 2) {
4791 targettailmorphness = 1;
4794 if (tailmorphstart == 3 && tailmorphend == 3) {
4796 targettailmorphness = 1;
4799 if (tailmorphstart == 4 && tailmorphend == 4) {
4801 targettailmorphness = 1;
4808 unconscioustime = 0;
4810 if (dead == 1 || howactive == typesleeping) {
4811 unconscioustime += multiplier;
4812 //If unconscious, close eyes and mouth
4813 if (righthandmorphend != 0)
4814 righthandmorphness = 0;
4815 righthandmorphend = 0;
4816 targetrighthandmorphness = 1;
4818 if (lefthandmorphend != 0)
4819 lefthandmorphness = 0;
4820 lefthandmorphend = 0;
4821 targetlefthandmorphness = 1;
4823 if (headmorphend != 3 && headmorphend != 5)
4826 targetheadmorphness = 1;
4830 if (howactive > typesleeping) {
4833 if (bloodtoggle && !bled) {
4834 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4836 if (bloodtoggle && !bled)
4837 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4838 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4839 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4843 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4848 if (dead == 2 || howactive > typesleeping) {
4849 //If dead, open mouth and hands
4850 if (righthandmorphend != 0)
4851 righthandmorphness = 0;
4852 righthandmorphend = 0;
4853 targetrighthandmorphness = 1;
4855 if (lefthandmorphend != 0)
4856 lefthandmorphness = 0;
4857 lefthandmorphend = 0;
4858 targetlefthandmorphness = 1;
4860 if (headmorphend != 2)
4863 targetheadmorphness = 1;
4866 if (stunned > 0 && !dead && headmorphend != 2) {
4867 if (headmorphend != 4)
4870 targetheadmorphness = 1;
4873 if (damage > damagetolerance && !dead) {
4876 unconscioustime = 0;
4878 if (creature == wolftype) {
4879 award_bonus(0, Wolfbonus);
4884 if (weaponactive != -1) {
4885 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4886 weapons[weaponids[0]].velocity.x += .01;
4889 weaponids[0] = weaponids[num_weapons];
4890 if (weaponstuck == num_weapons)
4894 for (unsigned i = 0; i < Person::players.size(); i++) {
4895 Person::players[i]->wentforweapon = 0;
4901 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4910 damage -= multiplier * 13;
4912 permanentdamage -= multiplier * 4;
4913 if (isIdle() || isCrouch()) {
4915 permanentdamage -= multiplier * 4;
4919 if (permanentdamage < 0)
4920 permanentdamage = 0;
4921 if (superpermanentdamage < 0)
4922 superpermanentdamage = 0;
4923 if (permanentdamage < superpermanentdamage) {
4924 permanentdamage = superpermanentdamage;
4926 if (damage < permanentdamage) {
4927 damage = permanentdamage;
4929 if (dead == 1 && damage < damagetolerance) {
4933 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4934 skeleton.joints[i].velocity = 0;
4937 if (permanentdamage > damagetolerance && dead != 2) {
4940 if (weaponactive != -1) {
4941 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4942 weapons[weaponids[0]].velocity.x += .01;
4945 weaponids[0] = weaponids[num_weapons];
4946 if (weaponstuck == num_weapons)
4950 for (unsigned i = 0; i < Person::players.size(); i++) {
4951 Person::players[i]->wentforweapon = 0;
4957 if (!dead && creature == wolftype) {
4958 award_bonus(0, Wolfbonus);
4961 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4962 award_bonus(id, touchofdeath);
4963 if (id != 0 && unconscioustime > .1) {
4971 emit_sound_at(breaksound, coords);
4974 if (skeleton.free == 1) {
4976 pause_sound(whooshsound);
4979 //If knocked over, open hands and close mouth
4980 if (righthandmorphend != 0)
4981 righthandmorphness = 0;
4982 righthandmorphend = 0;
4983 targetrighthandmorphness = 1;
4985 if (lefthandmorphend != 0)
4986 lefthandmorphness = 0;
4987 lefthandmorphend = 0;
4988 targetlefthandmorphness = 1;
4990 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4991 if (headmorphend != 0)
4994 targetheadmorphness = 1;
4998 skeleton.DoGravity(&scale);
5000 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
5001 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
5002 award_bonus(id, deepimpact);
5003 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5007 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5008 average += skeleton.joints[j].position;
5012 coords += average * scale;
5013 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5014 skeleton.joints[j].position -= average;
5016 average /= multiplier;
5019 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5020 velocity += skeleton.joints[i].velocity * scale;
5022 velocity /= skeleton.joints.size();
5024 if (!isnormal(velocity.x) && velocity.x) {
5028 if (findLength(&average) < 10 && dead && skeleton.free) {
5029 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5030 if (skeleton.longdead > 2000) {
5031 if (skeleton.longdead > 6000) {
5033 pause_sound(whooshsound);
5038 if (dead == 2 && bloodloss < damagetolerance) {
5040 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5042 if (bloodtoggle && !bled) {
5043 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5045 if (bloodtoggle && !bled)
5046 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5047 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5048 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5049 float size = .2 * 1.2;
5052 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5056 if (dead == 2 && bloodloss >= damagetolerance) {
5058 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5061 if (bloodtoggle && !bled) {
5062 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5064 if (bloodtoggle && !bled)
5065 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5066 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5067 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5071 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5078 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5079 bool canrecover = 1;
5080 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5081 startpoint = coords;
5084 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5086 if (velocity.y < -30)
5088 for (i = 0; i < objects.numobjects; i++) {
5089 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5090 colviewer = startpoint;
5091 coltarget = endpoint;
5092 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5101 terrainnormal = jointPos(groin) - jointPos(abdomen);
5102 if (joint(groin).locked && joint(abdomen).locked) {
5103 terrainnormal = jointPos(groin) - jointPos(abdomen);
5104 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5106 if (joint(abdomen).locked && joint(neck).locked) {
5107 terrainnormal = jointPos(abdomen) - jointPos(neck);
5108 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5110 if (joint(groin).locked && joint(neck).locked) {
5111 terrainnormal = jointPos(groin) - jointPos(neck);
5112 middle = (jointPos(groin) + jointPos(neck)) / 2;
5114 Normalise(&terrainnormal);
5116 targetyaw = -asin(0 - terrainnormal.x);
5117 targetyaw *= 360 / 6.28;
5118 if (terrainnormal.z < 0)
5119 targetyaw = 180 - targetyaw;
5123 animTarget = flipanim;
5124 crouchtogglekeydown = 1;
5129 animCurrent = tempanim;
5133 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5134 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5135 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5140 if (findLength(&average) < 10 && !dead && skeleton.free) {
5141 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5142 if (skeleton.longdead > (damage + 500) * 1.5) {
5144 pause_sound(whooshsound);
5150 terrainnormal = jointPos(groin) - jointPos(abdomen);
5151 if (joint(groin).locked && joint(abdomen).locked) {
5152 terrainnormal = jointPos(groin) - jointPos(abdomen);
5153 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5155 if (joint(abdomen).locked && joint(neck).locked) {
5156 terrainnormal = jointPos(abdomen) - jointPos(neck);
5157 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5159 if (joint(groin).locked && joint(neck).locked) {
5160 terrainnormal = jointPos(groin) - jointPos(neck);
5161 middle = (jointPos(groin) + jointPos(neck)) / 2;
5163 Normalise(&terrainnormal);
5165 targetyaw = -asin(0 - terrainnormal.x);
5166 targetyaw *= 360 / 6.28;
5167 if (terrainnormal.z < 0)
5168 targetyaw = 180 - targetyaw;
5171 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5174 if (skeleton.forward.y < 0) {
5175 animTarget = getupfrombackanim;
5179 if (skeleton.forward.y > -.3) {
5180 animTarget = getupfromfrontanim;
5188 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5189 animTarget = rollanim;
5190 targetyaw = lookyaw;
5207 if ( !leftkeydown && !rightkeydown)
5214 if (abs(targettilt2) > 50)
5216 animCurrent = tempanim;
5219 tilt2 = targettilt2;
5221 if (middle.y > 0 && animTarget != rollanim)
5222 targetoffset.y = middle.y + 1;
5224 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5225 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5226 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5233 if (num_weapons > 0)
5234 if (weapons[0].getType() == staff)
5236 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5237 if (velocity.y > -30) {
5239 tempvelocity = velocity;
5240 Normalise(&tempvelocity);
5241 targetyaw = -asin(0 - tempvelocity.x);
5242 targetyaw *= 360 / 6.28;
5244 targetyaw = 180 - targetyaw;
5248 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5249 animTarget = rollanim;
5252 animTarget = backhandspringanim;
5258 emit_sound_at(movewhooshsound, coords, 128.);
5260 animCurrent = animTarget;
5261 frameCurrent = frameTarget - 1;
5273 if (skeleton.freefall == 0)
5278 if (aitype != passivetype || skeleton.free == 1)
5279 if (findLengthfast(&velocity) > .1)
5280 for (i = 0; i < objects.numobjects; i++) {
5281 if (objects.type[i] == firetype)
5282 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) {
5284 if (!objects.onfire[i]) {
5285 emit_sound_at(firestartsound, objects.position[i]);
5287 objects.onfire[i] = 1;
5290 if (objects.onfire[i]) {
5295 if (objects.type[i] == bushtype)
5296 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) {
5298 if (!objects.onfire[i]) {
5299 emit_sound_at(firestartsound, objects.position[i]);
5301 objects.onfire[i] = 1;
5305 if (objects.onfire[i]) {
5309 if (objects.messedwith[i] <= 0) {
5313 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5316 addEnvSound(coords, 4 * findLength(&velocity));
5320 if (environment == grassyenvironment)
5321 howmany = findLength(&velocity) * 4;
5322 if (environment == snowyenvironment)
5323 howmany = findLength(&velocity) * 2;
5325 if (environment != desertenvironment)
5326 for (int j = 0; j < howmany; j++) {
5327 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5328 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5329 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5332 pos.x += float(abs(Random() % 100) - 50) / 200;
5333 pos.y += float(abs(Random() % 100) - 50) / 200;
5334 pos.z += float(abs(Random() % 100) - 50) / 200;
5335 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);
5336 Sprite::setLastSpriteSpecial(1);
5338 howmany = findLength(&velocity) * 4;
5340 if (environment == snowyenvironment)
5341 for (int j = 0; j < howmany; j++) {
5342 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5343 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5344 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5347 pos.x += float(abs(Random() % 100) - 50) / 200;
5348 pos.y += float(abs(Random() % 100) - 50) / 200;
5349 pos.z += float(abs(Random() % 100) - 50) / 200;
5350 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5351 Sprite::setLastSpriteSpecial(2);
5354 objects.rotx[i] += velocity.x * multiplier * 6;
5355 objects.roty[i] += velocity.z * multiplier * 6;
5356 objects.messedwith[i] = .5;
5359 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5360 if (objects.pitch[i] == 0)
5363 tempcoord = coords - objects.position[i];
5364 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5365 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5366 tempcoord += objects.position[i];
5368 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]) {
5369 if (objects.messedwith[i] <= 0) {
5373 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5376 addEnvSound(coords, 4 * findLength(&velocity));
5380 if (environment == grassyenvironment)
5381 howmany = findLength(&velocity) * 4;
5382 if (environment == snowyenvironment)
5383 howmany = findLength(&velocity) * 2;
5385 if (environment != desertenvironment)
5386 for (int j = 0; j < howmany; j++) {
5387 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5388 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5389 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5391 pos += velocity * .1;
5393 pos.x += float(abs(Random() % 100) - 50) / 150;
5394 pos.y += float(abs(Random() % 100) - 50) / 150;
5395 pos.z += float(abs(Random() % 100) - 50) / 150;
5396 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);
5397 Sprite::setLastSpriteSpecial(1);
5399 howmany = findLength(&velocity) * 4;
5401 if (environment == snowyenvironment)
5402 for (int j = 0; j < howmany; j++) {
5403 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5404 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5405 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5407 pos += velocity * .1;
5409 pos.x += float(abs(Random() % 100) - 50) / 150;
5410 pos.y += float(abs(Random() % 100) - 50) / 150;
5411 pos.z += float(abs(Random() % 100) - 50) / 150;
5412 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5413 Sprite::setLastSpriteSpecial(2);
5416 objects.messedwith[i] = .5;
5421 if (!skeleton.free) {
5424 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5427 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5429 if (tutoriallevel == 1 && id != 0)
5431 if (play && aitype != playercontrolled) {
5432 int whichsound = -1;
5433 i = abs(Random() % 4);
5434 if (speechdelay <= 0) {
5435 if (creature == rabbittype) {
5437 whichsound = rabbitchitter;
5439 whichsound = rabbitchitter2;
5441 if (creature == wolftype) {
5443 whichsound = growlsound;
5445 whichsound = growl2sound;
5450 if (whichsound != -1) {
5451 emit_sound_at(whichsound, coords);
5455 if (animTarget == staggerbackhighanim)
5457 if (animTarget == staggerbackhardanim)
5459 staggerdelay -= multiplier;
5460 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5462 if (velocity.y < -30 && animTarget == jumpdownanim)
5464 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5465 animTarget = getIdle();
5469 weaponmissdelay -= multiplier;
5470 highreversaldelay -= multiplier;
5471 lowreversaldelay -= multiplier;
5472 lastcollide -= multiplier;
5473 skiddelay -= multiplier;
5474 if (!isnormal(velocity.x) && velocity.x) {
5477 if (!isnormal(targettilt) && targettilt) {
5480 if (!isnormal(targettilt2) && targettilt2) {
5483 if (!isnormal(targetyaw) && targetyaw) {
5487 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5488 //open hands and close mouth
5489 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5490 righthandmorphness = 0;
5491 righthandmorphend = 0;
5492 targetrighthandmorphness = 1;
5495 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5496 lefthandmorphness = 0;
5497 lefthandmorphend = 0;
5498 targetlefthandmorphness = 1;
5501 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5504 targetheadmorphness = 1;
5508 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) {
5509 //open hands and mouth
5510 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5511 righthandmorphness = 0;
5512 righthandmorphend = 0;
5513 targetrighthandmorphness = 1;
5516 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5517 lefthandmorphness = 0;
5518 lefthandmorphend = 0;
5519 targetlefthandmorphness = 1;
5522 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5525 targetheadmorphness = 1;
5529 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5530 //close hands and mouth
5531 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5532 righthandmorphness = 0;
5533 righthandmorphend = 1;
5534 targetrighthandmorphness = 1;
5537 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5538 lefthandmorphness = 0;
5539 lefthandmorphend = 1;
5540 targetlefthandmorphness = 1;
5543 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5546 targetheadmorphness = 1;
5550 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) {
5551 //close hands and yell
5552 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5553 righthandmorphness = 0;
5554 righthandmorphend = 1;
5555 targetrighthandmorphness = 1;
5558 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5559 lefthandmorphness = 0;
5560 lefthandmorphend = 1;
5561 targetlefthandmorphness = 1;
5564 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5567 targetheadmorphness = 1;
5574 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5575 (victim->aitype != searchtype) && (aitype != passivetype) &&
5576 (aitype != searchtype) && (victim->id < Person::players.size())) {
5577 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5581 if (!dead && animTarget != hurtidleanim)
5582 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5583 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5586 targetheadmorphness = 1;
5590 if (weaponactive != -1) {
5591 if (weapons[weaponids[weaponactive]].getType() != staff) {
5592 righthandmorphstart = 1;
5593 righthandmorphend = 1;
5595 if (weapons[weaponids[weaponactive]].getType() == staff) {
5596 righthandmorphstart = 2;
5597 righthandmorphend = 2;
5599 targetrighthandmorphness = 1;
5602 terrainnormal = terrain.getNormal(coords.x, coords.z);
5604 if (Animation::animations[animTarget].attack != reversal) {
5605 if (!isnormal(coords.x))
5613 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5614 facing = flatfacing;
5615 ReflectVector(&facing, terrainnormal);
5618 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5620 targettilt2 = -facing.y * 20;
5625 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5627 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5628 flatvelocity = velocity;
5630 flatvelspeed = findLength(&flatvelocity);
5631 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5632 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5637 if (targettilt > 25)
5639 if (targettilt < -25)
5643 if (targettilt2 > 45)
5645 if (targettilt2 < -45)
5647 if (abs(tilt2 - targettilt2) < multiplier * 400)
5648 tilt2 = targettilt2;
5649 else if (tilt2 > targettilt2) {
5650 tilt2 -= multiplier * 400;
5651 } else if (tilt2 < targettilt2) {
5652 tilt2 += multiplier * 400;
5654 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5661 if (!isnormal(targettilt) && targettilt) {
5664 if (!isnormal(targettilt2) && targettilt2) {
5669 if (animTarget == rabbittackleanim) {
5670 velocity += facing * multiplier * speed * 700 * scale;
5671 velspeed = findLength(&velocity);
5672 if (velspeed > speed * 65 * scale) {
5673 velocity /= velspeed;
5674 velspeed = speed * 65 * scale;
5675 velocity *= velspeed;
5677 velocity.y += gravity * multiplier * 20;
5678 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5679 velspeed = findLength(&velocity);
5680 velocity = flatfacing * velspeed;
5682 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5683 if (isRun() || animTarget == rabbitkickanim) {
5684 velocity += facing * multiplier * speed * 700 * scale;
5685 velspeed = findLength(&velocity);
5686 if (velspeed > speed * 45 * scale) {
5687 velocity /= velspeed;
5688 velspeed = speed * 45 * scale;
5689 velocity *= velspeed;
5691 velocity.y += gravity * multiplier * 20;
5692 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5693 velspeed = findLength(&velocity);
5694 if (velspeed < speed * 30 * scale)
5695 velspeed = speed * 30 * scale;
5696 velocity = flatfacing * velspeed;
5698 } else if (isRun()) {
5699 velocity += facing * multiplier * speed * 700 * scale;
5700 velspeed = findLength(&velocity);
5701 if (creature == rabbittype) {
5702 if (velspeed > speed * 55 * scale) {
5703 velocity /= velspeed;
5704 velspeed = speed * 55 * scale;
5705 velocity *= velspeed;
5708 if (creature == wolftype) {
5709 if (velspeed > speed * 75 * scale) {
5710 velocity /= velspeed;
5711 velspeed = speed * 75 * scale;
5712 velocity *= velspeed;
5715 velocity.y += gravity * multiplier * 20;
5716 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5717 velspeed = findLength(&velocity);
5718 velocity = flatfacing * velspeed;
5721 if (animTarget == rollanim && targetFrame().label != 6) {
5722 velocity += facing * multiplier * speed * 700 * scale;
5723 velspeed = findLength(&velocity);
5724 if (velspeed > speed * 45 * scale) {
5725 velocity /= velspeed;
5726 velspeed = speed * 45 * scale;
5727 velocity *= velspeed;
5729 velocity.y += gravity * multiplier * 20;
5730 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5731 velspeed = findLength(&velocity);
5732 velocity = flatfacing * velspeed;
5735 if (animTarget == sneakanim || animTarget == walkanim) {
5736 velocity += facing * multiplier * speed * 700 * scale;
5737 velspeed = findLength(&velocity);
5738 if (velspeed > speed * 12 * scale) {
5739 velocity /= velspeed;
5740 velspeed = speed * 12 * scale;
5741 velocity *= velspeed;
5743 velocity.y += gravity * multiplier * 20;
5744 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5745 velspeed = findLength(&velocity);
5746 velocity = flatfacing * velspeed;
5749 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5750 velocity += facing * multiplier * speed * 700 * scale;
5751 velspeed = findLength(&velocity);
5752 if (velspeed > speed * 2 * scale) {
5753 velocity /= velspeed;
5754 velspeed = speed * 2 * scale;
5755 velocity *= velspeed;
5757 velocity.y += gravity * multiplier * 20;
5758 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5759 velspeed = findLength(&velocity);
5760 velocity = flatfacing * velspeed;
5764 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5765 velocity -= facing * multiplier * speed * 700 * scale;
5766 velspeed = findLength(&velocity);
5767 if (velspeed > speed * 2 * scale) {
5768 velocity /= velspeed;
5769 velspeed = speed * 2 * scale;
5770 velocity *= velspeed;
5772 velocity.y += gravity * multiplier * 20;
5773 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5774 velspeed = findLength(&velocity);
5775 velocity = flatfacing * velspeed * -1;
5778 if (animTarget == fightsidestep) {
5779 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5780 velspeed = findLength(&velocity);
5781 if (velspeed > speed * 12 * scale) {
5782 velocity /= velspeed;
5783 velspeed = speed * 12 * scale;
5784 velocity *= velspeed;
5786 velocity.y += gravity * multiplier * 20;
5787 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5788 velspeed = findLength(&velocity);
5789 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5792 if (animTarget == staggerbackhighanim) {
5793 coords -= facing * multiplier * speed * 16 * scale;
5796 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5797 coords -= facing * multiplier * speed * 20 * scale;
5801 if (animTarget == backhandspringanim) {
5802 //coords-=facing*multiplier*50*scale;
5803 velocity += facing * multiplier * speed * 700 * scale * -1;
5804 velspeed = findLength(&velocity);
5805 if (velspeed > speed * 50 * scale) {
5806 velocity /= velspeed;
5807 velspeed = speed * 50 * scale;
5808 velocity *= velspeed;
5810 velocity.y += gravity * multiplier * 20;
5811 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5812 velspeed = findLength(&velocity);
5813 velocity = flatfacing * velspeed * -1;
5815 if (animTarget == dodgebackanim) {
5816 //coords-=facing*multiplier*50*scale;
5817 velocity += facing * multiplier * speed * 700 * scale * -1;
5818 velspeed = findLength(&velocity);
5819 if (velspeed > speed * 60 * scale) {
5820 velocity /= velspeed;
5821 velspeed = speed * 60 * scale;
5822 velocity *= velspeed;
5824 velocity.y += gravity * multiplier * 20;
5825 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5826 velspeed = findLength(&velocity);
5827 velocity = flatfacing * velspeed * -1;
5830 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5831 velspeed = findLength(&velocity);
5835 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5836 velocity.y += gravity * multiplier;
5839 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5840 coords += velocity * multiplier;
5842 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5843 if (isFlip() && targetFrame().label == 7)
5846 if (animTarget == jumpupanim) {
5848 animTarget = getIdle();
5855 pause_sound(whooshsound);
5856 OPENAL_SetVolume(channels[whooshsound], 0);
5859 if (animTarget == jumpdownanim || isFlip()) {
5860 if (isFlip())jumppower = -4;
5861 animTarget = getLanding();
5862 emit_sound_at(landsound, coords, 128.);
5865 addEnvSound(coords);
5870 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5871 coords.y += gravity * multiplier * 2;
5872 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5873 coords.y = terrain.getHeight(coords.x, coords.z);
5878 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)) {
5879 velspeed = findLength(&velocity);
5881 if (velspeed < multiplier * 300 * scale) {
5884 velocity -= velocity / velspeed * multiplier * 300 * scale;
5885 if (velspeed > 5 && (isLanding() || isLandhard())) {
5886 skiddingdelay += multiplier;
5887 if (skiddelay <= 0) {
5888 FootLand(leftfoot, .5);
5889 FootLand(rightfoot, .5);
5897 velspeed = findLength(&velocity);
5899 if (velspeed < multiplier * 600 * scale) {
5902 velocity -= velocity / velspeed * multiplier * 600 * scale;
5904 if (velspeed > 5 && (isLanding() || isLandhard())) {
5905 skiddingdelay += multiplier;
5906 if (skiddelay <= 0) {
5907 FootLand(leftfoot, .5);
5908 FootLand(rightfoot, .5);
5915 if (skiddingdelay < 0)
5916 skiddingdelay += multiplier;
5917 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5919 if (!onterrain || environment == grassyenvironment) {
5920 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5922 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5926 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5927 terrainnormal = victim->coords - coords;
5928 Normalise(&terrainnormal);
5929 targetyaw = -asin(0 - terrainnormal.x);
5930 targetyaw *= 360 / 6.28;
5931 if (terrainnormal.z < 0)
5932 targetyaw = 180 - targetyaw;
5933 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5936 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5937 targetyaw = victim->targetyaw;
5939 if (animTarget == rabbittacklinganim) {
5940 coords = victim->coords;
5943 skeleton.oldfree = skeleton.free;
5947 midterrain.x = terrain.size * terrain.scale / 2;
5948 midterrain.z = terrain.size * terrain.scale / 2;
5949 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5951 tempposit = coords - midterrain;
5953 Normalise(&tempposit);
5954 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5955 coords.x = tempposit.x + midterrain.x;
5956 coords.z = tempposit.z + midterrain.z;
5962 * inverse kinematics helper function
5964 void IKHelper(Person *p, float interp)
5966 XYZ point, change, change2;
5967 float heightleft, heightright;
5969 // TODO: implement localToWorld and worldToLocal
5970 // but keep in mind it won't be the same math if player is ragdolled or something
5971 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5972 // then comb through code for places where to use it
5974 // point = localToWorld(jointPos(leftfoot))
5975 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5976 // adjust height of foot
5977 heightleft = terrain.getHeight(point.x, point.z) + .04;
5978 point.y = heightleft;
5979 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5980 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5981 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5982 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5983 // move ankle along with foot
5984 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5985 // average knee pos between old and new pos
5986 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5988 // do same as above for right leg
5989 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5990 heightright = terrain.getHeight(point.x, point.z) + .04;
5991 point.y = heightright;
5992 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5993 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5994 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5995 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5996 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5998 // fix up skeleton now that we've moved body parts?
5999 p->skeleton.DoConstraints(&p->coords, &p->scale);
6006 int Person::DrawSkeleton()
6008 int oldplayerdetail;
6009 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6010 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6020 glAlphaFunc(GL_GREATER, 0.0001);
6022 float terrainheight;
6026 if (!isnormal(tilt))
6028 if (!isnormal(tilt2))
6030 oldplayerdetail = playerdetail;
6032 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6035 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6038 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6043 if (playerdetail != oldplayerdetail) {
6045 normalsupdatedelay = 0;
6047 static float updatedelaychange;
6048 static float morphness;
6049 static float framemult;
6051 skeleton.FindForwards();
6052 if (howactive == typesittingwall) {
6053 skeleton.specialforward[1] = 0;
6054 skeleton.specialforward[1].z = 1;
6060 static int weaponattachmuscle;
6061 static int weaponrotatemuscle;
6062 static XYZ weaponpoint;
6063 static int start, endthing;
6064 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6065 if (!isSleeping() && !isSitting()) {
6066 // TODO: give these meaningful names
6067 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6068 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6069 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6070 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6072 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6074 if (creature == wolftype)
6078 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6079 IKHelper(this, target);
6080 if (creature == wolftype)
6081 IKHelper(this, target);
6084 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6085 IKHelper(this, 1 - target);
6086 if (creature == wolftype)
6087 IKHelper(this, 1 - target);
6091 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()))
6094 targetheadyaw = -targetyaw;
6095 targetheadpitch = 0;
6096 if (Animation::animations[animTarget].attack == 3)
6097 targetheadyaw += 180;
6099 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6100 skeleton.drawmodel.vertex[i] = 0;
6101 skeleton.drawmodel.vertex[i].y = 999;
6103 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6104 skeleton.drawmodellow.vertex[i] = 0;
6105 skeleton.drawmodellow.vertex[i].y = 999;
6107 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6108 skeleton.drawmodelclothes.vertex[i] = 0;
6109 skeleton.drawmodelclothes.vertex[i].y = 999;
6111 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6112 // convenience renames
6113 const int p1 = skeleton.muscles[i].parent1->label;
6114 const int p2 = skeleton.muscles[i].parent2->label;
6116 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6121 if (p1 == righthand || p2 == righthand) {
6122 morphness = righthandmorphness;
6123 start = righthandmorphstart;
6124 endthing = righthandmorphend;
6126 if (p1 == lefthand || p2 == lefthand) {
6127 morphness = lefthandmorphness;
6128 start = lefthandmorphstart;
6129 endthing = lefthandmorphend;
6131 if (p1 == head || p2 == head) {
6132 morphness = headmorphness;
6133 start = headmorphstart;
6134 endthing = headmorphend;
6136 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6137 morphness = chestmorphness;
6138 start = chestmorphstart;
6139 endthing = chestmorphend;
6141 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6142 morphness = tailmorphness;
6143 start = tailmorphstart;
6144 endthing = tailmorphend;
6147 skeleton.FindRotationMuscle(i, animTarget);
6148 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6149 glMatrixMode(GL_MODELVIEW);
6153 glRotatef(tilt2, 1, 0, 0);
6155 glRotatef(tilt, 0, 0, 1);
6158 glTranslatef(mid.x, mid.y, mid.z);
6160 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6161 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6163 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6164 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6166 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6167 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6169 if (playerdetail || skeleton.free == 3) {
6170 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6171 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6172 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6173 glMatrixMode(GL_MODELVIEW);
6175 if (p1 == abdomen || p2 == abdomen)
6176 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6177 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6178 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6179 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6180 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6181 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6182 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6183 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6184 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6185 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6186 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6187 if (p1 == head || p2 == head)
6188 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6189 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6190 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6191 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6192 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6193 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6194 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6198 if (!playerdetail || skeleton.free == 3) {
6199 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6200 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6201 glMatrixMode(GL_MODELVIEW);
6203 if (p1 == abdomen || p2 == abdomen)
6204 glTranslatef(v0.x * proportionbody.x,
6205 v0.y * proportionbody.y,
6206 v0.z * proportionbody.z);
6207 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6208 glTranslatef(v0.x * proportionarms.x,
6209 v0.y * proportionarms.y,
6210 v0.z * proportionarms.z);
6211 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6212 glTranslatef(v0.x * proportionlegs.x,
6213 v0.y * proportionlegs.y,
6214 v0.z * proportionlegs.z);
6215 if (p1 == head || p2 == head)
6216 glTranslatef(v0.x * proportionhead.x,
6217 v0.y * proportionhead.y,
6218 v0.z * proportionhead.z);
6220 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6221 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6222 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6223 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6229 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6230 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6232 glMatrixMode(GL_MODELVIEW);
6236 glRotatef(tilt2, 1, 0, 0);
6238 glRotatef(tilt, 0, 0, 1);
6239 glTranslatef(mid.x, mid.y, mid.z);
6240 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6241 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6243 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6244 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6246 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6247 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6249 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6250 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6251 glMatrixMode(GL_MODELVIEW);
6253 if (p1 == abdomen || p2 == abdomen)
6254 glTranslatef(v0.x * proportionbody.x,
6255 v0.y * proportionbody.y,
6256 v0.z * proportionbody.z);
6257 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6258 glTranslatef(v0.x * proportionarms.x,
6259 v0.y * proportionarms.y,
6260 v0.z * proportionarms.z);
6261 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6262 glTranslatef(v0.x * proportionlegs.x,
6263 v0.y * proportionlegs.y,
6264 v0.z * proportionlegs.z);
6265 if (p1 == head || p2 == head)
6266 glTranslatef(v0.x * proportionhead.x,
6267 v0.y * proportionhead.y,
6268 v0.z * proportionhead.z);
6269 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6270 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6271 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6272 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6277 updatedelay = 1 + (float)(Random() % 100) / 1000;
6279 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6280 normalsupdatedelay = 1;
6281 if (playerdetail || skeleton.free == 3)
6282 skeleton.drawmodel.CalculateNormals(0);
6283 if (!playerdetail || skeleton.free == 3)
6284 skeleton.drawmodellow.CalculateNormals(0);
6285 if (skeleton.clothes)
6286 skeleton.drawmodelclothes.CalculateNormals(0);
6288 if (playerdetail || skeleton.free == 3)
6289 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6290 if (!playerdetail || skeleton.free == 3)
6291 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6292 if (skeleton.clothes) {
6293 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6298 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6299 if (updatedelaychange > -realmultiplier * 30)
6300 updatedelaychange = -realmultiplier * 30;
6301 if (updatedelaychange > -framemult * 4)
6302 updatedelaychange = -framemult * 4;
6303 if (skeleton.free == 1)
6304 updatedelaychange *= 6;
6306 updatedelaychange *= 8;
6307 updatedelay += updatedelaychange;
6309 glMatrixMode(GL_MODELVIEW);
6311 glTranslatef(coords.x, coords.y - .02, coords.z);
6312 if (!skeleton.free) {
6313 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6314 glRotatef(yaw, 0, 1, 0);
6318 glColor4f(.4, 1, .4, 1);
6319 glDisable(GL_LIGHTING);
6320 glDisable(GL_TEXTURE_2D);
6323 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6324 XYZ &v0 = skeleton.drawmodel.vertex[i];
6325 glVertex3f(v0.x, v0.y, v0.z);
6331 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6332 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6333 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6334 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6335 glVertex3f(v0.x, v0.y, v0.z);
6336 glVertex3f(v1.x, v1.y, v1.z);
6337 glVertex3f(v1.x, v1.y, v1.z);
6338 glVertex3f(v2.x, v2.y, v2.z);
6339 glVertex3f(v2.x, v2.y, v2.z);
6340 glVertex3f(v0.x, v0.y, v0.z);
6346 terrainlight = terrain.getLighting(coords.x, coords.z);
6347 distance = distsq(&viewer, &coords);
6348 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6352 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6353 if (terrainheight < 1)
6355 if (terrainheight > 1.7)
6356 terrainheight = 1.7;
6358 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6359 glDisable(GL_BLEND);
6360 glAlphaFunc(GL_GREATER, 0.0001);
6361 glEnable(GL_TEXTURE_2D);
6363 glDisable(GL_TEXTURE_2D);
6364 glColor4f(.7, .35, 0, .5);
6366 glEnable(GL_LIGHTING);
6369 if (tutoriallevel && id != 0) {
6370 glColor4f(.7, .7, .7, 0.6);
6372 glEnable(GL_LIGHTING);
6374 if (canattack && cananger)
6375 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6376 glDisable(GL_TEXTURE_2D);
6377 glColor4f(1, 0, 0, 0.8);
6379 glMatrixMode(GL_TEXTURE);
6381 glTranslatef(0, -smoketex, 0);
6382 glTranslatef(-smoketex, 0, 0);
6386 if ((tutoriallevel && id != 0))
6387 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6389 skeleton.drawmodel.draw();
6392 if (!playerdetail) {
6393 if ((tutoriallevel && id != 0))
6394 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6396 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6399 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6400 if (tutoriallevel && id != 0) {
6402 glMatrixMode(GL_MODELVIEW);
6403 glEnable(GL_TEXTURE_2D);
6404 glColor4f(.7, .7, .7, 0.6);
6406 glEnable(GL_LIGHTING);
6408 if (canattack && cananger)
6409 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6410 glDisable(GL_TEXTURE_2D);
6411 glColor4f(1, 0, 0, 0.8);
6413 glMatrixMode(GL_TEXTURE);
6415 glTranslatef(0, -smoketex * .6, 0);
6416 glTranslatef(smoketex * .6, 0, 0);
6419 if ((tutoriallevel && id != 0))
6420 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6422 skeleton.drawmodel.draw();
6425 if (!playerdetail) {
6426 if ((tutoriallevel && id != 0))
6427 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6429 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6434 if (tutoriallevel && id != 0) {
6436 glMatrixMode(GL_MODELVIEW);
6437 glEnable(GL_TEXTURE_2D);
6439 if (skeleton.clothes) {
6443 skeleton.drawmodelclothes.draw();
6445 skeleton.drawmodelclothes.drawimmediate();
6451 if (num_weapons > 0) {
6452 for (k = 0; k < num_weapons; k++) {
6454 if (weaponactive == k) {
6455 if (weapons[i].getType() != staff) {
6456 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6457 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6458 weaponattachmuscle = j;
6461 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6462 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) {
6463 weaponrotatemuscle = j;
6466 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6467 if (creature == wolftype)
6468 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6470 if (weapons[i].getType() == staff) {
6471 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6472 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6473 weaponattachmuscle = j;
6476 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6477 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) {
6478 weaponrotatemuscle = j;
6481 //weaponpoint=jointPos(rightwrist);
6482 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6483 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6484 XYZ tempnormthing, vec1, vec2;
6485 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6486 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6487 CrossProduct(&vec1, &vec2, &tempnormthing);
6488 Normalise(&tempnormthing);
6489 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6490 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6493 if (weaponactive != k && weaponstuck != k) {
6494 if (weapons[i].getType() == knife)
6495 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6496 if (weapons[i].getType() == sword)
6497 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6498 if (weapons[i].getType() == staff)
6499 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6500 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6501 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) {
6502 weaponrotatemuscle = j;
6506 if (weaponstuck == k) {
6507 if (weaponstuckwhere == 0)
6508 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6510 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6511 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6512 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) {
6513 weaponrotatemuscle = j;
6517 if (skeleton.free) {
6518 weapons[i].position = weaponpoint * scale + coords;
6519 weapons[i].bigrotation = 0;
6520 weapons[i].bigtilt = 0;
6521 weapons[i].bigtilt2 = 0;
6523 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;
6524 weapons[i].bigrotation = yaw;
6525 weapons[i].bigtilt = tilt;
6526 weapons[i].bigtilt2 = tilt2;
6528 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6529 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6530 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6531 if (weaponactive == k) {
6532 if (weapons[i].getType() == knife) {
6533 weapons[i].smallrotation = 180;
6534 weapons[i].smallrotation2 = 0;
6535 if (isCrouch() || wasCrouch()) {
6536 weapons[i].smallrotation2 = 20;
6538 if (animTarget == hurtidleanim) {
6539 weapons[i].smallrotation2 = 50;
6541 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6542 XYZ temppoint1, temppoint2;
6545 temppoint1 = jointPos(righthand);
6546 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6547 distance = findDistance(&temppoint1, &temppoint2);
6548 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6549 weapons[i].rotation2 *= 360 / 6.28;
6552 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6553 weapons[i].rotation1 *= 360 / 6.28;
6554 weapons[i].rotation3 = 0;
6555 weapons[i].smallrotation = -90;
6556 weapons[i].smallrotation2 = 0;
6557 if (temppoint1.x > temppoint2.x)
6558 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6560 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6561 XYZ temppoint1, temppoint2;
6564 temppoint1 = jointPos(righthand);
6565 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6566 distance = findDistance(&temppoint1, &temppoint2);
6567 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6568 weapons[i].rotation2 *= 360 / 6.28;
6571 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6572 weapons[i].rotation1 *= 360 / 6.28;
6573 weapons[i].rotation3 = 0;
6574 weapons[i].smallrotation = 90;
6575 weapons[i].smallrotation2 = 0;
6576 if (temppoint1.x > temppoint2.x)
6577 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6579 if (animTarget == knifethrowanim) {
6580 weapons[i].smallrotation = 90;
6581 //weapons[i].smallrotation2=-90;
6582 weapons[i].smallrotation2 = 0;
6583 weapons[i].rotation1 = 0;
6584 weapons[i].rotation2 = 0;
6585 weapons[i].rotation3 = 0;
6587 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6588 weapons[i].smallrotation = -90;
6589 weapons[i].rotation1 = 0;
6590 weapons[i].rotation2 = 0;
6591 weapons[i].rotation3 = 0;
6594 if (weapons[i].getType() == sword) {
6595 weapons[i].smallrotation = 0;
6596 weapons[i].smallrotation2 = 0;
6597 if (animTarget == knifethrowanim) {
6598 weapons[i].smallrotation = -90;
6599 weapons[i].smallrotation2 = 0;
6600 weapons[i].rotation1 = 0;
6601 weapons[i].rotation2 = 0;
6602 weapons[i].rotation3 = 0;
6604 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)) {
6605 XYZ temppoint1, temppoint2;
6608 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6609 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6610 distance = findDistance(&temppoint1, &temppoint2);
6611 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6612 weapons[i].rotation2 *= 360 / 6.28;
6615 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6616 weapons[i].rotation1 *= 360 / 6.28;
6617 weapons[i].rotation3 = 0;
6618 weapons[i].smallrotation = 90;
6619 weapons[i].smallrotation2 = 0;
6620 if (temppoint1.x > temppoint2.x)
6621 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6624 if (weapons[i].getType() == staff) {
6625 weapons[i].smallrotation = 100;
6626 weapons[i].smallrotation2 = 0;
6627 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6628 XYZ temppoint1, temppoint2;
6631 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6632 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6633 distance = findDistance(&temppoint1, &temppoint2);
6634 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6635 weapons[i].rotation2 *= 360 / 6.28;
6638 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6639 weapons[i].rotation1 *= 360 / 6.28;
6640 weapons[i].rotation3 = 0;
6641 weapons[i].smallrotation = 90;
6642 weapons[i].smallrotation2 = 0;
6643 if (temppoint1.x > temppoint2.x)
6644 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6648 if (weaponactive != k && weaponstuck != k) {
6649 if (weapons[i].getType() == knife) {
6650 weapons[i].smallrotation = -70;
6651 weapons[i].smallrotation2 = 10;
6653 if (weapons[i].getType() == sword) {
6654 weapons[i].smallrotation = -100;
6655 weapons[i].smallrotation2 = -8;
6657 if (weapons[i].getType() == staff) {
6658 weapons[i].smallrotation = -100;
6659 weapons[i].smallrotation2 = -8;
6662 if (weaponstuck == k) {
6663 if (weaponstuckwhere == 0)
6664 weapons[i].smallrotation = 180;
6666 weapons[i].smallrotation = 0;
6667 weapons[i].smallrotation2 = 10;
6676 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6678 if (animCurrent != animTarget)
6680 if (skeleton.free == 2)
6689 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6692 static float distance;
6693 static float olddistance;
6694 static int intersecting;
6695 static int firstintersecting;
6698 static XYZ start, end;
6699 static float slopethreshold = -.4;
6701 firstintersecting = -1;
6705 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6708 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6709 for (i = 0; i < 4; i++) {
6710 for (j = 0; j < model->TriangleNum; j++) {
6711 if (model->facenormals[j].y <= slopethreshold) {
6713 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)));
6714 if (distance < radius) {
6715 point = *p1 - model->facenormals[j] * distance;
6716 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]]))
6719 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6720 &model->vertex[model->Triangles[j].vertex[1]],
6723 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6724 &model->vertex[model->Triangles[j].vertex[2]],
6727 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6728 &model->vertex[model->Triangles[j].vertex[2]],
6731 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6735 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)) {
6736 p1->y = point.y + radius;
6737 if ((animTarget == jumpdownanim || isFlip())) {
6738 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6741 if (animTarget == jumpupanim) {
6743 animTarget = getIdle();
6750 pause_sound(whooshsound);
6751 OPENAL_SetVolume(channels[whooshsound], 0);
6754 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6757 animTarget = getLanding();
6758 emit_sound_at(landsound, coords, 128.);
6761 addEnvSound(coords);
6768 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6769 olddistance = distance;
6770 firstintersecting = j;
6775 for (j = 0; j < model->TriangleNum; j++) {
6776 if (model->facenormals[j].y > slopethreshold) {
6779 start.y -= radius / 4;
6780 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6781 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6782 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6783 distance = abs((model->facenormals[j].x * start.x)
6784 + (model->facenormals[j].y * start.y)
6785 + (model->facenormals[j].z * start.z)
6786 - ((model->facenormals[j].x * v0.x)
6787 + (model->facenormals[j].y * v0.y)
6788 + (model->facenormals[j].z * v0.z)));
6789 if (distance < radius * .5) {
6790 point = start - model->facenormals[j] * distance;
6791 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6794 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6796 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6798 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6800 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6801 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6803 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6804 if (findLengthfast(&start) < findLengthfast(&velocity))
6807 *p1 += model->facenormals[j] * (distance - radius * .5);
6810 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6811 olddistance = distance;
6812 firstintersecting = j;
6819 *p = DoRotation(*p, 0, *rotate, 0);
6822 *p1 = DoRotation(*p1, 0, *rotate, 0);
6824 return firstintersecting;
6827 void Person::takeWeapon(int weaponId)
6830 weapons[weaponId].owner = id;
6831 if (num_weapons > 0) {
6832 weaponids[num_weapons] = weaponids[0];
6835 weaponids[0] = weaponId;
6838 void Person::addClothes()
6840 if (numclothes > 0) {
6841 for (int i = 0; i < numclothes; i++) {
6848 bool Person::addClothes(const int& clothesId)
6851 const std::string fileName = clothes[clothesId];
6853 GLubyte* array = &skeleton.skinText[0];
6857 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6862 float tintr = clothestintr[clothesId];
6863 float tintg = clothestintg[clothesId];
6864 float tintb = clothestintb[clothesId];
6866 if (tintr > 1) tintr = 1;
6867 if (tintg > 1) tintg = 1;
6868 if (tintb > 1) tintb = 1;
6870 if (tintr < 0) tintr = 0;
6871 if (tintg < 0) tintg = 0;
6872 if (tintb < 0) tintb = 0;
6874 int bytesPerPixel = texture.bpp / 8;
6878 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6879 if (bytesPerPixel == 3)
6881 else if ((i + 1) % 4 == 0)
6882 alphanum = texture.data[i];
6883 if ((i + 1) % 4 || bytesPerPixel == 3) {
6885 texture.data[i] *= tintr;
6887 texture.data[i] *= tintg;
6889 texture.data[i] *= tintb;
6890 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);