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 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation/Animation.h"
29 #include "Utils/Folders.h"
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 (int 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 = abs(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 (int 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 (int 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 (int 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 (int 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 (int 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[abs(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[abs(Random() % skeleton.joints.size())].velchange -= change;
1774 if (checkcollision) {
1781 for (j = 0; j < skeleton.joints.size(); j++) {
1782 average += skeleton.joints[j].position;
1786 coords += average * scale;
1787 for (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 (int 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))) {
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;
2080 } else if (targetFrame().label == 4)
2081 whichsound = knifeswishsound;
2082 if (targetFrame().label == 8 && tutoriallevel != 1)
2083 whichsound = landsound2;
2085 emit_sound_at(whichsound, coords, 256.);
2088 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2089 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2090 addEnvSound(coords, 15);
2092 addEnvSound(coords, 6);
2096 if (targetFrame().label == 3) {
2098 emit_sound_at(whichsound, coords, 128.);
2103 if (tutoriallevel != 1 || id == 0)
2104 if (speechdelay <= 0)
2105 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2106 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2107 int whichsound = -1;
2108 if (targetFrame().label == 4 && aitype != playercontrolled) {
2109 if (Animation::animations[animTarget].attack != neutral) {
2110 unsigned r = abs(Random() % 4);
2111 if (creature == rabbittype) {
2112 if (r == 0) whichsound = rabbitattacksound;
2113 if (r == 1) whichsound = rabbitattack2sound;
2114 if (r == 2) whichsound = rabbitattack3sound;
2115 if (r == 3) whichsound = rabbitattack4sound;
2117 if (creature == wolftype) {
2118 if (r == 0) whichsound = barksound;
2119 if (r == 1) whichsound = bark2sound;
2120 if (r == 2) whichsound = bark3sound;
2121 if (r == 3) whichsound = barkgrowlsound;
2127 if (whichsound != -1) {
2128 emit_sound_at(whichsound, coords);
2134 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2135 FootLand(leftfoot, 1);
2136 FootLand(rightfoot, 1);
2140 currentoffset = targetoffset;
2141 frameTarget = frameCurrent;
2142 animCurrent = animTarget;
2145 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2146 for (unsigned i = 0; i < weapons.size(); i++) {
2147 if (weapons[i].owner == -1)
2148 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2149 if (distsq(&coords, &weapons[i].position) >= 1) {
2150 if (weapons[i].getType() != staff) {
2151 emit_sound_at(knifedrawsound, coords, 128.);
2160 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2161 for (unsigned i = 0; i < weapons.size(); i++) {
2162 bool willwork = true;
2163 if (weapons[i].owner != -1)
2164 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2165 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2166 if (Person::players[weapons[i].owner]->num_weapons > 1)
2168 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2169 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2170 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2171 bool fleshstuck = false;
2172 if (weapons[i].owner != -1)
2173 if (victim->weaponstuck != -1) {
2174 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2179 emit_sound_at(fleshstabremovesound, coords, 128.);
2181 if (weapons[i].getType() != staff) {
2182 emit_sound_at(knifedrawsound, coords, 128.);
2185 if (weapons[i].owner != -1) {
2186 victim = Person::players[weapons[i].owner];
2187 if (victim->num_weapons == 1)
2188 victim->num_weapons = 0;
2190 victim->num_weapons = 1;
2192 //victim->weaponactive=-1;
2193 victim->skeleton.longdead = 0;
2194 victim->skeleton.free = 1;
2195 victim->skeleton.broken = 0;
2197 for (int j = 0; j < victim->skeleton.joints.size(); j++) {
2198 victim->skeleton.joints[j].velchange = 0;
2199 victim->skeleton.joints[j].locked = 0;
2205 Normalise(&relative);
2206 XYZ footvel, footpoint;
2208 footpoint = weapons[i].position;
2209 if (victim->weaponstuck != -1) {
2210 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2212 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2213 weapons[i].bloody = 2;
2214 weapons[i].blooddrip = 5;
2215 victim->weaponstuck = -1;
2218 if (victim->num_weapons > 0) {
2219 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2220 victim->weaponstuck = 0;
2221 if (victim->weaponids[0] == int(i))
2222 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2225 victim->jointVel(abdomen) += relative * 6;
2226 victim->jointVel(neck) += relative * 6;
2227 victim->jointVel(rightshoulder) += relative * 6;
2228 victim->jointVel(leftshoulder) += relative * 6;
2236 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2237 if (weaponactive == -1)
2239 else if (weaponactive == 0) {
2241 if (num_weapons == 2) {
2243 buffer = weaponids[0];
2244 weaponids[0] = weaponids[1];
2245 weaponids[1] = buffer;
2248 if (weaponactive == -1) {
2249 emit_sound_at(knifesheathesound, coords, 128.);
2251 if (weaponactive != -1) {
2252 emit_sound_at(knifedrawsound, coords, 128.);
2257 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2258 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2259 Normalise(&rotatetarget);
2260 targetyaw = -asin(0 - rotatetarget.x);
2261 targetyaw *= 360 / 6.28;
2262 if (rotatetarget.z < 0)
2263 targetyaw = 180 - targetyaw;
2265 if (animTarget == walljumprightkickanim)
2267 if (animTarget == walljumpleftkickanim)
2273 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2276 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2281 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2282 animTarget = rabbittackleanim;
2284 emit_sound_at(jumpsound, coords);
2292 targetloc = velocity;
2293 Normalise(&targetloc);
2294 targetloc += coords;
2295 for (unsigned i = 0; i < Person::players.size(); i++) {
2297 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2298 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2302 if (closestid != -1)
2303 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2305 victim = Person::players[closestid];
2306 coords = victim->coords;
2307 animCurrent = rabbittacklinganim;
2308 animTarget = rabbittacklinganim;
2312 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2313 rotatetarget = coords - victim->coords;
2314 Normalise(&rotatetarget);
2315 targetyaw = -asin(0 - rotatetarget.x);
2316 targetyaw *= 360 / 6.28;
2317 if (rotatetarget.z < 0)
2318 targetyaw = 180 - targetyaw;
2320 if (animTarget != rabbitrunninganim) {
2321 emit_sound_at(jumpsound, coords, 128.);
2327 float damagemult = 1 * power;
2328 if (creature == wolftype)
2329 damagemult = 2.5 * power;
2331 damagemult /= victim->damagetolerance / 200;
2333 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)) {
2334 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2335 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2339 if (Random() % 2 || creature == wolftype) {
2342 if (creature == wolftype)
2345 if (tutoriallevel != 1) {
2346 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2348 if (creature == wolftype) {
2349 emit_sound_at(clawslicesound, victim->coords, 128.);
2351 victim->DoBloodBig(2 / victim->armorhead, 175);
2355 relative = victim->coords - coords;
2357 Normalise(&relative);
2358 relative = DoRotation(relative, 0, -90, 0);
2359 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2360 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2362 victim->jointVel(head) += relative * damagemult * 200;
2364 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2370 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2371 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2375 if (Random() % 2 || creature == wolftype) {
2377 if (creature == wolftype)
2380 emit_sound_at(whooshhitsound, victim->coords);
2381 if (creature == wolftype) {
2382 emit_sound_at(clawslicesound, victim->coords, 128.);
2384 victim->DoBloodBig(2, 175);
2388 relative = victim->coords - coords;
2390 Normalise(&relative);
2392 Normalise(&relative);
2393 relative = DoRotation(relative, 0, 90, 0);
2394 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2395 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2397 victim->jointVel(head) += relative * damagemult * 100;
2399 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2403 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2404 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2410 if (tutoriallevel != 1) {
2411 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2413 if (creature == wolftype) {
2414 emit_sound_at(clawslicesound, victim->coords, 128.);
2416 victim->DoBloodBig(2 / victim->armorhead, 175);
2422 Normalise(&relative);
2423 relative = DoRotation(relative, 0, -90, 0);
2424 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2425 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2427 victim->jointVel(head) += relative * damagemult * 200;
2429 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2431 if (victim->damage > victim->damagetolerance)
2432 award_bonus(id, style);
2438 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2439 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2445 if (tutoriallevel != 1) {
2446 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2448 if (creature == wolftype) {
2449 emit_sound_at(clawslicesound, victim->coords, 128.);
2451 victim->DoBloodBig(2 / victim->armorhead, 175);
2457 Normalise(&relative);
2458 relative = DoRotation(relative, 0, 90, 0);
2459 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2460 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2462 victim->jointVel(head) += relative * damagemult * 200;
2464 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2466 if (victim->damage > victim->damagetolerance)
2467 award_bonus(id, style);
2473 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2474 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2482 emit_sound_at(whooshhitsound, victim->coords);
2485 relative = victim->coords - coords;
2487 Normalise(&relative);
2488 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2489 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2491 victim->jointVel(head) += relative * damagemult * 100;
2493 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2497 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2498 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2502 emit_sound_at(whooshhitsound, victim->coords, 128.);
2504 victim->skeleton.longdead = 0;
2505 victim->skeleton.free = 1;
2506 victim->skeleton.broken = 0;
2507 victim->skeleton.spinny = 1;
2509 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2510 victim->skeleton.joints[i].velchange = 0;
2511 victim->skeleton.joints[i].delay = 0;
2512 victim->skeleton.joints[i].locked = 0;
2513 //victim->skeleton.joints[i].velocity=0;
2519 Normalise(&relative);
2520 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2521 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2522 victim->skeleton.joints[i].position.y += relative.y * .3;
2523 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2524 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2526 victim->Puff(abdomen);
2527 victim->jointVel(abdomen).y = relative.y * 400;
2531 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2532 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2536 if (tutoriallevel != 1) {
2537 emit_sound_at(heavyimpactsound, coords, 128.);
2540 relative = victim->coords - coords;
2542 Normalise(&relative);
2543 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2544 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2546 victim->Puff(abdomen);
2547 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2551 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2552 victim->jointVel(abdomen) += relative * damagemult * 300;
2556 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2557 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2561 if (tutoriallevel != 1) {
2562 emit_sound_at(thudsound, coords);
2565 victim->skeleton.longdead = 0;
2566 victim->skeleton.free = 1;
2567 victim->skeleton.broken = 0;
2568 victim->skeleton.spinny = 1;
2570 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2571 victim->skeleton.joints[i].velchange = 0;
2572 //victim->skeleton.joints[i].delay=0;
2573 victim->skeleton.joints[i].locked = 0;
2576 relative = victim->coords - coords;
2577 Normalise(&relative);
2579 Normalise(&relative);
2580 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2581 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2586 victim->Puff(abdomen);
2587 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2588 victim->jointVel(abdomen) += relative * damagemult * 200;
2597 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2600 if (!victim->skeleton.free)
2604 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2605 emit_sound_at(knifesheathesound, coords, 128.);
2608 if (victim && hasvictim) {
2609 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2611 XYZ where, startpoint, endpoint, movepoint, colpoint;
2612 float rotationpoint;
2614 if (weapons[weaponids[weaponactive]].getType() == knife) {
2615 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2616 where -= victim->coords;
2617 if (!victim->skeleton.free)
2618 where = DoRotation(where, 0, -victim->yaw, 0);
2621 startpoint.y += 100;
2625 if (weapons[weaponids[weaponactive]].getType() == sword) {
2626 where = weapons[weaponids[weaponactive]].position;
2627 where -= victim->coords;
2628 if (!victim->skeleton.free)
2629 where = DoRotation(where, 0, -victim->yaw, 0);
2631 where = weapons[weaponids[weaponactive]].tippoint;
2632 where -= victim->coords;
2633 if (!victim->skeleton.free)
2634 where = DoRotation(where, 0, -victim->yaw, 0);
2637 if (weapons[weaponids[weaponactive]].getType() == staff) {
2638 where = weapons[weaponids[weaponactive]].position;
2639 where -= victim->coords;
2640 if (!victim->skeleton.free)
2641 where = DoRotation(where, 0, -victim->yaw, 0);
2643 where = weapons[weaponids[weaponactive]].tippoint;
2644 where -= victim->coords;
2645 if (!victim->skeleton.free)
2646 where = DoRotation(where, 0, -victim->yaw, 0);
2651 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2653 if (whichtri != -1) {
2654 if (victim->dead != 2) {
2655 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2657 award_bonus(id, FinishedBonus);
2660 weapons[weaponids[weaponactive]].bloody = 2;
2662 victim->skeleton.longdead = 0;
2663 victim->skeleton.free = 1;
2664 victim->skeleton.broken = 0;
2666 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2667 victim->skeleton.joints[i].velchange = 0;
2668 victim->skeleton.joints[i].locked = 0;
2669 //victim->skeleton.joints[i].velocity=0;
2671 emit_sound_at(fleshstabsound, coords, 128);
2674 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2675 weapons[weaponids[weaponactive]].blooddrip += 5;
2676 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2678 if (whichtri == -1) {
2680 emit_sound_at(knifesheathesound, coords, 128.);
2686 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2688 emit_sound_at(knifedrawsound, coords, 128);
2691 if (victim && hasvictim) {
2692 XYZ footvel, footpoint;
2694 emit_sound_at(fleshstabremovesound, coords, 128.);
2697 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2699 if (weapons[weaponids[weaponactive]].getType() == sword) {
2700 XYZ where, startpoint, endpoint, movepoint;
2701 float rotationpoint;
2704 where = weapons[weaponids[weaponactive]].position;
2705 where -= victim->coords;
2706 if (!victim->skeleton.free)
2707 where = DoRotation(where, 0, -victim->yaw, 0);
2709 where = weapons[weaponids[weaponactive]].tippoint;
2710 where -= victim->coords;
2711 if (!victim->skeleton.free)
2712 where = DoRotation(where, 0, -victim->yaw, 0);
2717 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2718 footpoint += victim->coords;
2720 if (whichtri == -1) {
2721 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2724 if (weapons[weaponids[weaponactive]].getType() == staff) {
2725 XYZ where, startpoint, endpoint, movepoint;
2726 float rotationpoint;
2729 where = weapons[weaponids[weaponactive]].position;
2730 where -= victim->coords;
2731 if (!victim->skeleton.free)
2732 where = DoRotation(where, 0, -victim->yaw, 0);
2734 where = weapons[weaponids[weaponactive]].tippoint;
2735 where -= victim->coords;
2736 if (!victim->skeleton.free)
2737 where = DoRotation(where, 0, -victim->yaw, 0);
2742 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2743 footpoint += victim->coords;
2745 if (whichtri == -1) {
2746 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2749 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2751 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2752 victim->skeleton.longdead = 0;
2753 victim->skeleton.free = 1;
2754 victim->skeleton.broken = 0;
2756 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2757 victim->skeleton.joints[i].velchange = 0;
2758 victim->skeleton.joints[i].locked = 0;
2759 //victim->skeleton.joints[i].velocity=0;
2765 Normalise(&relative);
2766 //victim->Puff(abdomen);
2768 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2770 if (victim->bloodloss < victim->damagetolerance) {
2771 victim->bloodloss += 1000;
2775 victim->jointVel(abdomen) += relative * damagemult * 20;
2779 if (!hasvictim && onterrain) {
2780 weapons[weaponids[weaponactive]].bloody = 0;
2781 weapons[weaponids[weaponactive]].blooddrip = 0;
2785 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2786 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2794 if (tutoriallevel != 1) {
2795 emit_sound_at(heavyimpactsound, victim->coords, 128);
2800 relative = victim->coords - coords;
2802 Normalise(&relative);
2803 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2804 victim->skeleton.joints[i].velocity = relative * 30;
2806 victim->jointVel(head) += relative * damagemult * 150;
2808 victim->frameTarget = 0;
2809 victim->animTarget = staggerbackhardanim;
2810 victim->targetyaw = targetyaw + 180;
2812 victim->stunned = 1;
2815 victim->Puff(abdomen);
2816 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2823 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2824 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2828 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) {
2829 if (tutoriallevel != 1) {
2830 emit_sound_at(thudsound, victim->coords);
2832 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2833 if (tutoriallevel != 1) {
2834 emit_sound_at(whooshhitsound, victim->coords);
2837 if (tutoriallevel != 1) {
2838 emit_sound_at(heavyimpactsound, victim->coords);
2842 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2845 relative = victim->coords - coords;
2847 Normalise(&relative);
2849 Normalise(&relative);
2850 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
2851 victim->skeleton.joints[i].velocity = relative * 5;
2853 victim->jointVel(abdomen) += relative * damagemult * 400;
2855 victim->frameTarget = 0;
2856 victim->animTarget = staggerbackhardanim;
2857 victim->targetyaw = targetyaw + 180;
2859 victim->stunned = 1;
2861 victim->Puff(abdomen);
2862 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2868 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2869 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2870 if (victim->id == 0)
2872 emit_sound_at(landsound2, victim->coords);
2878 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2879 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2880 if (victim->id == 0)
2883 if (weaponactive != -1) {
2884 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2885 if (weapons[victim->weaponids[0]].getType() == staff)
2886 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2887 if (weapons[weaponids[0]].getType() == staff)
2888 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2890 emit_sound_at(swordstaffsound, victim->coords);
2892 emit_sound_at(metalhitsound, victim->coords);
2900 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2901 if (weaponactive != -1) {
2904 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);
2906 weapons[weaponids[0]].thrown(aim * 50);
2909 weaponids[0] = weaponids[num_weapons];
2915 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2917 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2919 if (tutoriallevel != 1)
2920 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2922 award_bonus(id, Slicebonus);
2923 if (tutoriallevel != 1) {
2924 emit_sound_at(knifeslicesound, victim->coords);
2926 //victim->jointVel(abdomen)+=relative*damagemult*200;
2927 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2928 if (victim->id != 0 || difficulty == 2) {
2929 victim->frameTarget = 0;
2930 victim->animTarget = staggerbackhardanim;
2931 victim->targetyaw = targetyaw + 180;
2935 victim->lowreversaldelay = 0;
2936 victim->highreversaldelay = 0;
2937 if (aitype != playercontrolled)
2938 weaponmissdelay = .6;
2940 if (tutoriallevel != 1)
2941 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2942 weapons[weaponids[weaponactive]].bloody = 1;
2943 if (tutoriallevel != 1)
2944 weapons[weaponids[weaponactive]].blooddrip += 3;
2946 XYZ footvel, footpoint;
2948 if (skeleton.free) {
2949 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2951 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2953 if (tutoriallevel != 1) {
2955 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2956 footvel = DoRotation(facing, 0, 90, 0) * .8;
2958 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2959 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2960 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2961 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2963 if (tutoriallevel == 1) {
2964 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2966 victim->DoDamage(damagemult * 0);
2969 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2970 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2971 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2972 award_bonus(id, Slashbonus);
2974 if (tutoriallevel != 1) {
2975 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2976 victim->DoBloodBig(2 / victim->armorhigh, 190);
2978 victim->DoBloodBig(2 / victim->armorhigh, 185);
2979 victim->deathbleeding = 1;
2980 emit_sound_at(swordslicesound, victim->coords);
2982 //victim->jointVel(abdomen)+=relative*damagemult*200;
2983 if (tutoriallevel != 1) {
2984 victim->frameTarget = 0;
2985 victim->animTarget = staggerbackhardanim;
2986 victim->targetyaw = targetyaw + 180;
2990 if (tutoriallevel != 1) {
2991 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2992 weapons[weaponids[weaponactive]].bloody = 1;
2993 weapons[weaponids[weaponactive]].blooddrip += 3;
2995 float bloodlossamount;
2996 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2997 victim->bloodloss += bloodlossamount / victim->armorhigh;
2998 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2999 victim->DoDamage(damagemult * 0);
3001 XYZ footvel, footpoint;
3003 if (skeleton.free) {
3004 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3006 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3009 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3010 footvel = DoRotation(facing, 0, 90, 0) * .8;
3012 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3013 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3014 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3015 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3018 if (victim->weaponactive != -1) {
3019 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3020 if (weapons[victim->weaponids[0]].getType() == staff)
3021 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3022 if (weapons[weaponids[0]].getType() == staff)
3023 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3025 emit_sound_at(swordstaffsound, victim->coords);
3027 emit_sound_at(metalhitsound, victim->coords);
3033 victim->Puff(righthand);
3035 victim->frameTarget = 0;
3036 victim->animTarget = staggerbackhighanim;
3037 victim->targetyaw = targetyaw + 180;
3039 aim = DoRotation(facing, 0, 90, 0) * 21;
3041 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3042 victim->num_weapons--;
3043 if (victim->num_weapons) {
3044 victim->weaponids[0] = victim->weaponids[num_weapons];
3045 if (victim->weaponstuck == victim->num_weapons)
3046 victim->weaponstuck = 0;
3048 victim->weaponactive = -1;
3049 for (unsigned i = 0; i < Person::players.size(); i++) {
3050 Person::players[i]->wentforweapon = 0;
3057 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3058 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3059 if (tutoriallevel != 1) {
3060 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3064 if (Random() % 2 || creature == wolftype) {
3067 emit_sound_at(staffheadsound, victim->coords);
3071 relative = victim->coords - coords;
3073 Normalise(&relative);
3074 relative = DoRotation(relative, 0, 90, 0);
3076 Normalise(&relative);
3077 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3078 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3080 victim->jointVel(head) += relative * damagemult * 230;
3081 victim->jointVel(neck) += relative * damagemult * 230;
3083 if (tutoriallevel != 1) {
3084 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3086 award_bonus(id, solidhit, 30);
3091 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3092 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3093 if (tutoriallevel != 1) {
3094 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3098 if (Random() % 2 || creature == wolftype) {
3101 emit_sound_at(staffheadsound, victim->coords);
3105 relative = victim->coords - coords;
3107 Normalise(&relative);
3108 relative = DoRotation(relative, 0, -90, 0);
3109 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3110 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3112 victim->jointVel(head) += relative * damagemult * 220;
3113 victim->jointVel(neck) += relative * damagemult * 220;
3115 if (tutoriallevel != 1) {
3116 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3118 award_bonus(id, solidhit, 60);
3123 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3124 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3126 if (tutoriallevel != 1) {
3128 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3131 if (Random() % 2 || creature == wolftype) {
3134 emit_sound_at(staffbodysound, victim->coords);
3136 victim->skeleton.longdead = 0;
3137 victim->skeleton.free = 1;
3138 victim->skeleton.broken = 0;
3140 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3141 victim->skeleton.joints[i].velchange = 0;
3142 victim->skeleton.joints[i].locked = 0;
3143 //victim->skeleton.joints[i].velocity=0;
3150 Normalise(&relative);
3151 if (!victim->dead) {
3152 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3153 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3155 victim->jointVel(abdomen) += relative * damagemult * 40;
3158 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3159 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3162 victim->Puff(abdomen);
3163 if (tutoriallevel != 1) {
3164 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3166 if (!victim->dead) {
3167 award_bonus(id, solidhit, 40);
3173 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3174 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3179 relative = victim->coords - coords;
3181 Normalise(&relative);
3185 if (Animation::animations[victim->animTarget].height == lowheight) {
3191 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3192 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3194 victim->jointVel(head) += relative * damagemult * 200;
3195 if (tutoriallevel != 1) {
3196 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3199 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3200 if (victim->howactive == typesleeping)
3201 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3202 if (creature == wolftype) {
3203 emit_sound_at(clawslicesound, victim->coords, 128.);
3205 victim->DoBloodBig(2 / victim->armorhead, 175);
3208 if (victim->damage >= victim->damagetolerance)
3210 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3211 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3213 victim->jointVel(abdomen) += relative * damagemult * 200;
3214 victim->frameTarget = 0;
3215 victim->animTarget = staggerbackhighanim;
3216 victim->targetyaw = targetyaw + 180;
3218 if (tutoriallevel != 1) {
3219 emit_sound_at(landsound2, victim->coords, 128.);
3221 victim->Puff(abdomen);
3222 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3223 if (creature == wolftype) {
3224 emit_sound_at(clawslicesound, victim->coords, 128.);
3226 victim->DoBloodBig(2 / victim->armorhigh, 170);
3233 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3234 if ((victim->animTarget != jumpupanim) &&
3235 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3236 (victim != this->shared_from_this())) {
3240 if (tutoriallevel != 1) {
3241 emit_sound_at(landsound2, victim->coords, 128.);
3244 relative = victim->coords - coords;
3246 Normalise(&relative);
3248 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3251 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3252 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3254 relative = DoRotation(relative, 0, -90, 0);
3256 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3257 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)
3258 victim->skeleton.joints[i].velocity = relative * 80;
3260 victim->Puff(rightankle);
3261 victim->Puff(leftankle);
3262 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3264 if (victim->damage >= victim->damagetolerance)
3266 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3267 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3269 relative = DoRotation(relative, 0, -90, 0);
3270 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3271 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)
3272 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3274 victim->jointVel(abdomen) += relative * damagemult * 200;
3275 victim->frameTarget = 0;
3276 victim->animTarget = staggerbackhighanim;
3277 victim->targetyaw = targetyaw + 180;
3279 if (tutoriallevel != 1) {
3280 emit_sound_at(landsound2, victim->coords, 128.);
3282 victim->Puff(abdomen);
3283 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3291 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3292 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3300 if (tutoriallevel != 1) {
3301 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3303 if (creature == wolftype) {
3304 emit_sound_at(clawslicesound, victim->coords, 128);
3306 victim->DoBloodBig(2 / victim->armorhigh, 170);
3310 relative = victim->coords - oldcoords;
3312 Normalise(&relative);
3313 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3314 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3316 victim->jointVel(abdomen) += relative * damagemult * 200;
3317 victim->Puff(abdomen);
3318 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3320 award_bonus(id, Reversal);
3323 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3324 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3325 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3326 takeWeapon(victim->weaponids[victim->weaponactive]);
3327 victim->num_weapons--;
3328 if (victim->num_weapons > 0) {
3329 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3331 victim->weaponactive = -1;
3336 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3344 emit_sound_at(whooshhitsound, victim->coords, 128.);
3347 relative = victim->coords - oldcoords;
3349 Normalise(&relative);
3350 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3351 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3353 victim->jointVel(abdomen) += relative * damagemult * 200;
3355 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3358 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3367 award_bonus(id, staffreversebonus);
3369 if (tutoriallevel != 1) {
3370 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3373 award_bonus(id, staffreversebonus); // Huh, again?
3376 relative = victim->coords - oldcoords;
3378 Normalise(&relative);
3379 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3380 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3382 victim->jointVel(abdomen) += relative * damagemult * 200;
3384 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3387 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3393 Normalise(&relative);
3395 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3396 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3398 victim->jointVel(lefthand) *= .1;
3399 victim->jointVel(leftwrist) *= .2;
3400 victim->jointVel(leftelbow) *= .5;
3401 victim->jointVel(leftshoulder) *= .7;
3402 victim->jointVel(righthand) *= .1;
3403 victim->jointVel(rightwrist) *= .2;
3404 victim->jointVel(rightelbow) *= .5;
3405 victim->jointVel(rightshoulder) *= .7;
3407 victim->Puff(abdomen);
3408 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3410 award_bonus(id, Reversal);
3414 if (weaponactive != -1 || creature == wolftype)
3416 if (creature == rabbittype && weaponactive != -1)
3417 if (weapons[weaponids[0]].getType() == staff)
3420 if (weaponactive != -1) {
3421 victim->DoBloodBig(2 / victim->armorhigh, 225);
3422 emit_sound_at(knifeslicesound, victim->coords);
3423 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3424 weapons[weaponids[weaponactive]].bloody = 1;
3425 weapons[weaponids[weaponactive]].blooddrip += 3;
3427 if (weaponactive == -1 && creature == wolftype) {
3428 emit_sound_at(clawslicesound, victim->coords, 128.);
3430 victim->DoBloodBig(2 / victim->armorhigh, 175);
3437 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3443 Normalise(&relative);
3445 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3446 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3448 victim->jointVel(lefthand) *= .1 - 1;
3449 victim->jointVel(leftwrist) *= .2 - 1;
3450 victim->jointVel(leftelbow) *= .5 - 1;
3451 victim->jointVel(leftshoulder) *= .7 - 1;
3452 victim->jointVel(righthand) *= .1 - 1;
3453 victim->jointVel(rightwrist) *= .2 - 1;
3454 victim->jointVel(rightelbow) *= .5 - 1;
3455 victim->jointVel(rightshoulder) *= .7 - 1;
3457 award_bonus(id, swordreversebonus);
3460 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3468 if (tutoriallevel != 1) {
3469 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3473 relative = victim->coords - oldcoords;
3475 Normalise(&relative);
3476 relative = DoRotation(relative, 0, -90, 0);
3477 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3478 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3480 victim->jointVel(abdomen) += relative * damagemult * 200;
3481 victim->Puff(abdomen);
3482 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3484 award_bonus(id, Reversal);
3487 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3490 victim->skeleton.spinny = 0;
3492 relative = facing * -1;
3494 Normalise(&relative);
3495 if (victim->id == 0)
3497 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3498 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3500 victim->damage = victim->damagetolerance;
3501 victim->permanentdamage = victim->damagetolerance - 1;
3504 if (weaponactive != -1 || creature == wolftype)
3506 if (creature == rabbittype && weaponactive != -1)
3507 if (weapons[weaponids[0]].getType() == staff)
3510 if (weaponactive != -1) {
3511 victim->DoBloodBig(200, 225);
3512 emit_sound_at(knifeslicesound, victim->coords);
3514 weapons[weaponids[weaponactive]].bloody = 2;
3515 weapons[weaponids[weaponactive]].blooddrip += 5;
3518 if (creature == wolftype && weaponactive == -1) {
3519 emit_sound_at(clawslicesound, victim->coords, 128.);
3521 victim->DoBloodBig(2, 175);
3524 award_bonus(id, spinecrusher);
3527 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3528 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3530 if (animTarget == knifefollowanim)
3531 victim->DoBloodBig(200, 210);
3532 if (animTarget == knifesneakattackanim) {
3533 XYZ footvel, footpoint;
3535 footpoint = weapons[weaponids[0]].tippoint;
3537 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3538 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3542 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3543 victim->DoBloodBig(200, 195);
3544 award_bonus(id, tracheotomy);
3546 if (animTarget == knifefollowanim) {
3547 award_bonus(id, Stabbonus);
3548 XYZ footvel, footpoint;
3550 footpoint = weapons[weaponids[0]].tippoint;
3552 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3553 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3554 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3555 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3556 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3557 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3560 victim->bloodloss += 10000;
3561 victim->velocity = 0;
3562 emit_sound_at(fleshstabsound, victim->coords);
3564 weapons[weaponids[weaponactive]].bloody = 2;
3565 weapons[weaponids[weaponactive]].blooddrip += 5;
3569 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3571 victim->velocity = 0;
3572 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3573 victim->skeleton.joints[i].velocity = 0;
3575 if (animTarget == knifefollowanim) {
3577 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3578 victim->skeleton.joints[i].velocity = 0;
3581 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3582 emit_sound_at(fleshstabremovesound, victim->coords);
3584 weapons[weaponids[weaponactive]].bloody = 2;
3585 weapons[weaponids[weaponactive]].blooddrip += 5;
3587 XYZ footvel, footpoint;
3589 footpoint = weapons[weaponids[0]].tippoint;
3591 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3592 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3593 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3594 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3595 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3596 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3600 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3601 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3602 award_bonus(id, backstab);
3606 XYZ footvel, footpoint;
3608 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3610 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3611 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3612 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3613 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3614 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3615 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3616 victim->DoBloodBig(200, 180);
3617 victim->DoBloodBig(200, 215);
3618 victim->bloodloss += 10000;
3619 victim->velocity = 0;
3620 emit_sound_at(fleshstabsound, victim->coords);
3622 weapons[weaponids[weaponactive]].bloody = 2;
3623 weapons[weaponids[weaponactive]].blooddrip += 5;
3627 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3629 victim->velocity = 0;
3630 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3631 victim->skeleton.joints[i].velocity = 0;
3633 if (weaponactive != -1) {
3634 emit_sound_at(fleshstabremovesound, victim->coords);
3636 weapons[weaponids[weaponactive]].bloody = 2;
3637 weapons[weaponids[weaponactive]].blooddrip += 5;
3639 XYZ footvel, footpoint;
3641 footpoint = weapons[weaponids[0]].tippoint;
3643 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3644 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3645 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3646 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3647 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3648 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3652 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3660 if (weaponactive == -1) {
3661 if (tutoriallevel != 1) {
3662 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3667 if (weaponactive != -1 || creature == wolftype)
3669 if (creature == rabbittype && weaponactive != -1)
3670 if (weapons[weaponids[0]].getType() == staff)
3673 if (weaponactive != -1) {
3674 victim->DoBloodBig(2 / victim->armorhead, 225);
3675 emit_sound_at(knifeslicesound, victim->coords);
3676 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3677 weapons[weaponids[weaponactive]].bloody = 1;
3678 weapons[weaponids[weaponactive]].blooddrip += 3;
3680 if (weaponactive == -1 && creature == wolftype) {
3681 emit_sound_at(clawslicesound, victim->coords, 128.);
3683 victim->DoBloodBig(2 / victim->armorhead, 175);
3687 award_bonus(id, Reversal);
3692 relative = facing * -1;
3694 Normalise(&relative);
3695 relative = DoRotation(relative, 0, 90, 0);
3697 Normalise(&relative);
3698 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3699 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3701 victim->jointVel(head) += relative * damagemult * 200;
3702 if (victim->damage < victim->damagetolerance - 100)
3703 victim->velocity = relative * 200;
3704 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3705 victim->velocity = 0;
3708 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))) {
3712 relative = facing * -1;
3714 Normalise(&relative);
3715 relative = DoRotation(relative, 0, 90, 0);
3717 Normalise(&relative);
3718 for (int i = 0; i < victim->skeleton.joints.size(); i++) {
3719 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3721 victim->jointVel(head) += relative * damagemult * 200;
3724 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3725 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3726 award_bonus(id, reverseko);
3732 if (frameTarget > Animation::animations[animCurrent].frames.size() - 1) {
3735 animTarget = getIdle();
3736 FootLand(leftfoot, 1);
3737 FootLand(rightfoot, 1);
3739 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3740 animTarget = rollanim;
3742 emit_sound_at(movewhooshsound, coords, 128.);
3744 if (animCurrent == staggerbackhighanim) {
3745 animTarget = getIdle();
3747 if (animCurrent == staggerbackhardanim) {
3748 animTarget = getIdle();
3750 if (animCurrent == removeknifeanim) {
3751 animTarget = getIdle();
3753 if (animCurrent == crouchremoveknifeanim) {
3754 animTarget = getCrouch();
3756 if (animCurrent == backhandspringanim) {
3757 animTarget = getIdle();
3759 if (animCurrent == dodgebackanim) {
3760 animTarget = getIdle();
3762 if (animCurrent == drawleftanim) {
3763 animTarget = getIdle();
3765 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3766 animTarget = getIdle();
3767 if (animCurrent == crouchdrawrightanim) {
3768 animTarget = getCrouch();
3770 if (weaponactive == -1)
3772 else if (weaponactive == 0) {
3774 if (num_weapons == 2) {
3776 buffer = weaponids[0];
3777 weaponids[0] = weaponids[1];
3778 weaponids[1] = buffer;
3782 if (weaponactive == -1) {
3783 emit_sound_at(knifesheathesound, coords, 128.);
3785 if (weaponactive != -1) {
3786 emit_sound_at(knifedrawsound, coords, 128.);
3789 if (animCurrent == rollanim) {
3790 animTarget = getCrouch();
3791 FootLand(leftfoot, 1);
3792 FootLand(rightfoot, 1);
3795 if (animTarget == walljumprightkickanim) {
3798 if (animTarget == walljumpleftkickanim) {
3801 animTarget = jumpdownanim;
3803 if (animCurrent == climbanim) {
3804 animTarget = getCrouch();
3806 coords += facing * .1;
3807 if (!isnormal(coords.x))
3818 if (animTarget == rabbitkickreversalanim) {
3819 animTarget = getCrouch();
3822 if (animTarget == jumpreversalanim) {
3823 animTarget = getCrouch();
3826 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3827 if (attackkeydown && animTarget != walljumpfrontanim) {
3829 float closestdist = -1;
3831 if (Person::players.size() > 1)
3832 for (unsigned i = 0; i < Person::players.size(); i++) {
3833 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3834 distance = distsq(&Person::players[i]->coords, &coords);
3835 if (closestdist == -1 || distance < closestdist) {
3836 closestdist = distance;
3841 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3842 victim = Person::players[closest];
3843 animTarget = walljumprightkickanim;
3845 XYZ rotatetarget = victim->coords - coords;
3846 Normalise(&rotatetarget);
3847 yaw = -asin(0 - rotatetarget.x);
3849 if (rotatetarget.z < 0)
3851 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3852 velocity = (victim->coords - coords) * 4;
3857 if (animTarget == walljumpbackanim) {
3858 animTarget = backflipanim;
3860 velocity = facing * -8;
3863 resume_stream(whooshsound);
3865 if (animTarget == walljumprightanim) {
3866 animTarget = rightflipanim;
3870 velocity = DoRotation(facing, 0, 30, 0) * -8;
3873 if (animTarget == walljumpfrontanim) {
3874 animTarget = frontflipanim;
3878 velocity = facing * 8;
3882 resume_stream(whooshsound);
3884 if (animTarget == walljumpleftanim) {
3885 if (attackkeydown) {
3887 float closestdist = -1;
3889 if (Person::players.size() > 1)
3890 for (unsigned i = 0; i < Person::players.size(); i++) {
3891 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3892 distance = distsq(&Person::players[i]->coords, &coords);
3893 if (closestdist == -1 || distance < closestdist) {
3894 closestdist = distance;
3899 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3900 victim = Person::players[closest];
3901 animTarget = walljumpleftkickanim;
3903 XYZ rotatetarget = victim->coords - coords;
3904 Normalise(&rotatetarget);
3905 yaw = -asin(0 - rotatetarget.x);
3907 if (rotatetarget.z < 0)
3909 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3910 velocity = (victim->coords - coords) * 4;
3915 if (animTarget != walljumpleftkickanim) {
3916 animTarget = leftflipanim;
3920 velocity = DoRotation(facing, 0, -30, 0) * -8;
3924 resume_stream(whooshsound);
3926 if (animTarget == sneakattackanim) {
3927 animCurrent = getCrouch();
3928 animTarget = getCrouch();
3935 transspeed = 1000000;
3936 targetheadyaw += 180;
3937 coords -= facing * .7;
3939 coords.y = terrain.getHeight(coords.x, coords.z);
3943 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3944 animTarget = getIdle();
3947 coords.y = terrain.getHeight(coords.x, coords.z);
3951 if (animCurrent == knifefollowanim) {
3952 animTarget = getIdle();
3955 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3956 float ycoords = oldcoords.y;
3957 animTarget = getStop();
3962 transspeed = 1000000;
3963 targetheadyaw += 180;
3964 if (!isnormal(coords.x))
3966 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3967 oldcoords = coords + facing * .5;
3968 else if (animCurrent == sweepreversalanim)
3969 oldcoords = coords + facing * 1.1;
3970 else if (animCurrent == upunchreversalanim) {
3971 oldcoords = coords + facing * 1.5;
3974 targetheadyaw += 180;
3977 } else if (animCurrent == knifeslashreversalanim) {
3978 oldcoords = coords + facing * .5;
3981 targetheadyaw += 90;
3984 } else if (animCurrent == staffspinhitreversalanim) {
3987 targetheadyaw += 180;
3992 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3994 oldcoords.y = ycoords;
3995 currentoffset = coords - oldcoords;
4001 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4006 if (Animation::animations[animTarget].attack == reversed) {
4008 if (animTarget == sweepreversedanim)
4010 animTarget = backhandspringanim;
4012 emit_sound_at(landsound, coords, 128);
4014 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4015 animTarget = rollanim;
4018 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4019 coords.y = oldcoords.y;
4021 if (animCurrent == knifeslashreversedanim) {
4022 animTarget = rollanim;
4027 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4028 coords.y = oldcoords.y;
4032 animTarget = jumpdownanim;
4035 animTarget = getIdle();
4037 animTarget = getIdle();
4038 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4039 animTarget = getIdle();
4041 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4042 coords.y = oldcoords.y;
4043 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4044 targetoffset.y = coords.y;
4046 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4047 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4048 currentoffset.y -= (coords.y - targetoffset.y);
4049 coords.y = targetoffset.y;
4051 normalsupdatedelay = 0;
4053 if (animCurrent == upunchanim) {
4054 animTarget = getStop();
4055 normalsupdatedelay = 0;
4058 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4062 if (num_weapons > 0)
4063 if (weapons[0].getType() == staff)
4069 rabbitkickragdoll = 1;
4071 if (animCurrent == rabbitkickreversedanim) {
4077 skeleton.spinny = 0;
4078 SolidHitBonus(!id); // FIXME: tricky id
4082 animTarget = rollanim;
4085 pause_sound(whooshsound);
4089 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4093 skeleton.spinny = 0;
4095 if (animCurrent == jumpreversedanim) {
4101 skeleton.spinny = 0;
4102 SolidHitBonus(!id); // FIXME: tricky id
4106 animTarget = rollanim;
4107 coords += facing * 2;
4109 pause_sound(whooshsound);
4114 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) {
4115 animTarget = getupfromfrontanim;
4117 } else if (Animation::animations[animCurrent].attack == normalattack) {
4118 animTarget = getIdle();
4121 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4122 animTarget = blockhighleftstrikeanim;
4124 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4125 animTarget = getIdle();
4128 if (animCurrent == spinkickanim && victim->skeleton.free) {
4129 if (creature == rabbittype)
4130 animTarget = fightidleanim;
4135 if (isIdle() && !wasIdle())
4136 normalsupdatedelay = 0;
4138 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4139 animTarget = jumpdownanim;
4142 if (!skeleton.free) {
4144 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4145 if (!isRun() || !wasRun()) {
4146 if (targetFrame().speed > currentFrame().speed)
4147 target += multiplier * targetFrame().speed * speed * 2;
4148 if (targetFrame().speed <= currentFrame().speed)
4149 target += multiplier * currentFrame().speed * speed * 2;
4151 if (isRun() && wasRun()) {
4153 tempspeed = velspeed;
4154 if (tempspeed < 10 * speedmult)
4155 tempspeed = 10 * speedmult;
4156 /* FIXME - mixed of target and current here, is that intended? */
4157 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4159 } else if (transspeed)
4160 target += multiplier * transspeed * speed * 2;
4162 if (!isRun() || !wasRun()) {
4163 if (targetFrame().speed > currentFrame().speed)
4164 target += multiplier * targetFrame().speed * 2;
4165 if (targetFrame().speed <= currentFrame().speed)
4166 target += multiplier * currentFrame().speed * 2;
4170 if (animCurrent != animTarget)
4171 target = (target + oldtarget) / 2;
4174 frameCurrent = frameTarget;
4178 rot = targetrot * target;
4179 yaw += rot - oldrot;
4185 if (frameCurrent >= Animation::animations[animCurrent].frames.size()) {
4186 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4188 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4190 for (int i = 0; i < skeleton.joints.size(); i++) {
4191 skeleton.joints[i].position = currentFrame().joints[i].position;
4194 skeleton.FindForwards();
4196 for (int i = 0; i < skeleton.muscles.size(); i++) {
4197 if (skeleton.muscles[i].visible) {
4198 skeleton.FindRotationMuscle(i, animTarget);
4201 for (int i = 0; i < skeleton.muscles.size(); i++) {
4202 if (skeleton.muscles[i].visible) {
4203 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4204 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4205 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4206 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4207 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4208 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4213 for (int i = 0; i < skeleton.joints.size(); i++) {
4214 skeleton.joints[i].position = targetFrame().joints[i].position;
4217 skeleton.FindForwards();
4219 for (int i = 0; i < skeleton.muscles.size(); i++) {
4220 if (skeleton.muscles[i].visible) {
4221 skeleton.FindRotationMuscle(i, animTarget);
4224 for (int i = 0; i < skeleton.muscles.size(); i++) {
4225 if (skeleton.muscles[i].visible) {
4226 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4227 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4228 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4229 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4230 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4231 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4232 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4233 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4234 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4235 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4236 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4237 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4242 oldanimCurrent = animCurrent;
4243 oldanimTarget = animTarget;
4244 oldframeTarget = frameTarget;
4245 oldframeCurrent = frameCurrent;
4247 for (int i = 0; i < skeleton.joints.size(); i++) {
4248 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4249 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4251 offset = currentoffset * (1 - target) + targetoffset * target;
4252 for (int i = 0; i < skeleton.muscles.size(); i++) {
4253 if (skeleton.muscles[i].visible) {
4254 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4255 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4256 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4261 if (isLanding() && landhard) {
4264 animTarget = getLandhard();
4277 void Person::DoStuff()
4279 static XYZ terrainnormal;
4280 static XYZ flatfacing;
4281 static XYZ flatvelocity;
4282 static float flatvelspeed;
4286 static int bloodsize;
4287 static int startx, starty, endx, endy;
4288 static GLubyte color;
4289 static XYZ bloodvel;
4291 onfiredelay -= multiplier;
4292 if (onfiredelay < 0 && onfire) {
4293 if (Random() % 2 == 0) {
4299 crouchkeydowntime += multiplier;
4301 crouchkeydowntime = 0;
4302 jumpkeydowntime += multiplier;
4303 if (!jumpkeydown && skeleton.free)
4304 jumpkeydowntime = 0;
4306 if (hostile || damage > 0 || bloodloss > 0)
4309 if (isIdle() || isRun())
4312 if (num_weapons == 1 && weaponactive != -1)
4316 blooddimamount -= multiplier * .3;
4317 speechdelay -= multiplier;
4318 texupdatedelay -= multiplier;
4319 interestdelay -= multiplier;
4320 flamedelay -= multiplier;
4321 parriedrecently -= multiplier;
4323 victim = this->shared_from_this();
4328 speed = 1.1 * speedmult;
4330 speed = 1.0 * speedmult;
4332 rabbitkickragdoll = 0;
4336 if (id != 0 && (creature == rabbittype || difficulty != 2))
4338 if (id != 0 && creature == wolftype && difficulty == 2) {
4340 if (aitype != passivetype) {
4342 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) {
4348 if (animTarget == wolfrunninganim && !superruntoggle) {
4349 animTarget = getRun();
4353 if (weaponactive == -1 && num_weapons > 0) {
4354 if (weapons[weaponids[0]].getType() == staff) {
4360 burnt += multiplier;
4364 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4366 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4372 vel[0] = velocity.x;
4373 vel[1] = velocity.y;
4374 vel[2] = velocity.z;
4377 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4378 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4382 while (flamedelay < 0 && onfire) {
4384 howmany = abs(Random() % (skeleton.joints.size()));
4385 if (skeleton.free) {
4386 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4387 flatfacing = skeleton.joints[howmany].position * scale + coords;
4389 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4390 flatvelocity = (coords - oldcoords) / multiplier / 2;
4392 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4395 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4397 howmany = abs(Random() % (skeleton.joints.size()));
4398 if (skeleton.free) {
4399 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4400 flatfacing = skeleton.joints[howmany].position * scale + coords;
4402 flatvelocity = (coords - oldcoords) / multiplier / 2;
4403 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4405 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4409 bleeding -= multiplier * .3;
4410 if (bloodtoggle == 2) {
4411 skeleton.drawmodel.textureptr.bind();
4412 if ((bleeding <= 0) && (detail != 2))
4417 if (neckspurtamount > 0) {
4418 neckspurtamount -= multiplier;
4419 neckspurtdelay -= multiplier * 3;
4420 neckspurtparticledelay -= multiplier * 3;
4421 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4424 if (skeleton.free) {
4425 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4426 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4427 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4429 bloodvel.z = 5 * neckspurtamount;
4430 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4431 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4432 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4434 neckspurtparticledelay = .05;
4436 if (neckspurtdelay < 0) {
4441 if (deathbleeding > 0 && dead != 2) {
4442 if (deathbleeding < 5)
4443 bleeddelay -= deathbleeding * multiplier / 4;
4445 bleeddelay -= 5 * multiplier / 4;
4446 if (bleeddelay < 0 && bloodtoggle) {
4451 if (skeleton.free) {
4452 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4453 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4455 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4456 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4460 bloodloss += deathbleeding * multiplier * 80;
4461 deathbleeding -= multiplier * 1.6;
4462 if (deathbleeding < 0)
4464 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4465 if (weaponactive != -1) {
4466 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4467 weapons[weaponids[0]].velocity.x += .01;
4470 weaponids[0] = weaponids[num_weapons];
4471 if (weaponstuck == num_weapons)
4475 for (unsigned i = 0; i < Person::players.size(); i++) {
4476 Person::players[i]->wentforweapon = 0;
4484 if (!dead && creature == wolftype) {
4485 award_bonus(0, Wolfbonus);
4488 if (animTarget == knifefollowedanim && !skeleton.free) {
4489 for (int i = 0; i < skeleton.joints.size(); i++) {
4490 skeleton.joints[i].velocity = 0;
4491 skeleton.joints[i].velocity.y = -2;
4494 if (id != 0 && unconscioustime > .1) {
4502 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4503 texupdatedelay = .12;
4505 bloodsize = 5 - realtexdetail;
4509 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4510 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4511 endx = startx + bloodsize;
4512 endy = starty + bloodsize;
4522 if (endx > skeleton.skinsize - 1) {
4523 endx = skeleton.skinsize - 1;
4526 if (endy > skeleton.skinsize - 1) {
4527 endy = skeleton.skinsize - 1;
4535 for (i = startx; i < endx; i++) {
4536 for (j = starty; j < endy; j++) {
4537 if (Random() % 2 == 0) {
4538 color = Random() % 85 + 170;
4539 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4540 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4541 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4542 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4547 skeleton.drawmodel.textureptr.bind();
4551 if (skeleton.free) {
4552 bleedx += 4 * direction / realtexdetail;
4554 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4556 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4558 bleedy -= 4 / realtexdetail;
4560 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4562 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4566 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4567 righthandmorphness = targetrighthandmorphness;
4568 righthandmorphstart = righthandmorphend;
4569 } else if (righthandmorphness > targetrighthandmorphness) {
4570 righthandmorphness -= multiplier * 4;
4571 } else if (righthandmorphness < targetrighthandmorphness) {
4572 righthandmorphness += multiplier * 4;
4575 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4576 lefthandmorphness = targetlefthandmorphness;
4577 lefthandmorphstart = lefthandmorphend;
4578 } else if (lefthandmorphness > targetlefthandmorphness) {
4579 lefthandmorphness -= multiplier * 4;
4580 } else if (lefthandmorphness < targetlefthandmorphness) {
4581 lefthandmorphness += multiplier * 4;
4584 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4585 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4586 tailmorphness = targettailmorphness;
4587 tailmorphstart = tailmorphend;
4588 } else if (tailmorphness > targettailmorphness) {
4589 tailmorphness -= multiplier * 10;
4590 } else if (tailmorphness < targettailmorphness) {
4591 tailmorphness += multiplier * 10;
4595 if (creature == wolftype) {
4596 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4597 tailmorphness = targettailmorphness;
4598 tailmorphstart = tailmorphend;
4599 } else if (tailmorphness > targettailmorphness) {
4600 tailmorphness -= multiplier * 2;
4601 } else if (tailmorphness < targettailmorphness) {
4602 tailmorphness += multiplier * 2;
4606 if (headmorphend == 3 || headmorphstart == 3) {
4607 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4608 headmorphness = targetheadmorphness;
4609 headmorphstart = headmorphend;
4610 } else if (headmorphness > targetheadmorphness) {
4611 headmorphness -= multiplier * 7;
4612 } else if (headmorphness < targetheadmorphness) {
4613 headmorphness += multiplier * 7;
4615 } else if (headmorphend == 5 || headmorphstart == 5) {
4616 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4617 headmorphness = targetheadmorphness;
4618 headmorphstart = headmorphend;
4619 } else if (headmorphness > targetheadmorphness) {
4620 headmorphness -= multiplier * 10;
4621 } else if (headmorphness < targetheadmorphness) {
4622 headmorphness += multiplier * 10;
4625 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4626 headmorphness = targetheadmorphness;
4627 headmorphstart = headmorphend;
4628 } else if (headmorphness > targetheadmorphness) {
4629 headmorphness -= multiplier * 4;
4630 } else if (headmorphness < targetheadmorphness) {
4631 headmorphness += multiplier * 4;
4635 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4636 chestmorphness = targetchestmorphness;
4637 chestmorphstart = chestmorphend;
4638 } else if (chestmorphness > targetchestmorphness) {
4639 chestmorphness -= multiplier;
4640 } else if (chestmorphness < targetchestmorphness) {
4641 chestmorphness += multiplier;
4644 if (dead != 2 && howactive <= typesleeping) {
4645 if (chestmorphstart == 0 && chestmorphend == 0) {
4647 targetchestmorphness = 1;
4650 if (chestmorphstart != 0 && chestmorphend != 0) {
4652 targetchestmorphness = 1;
4654 if (environment == snowyenvironment) {
4657 if (skeleton.free) {
4658 footvel = skeleton.specialforward[0] * -1;
4659 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4661 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4662 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4664 if (animTarget == sleepanim)
4665 footvel = DoRotation(footvel, 0, 90, 0);
4666 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4670 if (!dead && howactive < typesleeping) {
4671 blinkdelay -= multiplier * 2;
4672 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4674 targetheadmorphness = 1;
4676 blinkdelay = (float)(abs(Random() % 40)) / 5;
4678 if (headmorphstart == 3 && headmorphend == 3) {
4680 targetheadmorphness = 1;
4685 twitchdelay -= multiplier * 1.5;
4686 if (animTarget != hurtidleanim) {
4687 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4689 targetheadmorphness = 1;
4691 twitchdelay = (float)(abs(Random() % 40)) / 5;
4693 if (headmorphstart == 5 && headmorphend == 5) {
4695 targetheadmorphness = 1;
4699 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4700 twitchdelay3 -= multiplier * 1;
4701 if (Random() % 2 == 0) {
4702 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4703 righthandmorphness = 0;
4704 targetrighthandmorphness = 1;
4705 righthandmorphend = 1;
4706 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4708 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4709 righthandmorphness = 0;
4710 targetrighthandmorphness = 1;
4711 righthandmorphend = 0;
4714 if (Random() % 2 == 0) {
4715 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4716 lefthandmorphness = 0;
4717 targetlefthandmorphness = 1;
4718 lefthandmorphend = 1;
4719 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4721 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4722 lefthandmorphness = 0;
4723 targetlefthandmorphness = 1;
4724 lefthandmorphend = 0;
4730 if (creature == rabbittype) {
4731 if (howactive < typesleeping)
4732 twitchdelay2 -= multiplier * 1.5;
4734 twitchdelay2 -= multiplier * 0.5;
4735 if (howactive <= typesleeping) {
4736 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4738 targettailmorphness = 1;
4740 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4742 if (tailmorphstart == 1 && tailmorphend == 1) {
4744 targettailmorphness = 1;
4747 if (tailmorphstart == 2 && tailmorphend == 2) {
4749 targettailmorphness = 1;
4756 if (creature == wolftype) {
4757 twitchdelay2 -= multiplier * 1.5;
4758 if (tailmorphend != 0)
4759 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4761 targettailmorphness = 1;
4765 if (tailmorphend != 5)
4766 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4768 targettailmorphness = 1;
4772 if (twitchdelay2 <= 0) {
4773 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4775 targettailmorphness = 1;
4778 if (tailmorphstart == 1 && tailmorphend == 1) {
4780 targettailmorphness = 1;
4783 if (tailmorphstart == 2 && tailmorphend == 2) {
4785 targettailmorphness = 1;
4788 if (tailmorphstart == 3 && tailmorphend == 3) {
4790 targettailmorphness = 1;
4793 if (tailmorphstart == 4 && tailmorphend == 4) {
4795 targettailmorphness = 1;
4802 unconscioustime = 0;
4804 if (dead == 1 || howactive == typesleeping) {
4805 unconscioustime += multiplier;
4806 //If unconscious, close eyes and mouth
4807 if (righthandmorphend != 0)
4808 righthandmorphness = 0;
4809 righthandmorphend = 0;
4810 targetrighthandmorphness = 1;
4812 if (lefthandmorphend != 0)
4813 lefthandmorphness = 0;
4814 lefthandmorphend = 0;
4815 targetlefthandmorphness = 1;
4817 if (headmorphend != 3 && headmorphend != 5)
4820 targetheadmorphness = 1;
4824 if (howactive > typesleeping) {
4827 if (bloodtoggle && !bled) {
4828 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4830 if (bloodtoggle && !bled)
4831 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4832 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4833 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4837 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4842 if (dead == 2 || howactive > typesleeping) {
4843 //If dead, open mouth and hands
4844 if (righthandmorphend != 0)
4845 righthandmorphness = 0;
4846 righthandmorphend = 0;
4847 targetrighthandmorphness = 1;
4849 if (lefthandmorphend != 0)
4850 lefthandmorphness = 0;
4851 lefthandmorphend = 0;
4852 targetlefthandmorphness = 1;
4854 if (headmorphend != 2)
4857 targetheadmorphness = 1;
4860 if (stunned > 0 && !dead && headmorphend != 2) {
4861 if (headmorphend != 4)
4864 targetheadmorphness = 1;
4867 if (damage > damagetolerance && !dead) {
4870 unconscioustime = 0;
4872 if (creature == wolftype) {
4873 award_bonus(0, Wolfbonus);
4878 if (weaponactive != -1) {
4879 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4880 weapons[weaponids[0]].velocity.x += .01;
4883 weaponids[0] = weaponids[num_weapons];
4884 if (weaponstuck == num_weapons)
4888 for (unsigned i = 0; i < Person::players.size(); i++) {
4889 Person::players[i]->wentforweapon = 0;
4895 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4904 damage -= multiplier * 13;
4906 permanentdamage -= multiplier * 4;
4907 if (isIdle() || isCrouch()) {
4909 permanentdamage -= multiplier * 4;
4913 if (permanentdamage < 0)
4914 permanentdamage = 0;
4915 if (superpermanentdamage < 0)
4916 superpermanentdamage = 0;
4917 if (permanentdamage < superpermanentdamage) {
4918 permanentdamage = superpermanentdamage;
4920 if (damage < permanentdamage) {
4921 damage = permanentdamage;
4923 if (dead == 1 && damage < damagetolerance) {
4927 for (int i = 0; i < skeleton.joints.size(); i++) {
4928 skeleton.joints[i].velocity = 0;
4931 if (permanentdamage > damagetolerance && dead != 2) {
4934 if (weaponactive != -1) {
4935 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4936 weapons[weaponids[0]].velocity.x += .01;
4939 weaponids[0] = weaponids[num_weapons];
4940 if (weaponstuck == num_weapons)
4944 for (unsigned i = 0; i < Person::players.size(); i++) {
4945 Person::players[i]->wentforweapon = 0;
4951 if (!dead && creature == wolftype) {
4952 award_bonus(0, Wolfbonus);
4955 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4956 award_bonus(id, touchofdeath);
4957 if (id != 0 && unconscioustime > .1) {
4965 emit_sound_at(breaksound, coords);
4968 if (skeleton.free == 1) {
4970 pause_sound(whooshsound);
4973 //If knocked over, open hands and close mouth
4974 if (righthandmorphend != 0)
4975 righthandmorphness = 0;
4976 righthandmorphend = 0;
4977 targetrighthandmorphness = 1;
4979 if (lefthandmorphend != 0)
4980 lefthandmorphness = 0;
4981 lefthandmorphend = 0;
4982 targetlefthandmorphness = 1;
4984 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4985 if (headmorphend != 0)
4988 targetheadmorphness = 1;
4992 skeleton.DoGravity(&scale);
4994 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4995 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4996 award_bonus(id, deepimpact);
4997 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5001 for (j = 0; j < skeleton.joints.size(); j++) {
5002 average += skeleton.joints[j].position;
5006 coords += average * scale;
5007 for (j = 0; j < skeleton.joints.size(); j++) {
5008 skeleton.joints[j].position -= average;
5010 average /= multiplier;
5013 for (int i = 0; i < skeleton.joints.size(); i++) {
5014 velocity += skeleton.joints[i].velocity * scale;
5016 velocity /= skeleton.joints.size();
5018 if (!isnormal(velocity.x) && velocity.x) {
5022 if (findLength(&average) < 10 && dead && skeleton.free) {
5023 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5024 if (skeleton.longdead > 2000) {
5025 if (skeleton.longdead > 6000) {
5027 pause_sound(whooshsound);
5032 if (dead == 2 && bloodloss < damagetolerance) {
5034 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5036 if (bloodtoggle && !bled) {
5037 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5039 if (bloodtoggle && !bled)
5040 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5041 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5042 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5043 float size = .2 * 1.2;
5046 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5050 if (dead == 2 && bloodloss >= damagetolerance) {
5052 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5055 if (bloodtoggle && !bled) {
5056 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5058 if (bloodtoggle && !bled)
5059 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5060 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5061 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5065 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5072 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5073 bool canrecover = 1;
5074 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5075 startpoint = coords;
5078 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5080 if (velocity.y < -30)
5082 for (i = 0; i < objects.numobjects; i++) {
5083 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5084 colviewer = startpoint;
5085 coltarget = endpoint;
5086 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5095 terrainnormal = jointPos(groin) - jointPos(abdomen);
5096 if (joint(groin).locked && joint(abdomen).locked) {
5097 terrainnormal = jointPos(groin) - jointPos(abdomen);
5098 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5100 if (joint(abdomen).locked && joint(neck).locked) {
5101 terrainnormal = jointPos(abdomen) - jointPos(neck);
5102 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5104 if (joint(groin).locked && joint(neck).locked) {
5105 terrainnormal = jointPos(groin) - jointPos(neck);
5106 middle = (jointPos(groin) + jointPos(neck)) / 2;
5108 Normalise(&terrainnormal);
5110 targetyaw = -asin(0 - terrainnormal.x);
5111 targetyaw *= 360 / 6.28;
5112 if (terrainnormal.z < 0)
5113 targetyaw = 180 - targetyaw;
5117 animTarget = flipanim;
5118 crouchtogglekeydown = 1;
5123 animCurrent = tempanim;
5127 for (int i = 0; i < skeleton.joints.size(); i++) {
5128 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5129 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5134 if (findLength(&average) < 10 && !dead && skeleton.free) {
5135 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5136 if (skeleton.longdead > (damage + 500) * 1.5) {
5138 pause_sound(whooshsound);
5144 terrainnormal = jointPos(groin) - jointPos(abdomen);
5145 if (joint(groin).locked && joint(abdomen).locked) {
5146 terrainnormal = jointPos(groin) - jointPos(abdomen);
5147 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5149 if (joint(abdomen).locked && joint(neck).locked) {
5150 terrainnormal = jointPos(abdomen) - jointPos(neck);
5151 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5153 if (joint(groin).locked && joint(neck).locked) {
5154 terrainnormal = jointPos(groin) - jointPos(neck);
5155 middle = (jointPos(groin) + jointPos(neck)) / 2;
5157 Normalise(&terrainnormal);
5159 targetyaw = -asin(0 - terrainnormal.x);
5160 targetyaw *= 360 / 6.28;
5161 if (terrainnormal.z < 0)
5162 targetyaw = 180 - targetyaw;
5165 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5168 if (skeleton.forward.y < 0) {
5169 animTarget = getupfrombackanim;
5173 if (skeleton.forward.y > -.3) {
5174 animTarget = getupfromfrontanim;
5182 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5183 animTarget = rollanim;
5184 targetyaw = lookyaw;
5201 if ( !leftkeydown && !rightkeydown)
5208 if (abs(targettilt2) > 50)
5210 animCurrent = tempanim;
5213 tilt2 = targettilt2;
5215 if (middle.y > 0 && animTarget != rollanim)
5216 targetoffset.y = middle.y + 1;
5218 for (int i = 0; i < skeleton.joints.size(); i++) {
5219 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5220 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5227 if (num_weapons > 0)
5228 if (weapons[0].getType() == staff)
5230 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5231 if (velocity.y > -30) {
5233 tempvelocity = velocity;
5234 Normalise(&tempvelocity);
5235 targetyaw = -asin(0 - tempvelocity.x);
5236 targetyaw *= 360 / 6.28;
5238 targetyaw = 180 - targetyaw;
5242 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5243 animTarget = rollanim;
5246 animTarget = backhandspringanim;
5252 emit_sound_at(movewhooshsound, coords, 128.);
5254 animCurrent = animTarget;
5255 frameCurrent = frameTarget - 1;
5267 if (skeleton.freefall == 0)
5272 if (aitype != passivetype || skeleton.free == 1)
5273 if (findLengthfast(&velocity) > .1)
5274 for (i = 0; i < objects.numobjects; i++) {
5275 if (objects.type[i] == firetype)
5276 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) {
5278 if (!objects.onfire[i]) {
5279 emit_sound_at(firestartsound, objects.position[i]);
5281 objects.onfire[i] = 1;
5284 if (objects.onfire[i]) {
5289 if (objects.type[i] == bushtype)
5290 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) {
5292 if (!objects.onfire[i]) {
5293 emit_sound_at(firestartsound, objects.position[i]);
5295 objects.onfire[i] = 1;
5299 if (objects.onfire[i]) {
5303 if (objects.messedwith[i] <= 0) {
5307 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5310 addEnvSound(coords, 4 * findLength(&velocity));
5314 if (environment == grassyenvironment)
5315 howmany = findLength(&velocity) * 4;
5316 if (environment == snowyenvironment)
5317 howmany = findLength(&velocity) * 2;
5319 if (environment != desertenvironment)
5320 for (j = 0; j < howmany; j++) {
5321 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5322 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5323 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5326 pos.x += float(abs(Random() % 100) - 50) / 200;
5327 pos.y += float(abs(Random() % 100) - 50) / 200;
5328 pos.z += float(abs(Random() % 100) - 50) / 200;
5329 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);
5330 Sprite::setLastSpriteSpecial(1);
5332 howmany = findLength(&velocity) * 4;
5334 if (environment == snowyenvironment)
5335 for (j = 0; j < howmany; j++) {
5336 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5337 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5338 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5341 pos.x += float(abs(Random() % 100) - 50) / 200;
5342 pos.y += float(abs(Random() % 100) - 50) / 200;
5343 pos.z += float(abs(Random() % 100) - 50) / 200;
5344 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5345 Sprite::setLastSpriteSpecial(2);
5348 objects.rotx[i] += velocity.x * multiplier * 6;
5349 objects.roty[i] += velocity.z * multiplier * 6;
5350 objects.messedwith[i] = .5;
5353 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5354 if (objects.pitch[i] == 0)
5357 tempcoord = coords - objects.position[i];
5358 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5359 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5360 tempcoord += objects.position[i];
5362 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]) {
5363 if (objects.messedwith[i] <= 0) {
5367 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5370 addEnvSound(coords, 4 * findLength(&velocity));
5374 if (environment == grassyenvironment)
5375 howmany = findLength(&velocity) * 4;
5376 if (environment == snowyenvironment)
5377 howmany = findLength(&velocity) * 2;
5379 if (environment != desertenvironment)
5380 for (j = 0; j < howmany; j++) {
5381 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5382 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5383 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5385 pos += velocity * .1;
5387 pos.x += float(abs(Random() % 100) - 50) / 150;
5388 pos.y += float(abs(Random() % 100) - 50) / 150;
5389 pos.z += float(abs(Random() % 100) - 50) / 150;
5390 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);
5391 Sprite::setLastSpriteSpecial(1);
5393 howmany = findLength(&velocity) * 4;
5395 if (environment == snowyenvironment)
5396 for (j = 0; j < howmany; j++) {
5397 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5398 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5399 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5401 pos += velocity * .1;
5403 pos.x += float(abs(Random() % 100) - 50) / 150;
5404 pos.y += float(abs(Random() % 100) - 50) / 150;
5405 pos.z += float(abs(Random() % 100) - 50) / 150;
5406 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5407 Sprite::setLastSpriteSpecial(2);
5410 objects.messedwith[i] = .5;
5415 if (!skeleton.free) {
5418 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5421 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5423 if (tutoriallevel == 1 && id != 0)
5425 if (play && aitype != playercontrolled) {
5426 int whichsound = -1;
5427 i = abs(Random() % 4);
5428 if (speechdelay <= 0) {
5429 if (creature == rabbittype) {
5431 whichsound = rabbitchitter;
5433 whichsound = rabbitchitter2;
5435 if (creature == wolftype) {
5437 whichsound = growlsound;
5439 whichsound = growl2sound;
5444 if (whichsound != -1) {
5445 emit_sound_at(whichsound, coords);
5449 if (animTarget == staggerbackhighanim)
5451 if (animTarget == staggerbackhardanim)
5453 staggerdelay -= multiplier;
5454 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5456 if (velocity.y < -30 && animTarget == jumpdownanim)
5458 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5459 animTarget = getIdle();
5463 weaponmissdelay -= multiplier;
5464 highreversaldelay -= multiplier;
5465 lowreversaldelay -= multiplier;
5466 lastcollide -= multiplier;
5467 skiddelay -= multiplier;
5468 if (!isnormal(velocity.x) && velocity.x) {
5471 if (!isnormal(targettilt) && targettilt) {
5474 if (!isnormal(targettilt2) && targettilt2) {
5477 if (!isnormal(targetyaw) && targetyaw) {
5481 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5482 //open hands and close mouth
5483 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5484 righthandmorphness = 0;
5485 righthandmorphend = 0;
5486 targetrighthandmorphness = 1;
5489 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5490 lefthandmorphness = 0;
5491 lefthandmorphend = 0;
5492 targetlefthandmorphness = 1;
5495 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5498 targetheadmorphness = 1;
5502 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) {
5503 //open hands and mouth
5504 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5505 righthandmorphness = 0;
5506 righthandmorphend = 0;
5507 targetrighthandmorphness = 1;
5510 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5511 lefthandmorphness = 0;
5512 lefthandmorphend = 0;
5513 targetlefthandmorphness = 1;
5516 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5519 targetheadmorphness = 1;
5523 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5524 //close hands and mouth
5525 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5526 righthandmorphness = 0;
5527 righthandmorphend = 1;
5528 targetrighthandmorphness = 1;
5531 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5532 lefthandmorphness = 0;
5533 lefthandmorphend = 1;
5534 targetlefthandmorphness = 1;
5537 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5540 targetheadmorphness = 1;
5544 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) {
5545 //close hands and yell
5546 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5547 righthandmorphness = 0;
5548 righthandmorphend = 1;
5549 targetrighthandmorphness = 1;
5552 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5553 lefthandmorphness = 0;
5554 lefthandmorphend = 1;
5555 targetlefthandmorphness = 1;
5558 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5561 targetheadmorphness = 1;
5568 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5569 (victim->aitype != searchtype) && (aitype != passivetype) &&
5570 (aitype != searchtype) && (victim->id < Person::players.size())) {
5571 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5575 if (!dead && animTarget != hurtidleanim)
5576 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5577 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5580 targetheadmorphness = 1;
5584 if (weaponactive != -1) {
5585 if (weapons[weaponids[weaponactive]].getType() != staff) {
5586 righthandmorphstart = 1;
5587 righthandmorphend = 1;
5589 if (weapons[weaponids[weaponactive]].getType() == staff) {
5590 righthandmorphstart = 2;
5591 righthandmorphend = 2;
5593 targetrighthandmorphness = 1;
5596 terrainnormal = terrain.getNormal(coords.x, coords.z);
5598 if (Animation::animations[animTarget].attack != reversal) {
5599 if (!isnormal(coords.x))
5607 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5608 facing = flatfacing;
5609 ReflectVector(&facing, terrainnormal);
5612 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5614 targettilt2 = -facing.y * 20;
5619 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5621 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5622 flatvelocity = velocity;
5624 flatvelspeed = findLength(&flatvelocity);
5625 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5626 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5631 if (targettilt > 25)
5633 if (targettilt < -25)
5637 if (targettilt2 > 45)
5639 if (targettilt2 < -45)
5641 if (abs(tilt2 - targettilt2) < multiplier * 400)
5642 tilt2 = targettilt2;
5643 else if (tilt2 > targettilt2) {
5644 tilt2 -= multiplier * 400;
5645 } else if (tilt2 < targettilt2) {
5646 tilt2 += multiplier * 400;
5648 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5655 if (!isnormal(targettilt) && targettilt) {
5658 if (!isnormal(targettilt2) && targettilt2) {
5663 if (animTarget == rabbittackleanim) {
5664 velocity += facing * multiplier * speed * 700 * scale;
5665 velspeed = findLength(&velocity);
5666 if (velspeed > speed * 65 * scale) {
5667 velocity /= velspeed;
5668 velspeed = speed * 65 * scale;
5669 velocity *= velspeed;
5671 velocity.y += gravity * multiplier * 20;
5672 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5673 velspeed = findLength(&velocity);
5674 velocity = flatfacing * velspeed;
5676 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5677 if (isRun() || animTarget == rabbitkickanim) {
5678 velocity += facing * multiplier * speed * 700 * scale;
5679 velspeed = findLength(&velocity);
5680 if (velspeed > speed * 45 * scale) {
5681 velocity /= velspeed;
5682 velspeed = speed * 45 * scale;
5683 velocity *= velspeed;
5685 velocity.y += gravity * multiplier * 20;
5686 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5687 velspeed = findLength(&velocity);
5688 if (velspeed < speed * 30 * scale)
5689 velspeed = speed * 30 * scale;
5690 velocity = flatfacing * velspeed;
5692 } else if (isRun()) {
5693 velocity += facing * multiplier * speed * 700 * scale;
5694 velspeed = findLength(&velocity);
5695 if (creature == rabbittype) {
5696 if (velspeed > speed * 55 * scale) {
5697 velocity /= velspeed;
5698 velspeed = speed * 55 * scale;
5699 velocity *= velspeed;
5702 if (creature == wolftype) {
5703 if (velspeed > speed * 75 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 75 * scale;
5706 velocity *= velspeed;
5709 velocity.y += gravity * multiplier * 20;
5710 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5711 velspeed = findLength(&velocity);
5712 velocity = flatfacing * velspeed;
5715 if (animTarget == rollanim && targetFrame().label != 6) {
5716 velocity += facing * multiplier * speed * 700 * scale;
5717 velspeed = findLength(&velocity);
5718 if (velspeed > speed * 45 * scale) {
5719 velocity /= velspeed;
5720 velspeed = speed * 45 * scale;
5721 velocity *= velspeed;
5723 velocity.y += gravity * multiplier * 20;
5724 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5725 velspeed = findLength(&velocity);
5726 velocity = flatfacing * velspeed;
5729 if (animTarget == sneakanim || animTarget == walkanim) {
5730 velocity += facing * multiplier * speed * 700 * scale;
5731 velspeed = findLength(&velocity);
5732 if (velspeed > speed * 12 * scale) {
5733 velocity /= velspeed;
5734 velspeed = speed * 12 * scale;
5735 velocity *= velspeed;
5737 velocity.y += gravity * multiplier * 20;
5738 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5739 velspeed = findLength(&velocity);
5740 velocity = flatfacing * velspeed;
5743 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5744 velocity += facing * multiplier * speed * 700 * scale;
5745 velspeed = findLength(&velocity);
5746 if (velspeed > speed * 2 * scale) {
5747 velocity /= velspeed;
5748 velspeed = speed * 2 * scale;
5749 velocity *= velspeed;
5751 velocity.y += gravity * multiplier * 20;
5752 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5753 velspeed = findLength(&velocity);
5754 velocity = flatfacing * velspeed;
5758 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5759 velocity -= facing * multiplier * speed * 700 * scale;
5760 velspeed = findLength(&velocity);
5761 if (velspeed > speed * 2 * scale) {
5762 velocity /= velspeed;
5763 velspeed = speed * 2 * scale;
5764 velocity *= velspeed;
5766 velocity.y += gravity * multiplier * 20;
5767 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5768 velspeed = findLength(&velocity);
5769 velocity = flatfacing * velspeed * -1;
5772 if (animTarget == fightsidestep) {
5773 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5774 velspeed = findLength(&velocity);
5775 if (velspeed > speed * 12 * scale) {
5776 velocity /= velspeed;
5777 velspeed = speed * 12 * scale;
5778 velocity *= velspeed;
5780 velocity.y += gravity * multiplier * 20;
5781 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5782 velspeed = findLength(&velocity);
5783 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5786 if (animTarget == staggerbackhighanim) {
5787 coords -= facing * multiplier * speed * 16 * scale;
5790 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5791 coords -= facing * multiplier * speed * 20 * scale;
5795 if (animTarget == backhandspringanim) {
5796 //coords-=facing*multiplier*50*scale;
5797 velocity += facing * multiplier * speed * 700 * scale * -1;
5798 velspeed = findLength(&velocity);
5799 if (velspeed > speed * 50 * scale) {
5800 velocity /= velspeed;
5801 velspeed = speed * 50 * scale;
5802 velocity *= velspeed;
5804 velocity.y += gravity * multiplier * 20;
5805 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5806 velspeed = findLength(&velocity);
5807 velocity = flatfacing * velspeed * -1;
5809 if (animTarget == dodgebackanim) {
5810 //coords-=facing*multiplier*50*scale;
5811 velocity += facing * multiplier * speed * 700 * scale * -1;
5812 velspeed = findLength(&velocity);
5813 if (velspeed > speed * 60 * scale) {
5814 velocity /= velspeed;
5815 velspeed = speed * 60 * scale;
5816 velocity *= velspeed;
5818 velocity.y += gravity * multiplier * 20;
5819 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5820 velspeed = findLength(&velocity);
5821 velocity = flatfacing * velspeed * -1;
5824 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5825 velspeed = findLength(&velocity);
5829 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5830 velocity.y += gravity * multiplier;
5833 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5834 coords += velocity * multiplier;
5836 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5837 if (isFlip() && targetFrame().label == 7)
5840 if (animTarget == jumpupanim) {
5842 animTarget = getIdle();
5849 pause_sound(whooshsound);
5850 OPENAL_SetVolume(channels[whooshsound], 0);
5853 if (animTarget == jumpdownanim || isFlip()) {
5854 if (isFlip())jumppower = -4;
5855 animTarget = getLanding();
5856 emit_sound_at(landsound, coords, 128.);
5859 addEnvSound(coords);
5864 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5865 coords.y += gravity * multiplier * 2;
5866 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5867 coords.y = terrain.getHeight(coords.x, coords.z);
5872 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)) {
5873 velspeed = findLength(&velocity);
5875 if (velspeed < multiplier * 300 * scale) {
5878 velocity -= velocity / velspeed * multiplier * 300 * scale;
5879 if (velspeed > 5 && (isLanding() || isLandhard())) {
5880 skiddingdelay += multiplier;
5881 if (skiddelay <= 0) {
5882 FootLand(leftfoot, .5);
5883 FootLand(rightfoot, .5);
5891 velspeed = findLength(&velocity);
5893 if (velspeed < multiplier * 600 * scale) {
5896 velocity -= velocity / velspeed * multiplier * 600 * scale;
5898 if (velspeed > 5 && (isLanding() || isLandhard())) {
5899 skiddingdelay += multiplier;
5900 if (skiddelay <= 0) {
5901 FootLand(leftfoot, .5);
5902 FootLand(rightfoot, .5);
5909 if (skiddingdelay < 0)
5910 skiddingdelay += multiplier;
5911 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5913 if (!onterrain || environment == grassyenvironment) {
5914 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5916 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5920 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5921 terrainnormal = victim->coords - coords;
5922 Normalise(&terrainnormal);
5923 targetyaw = -asin(0 - terrainnormal.x);
5924 targetyaw *= 360 / 6.28;
5925 if (terrainnormal.z < 0)
5926 targetyaw = 180 - targetyaw;
5927 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5930 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5931 targetyaw = victim->targetyaw;
5933 if (animTarget == rabbittacklinganim) {
5934 coords = victim->coords;
5937 skeleton.oldfree = skeleton.free;
5941 midterrain.x = terrain.size * terrain.scale / 2;
5942 midterrain.z = terrain.size * terrain.scale / 2;
5943 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5945 tempposit = coords - midterrain;
5947 Normalise(&tempposit);
5948 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5949 coords.x = tempposit.x + midterrain.x;
5950 coords.z = tempposit.z + midterrain.z;
5956 * inverse kinematics helper function
5958 void IKHelper(Person *p, float interp)
5960 XYZ point, change, change2;
5961 float heightleft, heightright;
5963 // TODO: implement localToWorld and worldToLocal
5964 // but keep in mind it won't be the same math if player is ragdolled or something
5965 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5966 // then comb through code for places where to use it
5968 // point = localToWorld(jointPos(leftfoot))
5969 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5970 // adjust height of foot
5971 heightleft = terrain.getHeight(point.x, point.z) + .04;
5972 point.y = heightleft;
5973 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5974 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5975 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5976 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5977 // move ankle along with foot
5978 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5979 // average knee pos between old and new pos
5980 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5982 // do same as above for right leg
5983 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5984 heightright = terrain.getHeight(point.x, point.z) + .04;
5985 point.y = heightright;
5986 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5987 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5988 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5989 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5990 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5992 // fix up skeleton now that we've moved body parts?
5993 p->skeleton.DoConstraints(&p->coords, &p->scale);
6000 int Person::DrawSkeleton()
6002 int oldplayerdetail;
6003 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6004 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6014 glAlphaFunc(GL_GREATER, 0.0001);
6016 float terrainheight;
6020 if (!isnormal(tilt))
6022 if (!isnormal(tilt2))
6024 oldplayerdetail = playerdetail;
6026 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6029 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6032 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6037 if (playerdetail != oldplayerdetail) {
6039 normalsupdatedelay = 0;
6041 static float updatedelaychange;
6042 static float morphness;
6043 static float framemult;
6045 skeleton.FindForwards();
6046 if (howactive == typesittingwall) {
6047 skeleton.specialforward[1] = 0;
6048 skeleton.specialforward[1].z = 1;
6054 static int weaponattachmuscle;
6055 static int weaponrotatemuscle;
6056 static XYZ weaponpoint;
6057 static int start, endthing;
6058 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6059 if (!isSleeping() && !isSitting()) {
6060 // TODO: give these meaningful names
6061 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6062 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6063 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6064 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6066 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6068 if (creature == wolftype)
6072 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6073 IKHelper(this, target);
6074 if (creature == wolftype)
6075 IKHelper(this, target);
6078 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6079 IKHelper(this, 1 - target);
6080 if (creature == wolftype)
6081 IKHelper(this, 1 - target);
6085 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()))
6088 targetheadyaw = -targetyaw;
6089 targetheadpitch = 0;
6090 if (Animation::animations[animTarget].attack == 3)
6091 targetheadyaw += 180;
6093 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6094 skeleton.drawmodel.vertex[i] = 0;
6095 skeleton.drawmodel.vertex[i].y = 999;
6097 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6098 skeleton.drawmodellow.vertex[i] = 0;
6099 skeleton.drawmodellow.vertex[i].y = 999;
6101 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6102 skeleton.drawmodelclothes.vertex[i] = 0;
6103 skeleton.drawmodelclothes.vertex[i].y = 999;
6105 for (int i = 0; i < skeleton.muscles.size(); i++) {
6106 // convenience renames
6107 const int p1 = skeleton.muscles[i].parent1->label;
6108 const int p2 = skeleton.muscles[i].parent2->label;
6110 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6115 if (p1 == righthand || p2 == righthand) {
6116 morphness = righthandmorphness;
6117 start = righthandmorphstart;
6118 endthing = righthandmorphend;
6120 if (p1 == lefthand || p2 == lefthand) {
6121 morphness = lefthandmorphness;
6122 start = lefthandmorphstart;
6123 endthing = lefthandmorphend;
6125 if (p1 == head || p2 == head) {
6126 morphness = headmorphness;
6127 start = headmorphstart;
6128 endthing = headmorphend;
6130 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6131 morphness = chestmorphness;
6132 start = chestmorphstart;
6133 endthing = chestmorphend;
6135 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6136 morphness = tailmorphness;
6137 start = tailmorphstart;
6138 endthing = tailmorphend;
6141 skeleton.FindRotationMuscle(i, animTarget);
6142 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6143 glMatrixMode(GL_MODELVIEW);
6147 glRotatef(tilt2, 1, 0, 0);
6149 glRotatef(tilt, 0, 0, 1);
6152 glTranslatef(mid.x, mid.y, mid.z);
6154 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6155 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6157 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6158 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6160 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6161 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6163 if (playerdetail || skeleton.free == 3) {
6164 for (j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6165 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6166 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6167 glMatrixMode(GL_MODELVIEW);
6169 if (p1 == abdomen || p2 == abdomen)
6170 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6171 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6172 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6173 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6174 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6175 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6176 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6177 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6178 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6179 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6180 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6181 if (p1 == head || p2 == head)
6182 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6183 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6184 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6185 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6186 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6187 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6188 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6192 if (!playerdetail || skeleton.free == 3) {
6193 for (j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6194 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6195 glMatrixMode(GL_MODELVIEW);
6197 if (p1 == abdomen || p2 == abdomen)
6198 glTranslatef(v0.x * proportionbody.x,
6199 v0.y * proportionbody.y,
6200 v0.z * proportionbody.z);
6201 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6202 glTranslatef(v0.x * proportionarms.x,
6203 v0.y * proportionarms.y,
6204 v0.z * proportionarms.z);
6205 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6206 glTranslatef(v0.x * proportionlegs.x,
6207 v0.y * proportionlegs.y,
6208 v0.z * proportionlegs.z);
6209 if (p1 == head || p2 == head)
6210 glTranslatef(v0.x * proportionhead.x,
6211 v0.y * proportionhead.y,
6212 v0.z * proportionhead.z);
6214 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6215 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6216 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6217 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6223 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6224 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6226 glMatrixMode(GL_MODELVIEW);
6230 glRotatef(tilt2, 1, 0, 0);
6232 glRotatef(tilt, 0, 0, 1);
6233 glTranslatef(mid.x, mid.y, mid.z);
6234 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6235 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6237 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6238 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6240 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6241 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6243 for (j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6244 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6245 glMatrixMode(GL_MODELVIEW);
6247 if (p1 == abdomen || p2 == abdomen)
6248 glTranslatef(v0.x * proportionbody.x,
6249 v0.y * proportionbody.y,
6250 v0.z * proportionbody.z);
6251 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6252 glTranslatef(v0.x * proportionarms.x,
6253 v0.y * proportionarms.y,
6254 v0.z * proportionarms.z);
6255 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6256 glTranslatef(v0.x * proportionlegs.x,
6257 v0.y * proportionlegs.y,
6258 v0.z * proportionlegs.z);
6259 if (p1 == head || p2 == head)
6260 glTranslatef(v0.x * proportionhead.x,
6261 v0.y * proportionhead.y,
6262 v0.z * proportionhead.z);
6263 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6264 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6265 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6266 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6271 updatedelay = 1 + (float)(Random() % 100) / 1000;
6273 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6274 normalsupdatedelay = 1;
6275 if (playerdetail || skeleton.free == 3)
6276 skeleton.drawmodel.CalculateNormals(0);
6277 if (!playerdetail || skeleton.free == 3)
6278 skeleton.drawmodellow.CalculateNormals(0);
6279 if (skeleton.clothes)
6280 skeleton.drawmodelclothes.CalculateNormals(0);
6282 if (playerdetail || skeleton.free == 3)
6283 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6284 if (!playerdetail || skeleton.free == 3)
6285 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6286 if (skeleton.clothes) {
6287 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6292 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6293 if (updatedelaychange > -realmultiplier * 30)
6294 updatedelaychange = -realmultiplier * 30;
6295 if (updatedelaychange > -framemult * 4)
6296 updatedelaychange = -framemult * 4;
6297 if (skeleton.free == 1)
6298 updatedelaychange *= 6;
6300 updatedelaychange *= 8;
6301 updatedelay += updatedelaychange;
6303 glMatrixMode(GL_MODELVIEW);
6305 glTranslatef(coords.x, coords.y - .02, coords.z);
6306 if (!skeleton.free) {
6307 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6308 glRotatef(yaw, 0, 1, 0);
6312 glColor4f(.4, 1, .4, 1);
6313 glDisable(GL_LIGHTING);
6314 glDisable(GL_TEXTURE_2D);
6317 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6318 XYZ &v0 = skeleton.drawmodel.vertex[i];
6319 glVertex3f(v0.x, v0.y, v0.z);
6325 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6326 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6327 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6328 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6329 glVertex3f(v0.x, v0.y, v0.z);
6330 glVertex3f(v1.x, v1.y, v1.z);
6331 glVertex3f(v1.x, v1.y, v1.z);
6332 glVertex3f(v2.x, v2.y, v2.z);
6333 glVertex3f(v2.x, v2.y, v2.z);
6334 glVertex3f(v0.x, v0.y, v0.z);
6340 terrainlight = terrain.getLighting(coords.x, coords.z);
6341 distance = distsq(&viewer, &coords);
6342 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6346 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6347 if (terrainheight < 1)
6349 if (terrainheight > 1.7)
6350 terrainheight = 1.7;
6352 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6353 glDisable(GL_BLEND);
6354 glAlphaFunc(GL_GREATER, 0.0001);
6355 glEnable(GL_TEXTURE_2D);
6357 glDisable(GL_TEXTURE_2D);
6358 glColor4f(.7, .35, 0, .5);
6360 glEnable(GL_LIGHTING);
6363 if (tutoriallevel && id != 0) {
6364 glColor4f(.7, .7, .7, 0.6);
6366 glEnable(GL_LIGHTING);
6368 if (canattack && cananger)
6369 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6370 glDisable(GL_TEXTURE_2D);
6371 glColor4f(1, 0, 0, 0.8);
6373 glMatrixMode(GL_TEXTURE);
6375 glTranslatef(0, -smoketex, 0);
6376 glTranslatef(-smoketex, 0, 0);
6380 if ((tutoriallevel && id != 0))
6381 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6383 skeleton.drawmodel.draw();
6386 if (!playerdetail) {
6387 if ((tutoriallevel && id != 0))
6388 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6390 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6393 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6394 if (tutoriallevel && id != 0) {
6396 glMatrixMode(GL_MODELVIEW);
6397 glEnable(GL_TEXTURE_2D);
6398 glColor4f(.7, .7, .7, 0.6);
6400 glEnable(GL_LIGHTING);
6402 if (canattack && cananger)
6403 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6404 glDisable(GL_TEXTURE_2D);
6405 glColor4f(1, 0, 0, 0.8);
6407 glMatrixMode(GL_TEXTURE);
6409 glTranslatef(0, -smoketex * .6, 0);
6410 glTranslatef(smoketex * .6, 0, 0);
6413 if ((tutoriallevel && id != 0))
6414 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6416 skeleton.drawmodel.draw();
6419 if (!playerdetail) {
6420 if ((tutoriallevel && id != 0))
6421 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6423 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6428 if (tutoriallevel && id != 0) {
6430 glMatrixMode(GL_MODELVIEW);
6431 glEnable(GL_TEXTURE_2D);
6433 if (skeleton.clothes) {
6437 skeleton.drawmodelclothes.draw();
6439 skeleton.drawmodelclothes.drawimmediate();
6445 if (num_weapons > 0) {
6446 for (k = 0; k < num_weapons; k++) {
6448 if (weaponactive == k) {
6449 if (weapons[i].getType() != staff) {
6450 for (j = 0; j < skeleton.muscles.size(); j++) {
6451 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6452 weaponattachmuscle = j;
6455 for (j = 0; j < skeleton.muscles.size(); j++) {
6456 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) {
6457 weaponrotatemuscle = j;
6460 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6461 if (creature == wolftype)
6462 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6464 if (weapons[i].getType() == staff) {
6465 for (j = 0; j < skeleton.muscles.size(); j++) {
6466 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6467 weaponattachmuscle = j;
6470 for (j = 0; j < skeleton.muscles.size(); j++) {
6471 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) {
6472 weaponrotatemuscle = j;
6475 //weaponpoint=jointPos(rightwrist);
6476 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6477 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6478 XYZ tempnormthing, vec1, vec2;
6479 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6480 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6481 CrossProduct(&vec1, &vec2, &tempnormthing);
6482 Normalise(&tempnormthing);
6483 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6484 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6487 if (weaponactive != k && weaponstuck != k) {
6488 if (weapons[i].getType() == knife)
6489 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6490 if (weapons[i].getType() == sword)
6491 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6492 if (weapons[i].getType() == staff)
6493 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6494 for (j = 0; j < skeleton.muscles.size(); j++) {
6495 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) {
6496 weaponrotatemuscle = j;
6500 if (weaponstuck == k) {
6501 if (weaponstuckwhere == 0)
6502 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6504 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6505 for (j = 0; j < skeleton.muscles.size(); j++) {
6506 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) {
6507 weaponrotatemuscle = j;
6511 if (skeleton.free) {
6512 weapons[i].position = weaponpoint * scale + coords;
6513 weapons[i].bigrotation = 0;
6514 weapons[i].bigtilt = 0;
6515 weapons[i].bigtilt2 = 0;
6517 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;
6518 weapons[i].bigrotation = yaw;
6519 weapons[i].bigtilt = tilt;
6520 weapons[i].bigtilt2 = tilt2;
6522 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6523 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6524 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6525 if (weaponactive == k) {
6526 if (weapons[i].getType() == knife) {
6527 weapons[i].smallrotation = 180;
6528 weapons[i].smallrotation2 = 0;
6529 if (isCrouch() || wasCrouch()) {
6530 weapons[i].smallrotation2 = 20;
6532 if (animTarget == hurtidleanim) {
6533 weapons[i].smallrotation2 = 50;
6535 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6536 XYZ temppoint1, temppoint2;
6539 temppoint1 = jointPos(righthand);
6540 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6541 distance = findDistance(&temppoint1, &temppoint2);
6542 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6543 weapons[i].rotation2 *= 360 / 6.28;
6546 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6547 weapons[i].rotation1 *= 360 / 6.28;
6548 weapons[i].rotation3 = 0;
6549 weapons[i].smallrotation = -90;
6550 weapons[i].smallrotation2 = 0;
6551 if (temppoint1.x > temppoint2.x)
6552 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6554 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6555 XYZ temppoint1, temppoint2;
6558 temppoint1 = jointPos(righthand);
6559 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6560 distance = findDistance(&temppoint1, &temppoint2);
6561 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6562 weapons[i].rotation2 *= 360 / 6.28;
6565 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6566 weapons[i].rotation1 *= 360 / 6.28;
6567 weapons[i].rotation3 = 0;
6568 weapons[i].smallrotation = 90;
6569 weapons[i].smallrotation2 = 0;
6570 if (temppoint1.x > temppoint2.x)
6571 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6573 if (animTarget == knifethrowanim) {
6574 weapons[i].smallrotation = 90;
6575 //weapons[i].smallrotation2=-90;
6576 weapons[i].smallrotation2 = 0;
6577 weapons[i].rotation1 = 0;
6578 weapons[i].rotation2 = 0;
6579 weapons[i].rotation3 = 0;
6581 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6582 weapons[i].smallrotation = -90;
6583 weapons[i].rotation1 = 0;
6584 weapons[i].rotation2 = 0;
6585 weapons[i].rotation3 = 0;
6588 if (weapons[i].getType() == sword) {
6589 weapons[i].smallrotation = 0;
6590 weapons[i].smallrotation2 = 0;
6591 if (animTarget == knifethrowanim) {
6592 weapons[i].smallrotation = -90;
6593 weapons[i].smallrotation2 = 0;
6594 weapons[i].rotation1 = 0;
6595 weapons[i].rotation2 = 0;
6596 weapons[i].rotation3 = 0;
6598 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)) {
6599 XYZ temppoint1, temppoint2;
6602 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6603 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6604 distance = findDistance(&temppoint1, &temppoint2);
6605 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6606 weapons[i].rotation2 *= 360 / 6.28;
6609 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6610 weapons[i].rotation1 *= 360 / 6.28;
6611 weapons[i].rotation3 = 0;
6612 weapons[i].smallrotation = 90;
6613 weapons[i].smallrotation2 = 0;
6614 if (temppoint1.x > temppoint2.x)
6615 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6618 if (weapons[i].getType() == staff) {
6619 weapons[i].smallrotation = 100;
6620 weapons[i].smallrotation2 = 0;
6621 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6622 XYZ temppoint1, temppoint2;
6625 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6626 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6627 distance = findDistance(&temppoint1, &temppoint2);
6628 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6629 weapons[i].rotation2 *= 360 / 6.28;
6632 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6633 weapons[i].rotation1 *= 360 / 6.28;
6634 weapons[i].rotation3 = 0;
6635 weapons[i].smallrotation = 90;
6636 weapons[i].smallrotation2 = 0;
6637 if (temppoint1.x > temppoint2.x)
6638 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6642 if (weaponactive != k && weaponstuck != k) {
6643 if (weapons[i].getType() == knife) {
6644 weapons[i].smallrotation = -70;
6645 weapons[i].smallrotation2 = 10;
6647 if (weapons[i].getType() == sword) {
6648 weapons[i].smallrotation = -100;
6649 weapons[i].smallrotation2 = -8;
6651 if (weapons[i].getType() == staff) {
6652 weapons[i].smallrotation = -100;
6653 weapons[i].smallrotation2 = -8;
6656 if (weaponstuck == k) {
6657 if (weaponstuckwhere == 0)
6658 weapons[i].smallrotation = 180;
6660 weapons[i].smallrotation = 0;
6661 weapons[i].smallrotation2 = 10;
6670 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6672 if (animCurrent != animTarget)
6674 if (skeleton.free == 2)
6683 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6686 static float distance;
6687 static float olddistance;
6688 static int intersecting;
6689 static int firstintersecting;
6692 static XYZ start, end;
6693 static float slopethreshold = -.4;
6695 firstintersecting = -1;
6699 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6702 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6703 for (i = 0; i < 4; i++) {
6704 for (j = 0; j < model->TriangleNum; j++) {
6705 if (model->facenormals[j].y <= slopethreshold) {
6707 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)));
6708 if (distance < radius) {
6709 point = *p1 - model->facenormals[j] * distance;
6710 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]]))
6713 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6714 &model->vertex[model->Triangles[j].vertex[1]],
6717 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6718 &model->vertex[model->Triangles[j].vertex[2]],
6721 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6722 &model->vertex[model->Triangles[j].vertex[2]],
6725 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6729 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)) {
6730 p1->y = point.y + radius;
6731 if ((animTarget == jumpdownanim || isFlip())) {
6732 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6735 if (animTarget == jumpupanim) {
6737 animTarget = getIdle();
6744 pause_sound(whooshsound);
6745 OPENAL_SetVolume(channels[whooshsound], 0);
6748 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6751 animTarget = getLanding();
6752 emit_sound_at(landsound, coords, 128.);
6755 addEnvSound(coords);
6762 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6763 olddistance = distance;
6764 firstintersecting = j;
6769 for (j = 0; j < model->TriangleNum; j++) {
6770 if (model->facenormals[j].y > slopethreshold) {
6773 start.y -= radius / 4;
6774 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6775 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6776 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6777 distance = abs((model->facenormals[j].x * start.x)
6778 + (model->facenormals[j].y * start.y)
6779 + (model->facenormals[j].z * start.z)
6780 - ((model->facenormals[j].x * v0.x)
6781 + (model->facenormals[j].y * v0.y)
6782 + (model->facenormals[j].z * v0.z)));
6783 if (distance < radius * .5) {
6784 point = start - model->facenormals[j] * distance;
6785 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6788 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6790 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6792 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6794 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6795 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6797 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6798 if (findLengthfast(&start) < findLengthfast(&velocity))
6801 *p1 += model->facenormals[j] * (distance - radius * .5);
6804 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6805 olddistance = distance;
6806 firstintersecting = j;
6813 *p = DoRotation(*p, 0, *rotate, 0);
6816 *p1 = DoRotation(*p1, 0, *rotate, 0);
6818 return firstintersecting;
6821 void Person::takeWeapon(int weaponId)
6824 weapons[weaponId].owner = id;
6825 if (num_weapons > 0) {
6826 weaponids[num_weapons] = weaponids[0];
6829 weaponids[0] = weaponId;
6832 void Person::addClothes()
6834 if (numclothes > 0) {
6835 for (int i = 0; i < numclothes; i++) {
6842 bool Person::addClothes(const int& clothesId)
6845 const std::string fileName = clothes[clothesId];
6847 GLubyte* array = &skeleton.skinText[0];
6851 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6856 float tintr = clothestintr[clothesId];
6857 float tintg = clothestintg[clothesId];
6858 float tintb = clothestintb[clothesId];
6860 if (tintr > 1) tintr = 1;
6861 if (tintg > 1) tintg = 1;
6862 if (tintb > 1) tintb = 1;
6864 if (tintr < 0) tintr = 0;
6865 if (tintg < 0) tintg = 0;
6866 if (tintb < 0) tintb = 0;
6868 int bytesPerPixel = texture.bpp / 8;
6872 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6873 if (bytesPerPixel == 3)
6875 else if ((i + 1) % 4 == 0)
6876 alphanum = texture.data[i];
6877 if ((i + 1) % 4 || bytesPerPixel == 3) {
6879 texture.data[i] *= tintr;
6881 texture.data[i] *= tintg;
6883 texture.data[i] *= tintb;
6884 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);