2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 #include "Objects/Person.hpp"
23 #include "Animation/Animation.hpp"
24 #include "Audio/openal_wrapper.hpp"
25 #include "Audio/Sounds.hpp"
27 #include "Level/Awards.hpp"
28 #include "Level/Dialog.hpp"
29 #include "Utils/Folders.hpp"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern float realtexdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern GLubyte wolfbloodText[512 * 512 * 3];
46 extern int bloodtoggle;
47 extern bool autoslomo;
48 extern float camerashake;
50 extern float viewdistance;
51 extern float blackout;
52 extern int difficulty;
54 extern float fadestart;
56 extern bool winfreeze;
57 extern bool showpoints;
58 extern bool immediate;
59 extern int tutoriallevel;
60 extern float smoketex;
61 extern int tutorialstage;
62 extern bool reversaltrain;
63 extern bool canattack;
65 extern float damagedealt;
67 extern float hostiletime;
69 extern bool gamestarted;
71 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
76 animCurrent(bounceidleanim),
77 animTarget(bounceidleanim),
84 howactive(typeactive),
86 superruntoggle(false),
87 lastattack(0), lastattack2(0), lastattack3(0),
88 currentoffset(), targetoffset(), offset(),
120 rabbitkickenabled(false),
129 damagetolerance(200),
132 superpermanentdamage(0),
146 bleedx(0), bleedy(0),
150 headyaw(0), headpitch(0),
151 targetheadyaw(0), targetheadpitch(0),
162 normalsupdatedelay(0),
165 forwardkeydown(false),
166 forwardstogglekeydown(false),
171 jumptogglekeydown(false),
172 crouchkeydown(false),
173 crouchtogglekeydown(false),
175 drawtogglekeydown(false),
177 throwtogglekeydown(false),
178 attackkeydown(false),
183 crouchkeydowntime(0),
197 whichdirection(false),
198 whichdirectiondelay(0),
199 avoidsomething(false),
208 lefthandmorphness(0),
209 righthandmorphness(0),
213 targetlefthandmorphness(0),
214 targetrighthandmorphness(0),
215 targetheadmorphness(1),
216 targetchestmorphness(0),
217 targettailmorphness(0),
218 lefthandmorphstart(0), lefthandmorphend(0),
219 righthandmorphstart(0), righthandmorphend(0),
220 headmorphstart(0), headmorphend(0),
221 chestmorphstart(0), chestmorphend(0),
222 tailmorphstart(0), tailmorphend(0),
225 highreversaldelay(0),
228 creature(rabbittype),
275 finalpathfindpoint(0),
276 targetpathfindpoint(0),
277 lastpathfindpoint(0),
278 lastpathfindpoint2(0),
279 lastpathfindpoint3(0),
280 lastpathfindpoint4(0),
297 neckspurtparticledelay(0),
301 rabbitkickragdoll(false),
309 /* Read a person in tfile. Throws an error if it’s not valid */
310 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
313 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
315 funpackf(tfile, "Bi", &howactive);
317 howactive = typeactive;
320 funpackf(tfile, "Bf", &scale);
325 funpackf(tfile, "Bb", &immobile);
330 funpackf(tfile, "Bf", &yaw);
335 if (num_weapons < 0 || num_weapons > 5) {
336 throw InvalidPersonException();
338 if (num_weapons > 0 && num_weapons < 5) {
339 for (int j = 0; j < num_weapons; j++) {
340 weaponids[j] = weapons.size();
342 funpackf(tfile, "Bi", &type);
343 weapons.push_back(Weapon(type, id));
346 funpackf(tfile, "Bi", &numwaypoints);
347 for (int j = 0; j < numwaypoints; j++) {
348 funpackf(tfile, "Bf", &waypoints[j].x);
349 funpackf(tfile, "Bf", &waypoints[j].y);
350 funpackf(tfile, "Bf", &waypoints[j].z);
352 funpackf(tfile, "Bi", &waypointtype[j]);
354 waypointtype[j] = wpkeepwalking;
358 funpackf(tfile, "Bi", &waypoint);
359 if (waypoint > (numwaypoints - 1)) {
363 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
364 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
365 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
366 funpackf(tfile, "Bf Bf", &power, &speedmult);
368 float headprop, legprop, armprop, bodyprop;
371 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
379 if (creature == wolftype) {
380 proportionhead = 1.1 * headprop;
381 proportionbody = 1.1 * bodyprop;
382 proportionarms = 1.1 * armprop;
383 proportionlegs = 1.1 * legprop;
384 } else if (creature == rabbittype) {
385 proportionhead = 1.2 * headprop;
386 proportionbody = 1.05 * bodyprop;
387 proportionarms = 1.00 * armprop;
388 proportionlegs = 1.1 * legprop;
389 proportionlegs.y = 1.05 * legprop;
392 funpackf(tfile, "Bi", &numclothes);
393 for (int k = 0; k < numclothes; k++) {
395 funpackf(tfile, "Bi", &templength);
396 for (int l = 0; l < templength; l++)
397 funpackf(tfile, "Bb", &clothes[k][l]);
398 clothes[k][templength] = '\0';
399 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
405 if (creature == wolftype) {
407 damagetolerance = 300;
414 realoldcoords = coords;
417 void Person::skeletonLoad(bool clothes)
420 if (creature != wolftype) {
422 "Skeleton/BasicFigure",
423 "Skeleton/BasicFigureLow",
424 "Skeleton/RabbitBelt",
426 "Models/Body2.solid",
427 "Models/Body3.solid",
428 "Models/Body4.solid",
429 "Models/Body5.solid",
430 "Models/Body6.solid",
431 "Models/Body7.solid",
432 "Models/BodyLow.solid",
438 "Skeleton/BasicFigureWolf",
439 "Skeleton/BasicFigureWolfLow",
440 "Skeleton/RabbitBelt",
442 "Models/Wolf2.solid",
443 "Models/Wolf3.solid",
444 "Models/Wolf4.solid",
445 "Models/Wolf5.solid",
446 "Models/Wolf6.solid",
447 "Models/Wolf7.solid",
448 "Models/WolfLow.solid",
454 skeleton.drawmodel.textureptr.load(creatureskin[creature][whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize);
460 * GameTick/doPlayerCollisions
462 void Person::CheckKick()
465 && (animTarget == rabbitkickanim
467 && victim != this->shared_from_this()
469 && animCurrent == rabbitkickanim)
470 && distsq(&coords, &victim->coords) < 1.2
471 && !victim->skeleton.free))
474 if (Animation::animations[victim->animTarget].height != lowheight) {
475 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
476 XYZ relative = velocity;
478 Normalise(&relative);
482 if (tutoriallevel != 1)
483 emit_sound_at(heavyimpactsound, victim->coords);
485 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
486 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
489 victim->DoDamage(100 * damagemult / victim->protectionhigh);
495 animTarget = backflipanim;
497 velocity = facing * -10;
501 resume_stream(whooshsound);
503 award_bonus(id, cannon);
504 } else if (victim->isCrouch()) {
505 animTarget = rabbitkickreversedanim;
506 animCurrent = rabbitkickreversedanim;
507 victim->animCurrent = rabbitkickreversalanim;
508 victim->animTarget = rabbitkickreversalanim;
514 victim->oldcoords = victim->coords;
515 coords = victim->coords;
516 victim->targetyaw = targetyaw;
517 victim->victim = this->shared_from_this();
524 * GameTick/doPlayerCollisions - spread fire between players
525 * GameTick/doDevKeys - press f to ignite
526 * Person::DoStuff - spread fire from lit campfires and bushes
528 void Person::CatchFire()
530 XYZ flatfacing, flatvelocity;
532 for (int i = 0; i < 10; i++) {
533 howmany = fabs(Random() % (skeleton.joints.size()));
535 flatvelocity = skeleton.joints[howmany].velocity;
536 flatfacing = skeleton.joints[howmany].position * scale + coords;
538 flatvelocity = velocity;
539 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
541 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
546 emit_sound_at(firestartsound, coords);
548 emit_stream_at(stream_firesound, coords);
556 * idle animation for this creature (depending on status)
558 int Person::getIdle()
560 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
562 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
563 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
564 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
565 victim->id < Person::players.size())) {
566 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
567 if (creature == rabbittype)
568 return fightidleanim;
569 if (creature == wolftype)
572 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
573 if (weapons[weaponids[weaponactive]].getType() == knife)
574 return knifefightidleanim;
575 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
576 return swordfightidlebothanim;
577 if (weapons[weaponids[weaponactive]].getType() == sword)
578 return swordfightidleanim;
579 if (weapons[weaponids[weaponactive]].getType() == staff)
580 return swordfightidleanim;
582 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
583 return fightsidestep;
585 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
587 if (howactive == typesitting) return sitanim;
588 if (howactive == typesittingwall) return sitwallanim;
589 if (howactive == typesleeping) return sleepanim;
590 if (howactive == typedead1) return dead1anim;
591 if (howactive == typedead2) return dead2anim;
592 if (howactive == typedead3) return dead3anim;
593 if (howactive == typedead4) return dead4anim;
594 if (creature == rabbittype) return bounceidleanim;
595 if (creature == wolftype) return wolfidle;
600 * crouch animation for this creature
602 int Person::getCrouch()
604 if (creature == rabbittype)
606 if (creature == wolftype)
607 return wolfcrouchanim;
612 * running animation for this creature (can be upright or all fours)
616 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
618 if (creature == wolftype && (!superruntoggle))
621 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
622 return rabbitrunninganim;
623 if (creature == wolftype && (superruntoggle))
624 return wolfrunninganim;
630 int Person::getStop()
632 if (creature == rabbittype)
634 if (creature == wolftype)
641 int Person::getLanding()
643 if (creature == rabbittype)
645 if (creature == wolftype)
652 int Person::getLandhard()
654 if (creature == rabbittype)
656 if (creature == wolftype)
657 return wolflandhardanim;
664 * Person::DoAnimations
667 SolidHitBonus(int playerid)
669 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
670 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
672 award_bonus(playerid, solidhit);
676 * spawns blood effects
678 void Person::DoBlood(float howmuch, int which)
680 // FIXME: should abstract out inputs
681 static int bleedxint, bleedyint;
683 if (bloodtoggle && tutoriallevel != 1) {
684 if (bleeding <= 0 && spurt) {
686 for (int i = 0; i < 3; i++) {
687 // emit blood particles
690 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
691 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
692 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
693 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
696 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
697 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
698 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
699 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
702 if (Random() % 2 == 0) // 50% chance
703 for (int i = 0; i < 3; i++) {
704 if (Random() % 2 != 0) {
705 // emit teeth particles
708 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
709 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
712 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
713 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
717 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
719 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
721 Sprite::setLastSpriteSpecial(3); // sets it to teeth
726 // FIXME: manipulating attributes
727 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
730 if (creature == rabbittype)
731 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) {
732 bleedxint = abs(Random() % 512);
733 bleedyint = abs(Random() % 512);
735 if (creature == wolftype)
736 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) {
737 bleedxint = abs(Random() % 512);
738 bleedyint = abs(Random() % 512);
742 bleedy /= realtexdetail;
743 bleedx /= realtexdetail;
744 direction = abs(Random() % 2) * 2 - 1;
753 * spawns big blood effects and ???
754 * modifies character's skin texture
756 void Person::DoBloodBig(float howmuch, int which)
758 static int bleedxint, bleedyint, i, j;
760 if (howmuch && id == 0)
763 if (tutoriallevel != 1 || id == 0)
764 if (aitype != playercontrolled && howmuch > 0) {
768 if (creature == wolftype) {
769 int i = abs(Random() % 2);
771 whichsound = snarlsound;
773 whichsound = snarl2sound;
775 if (creature == rabbittype) {
776 int i = abs(Random() % 2);
778 whichsound = rabbitpainsound;
779 if (i == 1 && howmuch >= 2)
780 whichsound = rabbitpain1sound;
783 if (whichsound != -1) {
784 emit_sound_at(whichsound, coords);
789 if (id == 0 && howmuch > 0) {
793 if (bloodtoggle && decals && tutoriallevel != 1) {
794 if (bleeding <= 0 && spurt) {
796 for (int i = 0; i < 3; i++) {
797 // emit blood particles
798 // FIXME: copypaste from above
801 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
802 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
803 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
804 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
807 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
808 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
809 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
810 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
815 // weird texture manipulation code follows.
816 // looks like this is painting blood onto the character's skin texture
817 // FIXME: surely there's a better way
819 int offsetx = 0, offsety = 0;
821 offsety = Random() % 40;
822 offsetx = abs(Random() % 60);
824 if (which == 190 || which == 185) {
825 offsety = Random() % 40;
826 offsetx = abs(Random() % 100) - 20;
829 offsety = Random() % 10;
830 offsetx = Random() % 10;
833 offsety = Random() % 20;
834 offsetx = Random() % 20;
836 if (which == 220 || which == 215) {
846 if (creature == rabbittype)
847 for (i = 0; i < 512; i++) {
848 for (j = 0; j < 512; j++) {
849 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
850 if (i < startx) startx = i;
851 if (j < starty) starty = j;
852 if (i > endx) endx = i;
853 if (j > endy) endy = j;
857 if (creature == wolftype)
858 for (i = 0; i < 512; i++) {
859 for (j = 0; j < 512; j++) {
860 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
861 if (i < startx) startx = i;
862 if (j < starty) starty = j;
863 if (i > endx) endx = i;
864 if (j > endy) endy = j;
874 if (startx < 0) startx = 0;
875 if (starty < 0) starty = 0;
876 if (endx > 512 - 1) endx = 512 - 1;
877 if (endy > 512 - 1) endy = 512 - 1;
878 if (endx < startx) endx = startx;
879 if (endy < starty) endy = starty;
881 startx /= realtexdetail;
882 starty /= realtexdetail;
883 endx /= realtexdetail;
884 endy /= realtexdetail;
886 int texdetailint = realtexdetail;
888 if (creature == rabbittype)
889 for (i = startx; i < endx; i++) {
890 for (j = starty; j < endy; j++) {
891 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) {
892 color = Random() % 85 + 170;
893 where = i * skeleton.skinsize * 3 + j * 3;
894 if (skeleton.skinText[where + 0] > color / 2)
895 skeleton.skinText[where + 0] = color / 2;
896 skeleton.skinText[where + 1] = 0;
897 skeleton.skinText[where + 2] = 0;
901 if (creature == wolftype)
902 for (i = startx; i < endx; i++) {
903 for (j = starty; j < endy; j++) {
904 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) {
905 color = Random() % 85 + 170;
906 where = i * skeleton.skinsize * 3 + j * 3;
907 if (skeleton.skinText[where + 0] > color / 2)
908 skeleton.skinText[where + 0] = color / 2;
909 skeleton.skinText[where + 1] = 0;
910 skeleton.skinText[where + 2] = 0;
914 skeleton.drawmodel.textureptr.bind();
919 if (creature == rabbittype)
920 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) {
921 bleedxint = abs(Random() % 512);
922 bleedyint = abs(Random() % 512);
924 if (creature == wolftype)
925 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) {
926 bleedxint = abs(Random() % 512);
927 bleedyint = abs(Random() % 512);
929 bleedy = bleedxint + offsetx;
930 bleedx = bleedyint + offsety;
931 bleedy /= realtexdetail;
932 bleedx /= realtexdetail;
937 if (bleedx > skeleton.skinsize - 1)
938 bleedx = skeleton.skinsize - 1;
939 if (bleedy > skeleton.skinsize - 1)
940 bleedy = skeleton.skinsize - 1;
941 direction = abs(Random() % 2) * 2 - 1;
944 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
945 deathbleeding += bleeding;
946 bloodloss += bleeding * 3;
948 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
949 if (abs(Random() % 2) == 0) {
950 aitype = gethelptype;
953 aitype = attacktypecutoff;
961 * similar to DoBloodBig
963 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
967 static XYZ startpoint, endpoint, colpoint, movepoint;
968 static float rotationpoint;
970 static XYZ p1, p2, p3, p0;
973 float coordsx, coordsy;
976 if (bloodtoggle && decals && tutoriallevel != 1) {
979 where = DoRotation(where, 0, -yaw, 0);
987 // ray testing for a tri in the character model
988 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
989 if (whichtri != -1) {
990 // low level geometry math
992 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
993 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
994 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
996 bary.x = distsq(&p0, &p1);
997 bary.y = distsq(&p0, &p2);
998 bary.z = distsq(&p0, &p3);
1000 total = bary.x + bary.y + bary.z;
1005 bary.x = 1 - bary.x;
1006 bary.y = 1 - bary.y;
1007 bary.z = 1 - bary.z;
1009 total = bary.x + bary.y + bary.z;
1015 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
1016 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
1017 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
1018 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
1019 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
1020 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
1021 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;
1022 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;
1024 if (bleeding <= 0 && spurt) {
1026 for (int i = 0; i < 3; i++) {
1027 // emit blood particles
1028 // FIXME: more copypaste code
1030 if (skeleton.free) {
1031 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
1032 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1033 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
1034 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
1037 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
1038 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
1039 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
1040 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
1045 // texture manipulation follows
1047 int offsetx = 0, offsety = 0;
1048 offsetx = (1 + coordsy) * 512 - 291;
1049 offsety = coordsx * 512 - 437;
1056 if (creature == rabbittype)
1057 for (i = 0; i < 512; i++) {
1058 for (j = 0; j < 512; j++) {
1059 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1060 if (i < startx) startx = i;
1061 if (j < starty) starty = j;
1062 if (i > endx) endx = i;
1063 if (j > endy) endy = j;
1067 if (creature == wolftype)
1068 for (i = 0; i < 512; i++) {
1069 for (j = 0; j < 512; j++) {
1070 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1071 if (i < startx) startx = i;
1072 if (j < starty) starty = j;
1073 if (i > endx) endx = i;
1074 if (j > endy) endy = j;
1083 if (startx < 0) startx = 0;
1084 if (starty < 0) starty = 0;
1085 if (endx > 512 - 1) endx = 512 - 1;
1086 if (endy > 512 - 1) endy = 512 - 1;
1087 if (endx < startx) endx = startx;
1088 if (endy < starty) endy = starty;
1090 startx /= realtexdetail;
1091 starty /= realtexdetail;
1092 endx /= realtexdetail;
1093 endy /= realtexdetail;
1095 int texdetailint = realtexdetail;
1097 if (creature == rabbittype)
1098 for (i = startx; i < endx; i++) {
1099 for (j = starty; j < endy; j++) {
1100 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) {
1101 color = Random() % 85 + 170;
1102 where = i * skeleton.skinsize * 3 + j * 3;
1103 if (skeleton.skinText[where + 0] > color / 2)
1104 skeleton.skinText[where + 0] = color / 2;
1105 skeleton.skinText[where + 1] = 0;
1106 skeleton.skinText[where + 2] = 0;
1107 } 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) {
1108 color = Random() % 85 + 170;
1109 where = i * skeleton.skinsize * 3 + j * 3;
1110 if (skeleton.skinText[where + 0] > color / 2)
1111 skeleton.skinText[where + 0] = color / 2;
1112 skeleton.skinText[where + 1] = 0;
1113 skeleton.skinText[where + 2] = 0;
1117 if (creature == wolftype)
1118 for (i = startx; i < endx; i++) {
1119 for (j = starty; j < endy; j++) {
1120 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) {
1121 color = Random() % 85 + 170;
1122 where = i * skeleton.skinsize * 3 + j * 3;
1123 if (skeleton.skinText[where + 0] > color / 2)
1124 skeleton.skinText[where + 0] = color / 2;
1125 skeleton.skinText[where + 1] = 0;
1126 skeleton.skinText[where + 2] = 0;
1127 } 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) {
1128 color = Random() % 85 + 170;
1129 where = i * skeleton.skinsize * 3 + j * 3;
1130 if (skeleton.skinText[where + 0] > color / 2)
1131 skeleton.skinText[where + 0] = color / 2;
1132 skeleton.skinText[where + 1] = 0;
1133 skeleton.skinText[where + 2] = 0;
1137 skeleton.drawmodel.textureptr.bind();
1140 bleedy = (1 + coordsy) * 512;
1141 bleedx = coordsx * 512;
1142 bleedy /= realtexdetail;
1143 bleedx /= realtexdetail;
1148 if (bleedx > skeleton.skinsize - 1)
1149 bleedx = skeleton.skinsize - 1;
1150 if (bleedy > skeleton.skinsize - 1)
1151 bleedy = skeleton.skinsize - 1;
1152 direction = abs(Random() % 2) * 2 - 1;
1157 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1158 deathbleeding += bleeding;
1159 bloodloss += bleeding * 3;
1161 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1162 if (abs(Random() % 2) == 0) {
1163 aitype = gethelptype;
1166 aitype = attacktypecutoff;
1177 * guessing this performs a reversal
1179 void Person::Reverse()
1181 if (!((victim->aitype == playercontrolled
1183 || staggerdelay <= 0)
1184 && victim->animTarget != jumpupanim
1185 && victim->animTarget != jumpdownanim
1186 && (tutoriallevel != 1 || cananger)
1190 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1191 && (victim->id != 0 || difficulty >= 2)
1192 && (creature != wolftype || victim->creature == wolftype))
1195 if (animTarget == sweepanim) {
1196 animTarget = sweepreversedanim;
1197 animCurrent = sweepreversedanim;
1198 victim->animCurrent = sweepreversalanim;
1199 victim->animTarget = sweepreversalanim;
1201 if (animTarget == spinkickanim) {
1202 animTarget = spinkickreversedanim;
1203 animCurrent = spinkickreversedanim;
1204 victim->animCurrent = spinkickreversalanim;
1205 victim->animTarget = spinkickreversalanim;
1207 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1208 if (animTarget == rabbittacklinganim) {
1211 victim->frameCurrent = 6;
1212 victim->frameTarget = 7;
1214 animTarget = upunchreversedanim;
1215 animCurrent = upunchreversedanim;
1216 victim->animCurrent = upunchreversalanim;
1217 victim->animTarget = upunchreversalanim;
1219 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1220 if (victim->weaponactive != -1) {
1221 victim->throwtogglekeydown = 1;
1222 XYZ tempVelocity = victim->velocity * .2;
1223 if (tempVelocity.x == 0)
1224 tempVelocity.x = .1;
1225 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1226 victim->num_weapons--;
1227 if (victim->num_weapons) {
1228 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1229 if (victim->weaponstuck == victim->num_weapons)
1230 victim->weaponstuck = 0;
1233 victim->weaponactive = -1;
1234 for (unsigned j = 0; j < Person::players.size(); j++) {
1235 Person::players[j]->wentforweapon = 0;
1239 animTarget = staffhitreversedanim;
1240 animCurrent = staffhitreversedanim;
1241 victim->animCurrent = staffhitreversalanim;
1242 victim->animTarget = staffhitreversalanim;
1244 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1245 if (victim->weaponactive != -1) {
1246 victim->throwtogglekeydown = 1;
1247 XYZ tempVelocity = victim->velocity * .2;
1248 if (tempVelocity.x == 0)
1249 tempVelocity.x = .1;
1250 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1251 victim->num_weapons--;
1252 if (victim->num_weapons) {
1253 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1254 if (victim->weaponstuck == victim->num_weapons)
1255 victim->weaponstuck = 0;
1258 victim->weaponactive = -1;
1259 for (unsigned j = 0; j < Person::players.size(); j++) {
1260 Person::players[j]->wentforweapon = 0;
1263 animTarget = staffspinhitreversedanim;
1264 animCurrent = staffspinhitreversedanim;
1265 victim->animCurrent = staffspinhitreversalanim;
1266 victim->animTarget = staffspinhitreversalanim;
1268 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1269 if (victim->weaponactive != -1) {
1270 victim->throwtogglekeydown = 1;
1271 XYZ tempVelocity = victim->velocity * .2;
1272 if (tempVelocity.x == 0)
1273 tempVelocity.x = .1;
1274 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1275 victim->num_weapons--;
1276 if (victim->num_weapons) {
1277 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1278 if (victim->weaponstuck == victim->num_weapons)
1279 victim->weaponstuck = 0;
1282 victim->weaponactive = -1;
1283 for (unsigned j = 0; j < Person::players.size(); j++) {
1284 Person::players[j]->wentforweapon = 0;
1287 animTarget = swordslashreversedanim;
1288 animCurrent = swordslashreversedanim;
1289 victim->animCurrent = swordslashreversalanim;
1290 victim->animTarget = swordslashreversalanim;
1292 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1293 if (victim->weaponactive != -1) {
1294 victim->throwtogglekeydown = 1;
1295 XYZ tempVelocity = victim->velocity * .2;
1296 if (tempVelocity.x == 0)
1297 tempVelocity.x = .1;
1298 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1299 victim->num_weapons--;
1300 if (victim->num_weapons) {
1301 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1302 if (victim->weaponstuck == victim->num_weapons)
1303 victim->weaponstuck = 0;
1306 victim->weaponactive = -1;
1307 for (unsigned j = 0; j < Person::players.size(); j++) {
1308 Person::players[j]->wentforweapon = 0;
1311 animTarget = knifeslashreversedanim;
1312 animCurrent = knifeslashreversedanim;
1313 victim->animCurrent = knifeslashreversalanim;
1314 victim->animTarget = knifeslashreversalanim;
1316 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1317 victim->targettilt2 = targettilt2;
1318 victim->frameCurrent = frameCurrent;
1319 victim->frameTarget = frameTarget;
1320 victim->target = target;
1321 victim->velocity = 0;
1322 victim->oldcoords = victim->coords;
1323 victim->coords = coords;
1324 victim->targetyaw = targetyaw;
1325 victim->yaw = targetyaw;
1326 victim->victim = this->shared_from_this();
1328 if (animTarget == winduppunchanim) {
1329 animTarget = winduppunchblockedanim;
1330 victim->animTarget = blockhighleftanim;
1331 victim->frameTarget = 1;
1332 victim->target = .5;
1333 victim->victim = this->shared_from_this();
1334 victim->targetyaw = targetyaw + 180;
1336 if (animTarget == wolfslapanim) {
1337 animTarget = winduppunchblockedanim;
1338 victim->animTarget = blockhighleftanim;
1339 victim->frameTarget = 1;
1340 victim->target = .5;
1341 victim->victim = this->shared_from_this();
1342 victim->targetyaw = targetyaw + 180;
1344 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1345 animTarget = swordslashparriedanim;
1346 parriedrecently = .4;
1347 victim->parriedrecently = 0;
1348 victim->animTarget = swordslashparryanim;
1349 victim->frameTarget = 1;
1350 victim->target = .5;
1351 victim->victim = this->shared_from_this();
1352 victim->targetyaw = targetyaw + 180;
1354 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1355 if (victim->weaponactive != -1) {
1356 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1357 if (weapons[victim->weaponids[0]].getType() == staff)
1358 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1359 if (weapons[weaponids[0]].getType() == staff)
1360 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1361 emit_sound_at(swordstaffsound, victim->coords);
1363 emit_sound_at(metalhitsound, victim->coords);
1367 victim->Puff(righthand);
1369 victim->frameTarget = 0;
1370 victim->animTarget = staggerbackhighanim;
1371 victim->targetyaw = targetyaw + 180;
1373 aim = DoRotation(facing, 0, 90, 0) * 21;
1375 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1376 victim->num_weapons--;
1377 if (victim->num_weapons) {
1378 victim->weaponids[0] = victim->weaponids[num_weapons];
1379 if (victim->weaponstuck == victim->num_weapons)
1380 victim->weaponstuck = 0;
1382 victim->weaponactive = -1;
1383 for (unsigned i = 0; i < Person::players.size(); i++) {
1384 Person::players[i]->wentforweapon = 0;
1388 if (abs(Random() % 20) == 0) {
1389 if (weaponactive != -1) {
1390 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1391 if (weapons[victim->weaponids[0]].getType() == staff)
1392 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1393 if (weapons[weaponids[0]].getType() == staff)
1394 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1396 emit_sound_at(swordstaffsound, coords);
1398 emit_sound_at(metalhitsound, coords);
1406 animTarget = staggerbackhighanim;
1407 targetyaw = targetyaw + 180;
1409 aim = DoRotation(facing, 0, 90, 0) * 21;
1411 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1414 weaponids[0] = weaponids[num_weapons];
1415 if (weaponstuck == num_weapons)
1419 for (unsigned i = 0; i < Person::players.size(); i++) {
1420 Person::players[i]->wentforweapon = 0;
1427 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1428 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1429 victim->animTarget = dodgebackanim;
1430 victim->frameTarget = 0;
1434 rotatetarget = coords - victim->coords;
1435 Normalise(&rotatetarget);
1436 victim->targetyaw = -asin(0 - rotatetarget.x);
1437 victim->targetyaw *= 360 / 6.28;
1438 if (rotatetarget.z < 0)
1439 victim->targetyaw = 180 - victim->targetyaw;
1441 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1443 victim->lastattack3 = victim->lastattack2;
1444 victim->lastattack2 = victim->lastattack;
1445 victim->lastattack = victim->animTarget;
1447 victim->animTarget = sweepanim;
1448 victim->frameTarget = 0;
1452 rotatetarget = coords - victim->coords;
1453 Normalise(&rotatetarget);
1454 victim->targetyaw = -asin(0 - rotatetarget.x);
1455 victim->targetyaw *= 360 / 6.28;
1456 if (rotatetarget.z < 0)
1457 victim->targetyaw = 180 - victim->targetyaw;
1459 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1461 victim->lastattack3 = victim->lastattack2;
1462 victim->lastattack2 = victim->lastattack;
1463 victim->lastattack = victim->animTarget;
1468 victim->velocity = 0;
1470 if (aitype != playercontrolled) {
1472 if (escapednum < 2) {
1473 int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10));
1474 if ((Random() % chances) == 0) {
1480 if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal)
1487 void Person::DoDamage(float howmuch)
1489 // subtract health (temporary?)
1490 if (tutoriallevel != 1)
1491 damage += howmuch / power;
1494 damagedealt += howmuch / power;
1496 damagetaken += howmuch / power;
1499 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1502 if (tutoriallevel != 1)
1503 permanentdamage += howmuch / 2 / power;
1504 if (tutoriallevel != 1)
1505 superpermanentdamage += howmuch / 4 / power;
1507 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1509 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1513 camerashake += howmuch / 100;
1514 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1515 blackout = damage / damagetolerance;
1520 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1521 aitype = attacktypecutoff;
1522 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1523 if (abs(Random() % 2) == 0) {
1524 aitype = gethelptype;
1527 aitype = attacktypecutoff;
1531 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1534 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1535 if (skeleton.free) {
1536 flatvelocity2 = skeleton.joints[i].velocity;
1537 flatfacing2 = skeleton.joints[i].position * scale + coords;
1539 flatvelocity2 = velocity;
1540 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1542 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1543 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1544 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1545 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1546 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1547 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1550 emit_sound_at(splattersound, coords);
1555 if (!dead && creature == wolftype) {
1556 award_bonus(0, Wolfbonus);
1563 if (tutoriallevel != 1 || id == 0)
1564 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1565 int whichsound = -1;
1567 if (creature == wolftype) {
1568 int i = abs(Random() % 2);
1570 whichsound = snarlsound;
1572 whichsound = snarl2sound;
1574 if (creature == rabbittype) {
1575 int i = abs(Random() % 2);
1577 whichsound = rabbitpainsound;
1578 if (i == 1 && damage > damagetolerance)
1579 whichsound = rabbitpain1sound;
1582 if (whichsound != -1) {
1583 emit_sound_at(whichsound, coords);
1584 addEnvSound(coords);
1591 * calculate/animate head facing direction?
1593 void Person::DoHead()
1595 static XYZ rotatearound;
1597 static float lookspeed = 500;
1599 if (!freeze && !winfreeze) {
1602 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1603 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1605 while (targetheadyaw > 180)targetheadyaw -= 360;
1606 while (targetheadyaw < -180)targetheadyaw += 360;
1608 if (targetheadyaw > 160)
1609 targetheadpitch = targetheadpitch * -1;
1610 if (targetheadyaw < -160)
1611 targetheadpitch = targetheadpitch * -1;
1612 if (targetheadyaw > 160)
1613 targetheadyaw = targetheadyaw - 180;
1614 if (targetheadyaw < -160)
1615 targetheadyaw = targetheadyaw + 180;
1617 if (targetheadpitch > 120)
1618 targetheadpitch = 120;
1619 if (targetheadpitch < -120)
1620 targetheadpitch = -120;
1621 if (targetheadyaw > 120)
1622 targetheadyaw = 120;
1623 if (targetheadyaw < -120)
1624 targetheadyaw = -120;
1627 targetheadpitch = 0;
1629 if (targetheadyaw > 80)
1631 if (targetheadyaw < -80)
1632 targetheadyaw = -80;
1633 if (targetheadpitch > 50)
1634 targetheadpitch = 50;
1635 if (targetheadpitch < -50)
1636 targetheadpitch = -50;
1639 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1640 headyaw = targetheadyaw;
1641 else if (headyaw > targetheadyaw) {
1642 headyaw -= multiplier * lookspeed;
1643 } else if (headyaw < targetheadyaw) {
1644 headyaw += multiplier * lookspeed;
1647 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1648 headpitch = targetheadpitch;
1649 else if (headpitch > targetheadpitch) {
1650 headpitch -= multiplier * lookspeed / 2;
1651 } else if (headpitch < targetheadpitch) {
1652 headpitch += multiplier * lookspeed / 2;
1655 rotatearound = jointPos(neck);
1656 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1660 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1661 facing = DoRotation(facing, headpitch * .4, 0, 0);
1662 facing = DoRotation(facing, 0, headyaw * .4, 0);
1665 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1666 facing = DoRotation(facing, headpitch * .8, 0, 0);
1667 facing = DoRotation(facing, 0, headyaw * .8, 0);
1670 if (animTarget == walkanim) {
1671 facing = DoRotation(facing, headpitch * .6, 0, 0);
1672 facing = DoRotation(facing, 0, headyaw * .6, 0);
1675 skeleton.specialforward[0] = facing;
1676 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1677 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
1678 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1679 skeleton.FindRotationMuscle(i, animTarget);
1686 * ragdolls character?
1688 void Person::RagDoll(bool checkcollision)
1693 if (!skeleton.free) {
1696 if (id == 0 && isFlip())
1703 facing = DoRotation(facing, 0, yaw, 0);
1705 skeleton.freetime = 0;
1707 skeleton.longdead = 0;
1710 skeleton.broken = 0;
1711 skeleton.spinny = 1;
1713 skeleton.freefall = 1;
1715 if (!isnormal(velocity.x)) velocity.x = 0;
1716 if (!isnormal(velocity.y)) velocity.y = 0;
1717 if (!isnormal(velocity.z)) velocity.z = 0;
1718 if (!isnormal(yaw)) yaw = 0;
1719 if (!isnormal(coords.x)) coords = 0;
1720 if (!isnormal(tilt)) tilt = 0;
1721 if (!isnormal(tilt2)) tilt2 = 0;
1723 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1724 skeleton.joints[i].delay = 0;
1725 skeleton.joints[i].locked = 0;
1726 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1727 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1728 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1729 skeleton.joints[i].position.y += .1;
1730 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1731 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1734 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1735 skeleton.joints[i].velocity = 0;
1736 skeleton.joints[i].velchange = 0;
1738 skeleton.DoConstraints(&coords, &scale);
1739 if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) {
1740 skeleton.DoConstraints(&coords, &scale);
1741 skeleton.DoConstraints(&coords, &scale);
1742 skeleton.DoConstraints(&coords, &scale);
1743 skeleton.DoConstraints(&coords, &scale);
1746 speed = targetFrame().speed * 2;
1747 if (currentFrame().speed > targetFrame().speed) {
1748 speed = currentFrame().speed * 2;
1751 speed = transspeed * 2;
1755 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1756 if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height)
1757 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);
1759 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1760 change.x = (float)(Random() % 100) / 100;
1761 change.y = (float)(Random() % 100) / 100;
1762 change.z = (float)(Random() % 100) / 100;
1763 skeleton.joints[i].velocity += change;
1764 skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change;
1766 change.x = (float)(Random() % 100) / 100;
1767 change.y = (float)(Random() % 100) / 100;
1768 change.z = (float)(Random() % 100) / 100;
1769 skeleton.joints[i].velchange += change;
1770 skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change;
1773 if (checkcollision) {
1776 if (!skeleton.joints.empty()) {
1779 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1780 average += skeleton.joints[j].position;
1782 average /= skeleton.joints.size();
1783 coords += average * scale;
1784 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
1785 skeleton.joints[j].position -= average;
1789 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1790 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1791 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1792 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1793 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1796 if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) {
1797 coords.x = lowpoint.x;
1798 coords.z = lowpoint.z;
1807 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
1808 velocity += skeleton.joints[i].velocity * scale;
1810 velocity /= skeleton.joints.size();
1813 if (Random() % 2 == 0) {
1814 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1815 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1816 weapons[weaponids[0]].velocity.x += .01;
1819 weaponids[0] = weaponids[num_weapons];
1820 if (weaponstuck == num_weapons)
1824 for (unsigned i = 0; i < Person::players.size(); i++) {
1825 Person::players[i]->wentforweapon = 0;
1830 animTarget = bounceidleanim;
1831 animCurrent = bounceidleanim;
1841 void Person::FootLand(bodypart whichfoot, float opacity)
1843 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1844 cerr << "FootLand called on wrong bodypart" << endl;
1847 static XYZ terrainlight;
1848 static XYZ footvel, footpoint;
1849 if (opacity >= 1 || skiddelay <= 0) {
1852 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1853 if (distsq(&footpoint, &viewer))
1854 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1855 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1856 footvel = velocity / 5;
1859 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1860 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1861 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1862 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1863 if (environment == snowyenvironment) {
1864 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1866 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1868 } else if (environment == grassyenvironment) {
1869 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1870 } else if (environment == desertenvironment) {
1871 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1873 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1877 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1878 footvel = velocity / 5;
1881 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1882 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1883 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1890 * make a puff effect at a body part (dust effect?)
1892 void Person::Puff(int whichlabel)
1894 static XYZ footvel, footpoint;
1897 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1898 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1902 * I think I added this in an attempt to clean up code
1904 void Person::setAnimation(int animation)
1906 animTarget = animation;
1915 void Person::DoAnimations()
1917 if (!skeleton.free) {
1918 static float oldtarget;
1920 if (isIdle() && animCurrent != getIdle())
1921 normalsupdatedelay = 0;
1923 if (animTarget == tempanim || animCurrent == tempanim) {
1924 Animation::animations[tempanim] = tempanimation;
1926 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1932 vel[0] = velocity.x;
1933 vel[1] = velocity.y;
1934 vel[2] = velocity.z;
1937 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1938 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1940 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1942 if (!crouchkeydown && velocity.y >= -15)
1945 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1950 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1952 if (normaldotproduct(targfacing, velocity) >= -.3)
1953 animTarget = flipanim;
1955 animTarget = backflipanim;
1956 crouchtogglekeydown = 1;
1964 if (Animation::animations[animTarget].attack != reversed)
1966 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1967 crouchtogglekeydown = 0;
1968 if (aitype == playercontrolled)
1971 if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1974 crouchtogglekeydown = 1;
1978 if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1980 normalsupdatedelay = 0;
1984 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1986 emit_sound_at(fireendsound, coords);
1987 pause_sound(stream_firesound);
1991 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1992 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1994 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1995 if (normaldotproduct(victim->facing, facing) > 0)
1996 victim->animTarget = rabbittackledbackanim;
1998 victim->animTarget = rabbittackledfrontanim;
1999 victim->frameTarget = 2;
2002 victim->targetyaw = yaw;
2003 if (victim->aitype == gethelptype)
2004 victim->DoDamage(victim->damagetolerance - victim->damage);
2005 //victim->DoDamage(30);
2006 if (creature == wolftype) {
2008 emit_sound_at(clawslicesound, victim->coords);
2010 victim->DoBloodBig(1 / victim->armorhead, 210);
2012 award_bonus(id, TackleBonus,
2013 victim->aitype == gethelptype ? 50 : 0);
2017 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
2018 if (weapons[weaponids[0]].getType() == knife) {
2019 if (weaponactive == -1)
2021 else if (weaponactive == 0)
2024 if (weaponactive == -1) {
2025 emit_sound_at(knifesheathesound, coords);
2027 if (weaponactive != -1) {
2028 emit_sound_at(knifedrawsound, coords, 128);
2031 drawtogglekeydown = 1;
2034 if (tutoriallevel != 1 || id == 0)
2035 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2036 int whichsound = -1;
2038 if (terrain.getOpacity(coords.x, coords.z) < .2) {
2039 if (targetFrame().label == 1)
2040 whichsound = footstepsound;
2042 whichsound = footstepsound2;
2043 if (targetFrame().label == 1)
2044 FootLand(leftfoot, 1);
2045 if (targetFrame().label == 2)
2046 FootLand(rightfoot, 1);
2047 if (targetFrame().label == 3 && isRun()) {
2048 FootLand(rightfoot, 1);
2049 FootLand(leftfoot, 1);
2053 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2054 if (targetFrame().label == 1)
2055 whichsound = footstepsound3;
2057 whichsound = footstepsound4;
2061 if (targetFrame().label == 1)
2062 whichsound = footstepsound3;
2064 whichsound = footstepsound4;
2066 if (targetFrame().label == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2067 if (Animation::animations[animTarget].attack != neutral) {
2068 unsigned r = abs(Random() % 3);
2070 whichsound = lowwhooshsound;
2072 whichsound = midwhooshsound;
2074 whichsound = highwhooshsound;
2076 if (Animation::animations[animTarget].attack == neutral) {
2077 whichsound = movewhooshsound;
2079 } else if (targetFrame().label == 4) {
2080 whichsound = knifeswishsound;
2082 if (targetFrame().label == 8 && tutoriallevel != 1) {
2083 whichsound = landsound2;
2086 if (whichsound != -1) {
2087 emit_sound_at(whichsound, coords, 256.);
2090 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2091 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2092 addEnvSound(coords, 15);
2094 addEnvSound(coords, 6);
2099 if (targetFrame().label == 3) {
2101 emit_sound_at(whichsound, coords, 128.);
2107 if (tutoriallevel != 1 || id == 0)
2108 if (speechdelay <= 0)
2109 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2110 if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) {
2111 int whichsound = -1;
2112 if (targetFrame().label == 4 && aitype != playercontrolled) {
2113 if (Animation::animations[animTarget].attack != neutral) {
2114 unsigned r = abs(Random() % 4);
2115 if (creature == rabbittype) {
2116 if (r == 0) whichsound = rabbitattacksound;
2117 if (r == 1) whichsound = rabbitattack2sound;
2118 if (r == 2) whichsound = rabbitattack3sound;
2119 if (r == 3) whichsound = rabbitattack4sound;
2121 if (creature == wolftype) {
2122 if (r == 0) whichsound = barksound;
2123 if (r == 1) whichsound = bark2sound;
2124 if (r == 2) whichsound = bark3sound;
2125 if (r == 3) whichsound = barkgrowlsound;
2131 if (whichsound != -1) {
2132 emit_sound_at(whichsound, coords);
2138 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2139 FootLand(leftfoot, 1);
2140 FootLand(rightfoot, 1);
2144 currentoffset = targetoffset;
2145 frameTarget = frameCurrent;
2146 animCurrent = animTarget;
2149 if (animTarget == removeknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2150 for (unsigned i = 0; i < weapons.size(); i++) {
2151 if (weapons[i].owner == -1)
2152 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2153 if (distsq(&coords, &weapons[i].position) >= 1) {
2154 if (weapons[i].getType() != staff) {
2155 emit_sound_at(knifedrawsound, coords, 128.);
2164 if (animTarget == crouchremoveknifeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2165 for (unsigned i = 0; i < weapons.size(); i++) {
2166 bool willwork = true;
2167 if (weapons[i].owner != -1)
2168 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2169 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2170 if (Person::players[weapons[i].owner]->num_weapons > 1)
2172 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2173 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2174 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2175 bool fleshstuck = false;
2176 if (weapons[i].owner != -1)
2177 if (victim->weaponstuck != -1) {
2178 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2183 emit_sound_at(fleshstabremovesound, coords, 128.);
2185 if (weapons[i].getType() != staff) {
2186 emit_sound_at(knifedrawsound, coords, 128.);
2189 if (weapons[i].owner != -1) {
2190 victim = Person::players[weapons[i].owner];
2191 if (victim->num_weapons == 1)
2192 victim->num_weapons = 0;
2194 victim->num_weapons = 1;
2196 //victim->weaponactive=-1;
2197 victim->skeleton.longdead = 0;
2198 victim->skeleton.free = 1;
2199 victim->skeleton.broken = 0;
2201 for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) {
2202 victim->skeleton.joints[j].velchange = 0;
2203 victim->skeleton.joints[j].locked = 0;
2209 Normalise(&relative);
2210 XYZ footvel, footpoint;
2212 footpoint = weapons[i].position;
2213 if (victim->weaponstuck != -1) {
2214 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2216 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2217 weapons[i].bloody = 2;
2218 weapons[i].blooddrip = 5;
2219 victim->weaponstuck = -1;
2222 if (victim->num_weapons > 0) {
2223 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2224 victim->weaponstuck = 0;
2225 if (victim->weaponids[0] == int(i))
2226 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2229 victim->jointVel(abdomen) += relative * 6;
2230 victim->jointVel(neck) += relative * 6;
2231 victim->jointVel(rightshoulder) += relative * 6;
2232 victim->jointVel(leftshoulder) += relative * 6;
2240 if (animCurrent == drawleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2241 if (weaponactive == -1)
2243 else if (weaponactive == 0) {
2245 if (num_weapons == 2) {
2247 buffer = weaponids[0];
2248 weaponids[0] = weaponids[1];
2249 weaponids[1] = buffer;
2252 if (weaponactive == -1) {
2253 emit_sound_at(knifesheathesound, coords, 128.);
2255 if (weaponactive != -1) {
2256 emit_sound_at(knifedrawsound, coords, 128.);
2261 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2262 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2263 Normalise(&rotatetarget);
2264 targetyaw = -asin(0 - rotatetarget.x);
2265 targetyaw *= 360 / 6.28;
2266 if (rotatetarget.z < 0)
2267 targetyaw = 180 - targetyaw;
2269 if (animTarget == walljumprightkickanim)
2271 if (animTarget == walljumpleftkickanim)
2277 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2280 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2285 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2286 animTarget = rabbittackleanim;
2288 emit_sound_at(jumpsound, coords);
2296 targetloc = velocity;
2297 Normalise(&targetloc);
2298 targetloc += coords;
2299 for (unsigned i = 0; i < Person::players.size(); i++) {
2301 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2302 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2306 if (closestid != -1)
2307 if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2309 victim = Person::players[closestid];
2310 coords = victim->coords;
2311 animCurrent = rabbittacklinganim;
2312 animTarget = rabbittacklinganim;
2316 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2317 rotatetarget = coords - victim->coords;
2318 Normalise(&rotatetarget);
2319 targetyaw = -asin(0 - rotatetarget.x);
2320 targetyaw *= 360 / 6.28;
2321 if (rotatetarget.z < 0)
2322 targetyaw = 180 - targetyaw;
2324 if (animTarget != rabbitrunninganim) {
2325 emit_sound_at(jumpsound, coords, 128.);
2331 float damagemult = 1 * power;
2332 if (creature == wolftype)
2333 damagemult = 2.5 * power;
2335 damagemult /= victim->damagetolerance / 200;
2337 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)) {
2338 if (animTarget == spinkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2339 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2343 if (Random() % 2 || creature == wolftype) {
2346 if (creature == wolftype)
2349 if (tutoriallevel != 1) {
2350 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2352 if (creature == wolftype) {
2353 emit_sound_at(clawslicesound, victim->coords, 128.);
2355 victim->DoBloodBig(2 / victim->armorhead, 175);
2359 relative = victim->coords - coords;
2361 Normalise(&relative);
2362 relative = DoRotation(relative, 0, -90, 0);
2363 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2364 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2366 victim->jointVel(head) += relative * damagemult * 200;
2368 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2374 if (animTarget == wolfslapanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2375 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && Animation::animations[victim->animTarget].height != lowheight) {
2379 if (Random() % 2 || creature == wolftype) {
2381 if (creature == wolftype)
2384 emit_sound_at(whooshhitsound, victim->coords);
2385 if (creature == wolftype) {
2386 emit_sound_at(clawslicesound, victim->coords, 128.);
2388 victim->DoBloodBig(2, 175);
2392 relative = victim->coords - coords;
2394 Normalise(&relative);
2396 Normalise(&relative);
2397 relative = DoRotation(relative, 0, 90, 0);
2398 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2399 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2401 victim->jointVel(head) += relative * damagemult * 100;
2403 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2407 if (animTarget == walljumprightkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2408 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2414 if (tutoriallevel != 1) {
2415 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2417 if (creature == wolftype) {
2418 emit_sound_at(clawslicesound, victim->coords, 128.);
2420 victim->DoBloodBig(2 / victim->armorhead, 175);
2426 Normalise(&relative);
2427 relative = DoRotation(relative, 0, -90, 0);
2428 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2429 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2431 victim->jointVel(head) += relative * damagemult * 200;
2433 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2435 if (victim->damage > victim->damagetolerance)
2436 award_bonus(id, style);
2442 if (animTarget == walljumpleftkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2443 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2449 if (tutoriallevel != 1) {
2450 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2452 if (creature == wolftype) {
2453 emit_sound_at(clawslicesound, victim->coords, 128.);
2455 victim->DoBloodBig(2 / victim->armorhead, 175);
2461 Normalise(&relative);
2462 relative = DoRotation(relative, 0, 90, 0);
2463 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2464 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2466 victim->jointVel(head) += relative * damagemult * 200;
2468 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2470 if (victim->damage > victim->damagetolerance)
2471 award_bonus(id, style);
2477 if (animTarget == blockhighleftstrikeanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2478 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) {
2486 emit_sound_at(whooshhitsound, victim->coords);
2489 relative = victim->coords - coords;
2491 Normalise(&relative);
2492 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2493 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2495 victim->jointVel(head) += relative * damagemult * 100;
2497 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2501 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 8) {
2502 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2506 emit_sound_at(whooshhitsound, victim->coords, 128.);
2508 victim->skeleton.longdead = 0;
2509 victim->skeleton.free = 1;
2510 victim->skeleton.broken = 0;
2511 victim->skeleton.spinny = 1;
2513 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2514 victim->skeleton.joints[i].velchange = 0;
2515 victim->skeleton.joints[i].delay = 0;
2516 victim->skeleton.joints[i].locked = 0;
2517 //victim->skeleton.joints[i].velocity=0;
2523 Normalise(&relative);
2524 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2525 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2526 victim->skeleton.joints[i].position.y += relative.y * .3;
2527 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2528 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2530 victim->Puff(abdomen);
2531 victim->jointVel(abdomen).y = relative.y * 400;
2535 if (animTarget == killanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2536 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2540 if (tutoriallevel != 1) {
2541 emit_sound_at(heavyimpactsound, coords, 128.);
2544 relative = victim->coords - coords;
2546 Normalise(&relative);
2547 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2548 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2550 victim->Puff(abdomen);
2551 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2555 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2556 victim->jointVel(abdomen) += relative * damagemult * 300;
2560 if (animTarget == dropkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
2561 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2565 if (tutoriallevel != 1) {
2566 emit_sound_at(thudsound, coords);
2569 victim->skeleton.longdead = 0;
2570 victim->skeleton.free = 1;
2571 victim->skeleton.broken = 0;
2572 victim->skeleton.spinny = 1;
2574 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2575 victim->skeleton.joints[i].velchange = 0;
2576 //victim->skeleton.joints[i].delay=0;
2577 victim->skeleton.joints[i].locked = 0;
2580 relative = victim->coords - coords;
2581 Normalise(&relative);
2583 Normalise(&relative);
2584 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2585 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2590 victim->Puff(abdomen);
2591 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2592 victim->jointVel(abdomen) += relative * damagemult * 200;
2601 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2604 if (!victim->skeleton.free)
2608 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2609 emit_sound_at(knifesheathesound, coords, 128.);
2612 if (victim && hasvictim) {
2613 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2615 XYZ where, startpoint, endpoint, movepoint, colpoint;
2616 float rotationpoint;
2618 if (weapons[weaponids[weaponactive]].getType() == knife) {
2619 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2620 where -= victim->coords;
2621 if (!victim->skeleton.free)
2622 where = DoRotation(where, 0, -victim->yaw, 0);
2625 startpoint.y += 100;
2629 if (weapons[weaponids[weaponactive]].getType() == sword) {
2630 where = weapons[weaponids[weaponactive]].position;
2631 where -= victim->coords;
2632 if (!victim->skeleton.free)
2633 where = DoRotation(where, 0, -victim->yaw, 0);
2635 where = weapons[weaponids[weaponactive]].tippoint;
2636 where -= victim->coords;
2637 if (!victim->skeleton.free)
2638 where = DoRotation(where, 0, -victim->yaw, 0);
2641 if (weapons[weaponids[weaponactive]].getType() == staff) {
2642 where = weapons[weaponids[weaponactive]].position;
2643 where -= victim->coords;
2644 if (!victim->skeleton.free)
2645 where = DoRotation(where, 0, -victim->yaw, 0);
2647 where = weapons[weaponids[weaponactive]].tippoint;
2648 where -= victim->coords;
2649 if (!victim->skeleton.free)
2650 where = DoRotation(where, 0, -victim->yaw, 0);
2655 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2657 if (whichtri != -1) {
2658 if (victim->dead != 2) {
2659 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2661 award_bonus(id, FinishedBonus);
2664 weapons[weaponids[weaponactive]].bloody = 2;
2666 victim->skeleton.longdead = 0;
2667 victim->skeleton.free = 1;
2668 victim->skeleton.broken = 0;
2670 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2671 victim->skeleton.joints[i].velchange = 0;
2672 victim->skeleton.joints[i].locked = 0;
2673 //victim->skeleton.joints[i].velocity=0;
2675 emit_sound_at(fleshstabsound, coords, 128);
2678 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2679 weapons[weaponids[weaponactive]].blooddrip += 5;
2680 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2682 if (whichtri == -1) {
2684 emit_sound_at(knifesheathesound, coords, 128.);
2690 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
2692 emit_sound_at(knifedrawsound, coords, 128);
2695 if (victim && hasvictim) {
2696 XYZ footvel, footpoint;
2698 emit_sound_at(fleshstabremovesound, coords, 128.);
2701 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2703 if (weapons[weaponids[weaponactive]].getType() == sword) {
2704 XYZ where, startpoint, endpoint, movepoint;
2705 float rotationpoint;
2708 where = weapons[weaponids[weaponactive]].position;
2709 where -= victim->coords;
2710 if (!victim->skeleton.free)
2711 where = DoRotation(where, 0, -victim->yaw, 0);
2713 where = weapons[weaponids[weaponactive]].tippoint;
2714 where -= victim->coords;
2715 if (!victim->skeleton.free)
2716 where = DoRotation(where, 0, -victim->yaw, 0);
2721 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2722 footpoint += victim->coords;
2724 if (whichtri == -1) {
2725 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2728 if (weapons[weaponids[weaponactive]].getType() == staff) {
2729 XYZ where, startpoint, endpoint, movepoint;
2730 float rotationpoint;
2733 where = weapons[weaponids[weaponactive]].position;
2734 where -= victim->coords;
2735 if (!victim->skeleton.free)
2736 where = DoRotation(where, 0, -victim->yaw, 0);
2738 where = weapons[weaponids[weaponactive]].tippoint;
2739 where -= victim->coords;
2740 if (!victim->skeleton.free)
2741 where = DoRotation(where, 0, -victim->yaw, 0);
2746 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2747 footpoint += victim->coords;
2749 if (whichtri == -1) {
2750 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2753 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2755 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2756 victim->skeleton.longdead = 0;
2757 victim->skeleton.free = 1;
2758 victim->skeleton.broken = 0;
2760 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2761 victim->skeleton.joints[i].velchange = 0;
2762 victim->skeleton.joints[i].locked = 0;
2763 //victim->skeleton.joints[i].velocity=0;
2769 Normalise(&relative);
2770 //victim->Puff(abdomen);
2772 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2774 if (victim->bloodloss < victim->damagetolerance) {
2775 victim->bloodloss += 1000;
2779 victim->jointVel(abdomen) += relative * damagemult * 20;
2783 if (!hasvictim && onterrain) {
2784 weapons[weaponids[weaponactive]].bloody = 0;
2785 weapons[weaponids[weaponactive]].blooddrip = 0;
2789 if (animTarget == upunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2790 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2798 if (tutoriallevel != 1) {
2799 emit_sound_at(heavyimpactsound, victim->coords, 128);
2804 relative = victim->coords - coords;
2806 Normalise(&relative);
2807 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2808 victim->skeleton.joints[i].velocity = relative * 30;
2810 victim->jointVel(head) += relative * damagemult * 150;
2812 victim->frameTarget = 0;
2813 victim->animTarget = staggerbackhardanim;
2814 victim->targetyaw = targetyaw + 180;
2816 victim->stunned = 1;
2819 victim->Puff(abdomen);
2820 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2827 if (animTarget == winduppunchanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2828 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2832 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(thudsound, victim->coords);
2836 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) {
2837 if (tutoriallevel != 1) {
2838 emit_sound_at(whooshhitsound, victim->coords);
2841 if (tutoriallevel != 1) {
2842 emit_sound_at(heavyimpactsound, victim->coords);
2846 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight)
2849 relative = victim->coords - coords;
2851 Normalise(&relative);
2853 Normalise(&relative);
2854 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
2855 victim->skeleton.joints[i].velocity = relative * 5;
2857 victim->jointVel(abdomen) += relative * damagemult * 400;
2859 victim->frameTarget = 0;
2860 victim->animTarget = staggerbackhardanim;
2861 victim->targetyaw = targetyaw + 180;
2863 victim->stunned = 1;
2865 victim->Puff(abdomen);
2866 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2872 if (animTarget == blockhighleftanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2873 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2874 if (victim->id == 0)
2876 emit_sound_at(landsound2, victim->coords);
2882 if (animTarget == swordslashparryanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2883 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2884 if (victim->id == 0)
2887 if (weaponactive != -1) {
2888 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2889 if (weapons[victim->weaponids[0]].getType() == staff)
2890 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2891 if (weapons[weaponids[0]].getType() == staff)
2892 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2894 emit_sound_at(swordstaffsound, victim->coords);
2896 emit_sound_at(metalhitsound, victim->coords);
2904 if (animTarget == knifethrowanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2905 if (weaponactive != -1) {
2908 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);
2910 weapons[weaponids[0]].thrown(aim * 50);
2913 weaponids[0] = weaponids[num_weapons];
2919 if (animTarget == knifeslashstartanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
2921 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*Animation::animations[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2923 if (tutoriallevel != 1)
2924 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2926 award_bonus(id, Slicebonus);
2927 if (tutoriallevel != 1) {
2928 emit_sound_at(knifeslicesound, victim->coords);
2930 //victim->jointVel(abdomen)+=relative*damagemult*200;
2931 if (Animation::animations[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2932 if (victim->id != 0 || difficulty == 2) {
2933 victim->frameTarget = 0;
2934 victim->animTarget = staggerbackhardanim;
2935 victim->targetyaw = targetyaw + 180;
2939 victim->lowreversaldelay = 0;
2940 victim->highreversaldelay = 0;
2941 if (aitype != playercontrolled)
2942 weaponmissdelay = .6;
2944 if (tutoriallevel != 1)
2945 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2946 weapons[weaponids[weaponactive]].bloody = 1;
2947 if (tutoriallevel != 1)
2948 weapons[weaponids[weaponactive]].blooddrip += 3;
2950 XYZ footvel, footpoint;
2952 if (skeleton.free) {
2953 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2955 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2957 if (tutoriallevel != 1) {
2959 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2960 footvel = DoRotation(facing, 0, 90, 0) * .8;
2962 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2963 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2964 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2965 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2967 if (tutoriallevel == 1) {
2968 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2970 victim->DoDamage(damagemult * 0);
2973 if (animTarget == swordslashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
2974 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2975 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2976 award_bonus(id, Slashbonus);
2978 if (tutoriallevel != 1) {
2979 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2980 victim->DoBloodBig(2 / victim->armorhigh, 190);
2982 victim->DoBloodBig(2 / victim->armorhigh, 185);
2983 victim->deathbleeding = 1;
2984 emit_sound_at(swordslicesound, victim->coords);
2986 //victim->jointVel(abdomen)+=relative*damagemult*200;
2987 if (tutoriallevel != 1) {
2988 victim->frameTarget = 0;
2989 victim->animTarget = staggerbackhardanim;
2990 victim->targetyaw = targetyaw + 180;
2994 if (tutoriallevel != 1) {
2995 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2996 weapons[weaponids[weaponactive]].bloody = 1;
2997 weapons[weaponids[weaponactive]].blooddrip += 3;
2999 float bloodlossamount;
3000 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
3001 victim->bloodloss += bloodlossamount / victim->armorhigh;
3002 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
3003 victim->DoDamage(damagemult * 0);
3005 XYZ footvel, footpoint;
3007 if (skeleton.free) {
3008 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
3010 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
3013 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3014 footvel = DoRotation(facing, 0, 90, 0) * .8;
3016 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3017 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3018 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3019 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3022 if (victim->weaponactive != -1) {
3023 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
3024 if (weapons[victim->weaponids[0]].getType() == staff)
3025 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3026 if (weapons[weaponids[0]].getType() == staff)
3027 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
3029 emit_sound_at(swordstaffsound, victim->coords);
3031 emit_sound_at(metalhitsound, victim->coords);
3037 victim->Puff(righthand);
3039 victim->frameTarget = 0;
3040 victim->animTarget = staggerbackhighanim;
3041 victim->targetyaw = targetyaw + 180;
3043 aim = DoRotation(facing, 0, 90, 0) * 21;
3045 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
3046 victim->num_weapons--;
3047 if (victim->num_weapons) {
3048 victim->weaponids[0] = victim->weaponids[num_weapons];
3049 if (victim->weaponstuck == victim->num_weapons)
3050 victim->weaponstuck = 0;
3052 victim->weaponactive = -1;
3053 for (unsigned i = 0; i < Person::players.size(); i++) {
3054 Person::players[i]->wentforweapon = 0;
3061 if (animTarget == staffhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3062 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3063 if (tutoriallevel != 1) {
3064 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3068 if (Random() % 2 || creature == wolftype) {
3071 emit_sound_at(staffheadsound, victim->coords);
3075 relative = victim->coords - coords;
3077 Normalise(&relative);
3078 relative = DoRotation(relative, 0, 90, 0);
3080 Normalise(&relative);
3081 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3082 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3084 victim->jointVel(head) += relative * damagemult * 230;
3085 victim->jointVel(neck) += relative * damagemult * 230;
3087 if (tutoriallevel != 1) {
3088 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3090 award_bonus(id, solidhit, 30);
3095 if (animTarget == staffspinhitanim && Animation::animations[animTarget].frames[frameCurrent].label == 5 && victim->animTarget != rollanim) {
3096 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3097 if (tutoriallevel != 1) {
3098 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3102 if (Random() % 2 || creature == wolftype) {
3105 emit_sound_at(staffheadsound, victim->coords);
3109 relative = victim->coords - coords;
3111 Normalise(&relative);
3112 relative = DoRotation(relative, 0, -90, 0);
3113 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3114 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3116 victim->jointVel(head) += relative * damagemult * 220;
3117 victim->jointVel(neck) += relative * damagemult * 220;
3119 if (tutoriallevel != 1) {
3120 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3122 award_bonus(id, solidhit, 60);
3127 if (animTarget == staffgroundsmashanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3128 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3130 if (tutoriallevel != 1) {
3132 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3135 if (Random() % 2 || creature == wolftype) {
3138 emit_sound_at(staffbodysound, victim->coords);
3140 victim->skeleton.longdead = 0;
3141 victim->skeleton.free = 1;
3142 victim->skeleton.broken = 0;
3144 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3145 victim->skeleton.joints[i].velchange = 0;
3146 victim->skeleton.joints[i].locked = 0;
3147 //victim->skeleton.joints[i].velocity=0;
3154 Normalise(&relative);
3155 if (!victim->dead) {
3156 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3157 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3159 victim->jointVel(abdomen) += relative * damagemult * 40;
3162 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3163 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3166 victim->Puff(abdomen);
3167 if (tutoriallevel != 1) {
3168 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3170 if (!victim->dead) {
3171 award_bonus(id, solidhit, 40);
3177 if (animTarget == lowkickanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3178 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) {
3183 relative = victim->coords - coords;
3185 Normalise(&relative);
3189 if (Animation::animations[victim->animTarget].height == lowheight) {
3195 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3196 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3198 victim->jointVel(head) += relative * damagemult * 200;
3199 if (tutoriallevel != 1) {
3200 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3203 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3204 if (victim->howactive == typesleeping)
3205 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3206 if (creature == wolftype) {
3207 emit_sound_at(clawslicesound, victim->coords, 128.);
3209 victim->DoBloodBig(2 / victim->armorhead, 175);
3212 if (victim->damage >= victim->damagetolerance)
3214 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3215 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3217 victim->jointVel(abdomen) += relative * damagemult * 200;
3218 victim->frameTarget = 0;
3219 victim->animTarget = staggerbackhighanim;
3220 victim->targetyaw = targetyaw + 180;
3222 if (tutoriallevel != 1) {
3223 emit_sound_at(landsound2, victim->coords, 128.);
3225 victim->Puff(abdomen);
3226 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3227 if (creature == wolftype) {
3228 emit_sound_at(clawslicesound, victim->coords, 128.);
3230 victim->DoBloodBig(2 / victim->armorhigh, 170);
3237 if (animTarget == sweepanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3238 if ((victim->animTarget != jumpupanim) &&
3239 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3240 (victim != this->shared_from_this())) {
3244 if (tutoriallevel != 1) {
3245 emit_sound_at(landsound2, victim->coords, 128.);
3248 relative = victim->coords - coords;
3250 Normalise(&relative);
3252 if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3255 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3256 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3258 relative = DoRotation(relative, 0, -90, 0);
3260 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3261 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)
3262 victim->skeleton.joints[i].velocity = relative * 80;
3264 victim->Puff(rightankle);
3265 victim->Puff(leftankle);
3266 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3268 if (victim->damage >= victim->damagetolerance)
3270 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3271 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3273 relative = DoRotation(relative, 0, -90, 0);
3274 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3275 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)
3276 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3278 victim->jointVel(abdomen) += relative * damagemult * 200;
3279 victim->frameTarget = 0;
3280 victim->animTarget = staggerbackhighanim;
3281 victim->targetyaw = targetyaw + 180;
3283 if (tutoriallevel != 1) {
3284 emit_sound_at(landsound2, victim->coords, 128.);
3286 victim->Puff(abdomen);
3287 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3295 if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3296 if (animTarget == spinkickreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3304 if (tutoriallevel != 1) {
3305 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3307 if (creature == wolftype) {
3308 emit_sound_at(clawslicesound, victim->coords, 128);
3310 victim->DoBloodBig(2 / victim->armorhigh, 170);
3314 relative = victim->coords - oldcoords;
3316 Normalise(&relative);
3317 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3318 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3320 victim->jointVel(abdomen) += relative * damagemult * 200;
3321 victim->Puff(abdomen);
3322 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3324 award_bonus(id, Reversal);
3327 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3328 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3329 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3330 takeWeapon(victim->weaponids[victim->weaponactive]);
3331 victim->num_weapons--;
3332 if (victim->num_weapons > 0) {
3333 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3335 victim->weaponactive = -1;
3340 if (animTarget == staffhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3348 emit_sound_at(whooshhitsound, victim->coords, 128.);
3351 relative = victim->coords - oldcoords;
3353 Normalise(&relative);
3354 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3355 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3357 victim->jointVel(abdomen) += relative * damagemult * 200;
3359 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3362 if (animTarget == staffspinhitreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3371 award_bonus(id, staffreversebonus);
3373 if (tutoriallevel != 1) {
3374 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3377 award_bonus(id, staffreversebonus); // Huh, again?
3380 relative = victim->coords - oldcoords;
3382 Normalise(&relative);
3383 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3384 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3386 victim->jointVel(abdomen) += relative * damagemult * 200;
3388 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3391 if (animTarget == upunchreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3397 Normalise(&relative);
3399 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3400 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3402 victim->jointVel(lefthand) *= .1;
3403 victim->jointVel(leftwrist) *= .2;
3404 victim->jointVel(leftelbow) *= .5;
3405 victim->jointVel(leftshoulder) *= .7;
3406 victim->jointVel(righthand) *= .1;
3407 victim->jointVel(rightwrist) *= .2;
3408 victim->jointVel(rightelbow) *= .5;
3409 victim->jointVel(rightshoulder) *= .7;
3411 victim->Puff(abdomen);
3412 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3414 award_bonus(id, Reversal);
3418 if (weaponactive != -1 || creature == wolftype)
3420 if (creature == rabbittype && weaponactive != -1)
3421 if (weapons[weaponids[0]].getType() == staff)
3424 if (weaponactive != -1) {
3425 victim->DoBloodBig(2 / victim->armorhigh, 225);
3426 emit_sound_at(knifeslicesound, victim->coords);
3427 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3428 weapons[weaponids[weaponactive]].bloody = 1;
3429 weapons[weaponids[weaponactive]].blooddrip += 3;
3431 if (weaponactive == -1 && creature == wolftype) {
3432 emit_sound_at(clawslicesound, victim->coords, 128.);
3434 victim->DoBloodBig(2 / victim->armorhigh, 175);
3441 if (animTarget == swordslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3447 Normalise(&relative);
3449 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3450 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3452 victim->jointVel(lefthand) *= .1 - 1;
3453 victim->jointVel(leftwrist) *= .2 - 1;
3454 victim->jointVel(leftelbow) *= .5 - 1;
3455 victim->jointVel(leftshoulder) *= .7 - 1;
3456 victim->jointVel(righthand) *= .1 - 1;
3457 victim->jointVel(rightwrist) *= .2 - 1;
3458 victim->jointVel(rightelbow) *= .5 - 1;
3459 victim->jointVel(rightshoulder) *= .7 - 1;
3461 award_bonus(id, swordreversebonus);
3464 if (hasvictim && animTarget == knifeslashreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3472 if (tutoriallevel != 1) {
3473 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3477 relative = victim->coords - oldcoords;
3479 Normalise(&relative);
3480 relative = DoRotation(relative, 0, -90, 0);
3481 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3482 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3484 victim->jointVel(abdomen) += relative * damagemult * 200;
3485 victim->Puff(abdomen);
3486 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3488 award_bonus(id, Reversal);
3491 if (hasvictim && animTarget == sneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3494 victim->skeleton.spinny = 0;
3496 relative = facing * -1;
3498 Normalise(&relative);
3499 if (victim->id == 0)
3501 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3502 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3504 victim->damage = victim->damagetolerance;
3505 victim->permanentdamage = victim->damagetolerance - 1;
3508 if (weaponactive != -1 || creature == wolftype)
3510 if (creature == rabbittype && weaponactive != -1)
3511 if (weapons[weaponids[0]].getType() == staff)
3514 if (weaponactive != -1) {
3515 victim->DoBloodBig(200, 225);
3516 emit_sound_at(knifeslicesound, victim->coords);
3518 weapons[weaponids[weaponactive]].bloody = 2;
3519 weapons[weaponids[weaponactive]].blooddrip += 5;
3522 if (creature == wolftype && weaponactive == -1) {
3523 emit_sound_at(clawslicesound, victim->coords, 128.);
3525 victim->DoBloodBig(2, 175);
3528 award_bonus(id, spinecrusher);
3531 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3532 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3534 if (animTarget == knifefollowanim)
3535 victim->DoBloodBig(200, 210);
3536 if (animTarget == knifesneakattackanim) {
3537 XYZ footvel, footpoint;
3539 footpoint = weapons[weaponids[0]].tippoint;
3541 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3542 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3543 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3544 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3545 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3546 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3547 victim->DoBloodBig(200, 195);
3548 award_bonus(id, tracheotomy);
3550 if (animTarget == knifefollowanim) {
3551 award_bonus(id, Stabbonus);
3552 XYZ footvel, footpoint;
3554 footpoint = weapons[weaponids[0]].tippoint;
3556 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3557 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3558 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3559 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3560 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3561 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3564 victim->bloodloss += 10000;
3565 victim->velocity = 0;
3566 emit_sound_at(fleshstabsound, victim->coords);
3568 weapons[weaponids[weaponactive]].bloody = 2;
3569 weapons[weaponids[weaponactive]].blooddrip += 5;
3573 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3575 victim->velocity = 0;
3576 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3577 victim->skeleton.joints[i].velocity = 0;
3579 if (animTarget == knifefollowanim) {
3581 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3582 victim->skeleton.joints[i].velocity = 0;
3585 if (weaponactive != -1 && Animation::animations[victim->animTarget].attack != reversal) {
3586 emit_sound_at(fleshstabremovesound, victim->coords);
3588 weapons[weaponids[weaponactive]].bloody = 2;
3589 weapons[weaponids[weaponactive]].blooddrip += 5;
3591 XYZ footvel, footpoint;
3593 footpoint = weapons[weaponids[0]].tippoint;
3595 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3596 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3597 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3598 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3599 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3600 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3604 if (hasvictim && (animTarget == swordsneakattackanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) {
3605 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3606 award_bonus(id, backstab);
3610 XYZ footvel, footpoint;
3612 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3614 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3615 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3616 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3617 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3618 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3619 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3620 victim->DoBloodBig(200, 180);
3621 victim->DoBloodBig(200, 215);
3622 victim->bloodloss += 10000;
3623 victim->velocity = 0;
3624 emit_sound_at(fleshstabsound, victim->coords);
3626 weapons[weaponids[weaponactive]].bloody = 2;
3627 weapons[weaponids[weaponactive]].blooddrip += 5;
3631 if (hasvictim && animTarget == swordsneakattackanim && Animation::animations[animTarget].frames[frameCurrent].label == 6) {
3633 victim->velocity = 0;
3634 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3635 victim->skeleton.joints[i].velocity = 0;
3637 if (weaponactive != -1) {
3638 emit_sound_at(fleshstabremovesound, victim->coords);
3640 weapons[weaponids[weaponactive]].bloody = 2;
3641 weapons[weaponids[weaponactive]].blooddrip += 5;
3643 XYZ footvel, footpoint;
3645 footpoint = weapons[weaponids[0]].tippoint;
3647 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3648 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3649 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3650 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3651 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3652 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3656 if (animTarget == sweepreversalanim && Animation::animations[animTarget].frames[frameCurrent].label == 7) {
3664 if (weaponactive == -1) {
3665 if (tutoriallevel != 1) {
3666 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3671 if (weaponactive != -1 || creature == wolftype)
3673 if (creature == rabbittype && weaponactive != -1)
3674 if (weapons[weaponids[0]].getType() == staff)
3677 if (weaponactive != -1) {
3678 victim->DoBloodBig(2 / victim->armorhead, 225);
3679 emit_sound_at(knifeslicesound, victim->coords);
3680 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3681 weapons[weaponids[weaponactive]].bloody = 1;
3682 weapons[weaponids[weaponactive]].blooddrip += 3;
3684 if (weaponactive == -1 && creature == wolftype) {
3685 emit_sound_at(clawslicesound, victim->coords, 128.);
3687 victim->DoBloodBig(2 / victim->armorhead, 175);
3691 award_bonus(id, Reversal);
3696 relative = facing * -1;
3698 Normalise(&relative);
3699 relative = DoRotation(relative, 0, 90, 0);
3701 Normalise(&relative);
3702 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3703 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3705 victim->jointVel(head) += relative * damagemult * 200;
3706 if (victim->damage < victim->damagetolerance - 100)
3707 victim->velocity = relative * 200;
3708 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3709 victim->velocity = 0;
3712 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))) {
3716 relative = facing * -1;
3718 Normalise(&relative);
3719 relative = DoRotation(relative, 0, 90, 0);
3721 Normalise(&relative);
3722 for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) {
3723 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3725 victim->jointVel(head) += relative * damagemult * 200;
3728 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3729 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3730 award_bonus(id, reverseko);
3736 if (frameTarget > int(Animation::animations[animCurrent].frames.size()) - 1) {
3739 animTarget = getIdle();
3740 FootLand(leftfoot, 1);
3741 FootLand(rightfoot, 1);
3743 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3744 animTarget = rollanim;
3746 emit_sound_at(movewhooshsound, coords, 128.);
3748 if (animCurrent == staggerbackhighanim) {
3749 animTarget = getIdle();
3751 if (animCurrent == staggerbackhardanim) {
3752 animTarget = getIdle();
3754 if (animCurrent == removeknifeanim) {
3755 animTarget = getIdle();
3757 if (animCurrent == crouchremoveknifeanim) {
3758 animTarget = getCrouch();
3760 if (animCurrent == backhandspringanim) {
3761 animTarget = getIdle();
3763 if (animCurrent == dodgebackanim) {
3764 animTarget = getIdle();
3766 if (animCurrent == drawleftanim) {
3767 animTarget = getIdle();
3769 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3770 animTarget = getIdle();
3771 if (animCurrent == crouchdrawrightanim) {
3772 animTarget = getCrouch();
3774 if (weaponactive == -1)
3776 else if (weaponactive == 0) {
3778 if (num_weapons == 2) {
3780 buffer = weaponids[0];
3781 weaponids[0] = weaponids[1];
3782 weaponids[1] = buffer;
3786 if (weaponactive == -1) {
3787 emit_sound_at(knifesheathesound, coords, 128.);
3789 if (weaponactive != -1) {
3790 emit_sound_at(knifedrawsound, coords, 128.);
3793 if (animCurrent == rollanim) {
3794 animTarget = getCrouch();
3795 FootLand(leftfoot, 1);
3796 FootLand(rightfoot, 1);
3799 if (animTarget == walljumprightkickanim) {
3802 if (animTarget == walljumpleftkickanim) {
3805 animTarget = jumpdownanim;
3807 if (animCurrent == climbanim) {
3808 animTarget = getCrouch();
3810 coords += facing * .1;
3811 if (!isnormal(coords.x))
3822 if (animTarget == rabbitkickreversalanim) {
3823 animTarget = getCrouch();
3826 if (animTarget == jumpreversalanim) {
3827 animTarget = getCrouch();
3830 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3831 if (attackkeydown && animTarget != walljumpfrontanim) {
3833 float closestdist = -1;
3835 if (Person::players.size() > 1)
3836 for (unsigned i = 0; i < Person::players.size(); i++) {
3837 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3838 distance = distsq(&Person::players[i]->coords, &coords);
3839 if (closestdist == -1 || distance < closestdist) {
3840 closestdist = distance;
3845 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3846 victim = Person::players[closest];
3847 animTarget = walljumprightkickanim;
3849 XYZ rotatetarget = victim->coords - coords;
3850 Normalise(&rotatetarget);
3851 yaw = -asin(0 - rotatetarget.x);
3853 if (rotatetarget.z < 0)
3855 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3856 velocity = (victim->coords - coords) * 4;
3861 if (animTarget == walljumpbackanim) {
3862 animTarget = backflipanim;
3864 velocity = facing * -8;
3867 resume_stream(whooshsound);
3869 if (animTarget == walljumprightanim) {
3870 animTarget = rightflipanim;
3874 velocity = DoRotation(facing, 0, 30, 0) * -8;
3877 if (animTarget == walljumpfrontanim) {
3878 animTarget = frontflipanim;
3882 velocity = facing * 8;
3886 resume_stream(whooshsound);
3888 if (animTarget == walljumpleftanim) {
3889 if (attackkeydown) {
3891 float closestdist = -1;
3893 if (Person::players.size() > 1)
3894 for (unsigned i = 0; i < Person::players.size(); i++) {
3895 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3896 distance = distsq(&Person::players[i]->coords, &coords);
3897 if (closestdist == -1 || distance < closestdist) {
3898 closestdist = distance;
3903 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3904 victim = Person::players[closest];
3905 animTarget = walljumpleftkickanim;
3907 XYZ rotatetarget = victim->coords - coords;
3908 Normalise(&rotatetarget);
3909 yaw = -asin(0 - rotatetarget.x);
3911 if (rotatetarget.z < 0)
3913 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3914 velocity = (victim->coords - coords) * 4;
3919 if (animTarget != walljumpleftkickanim) {
3920 animTarget = leftflipanim;
3924 velocity = DoRotation(facing, 0, -30, 0) * -8;
3928 resume_stream(whooshsound);
3930 if (animTarget == sneakattackanim) {
3931 animCurrent = getCrouch();
3932 animTarget = getCrouch();
3939 transspeed = 1000000;
3940 targetheadyaw += 180;
3941 coords -= facing * .7;
3943 coords.y = terrain.getHeight(coords.x, coords.z);
3947 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3948 animTarget = getIdle();
3951 coords.y = terrain.getHeight(coords.x, coords.z);
3955 if (animCurrent == knifefollowanim) {
3956 animTarget = getIdle();
3959 if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3960 float ycoords = oldcoords.y;
3961 animTarget = getStop();
3966 transspeed = 1000000;
3967 targetheadyaw += 180;
3968 if (!isnormal(coords.x))
3970 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3971 oldcoords = coords + facing * .5;
3972 else if (animCurrent == sweepreversalanim)
3973 oldcoords = coords + facing * 1.1;
3974 else if (animCurrent == upunchreversalanim) {
3975 oldcoords = coords + facing * 1.5;
3978 targetheadyaw += 180;
3981 } else if (animCurrent == knifeslashreversalanim) {
3982 oldcoords = coords + facing * .5;
3985 targetheadyaw += 90;
3988 } else if (animCurrent == staffspinhitreversalanim) {
3991 targetheadyaw += 180;
3996 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3998 oldcoords.y = ycoords;
3999 currentoffset = coords - oldcoords;
4005 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
4010 if (Animation::animations[animTarget].attack == reversed) {
4012 if (animTarget == sweepreversedanim)
4014 animTarget = backhandspringanim;
4016 emit_sound_at(landsound, coords, 128);
4018 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
4019 animTarget = rollanim;
4022 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4023 coords.y = oldcoords.y;
4025 if (animCurrent == knifeslashreversedanim) {
4026 animTarget = rollanim;
4031 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4032 coords.y = oldcoords.y;
4036 animTarget = jumpdownanim;
4039 animTarget = getIdle();
4041 animTarget = getIdle();
4042 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
4043 animTarget = getIdle();
4045 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
4046 coords.y = oldcoords.y;
4047 //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale;
4048 targetoffset.y = coords.y;
4050 targetoffset.y = terrain.getHeight(coords.x, coords.z);
4051 currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale;
4052 currentoffset.y -= (coords.y - targetoffset.y);
4053 coords.y = targetoffset.y;
4055 normalsupdatedelay = 0;
4057 if (animCurrent == upunchanim) {
4058 animTarget = getStop();
4059 normalsupdatedelay = 0;
4062 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4066 if (num_weapons > 0)
4067 if (weapons[0].getType() == staff)
4073 rabbitkickragdoll = 1;
4075 if (animCurrent == rabbitkickreversedanim) {
4081 skeleton.spinny = 0;
4082 SolidHitBonus(!id); // FIXME: tricky id
4086 animTarget = rollanim;
4089 pause_sound(whooshsound);
4093 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4097 skeleton.spinny = 0;
4099 if (animCurrent == jumpreversedanim) {
4105 skeleton.spinny = 0;
4106 SolidHitBonus(!id); // FIXME: tricky id
4110 animTarget = rollanim;
4111 coords += facing * 2;
4113 pause_sound(whooshsound);
4118 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) {
4119 animTarget = getupfromfrontanim;
4121 } else if (Animation::animations[animCurrent].attack == normalattack) {
4122 animTarget = getIdle();
4125 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4126 animTarget = blockhighleftstrikeanim;
4128 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4129 animTarget = getIdle();
4132 if (animCurrent == spinkickanim && victim->skeleton.free) {
4133 if (creature == rabbittype)
4134 animTarget = fightidleanim;
4139 if (isIdle() && !wasIdle())
4140 normalsupdatedelay = 0;
4142 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4143 animTarget = jumpdownanim;
4146 if (!skeleton.free) {
4148 if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) {
4149 if (!isRun() || !wasRun()) {
4150 if (targetFrame().speed > currentFrame().speed)
4151 target += multiplier * targetFrame().speed * speed * 2;
4152 if (targetFrame().speed <= currentFrame().speed)
4153 target += multiplier * currentFrame().speed * speed * 2;
4155 if (isRun() && wasRun()) {
4157 tempspeed = velspeed;
4158 if (tempspeed < 10 * speedmult)
4159 tempspeed = 10 * speedmult;
4160 /* FIXME - mixed of target and current here, is that intended? */
4161 target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale);
4163 } else if (transspeed)
4164 target += multiplier * transspeed * speed * 2;
4166 if (!isRun() || !wasRun()) {
4167 if (targetFrame().speed > currentFrame().speed)
4168 target += multiplier * targetFrame().speed * 2;
4169 if (targetFrame().speed <= currentFrame().speed)
4170 target += multiplier * currentFrame().speed * 2;
4174 if (animCurrent != animTarget)
4175 target = (target + oldtarget) / 2;
4178 frameCurrent = frameTarget;
4182 rot = targetrot * target;
4183 yaw += rot - oldrot;
4189 if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) {
4190 frameCurrent = Animation::animations[animCurrent].frames.size() - 1;
4192 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4194 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4195 skeleton.joints[i].position = currentFrame().joints[i].position;
4198 skeleton.FindForwards();
4200 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4201 if (skeleton.muscles[i].visible) {
4202 skeleton.FindRotationMuscle(i, animTarget);
4205 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4206 if (skeleton.muscles[i].visible) {
4207 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4208 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4209 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4210 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4211 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4212 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4217 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4218 skeleton.joints[i].position = targetFrame().joints[i].position;
4221 skeleton.FindForwards();
4223 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4224 if (skeleton.muscles[i].visible) {
4225 skeleton.FindRotationMuscle(i, animTarget);
4228 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4229 if (skeleton.muscles[i].visible) {
4230 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4231 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4232 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4233 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4234 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4235 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4236 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4237 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4238 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4239 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4240 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4241 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4246 oldanimCurrent = animCurrent;
4247 oldanimTarget = animTarget;
4248 oldframeTarget = frameTarget;
4249 oldframeCurrent = frameCurrent;
4251 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4252 skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target) - skeleton.joints[i].position) / multiplier;
4253 skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * (target);
4255 offset = currentoffset * (1 - target) + targetoffset * target;
4256 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
4257 if (skeleton.muscles[i].visible) {
4258 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4259 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4260 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4265 if (isLanding() && landhard) {
4268 animTarget = getLandhard();
4281 void Person::DoStuff()
4283 static XYZ terrainnormal;
4284 static XYZ flatfacing;
4285 static XYZ flatvelocity;
4286 static float flatvelspeed;
4288 static int bloodsize;
4289 static int startx, starty, endx, endy;
4290 static GLubyte color;
4291 static XYZ bloodvel;
4293 onfiredelay -= multiplier;
4294 if (onfiredelay < 0 && onfire) {
4295 if (Random() % 2 == 0) {
4301 crouchkeydowntime += multiplier;
4303 crouchkeydowntime = 0;
4304 jumpkeydowntime += multiplier;
4305 if (!jumpkeydown && skeleton.free)
4306 jumpkeydowntime = 0;
4308 if (hostile || damage > 0 || bloodloss > 0)
4311 if (isIdle() || isRun())
4314 if (num_weapons == 1 && weaponactive != -1)
4318 blooddimamount -= multiplier * .3;
4319 speechdelay -= multiplier;
4320 texupdatedelay -= multiplier;
4321 interestdelay -= multiplier;
4322 flamedelay -= multiplier;
4323 parriedrecently -= multiplier;
4325 victim = this->shared_from_this();
4330 speed = 1.1 * speedmult;
4332 speed = 1.0 * speedmult;
4334 rabbitkickragdoll = 0;
4338 if (id != 0 && (creature == rabbittype || difficulty != 2))
4340 if (id != 0 && creature == wolftype && difficulty == 2) {
4342 if (aitype != passivetype) {
4344 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) {
4350 if (animTarget == wolfrunninganim && !superruntoggle) {
4351 animTarget = getRun();
4355 if (weaponactive == -1 && num_weapons > 0) {
4356 if (weapons[weaponids[0]].getType() == staff) {
4362 burnt += multiplier;
4366 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4368 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4374 vel[0] = velocity.x;
4375 vel[1] = velocity.y;
4376 vel[2] = velocity.z;
4379 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4380 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4384 while (flamedelay < 0 && onfire) {
4386 int howmany = fabs(Random() % (skeleton.joints.size()));
4387 if (skeleton.free) {
4388 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4389 flatfacing = skeleton.joints[howmany].position * scale + coords;
4391 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4392 flatvelocity = (coords - oldcoords) / multiplier / 2;
4394 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4397 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4399 int howmany = fabs(Random() % (skeleton.joints.size()));
4400 if (skeleton.free) {
4401 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4402 flatfacing = skeleton.joints[howmany].position * scale + coords;
4404 flatvelocity = (coords - oldcoords) / multiplier / 2;
4405 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4407 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4411 bleeding -= multiplier * .3;
4412 if (bloodtoggle == 2) {
4413 skeleton.drawmodel.textureptr.bind();
4414 if ((bleeding <= 0) && (detail != 2))
4419 if (neckspurtamount > 0) {
4420 neckspurtamount -= multiplier;
4421 neckspurtdelay -= multiplier * 3;
4422 neckspurtparticledelay -= multiplier * 3;
4423 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4426 if (skeleton.free) {
4427 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4428 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4429 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4431 bloodvel.z = 5 * neckspurtamount;
4432 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4433 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4434 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4436 neckspurtparticledelay = .05;
4438 if (neckspurtdelay < 0) {
4443 if (deathbleeding > 0 && dead != 2) {
4444 if (deathbleeding < 5)
4445 bleeddelay -= deathbleeding * multiplier / 4;
4447 bleeddelay -= 5 * multiplier / 4;
4448 if (bleeddelay < 0 && bloodtoggle) {
4453 if (skeleton.free) {
4454 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4455 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4457 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4458 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4462 bloodloss += deathbleeding * multiplier * 80;
4463 deathbleeding -= multiplier * 1.6;
4464 if (deathbleeding < 0)
4466 if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) {
4467 if (weaponactive != -1) {
4468 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4469 weapons[weaponids[0]].velocity.x += .01;
4472 weaponids[0] = weaponids[num_weapons];
4473 if (weaponstuck == num_weapons)
4477 for (unsigned i = 0; i < Person::players.size(); i++) {
4478 Person::players[i]->wentforweapon = 0;
4486 if (!dead && creature == wolftype) {
4487 award_bonus(0, Wolfbonus);
4490 if (animTarget == knifefollowedanim && !skeleton.free) {
4491 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4492 skeleton.joints[i].velocity = 0;
4493 skeleton.joints[i].velocity.y = -2;
4496 if (id != 0 && unconscioustime > .1) {
4504 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4505 texupdatedelay = .12;
4507 bloodsize = 5 - realtexdetail;
4511 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4512 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4513 endx = startx + bloodsize;
4514 endy = starty + bloodsize;
4524 if (endx > skeleton.skinsize - 1) {
4525 endx = skeleton.skinsize - 1;
4528 if (endy > skeleton.skinsize - 1) {
4529 endy = skeleton.skinsize - 1;
4537 for (i = startx; i < endx; i++) {
4538 for (int j = starty; j < endy; j++) {
4539 if (Random() % 2 == 0) {
4540 color = Random() % 85 + 170;
4541 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4542 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4543 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4544 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4549 skeleton.drawmodel.textureptr.bind();
4553 if (skeleton.free) {
4554 bleedx += 4 * direction / realtexdetail;
4556 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4558 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4560 bleedy -= 4 / realtexdetail;
4562 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4564 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4568 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4569 righthandmorphness = targetrighthandmorphness;
4570 righthandmorphstart = righthandmorphend;
4571 } else if (righthandmorphness > targetrighthandmorphness) {
4572 righthandmorphness -= multiplier * 4;
4573 } else if (righthandmorphness < targetrighthandmorphness) {
4574 righthandmorphness += multiplier * 4;
4577 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4578 lefthandmorphness = targetlefthandmorphness;
4579 lefthandmorphstart = lefthandmorphend;
4580 } else if (lefthandmorphness > targetlefthandmorphness) {
4581 lefthandmorphness -= multiplier * 4;
4582 } else if (lefthandmorphness < targetlefthandmorphness) {
4583 lefthandmorphness += multiplier * 4;
4586 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4587 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4588 tailmorphness = targettailmorphness;
4589 tailmorphstart = tailmorphend;
4590 } else if (tailmorphness > targettailmorphness) {
4591 tailmorphness -= multiplier * 10;
4592 } else if (tailmorphness < targettailmorphness) {
4593 tailmorphness += multiplier * 10;
4597 if (creature == wolftype) {
4598 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4599 tailmorphness = targettailmorphness;
4600 tailmorphstart = tailmorphend;
4601 } else if (tailmorphness > targettailmorphness) {
4602 tailmorphness -= multiplier * 2;
4603 } else if (tailmorphness < targettailmorphness) {
4604 tailmorphness += multiplier * 2;
4608 if (headmorphend == 3 || headmorphstart == 3) {
4609 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4610 headmorphness = targetheadmorphness;
4611 headmorphstart = headmorphend;
4612 } else if (headmorphness > targetheadmorphness) {
4613 headmorphness -= multiplier * 7;
4614 } else if (headmorphness < targetheadmorphness) {
4615 headmorphness += multiplier * 7;
4617 } else if (headmorphend == 5 || headmorphstart == 5) {
4618 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4619 headmorphness = targetheadmorphness;
4620 headmorphstart = headmorphend;
4621 } else if (headmorphness > targetheadmorphness) {
4622 headmorphness -= multiplier * 10;
4623 } else if (headmorphness < targetheadmorphness) {
4624 headmorphness += multiplier * 10;
4627 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4628 headmorphness = targetheadmorphness;
4629 headmorphstart = headmorphend;
4630 } else if (headmorphness > targetheadmorphness) {
4631 headmorphness -= multiplier * 4;
4632 } else if (headmorphness < targetheadmorphness) {
4633 headmorphness += multiplier * 4;
4637 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4638 chestmorphness = targetchestmorphness;
4639 chestmorphstart = chestmorphend;
4640 } else if (chestmorphness > targetchestmorphness) {
4641 chestmorphness -= multiplier;
4642 } else if (chestmorphness < targetchestmorphness) {
4643 chestmorphness += multiplier;
4646 if (dead != 2 && howactive <= typesleeping) {
4647 if (chestmorphstart == 0 && chestmorphend == 0) {
4649 targetchestmorphness = 1;
4652 if (chestmorphstart != 0 && chestmorphend != 0) {
4654 targetchestmorphness = 1;
4656 if (environment == snowyenvironment) {
4659 if (skeleton.free) {
4660 footvel = skeleton.specialforward[0] * -1;
4661 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4663 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4664 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4666 if (animTarget == sleepanim)
4667 footvel = DoRotation(footvel, 0, 90, 0);
4668 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4672 if (!dead && howactive < typesleeping) {
4673 blinkdelay -= multiplier * 2;
4674 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4676 targetheadmorphness = 1;
4678 blinkdelay = (float)(abs(Random() % 40)) / 5;
4680 if (headmorphstart == 3 && headmorphend == 3) {
4682 targetheadmorphness = 1;
4687 twitchdelay -= multiplier * 1.5;
4688 if (animTarget != hurtidleanim) {
4689 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4691 targetheadmorphness = 1;
4693 twitchdelay = (float)(abs(Random() % 40)) / 5;
4695 if (headmorphstart == 5 && headmorphend == 5) {
4697 targetheadmorphness = 1;
4701 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4702 twitchdelay3 -= multiplier * 1;
4703 if (Random() % 2 == 0) {
4704 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4705 righthandmorphness = 0;
4706 targetrighthandmorphness = 1;
4707 righthandmorphend = 1;
4708 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4710 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4711 righthandmorphness = 0;
4712 targetrighthandmorphness = 1;
4713 righthandmorphend = 0;
4716 if (Random() % 2 == 0) {
4717 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4718 lefthandmorphness = 0;
4719 targetlefthandmorphness = 1;
4720 lefthandmorphend = 1;
4721 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4723 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4724 lefthandmorphness = 0;
4725 targetlefthandmorphness = 1;
4726 lefthandmorphend = 0;
4732 if (creature == rabbittype) {
4733 if (howactive < typesleeping)
4734 twitchdelay2 -= multiplier * 1.5;
4736 twitchdelay2 -= multiplier * 0.5;
4737 if (howactive <= typesleeping) {
4738 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4740 targettailmorphness = 1;
4742 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4744 if (tailmorphstart == 1 && tailmorphend == 1) {
4746 targettailmorphness = 1;
4749 if (tailmorphstart == 2 && tailmorphend == 2) {
4751 targettailmorphness = 1;
4758 if (creature == wolftype) {
4759 twitchdelay2 -= multiplier * 1.5;
4760 if (tailmorphend != 0)
4761 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4763 targettailmorphness = 1;
4767 if (tailmorphend != 5)
4768 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4770 targettailmorphness = 1;
4774 if (twitchdelay2 <= 0) {
4775 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4777 targettailmorphness = 1;
4780 if (tailmorphstart == 1 && tailmorphend == 1) {
4782 targettailmorphness = 1;
4785 if (tailmorphstart == 2 && tailmorphend == 2) {
4787 targettailmorphness = 1;
4790 if (tailmorphstart == 3 && tailmorphend == 3) {
4792 targettailmorphness = 1;
4795 if (tailmorphstart == 4 && tailmorphend == 4) {
4797 targettailmorphness = 1;
4804 unconscioustime = 0;
4806 if (dead == 1 || howactive == typesleeping) {
4807 unconscioustime += multiplier;
4808 //If unconscious, close eyes and mouth
4809 if (righthandmorphend != 0)
4810 righthandmorphness = 0;
4811 righthandmorphend = 0;
4812 targetrighthandmorphness = 1;
4814 if (lefthandmorphend != 0)
4815 lefthandmorphness = 0;
4816 lefthandmorphend = 0;
4817 targetlefthandmorphness = 1;
4819 if (headmorphend != 3 && headmorphend != 5)
4822 targetheadmorphness = 1;
4826 if (howactive > typesleeping) {
4829 if (bloodtoggle && !bled) {
4830 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4832 if (bloodtoggle && !bled)
4833 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4834 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4835 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
4839 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4844 if (dead == 2 || howactive > typesleeping) {
4845 //If dead, open mouth and hands
4846 if (righthandmorphend != 0)
4847 righthandmorphness = 0;
4848 righthandmorphend = 0;
4849 targetrighthandmorphness = 1;
4851 if (lefthandmorphend != 0)
4852 lefthandmorphness = 0;
4853 lefthandmorphend = 0;
4854 targetlefthandmorphness = 1;
4856 if (headmorphend != 2)
4859 targetheadmorphness = 1;
4862 if (stunned > 0 && !dead && headmorphend != 2) {
4863 if (headmorphend != 4)
4866 targetheadmorphness = 1;
4869 if (damage > damagetolerance && !dead) {
4872 unconscioustime = 0;
4874 if (creature == wolftype) {
4875 award_bonus(0, Wolfbonus);
4880 if (weaponactive != -1) {
4881 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4882 weapons[weaponids[0]].velocity.x += .01;
4885 weaponids[0] = weaponids[num_weapons];
4886 if (weaponstuck == num_weapons)
4890 for (unsigned i = 0; i < Person::players.size(); i++) {
4891 Person::players[i]->wentforweapon = 0;
4897 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4906 damage -= multiplier * 13;
4908 permanentdamage -= multiplier * 4;
4909 if (isIdle() || isCrouch()) {
4911 permanentdamage -= multiplier * 4;
4915 if (permanentdamage < 0)
4916 permanentdamage = 0;
4917 if (superpermanentdamage < 0)
4918 superpermanentdamage = 0;
4919 if (permanentdamage < superpermanentdamage) {
4920 permanentdamage = superpermanentdamage;
4922 if (damage < permanentdamage) {
4923 damage = permanentdamage;
4925 if (dead == 1 && damage < damagetolerance) {
4929 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
4930 skeleton.joints[i].velocity = 0;
4933 if (permanentdamage > damagetolerance && dead != 2) {
4936 if (weaponactive != -1) {
4937 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4938 weapons[weaponids[0]].velocity.x += .01;
4941 weaponids[0] = weaponids[num_weapons];
4942 if (weaponstuck == num_weapons)
4946 for (unsigned i = 0; i < Person::players.size(); i++) {
4947 Person::players[i]->wentforweapon = 0;
4953 if (!dead && creature == wolftype) {
4954 award_bonus(0, Wolfbonus);
4957 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4958 award_bonus(id, touchofdeath);
4959 if (id != 0 && unconscioustime > .1) {
4967 emit_sound_at(breaksound, coords);
4970 if (skeleton.free == 1) {
4972 pause_sound(whooshsound);
4975 //If knocked over, open hands and close mouth
4976 if (righthandmorphend != 0)
4977 righthandmorphness = 0;
4978 righthandmorphend = 0;
4979 targetrighthandmorphness = 1;
4981 if (lefthandmorphend != 0)
4982 lefthandmorphness = 0;
4983 lefthandmorphend = 0;
4984 targetlefthandmorphness = 1;
4986 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4987 if (headmorphend != 0)
4990 targetheadmorphness = 1;
4994 skeleton.DoGravity(&scale);
4996 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4997 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4998 award_bonus(id, deepimpact);
4999 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
5003 if (!skeleton.joints.empty()) {
5004 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5005 average += skeleton.joints[j].position;
5007 average /= skeleton.joints.size();
5008 coords += average * scale;
5009 for (unsigned j = 0; j < skeleton.joints.size(); j++) {
5010 skeleton.joints[j].position -= average;
5012 average /= multiplier;
5016 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5017 velocity += skeleton.joints[i].velocity * scale;
5019 velocity /= skeleton.joints.size();
5021 if (!isnormal(velocity.x) && velocity.x) {
5025 if (findLength(&average) < 10 && dead && skeleton.free) {
5026 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5027 if (skeleton.longdead > 2000) {
5028 if (skeleton.longdead > 6000) {
5030 pause_sound(whooshsound);
5035 if (dead == 2 && bloodloss < damagetolerance) {
5037 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
5039 if (bloodtoggle && !bled) {
5040 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
5042 if (bloodtoggle && !bled)
5043 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5044 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5045 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5046 float size = .2 * 1.2;
5049 Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
5053 if (dead == 2 && bloodloss >= damagetolerance) {
5055 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
5058 if (bloodtoggle && !bled) {
5059 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5061 if (bloodtoggle && !bled)
5062 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5063 int j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5064 XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0);
5068 Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5075 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5076 bool canrecover = 1;
5077 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5078 startpoint = coords;
5081 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5083 if (velocity.y < -30)
5085 for (i = 0; i < Object::objects.size(); i++) {
5086 if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) {
5087 colviewer = startpoint;
5088 coltarget = endpoint;
5089 if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1)
5098 terrainnormal = jointPos(groin) - jointPos(abdomen);
5099 if (joint(groin).locked && joint(abdomen).locked) {
5100 terrainnormal = jointPos(groin) - jointPos(abdomen);
5101 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5103 if (joint(abdomen).locked && joint(neck).locked) {
5104 terrainnormal = jointPos(abdomen) - jointPos(neck);
5105 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5107 if (joint(groin).locked && joint(neck).locked) {
5108 terrainnormal = jointPos(groin) - jointPos(neck);
5109 middle = (jointPos(groin) + jointPos(neck)) / 2;
5111 Normalise(&terrainnormal);
5113 targetyaw = -asin(0 - terrainnormal.x);
5114 targetyaw *= 360 / 6.28;
5115 if (terrainnormal.z < 0)
5116 targetyaw = 180 - targetyaw;
5120 animTarget = flipanim;
5121 crouchtogglekeydown = 1;
5126 animCurrent = tempanim;
5130 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5131 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5132 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5137 if (findLength(&average) < 10 && !dead && skeleton.free) {
5138 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5139 if (skeleton.longdead > (damage + 500) * 1.5) {
5141 pause_sound(whooshsound);
5147 terrainnormal = jointPos(groin) - jointPos(abdomen);
5148 if (joint(groin).locked && joint(abdomen).locked) {
5149 terrainnormal = jointPos(groin) - jointPos(abdomen);
5150 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5152 if (joint(abdomen).locked && joint(neck).locked) {
5153 terrainnormal = jointPos(abdomen) - jointPos(neck);
5154 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5156 if (joint(groin).locked && joint(neck).locked) {
5157 terrainnormal = jointPos(groin) - jointPos(neck);
5158 middle = (jointPos(groin) + jointPos(neck)) / 2;
5160 Normalise(&terrainnormal);
5162 targetyaw = -asin(0 - terrainnormal.x);
5163 targetyaw *= 360 / 6.28;
5164 if (terrainnormal.z < 0)
5165 targetyaw = 180 - targetyaw;
5168 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5171 if (skeleton.forward.y < 0) {
5172 animTarget = getupfrombackanim;
5176 if (skeleton.forward.y > -.3) {
5177 animTarget = getupfromfrontanim;
5185 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5186 animTarget = rollanim;
5187 targetyaw = lookyaw;
5204 if ( !leftkeydown && !rightkeydown)
5211 if (abs(targettilt2) > 50)
5213 animCurrent = tempanim;
5216 tilt2 = targettilt2;
5218 if (middle.y > 0 && animTarget != rollanim)
5219 targetoffset.y = middle.y + 1;
5221 for (unsigned i = 0; i < skeleton.joints.size(); i++) {
5222 tempanimation.frames[0].joints[i].position = skeleton.joints[i].position;
5223 tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0);
5230 if (num_weapons > 0)
5231 if (weapons[0].getType() == staff)
5233 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5234 if (velocity.y > -30) {
5236 tempvelocity = velocity;
5237 Normalise(&tempvelocity);
5238 targetyaw = -asin(0 - tempvelocity.x);
5239 targetyaw *= 360 / 6.28;
5241 targetyaw = 180 - targetyaw;
5245 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5246 animTarget = rollanim;
5249 animTarget = backhandspringanim;
5255 emit_sound_at(movewhooshsound, coords, 128.);
5257 animCurrent = animTarget;
5258 frameCurrent = frameTarget - 1;
5270 if (skeleton.freefall == 0)
5275 if (aitype != passivetype || skeleton.free == 1)
5276 if (findLengthfast(&velocity) > .1)
5277 for (i = 0; i < Object::objects.size(); i++) {
5278 if (Object::objects[i]->type == firetype)
5279 if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 49) {
5281 if (!Object::objects[i]->onfire) {
5282 emit_sound_at(firestartsound, Object::objects[i]->position);
5284 Object::objects[i]->onfire = 1;
5287 if (Object::objects[i]->onfire) {
5292 if (Object::objects[i]->type == bushtype)
5293 if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 49) {
5295 if (!Object::objects[i]->onfire) {
5296 emit_sound_at(firestartsound, Object::objects[i]->position);
5298 Object::objects[i]->onfire = 1;
5302 if (Object::objects[i]->onfire) {
5306 if (Object::objects[i]->messedwith <= 0) {
5310 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5313 addEnvSound(coords, 4 * findLength(&velocity));
5317 if (environment == grassyenvironment)
5318 howmany = findLength(&velocity) * 4;
5319 if (environment == snowyenvironment)
5320 howmany = findLength(&velocity) * 2;
5322 if (environment != desertenvironment)
5323 for (int j = 0; j < howmany; j++) {
5324 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5325 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5326 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5329 pos.x += float(abs(Random() % 100) - 50) / 200;
5330 pos.y += float(abs(Random() % 100) - 50) / 200;
5331 pos.z += float(abs(Random() % 100) - 50) / 200;
5332 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);
5333 Sprite::setLastSpriteSpecial(1);
5335 howmany = findLength(&velocity) * 4;
5337 if (environment == snowyenvironment)
5338 for (int j = 0; j < howmany; j++) {
5339 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5340 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5341 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5344 pos.x += float(abs(Random() % 100) - 50) / 200;
5345 pos.y += float(abs(Random() % 100) - 50) / 200;
5346 pos.z += float(abs(Random() % 100) - 50) / 200;
5347 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5348 Sprite::setLastSpriteSpecial(2);
5351 Object::objects[i]->rotx += velocity.x * multiplier * 6;
5352 Object::objects[i]->roty += velocity.z * multiplier * 6;
5353 Object::objects[i]->messedwith = .5;
5356 if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) {
5357 if (Object::objects[i]->pitch == 0)
5360 tempcoord = coords - Object::objects[i]->position;
5361 tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0);
5362 tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0);
5363 tempcoord += Object::objects[i]->position;
5365 if (distsqflat(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 8 && distsq(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale*Object::objects[i]->scale * 300 && tempcoord.y > Object::objects[i]->position.y + 3 * Object::objects[i]->scale) {
5366 if (Object::objects[i]->messedwith <= 0) {
5370 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5373 addEnvSound(coords, 4 * findLength(&velocity));
5377 if (environment == grassyenvironment)
5378 howmany = findLength(&velocity) * 4;
5379 if (environment == snowyenvironment)
5380 howmany = findLength(&velocity) * 2;
5382 if (environment != desertenvironment)
5383 for (int j = 0; j < howmany; j++) {
5384 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5385 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5386 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5388 pos += velocity * .1;
5390 pos.x += float(abs(Random() % 100) - 50) / 150;
5391 pos.y += float(abs(Random() % 100) - 50) / 150;
5392 pos.z += float(abs(Random() % 100) - 50) / 150;
5393 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);
5394 Sprite::setLastSpriteSpecial(1);
5396 howmany = findLength(&velocity) * 4;
5398 if (environment == snowyenvironment)
5399 for (int j = 0; j < howmany; j++) {
5400 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5401 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5402 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5404 pos += velocity * .1;
5406 pos.x += float(abs(Random() % 100) - 50) / 150;
5407 pos.y += float(abs(Random() % 100) - 50) / 150;
5408 pos.z += float(abs(Random() % 100) - 50) / 150;
5409 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5410 Sprite::setLastSpriteSpecial(2);
5413 Object::objects[i]->messedwith = .5;
5418 if (!skeleton.free) {
5421 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5424 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5426 if (tutoriallevel == 1 && id != 0)
5428 if (play && aitype != playercontrolled) {
5429 int whichsound = -1;
5430 i = abs(Random() % 4);
5431 if (speechdelay <= 0) {
5432 if (creature == rabbittype) {
5434 whichsound = rabbitchitter;
5436 whichsound = rabbitchitter2;
5438 if (creature == wolftype) {
5440 whichsound = growlsound;
5442 whichsound = growl2sound;
5447 if (whichsound != -1) {
5448 emit_sound_at(whichsound, coords);
5452 if (animTarget == staggerbackhighanim)
5454 if (animTarget == staggerbackhardanim)
5456 staggerdelay -= multiplier;
5457 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5459 if (velocity.y < -30 && animTarget == jumpdownanim)
5461 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5462 animTarget = getIdle();
5466 weaponmissdelay -= multiplier;
5467 highreversaldelay -= multiplier;
5468 lowreversaldelay -= multiplier;
5469 lastcollide -= multiplier;
5470 skiddelay -= multiplier;
5471 if (!isnormal(velocity.x) && velocity.x) {
5474 if (!isnormal(targettilt) && targettilt) {
5477 if (!isnormal(targettilt2) && targettilt2) {
5480 if (!isnormal(targetyaw) && targetyaw) {
5484 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5485 //open hands and close mouth
5486 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5487 righthandmorphness = 0;
5488 righthandmorphend = 0;
5489 targetrighthandmorphness = 1;
5492 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5493 lefthandmorphness = 0;
5494 lefthandmorphend = 0;
5495 targetlefthandmorphness = 1;
5498 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5501 targetheadmorphness = 1;
5505 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) {
5506 //open hands and mouth
5507 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5508 righthandmorphness = 0;
5509 righthandmorphend = 0;
5510 targetrighthandmorphness = 1;
5513 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5514 lefthandmorphness = 0;
5515 lefthandmorphend = 0;
5516 targetlefthandmorphness = 1;
5519 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5522 targetheadmorphness = 1;
5526 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5527 //close hands and mouth
5528 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5529 righthandmorphness = 0;
5530 righthandmorphend = 1;
5531 targetrighthandmorphness = 1;
5534 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5535 lefthandmorphness = 0;
5536 lefthandmorphend = 1;
5537 targetlefthandmorphness = 1;
5540 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5543 targetheadmorphness = 1;
5547 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) {
5548 //close hands and yell
5549 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5550 righthandmorphness = 0;
5551 righthandmorphend = 1;
5552 targetrighthandmorphness = 1;
5555 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5556 lefthandmorphness = 0;
5557 lefthandmorphend = 1;
5558 targetlefthandmorphness = 1;
5561 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5564 targetheadmorphness = 1;
5571 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5572 (victim->aitype != searchtype) && (aitype != passivetype) &&
5573 (aitype != searchtype) && (victim->id < Person::players.size())) {
5574 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5578 if (!dead && animTarget != hurtidleanim)
5579 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5580 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5583 targetheadmorphness = 1;
5587 if (weaponactive != -1) {
5588 if (weapons[weaponids[weaponactive]].getType() != staff) {
5589 righthandmorphstart = 1;
5590 righthandmorphend = 1;
5592 if (weapons[weaponids[weaponactive]].getType() == staff) {
5593 righthandmorphstart = 2;
5594 righthandmorphend = 2;
5596 targetrighthandmorphness = 1;
5599 terrainnormal = terrain.getNormal(coords.x, coords.z);
5601 if (Animation::animations[animTarget].attack != reversal) {
5602 if (!isnormal(coords.x))
5610 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5611 facing = flatfacing;
5612 ReflectVector(&facing, terrainnormal);
5615 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5617 targettilt2 = -facing.y * 20;
5622 if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5624 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5625 flatvelocity = velocity;
5627 flatvelspeed = findLength(&flatvelocity);
5628 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5629 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5634 if (targettilt > 25)
5636 if (targettilt < -25)
5640 if (targettilt2 > 45)
5642 if (targettilt2 < -45)
5644 if (abs(tilt2 - targettilt2) < multiplier * 400)
5645 tilt2 = targettilt2;
5646 else if (tilt2 > targettilt2) {
5647 tilt2 -= multiplier * 400;
5648 } else if (tilt2 < targettilt2) {
5649 tilt2 += multiplier * 400;
5651 if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5658 if (!isnormal(targettilt) && targettilt) {
5661 if (!isnormal(targettilt2) && targettilt2) {
5666 if (animTarget == rabbittackleanim) {
5667 velocity += facing * multiplier * speed * 700 * scale;
5668 velspeed = findLength(&velocity);
5669 if (velspeed > speed * 65 * scale) {
5670 velocity /= velspeed;
5671 velspeed = speed * 65 * scale;
5672 velocity *= velspeed;
5674 velocity.y += gravity * multiplier * 20;
5675 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5676 velspeed = findLength(&velocity);
5677 velocity = flatfacing * velspeed;
5679 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5680 if (isRun() || animTarget == rabbitkickanim) {
5681 velocity += facing * multiplier * speed * 700 * scale;
5682 velspeed = findLength(&velocity);
5683 if (velspeed > speed * 45 * scale) {
5684 velocity /= velspeed;
5685 velspeed = speed * 45 * scale;
5686 velocity *= velspeed;
5688 velocity.y += gravity * multiplier * 20;
5689 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5690 velspeed = findLength(&velocity);
5691 if (velspeed < speed * 30 * scale)
5692 velspeed = speed * 30 * scale;
5693 velocity = flatfacing * velspeed;
5695 } else if (isRun()) {
5696 velocity += facing * multiplier * speed * 700 * scale;
5697 velspeed = findLength(&velocity);
5698 if (creature == rabbittype) {
5699 if (velspeed > speed * 55 * scale) {
5700 velocity /= velspeed;
5701 velspeed = speed * 55 * scale;
5702 velocity *= velspeed;
5705 if (creature == wolftype) {
5706 if (velspeed > speed * 75 * scale) {
5707 velocity /= velspeed;
5708 velspeed = speed * 75 * scale;
5709 velocity *= velspeed;
5712 velocity.y += gravity * multiplier * 20;
5713 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5714 velspeed = findLength(&velocity);
5715 velocity = flatfacing * velspeed;
5718 if (animTarget == rollanim && targetFrame().label != 6) {
5719 velocity += facing * multiplier * speed * 700 * scale;
5720 velspeed = findLength(&velocity);
5721 if (velspeed > speed * 45 * scale) {
5722 velocity /= velspeed;
5723 velspeed = speed * 45 * scale;
5724 velocity *= velspeed;
5726 velocity.y += gravity * multiplier * 20;
5727 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5728 velspeed = findLength(&velocity);
5729 velocity = flatfacing * velspeed;
5732 if (animTarget == sneakanim || animTarget == walkanim) {
5733 velocity += facing * multiplier * speed * 700 * scale;
5734 velspeed = findLength(&velocity);
5735 if (velspeed > speed * 12 * scale) {
5736 velocity /= velspeed;
5737 velspeed = speed * 12 * scale;
5738 velocity *= velspeed;
5740 velocity.y += gravity * multiplier * 20;
5741 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5742 velspeed = findLength(&velocity);
5743 velocity = flatfacing * velspeed;
5746 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5747 velocity += facing * multiplier * speed * 700 * scale;
5748 velspeed = findLength(&velocity);
5749 if (velspeed > speed * 2 * scale) {
5750 velocity /= velspeed;
5751 velspeed = speed * 2 * scale;
5752 velocity *= velspeed;
5754 velocity.y += gravity * multiplier * 20;
5755 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5756 velspeed = findLength(&velocity);
5757 velocity = flatfacing * velspeed;
5761 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5762 velocity -= facing * multiplier * speed * 700 * scale;
5763 velspeed = findLength(&velocity);
5764 if (velspeed > speed * 2 * scale) {
5765 velocity /= velspeed;
5766 velspeed = speed * 2 * scale;
5767 velocity *= velspeed;
5769 velocity.y += gravity * multiplier * 20;
5770 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5771 velspeed = findLength(&velocity);
5772 velocity = flatfacing * velspeed * -1;
5775 if (animTarget == fightsidestep) {
5776 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5777 velspeed = findLength(&velocity);
5778 if (velspeed > speed * 12 * scale) {
5779 velocity /= velspeed;
5780 velspeed = speed * 12 * scale;
5781 velocity *= velspeed;
5783 velocity.y += gravity * multiplier * 20;
5784 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5785 velspeed = findLength(&velocity);
5786 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5789 if (animTarget == staggerbackhighanim) {
5790 coords -= facing * multiplier * speed * 16 * scale;
5793 if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) {
5794 coords -= facing * multiplier * speed * 20 * scale;
5798 if (animTarget == backhandspringanim) {
5799 //coords-=facing*multiplier*50*scale;
5800 velocity += facing * multiplier * speed * 700 * scale * -1;
5801 velspeed = findLength(&velocity);
5802 if (velspeed > speed * 50 * scale) {
5803 velocity /= velspeed;
5804 velspeed = speed * 50 * scale;
5805 velocity *= velspeed;
5807 velocity.y += gravity * multiplier * 20;
5808 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5809 velspeed = findLength(&velocity);
5810 velocity = flatfacing * velspeed * -1;
5812 if (animTarget == dodgebackanim) {
5813 //coords-=facing*multiplier*50*scale;
5814 velocity += facing * multiplier * speed * 700 * scale * -1;
5815 velspeed = findLength(&velocity);
5816 if (velspeed > speed * 60 * scale) {
5817 velocity /= velspeed;
5818 velspeed = speed * 60 * scale;
5819 velocity *= velspeed;
5821 velocity.y += gravity * multiplier * 20;
5822 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5823 velspeed = findLength(&velocity);
5824 velocity = flatfacing * velspeed * -1;
5827 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5828 velspeed = findLength(&velocity);
5832 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5833 velocity.y += gravity * multiplier;
5836 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5837 coords += velocity * multiplier;
5839 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5840 if (isFlip() && targetFrame().label == 7)
5843 if (animTarget == jumpupanim) {
5845 animTarget = getIdle();
5852 pause_sound(whooshsound);
5853 OPENAL_SetVolume(channels[whooshsound], 0);
5856 if (animTarget == jumpdownanim || isFlip()) {
5857 if (isFlip())jumppower = -4;
5858 animTarget = getLanding();
5859 emit_sound_at(landsound, coords, 128.);
5862 addEnvSound(coords);
5867 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5868 coords.y += gravity * multiplier * 2;
5869 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5870 coords.y = terrain.getHeight(coords.x, coords.z);
5875 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)) {
5876 velspeed = findLength(&velocity);
5878 if (velspeed < multiplier * 300 * scale) {
5881 velocity -= velocity / velspeed * multiplier * 300 * scale;
5882 if (velspeed > 5 && (isLanding() || isLandhard())) {
5883 skiddingdelay += multiplier;
5884 if (skiddelay <= 0) {
5885 FootLand(leftfoot, .5);
5886 FootLand(rightfoot, .5);
5894 velspeed = findLength(&velocity);
5896 if (velspeed < multiplier * 600 * scale) {
5899 velocity -= velocity / velspeed * multiplier * 600 * scale;
5901 if (velspeed > 5 && (isLanding() || isLandhard())) {
5902 skiddingdelay += multiplier;
5903 if (skiddelay <= 0) {
5904 FootLand(leftfoot, .5);
5905 FootLand(rightfoot, .5);
5912 if (skiddingdelay < 0)
5913 skiddingdelay += multiplier;
5914 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5916 if (!onterrain || environment == grassyenvironment) {
5917 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5919 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5923 if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5924 terrainnormal = victim->coords - coords;
5925 Normalise(&terrainnormal);
5926 targetyaw = -asin(0 - terrainnormal.x);
5927 targetyaw *= 360 / 6.28;
5928 if (terrainnormal.z < 0)
5929 targetyaw = 180 - targetyaw;
5930 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5933 if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5934 targetyaw = victim->targetyaw;
5936 if (animTarget == rabbittacklinganim) {
5937 coords = victim->coords;
5940 skeleton.oldfree = skeleton.free;
5944 midterrain.x = terrain.size * terrain.scale / 2;
5945 midterrain.z = terrain.size * terrain.scale / 2;
5946 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5948 tempposit = coords - midterrain;
5950 Normalise(&tempposit);
5951 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5952 coords.x = tempposit.x + midterrain.x;
5953 coords.z = tempposit.z + midterrain.z;
5959 * inverse kinematics helper function
5961 void IKHelper(Person *p, float interp)
5963 XYZ point, change, change2;
5964 float heightleft, heightright;
5966 // TODO: implement localToWorld and worldToLocal
5967 // but keep in mind it won't be the same math if player is ragdolled or something
5968 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5969 // then comb through code for places where to use it
5971 // point = localToWorld(jointPos(leftfoot))
5972 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5973 // adjust height of foot
5974 heightleft = terrain.getHeight(point.x, point.z) + .04;
5975 point.y = heightleft;
5976 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5977 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5978 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5979 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5980 // move ankle along with foot
5981 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5982 // average knee pos between old and new pos
5983 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5985 // do same as above for right leg
5986 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5987 heightright = terrain.getHeight(point.x, point.z) + .04;
5988 point.y = heightright;
5989 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5990 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5991 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5992 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5993 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5995 // fix up skeleton now that we've moved body parts?
5996 p->skeleton.DoConstraints(&p->coords, &p->scale);
6003 int Person::DrawSkeleton()
6005 int oldplayerdetail;
6006 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
6007 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
6017 glAlphaFunc(GL_GREATER, 0.0001);
6019 float terrainheight;
6023 if (!isnormal(tilt))
6025 if (!isnormal(tilt2))
6027 oldplayerdetail = playerdetail;
6029 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
6032 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
6035 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
6040 if (playerdetail != oldplayerdetail) {
6042 normalsupdatedelay = 0;
6044 static float updatedelaychange;
6045 static float morphness;
6046 static float framemult;
6048 skeleton.FindForwards();
6049 if (howactive == typesittingwall) {
6050 skeleton.specialforward[1] = 0;
6051 skeleton.specialforward[1].z = 1;
6057 static int weaponattachmuscle;
6058 static int weaponrotatemuscle;
6059 static XYZ weaponpoint;
6060 static int start, endthing;
6061 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6062 if (!isSleeping() && !isSitting()) {
6063 // TODO: give these meaningful names
6064 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6065 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6066 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6067 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6069 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6071 if (creature == wolftype)
6075 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6076 IKHelper(this, target);
6077 if (creature == wolftype)
6078 IKHelper(this, target);
6081 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6082 IKHelper(this, 1 - target);
6083 if (creature == wolftype)
6084 IKHelper(this, 1 - target);
6088 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()))
6091 targetheadyaw = -targetyaw;
6092 targetheadpitch = 0;
6093 if (Animation::animations[animTarget].attack == 3)
6094 targetheadyaw += 180;
6096 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6097 skeleton.drawmodel.vertex[i] = 0;
6098 skeleton.drawmodel.vertex[i].y = 999;
6100 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6101 skeleton.drawmodellow.vertex[i] = 0;
6102 skeleton.drawmodellow.vertex[i].y = 999;
6104 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6105 skeleton.drawmodelclothes.vertex[i] = 0;
6106 skeleton.drawmodelclothes.vertex[i].y = 999;
6108 for (unsigned i = 0; i < skeleton.muscles.size(); i++) {
6109 // convenience renames
6110 const int p1 = skeleton.muscles[i].parent1->label;
6111 const int p2 = skeleton.muscles[i].parent2->label;
6113 if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) {
6118 if (p1 == righthand || p2 == righthand) {
6119 morphness = righthandmorphness;
6120 start = righthandmorphstart;
6121 endthing = righthandmorphend;
6123 if (p1 == lefthand || p2 == lefthand) {
6124 morphness = lefthandmorphness;
6125 start = lefthandmorphstart;
6126 endthing = lefthandmorphend;
6128 if (p1 == head || p2 == head) {
6129 morphness = headmorphness;
6130 start = headmorphstart;
6131 endthing = headmorphend;
6133 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6134 morphness = chestmorphness;
6135 start = chestmorphstart;
6136 endthing = chestmorphend;
6138 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6139 morphness = tailmorphness;
6140 start = tailmorphstart;
6141 endthing = tailmorphend;
6144 skeleton.FindRotationMuscle(i, animTarget);
6145 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6146 glMatrixMode(GL_MODELVIEW);
6150 glRotatef(tilt2, 1, 0, 0);
6152 glRotatef(tilt, 0, 0, 1);
6155 glTranslatef(mid.x, mid.y, mid.z);
6157 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6158 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6160 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6161 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6163 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6164 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6166 if (playerdetail || skeleton.free == 3) {
6167 for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) {
6168 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6169 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6170 glMatrixMode(GL_MODELVIEW);
6172 if (p1 == abdomen || p2 == abdomen)
6173 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6174 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6175 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6176 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6177 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6178 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6179 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6180 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6181 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6182 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6183 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6184 if (p1 == head || p2 == head)
6185 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6186 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6187 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6188 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6189 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6190 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6191 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6195 if (!playerdetail || skeleton.free == 3) {
6196 for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) {
6197 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6198 glMatrixMode(GL_MODELVIEW);
6200 if (p1 == abdomen || p2 == abdomen)
6201 glTranslatef(v0.x * proportionbody.x,
6202 v0.y * proportionbody.y,
6203 v0.z * proportionbody.z);
6204 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6205 glTranslatef(v0.x * proportionarms.x,
6206 v0.y * proportionarms.y,
6207 v0.z * proportionarms.z);
6208 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6209 glTranslatef(v0.x * proportionlegs.x,
6210 v0.y * proportionlegs.y,
6211 v0.z * proportionlegs.z);
6212 if (p1 == head || p2 == head)
6213 glTranslatef(v0.x * proportionhead.x,
6214 v0.y * proportionhead.y,
6215 v0.z * proportionhead.z);
6217 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6218 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6219 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6220 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6226 if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) {
6227 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6229 glMatrixMode(GL_MODELVIEW);
6233 glRotatef(tilt2, 1, 0, 0);
6235 glRotatef(tilt, 0, 0, 1);
6236 glTranslatef(mid.x, mid.y, mid.z);
6237 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6238 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6240 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6241 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6243 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6244 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6246 for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) {
6247 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6248 glMatrixMode(GL_MODELVIEW);
6250 if (p1 == abdomen || p2 == abdomen)
6251 glTranslatef(v0.x * proportionbody.x,
6252 v0.y * proportionbody.y,
6253 v0.z * proportionbody.z);
6254 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6255 glTranslatef(v0.x * proportionarms.x,
6256 v0.y * proportionarms.y,
6257 v0.z * proportionarms.z);
6258 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6259 glTranslatef(v0.x * proportionlegs.x,
6260 v0.y * proportionlegs.y,
6261 v0.z * proportionlegs.z);
6262 if (p1 == head || p2 == head)
6263 glTranslatef(v0.x * proportionhead.x,
6264 v0.y * proportionhead.y,
6265 v0.z * proportionhead.z);
6266 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6267 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6268 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6269 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6274 updatedelay = 1 + (float)(Random() % 100) / 1000;
6276 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6277 normalsupdatedelay = 1;
6278 if (playerdetail || skeleton.free == 3)
6279 skeleton.drawmodel.CalculateNormals(0);
6280 if (!playerdetail || skeleton.free == 3)
6281 skeleton.drawmodellow.CalculateNormals(0);
6282 if (skeleton.clothes)
6283 skeleton.drawmodelclothes.CalculateNormals(0);
6285 if (playerdetail || skeleton.free == 3)
6286 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6287 if (!playerdetail || skeleton.free == 3)
6288 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6289 if (skeleton.clothes) {
6290 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6295 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6296 if (updatedelaychange > -realmultiplier * 30)
6297 updatedelaychange = -realmultiplier * 30;
6298 if (updatedelaychange > -framemult * 4)
6299 updatedelaychange = -framemult * 4;
6300 if (skeleton.free == 1)
6301 updatedelaychange *= 6;
6303 updatedelaychange *= 8;
6304 updatedelay += updatedelaychange;
6306 glMatrixMode(GL_MODELVIEW);
6308 glTranslatef(coords.x, coords.y - .02, coords.z);
6309 if (!skeleton.free) {
6310 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6311 glRotatef(yaw, 0, 1, 0);
6315 glColor4f(.4, 1, .4, 1);
6316 glDisable(GL_LIGHTING);
6317 glDisable(GL_TEXTURE_2D);
6320 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6321 XYZ &v0 = skeleton.drawmodel.vertex[i];
6322 glVertex3f(v0.x, v0.y, v0.z);
6328 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6329 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6330 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6331 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6332 glVertex3f(v0.x, v0.y, v0.z);
6333 glVertex3f(v1.x, v1.y, v1.z);
6334 glVertex3f(v1.x, v1.y, v1.z);
6335 glVertex3f(v2.x, v2.y, v2.z);
6336 glVertex3f(v2.x, v2.y, v2.z);
6337 glVertex3f(v0.x, v0.y, v0.z);
6343 terrainlight = terrain.getLighting(coords.x, coords.z);
6344 distance = distsq(&viewer, &coords);
6345 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6349 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6350 if (terrainheight < 1)
6352 if (terrainheight > 1.7)
6353 terrainheight = 1.7;
6355 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6356 glDisable(GL_BLEND);
6357 glAlphaFunc(GL_GREATER, 0.0001);
6358 glEnable(GL_TEXTURE_2D);
6360 glDisable(GL_TEXTURE_2D);
6361 glColor4f(.7, .35, 0, .5);
6363 glEnable(GL_LIGHTING);
6366 if (tutoriallevel && id != 0) {
6367 glColor4f(.7, .7, .7, 0.6);
6369 glEnable(GL_LIGHTING);
6371 if (canattack && cananger)
6372 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6373 glDisable(GL_TEXTURE_2D);
6374 glColor4f(1, 0, 0, 0.8);
6376 glMatrixMode(GL_TEXTURE);
6378 glTranslatef(0, -smoketex, 0);
6379 glTranslatef(-smoketex, 0, 0);
6383 if ((tutoriallevel && id != 0))
6384 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6386 skeleton.drawmodel.draw();
6389 if (!playerdetail) {
6390 if ((tutoriallevel && id != 0))
6391 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6393 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6396 if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed))
6397 if (tutoriallevel && id != 0) {
6399 glMatrixMode(GL_MODELVIEW);
6400 glEnable(GL_TEXTURE_2D);
6401 glColor4f(.7, .7, .7, 0.6);
6403 glEnable(GL_LIGHTING);
6405 if (canattack && cananger)
6406 if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) {
6407 glDisable(GL_TEXTURE_2D);
6408 glColor4f(1, 0, 0, 0.8);
6410 glMatrixMode(GL_TEXTURE);
6412 glTranslatef(0, -smoketex * .6, 0);
6413 glTranslatef(smoketex * .6, 0, 0);
6416 if ((tutoriallevel && id != 0))
6417 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6419 skeleton.drawmodel.draw();
6422 if (!playerdetail) {
6423 if ((tutoriallevel && id != 0))
6424 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6426 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6431 if (tutoriallevel && id != 0) {
6433 glMatrixMode(GL_MODELVIEW);
6434 glEnable(GL_TEXTURE_2D);
6436 if (skeleton.clothes) {
6440 skeleton.drawmodelclothes.draw();
6442 skeleton.drawmodelclothes.drawimmediate();
6448 if (num_weapons > 0) {
6449 for (k = 0; k < num_weapons; k++) {
6451 if (weaponactive == k) {
6452 if (weapons[i].getType() != staff) {
6453 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6454 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6455 weaponattachmuscle = j;
6458 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6459 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) {
6460 weaponrotatemuscle = j;
6463 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6464 if (creature == wolftype)
6465 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6467 if (weapons[i].getType() == staff) {
6468 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6469 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) {
6470 weaponattachmuscle = j;
6473 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6474 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) {
6475 weaponrotatemuscle = j;
6478 //weaponpoint=jointPos(rightwrist);
6479 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6480 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6481 XYZ tempnormthing, vec1, vec2;
6482 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6483 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6484 CrossProduct(&vec1, &vec2, &tempnormthing);
6485 Normalise(&tempnormthing);
6486 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6487 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6490 if (weaponactive != k && weaponstuck != k) {
6491 if (weapons[i].getType() == knife)
6492 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6493 if (weapons[i].getType() == sword)
6494 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6495 if (weapons[i].getType() == staff)
6496 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6497 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6498 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) {
6499 weaponrotatemuscle = j;
6503 if (weaponstuck == k) {
6504 if (weaponstuckwhere == 0)
6505 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6507 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6508 for (unsigned j = 0; j < skeleton.muscles.size(); j++) {
6509 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) {
6510 weaponrotatemuscle = j;
6514 if (skeleton.free) {
6515 weapons[i].position = weaponpoint * scale + coords;
6516 weapons[i].bigrotation = 0;
6517 weapons[i].bigtilt = 0;
6518 weapons[i].bigtilt2 = 0;
6520 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;
6521 weapons[i].bigrotation = yaw;
6522 weapons[i].bigtilt = tilt;
6523 weapons[i].bigtilt2 = tilt2;
6525 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6526 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6527 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6528 if (weaponactive == k) {
6529 if (weapons[i].getType() == knife) {
6530 weapons[i].smallrotation = 180;
6531 weapons[i].smallrotation2 = 0;
6532 if (isCrouch() || wasCrouch()) {
6533 weapons[i].smallrotation2 = 20;
6535 if (animTarget == hurtidleanim) {
6536 weapons[i].smallrotation2 = 50;
6538 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6539 XYZ temppoint1, temppoint2;
6542 temppoint1 = jointPos(righthand);
6543 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6544 distance = findDistance(&temppoint1, &temppoint2);
6545 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6546 weapons[i].rotation2 *= 360 / 6.28;
6549 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6550 weapons[i].rotation1 *= 360 / 6.28;
6551 weapons[i].rotation3 = 0;
6552 weapons[i].smallrotation = -90;
6553 weapons[i].smallrotation2 = 0;
6554 if (temppoint1.x > temppoint2.x)
6555 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6557 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6558 XYZ temppoint1, temppoint2;
6561 temppoint1 = jointPos(righthand);
6562 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6563 distance = findDistance(&temppoint1, &temppoint2);
6564 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6565 weapons[i].rotation2 *= 360 / 6.28;
6568 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6569 weapons[i].rotation1 *= 360 / 6.28;
6570 weapons[i].rotation3 = 0;
6571 weapons[i].smallrotation = 90;
6572 weapons[i].smallrotation2 = 0;
6573 if (temppoint1.x > temppoint2.x)
6574 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6576 if (animTarget == knifethrowanim) {
6577 weapons[i].smallrotation = 90;
6578 //weapons[i].smallrotation2=-90;
6579 weapons[i].smallrotation2 = 0;
6580 weapons[i].rotation1 = 0;
6581 weapons[i].rotation2 = 0;
6582 weapons[i].rotation3 = 0;
6584 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6585 weapons[i].smallrotation = -90;
6586 weapons[i].rotation1 = 0;
6587 weapons[i].rotation2 = 0;
6588 weapons[i].rotation3 = 0;
6591 if (weapons[i].getType() == sword) {
6592 weapons[i].smallrotation = 0;
6593 weapons[i].smallrotation2 = 0;
6594 if (animTarget == knifethrowanim) {
6595 weapons[i].smallrotation = -90;
6596 weapons[i].smallrotation2 = 0;
6597 weapons[i].rotation1 = 0;
6598 weapons[i].rotation2 = 0;
6599 weapons[i].rotation3 = 0;
6601 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)) {
6602 XYZ temppoint1, temppoint2;
6605 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6606 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6607 distance = findDistance(&temppoint1, &temppoint2);
6608 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6609 weapons[i].rotation2 *= 360 / 6.28;
6612 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6613 weapons[i].rotation1 *= 360 / 6.28;
6614 weapons[i].rotation3 = 0;
6615 weapons[i].smallrotation = 90;
6616 weapons[i].smallrotation2 = 0;
6617 if (temppoint1.x > temppoint2.x)
6618 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6621 if (weapons[i].getType() == staff) {
6622 weapons[i].smallrotation = 100;
6623 weapons[i].smallrotation2 = 0;
6624 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6625 XYZ temppoint1, temppoint2;
6628 temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand);
6629 temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target);
6630 distance = findDistance(&temppoint1, &temppoint2);
6631 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6632 weapons[i].rotation2 *= 360 / 6.28;
6635 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6636 weapons[i].rotation1 *= 360 / 6.28;
6637 weapons[i].rotation3 = 0;
6638 weapons[i].smallrotation = 90;
6639 weapons[i].smallrotation2 = 0;
6640 if (temppoint1.x > temppoint2.x)
6641 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6645 if (weaponactive != k && weaponstuck != k) {
6646 if (weapons[i].getType() == knife) {
6647 weapons[i].smallrotation = -70;
6648 weapons[i].smallrotation2 = 10;
6650 if (weapons[i].getType() == sword) {
6651 weapons[i].smallrotation = -100;
6652 weapons[i].smallrotation2 = -8;
6654 if (weapons[i].getType() == staff) {
6655 weapons[i].smallrotation = -100;
6656 weapons[i].smallrotation2 = -8;
6659 if (weaponstuck == k) {
6660 if (weaponstuckwhere == 0)
6661 weapons[i].smallrotation = 180;
6663 weapons[i].smallrotation = 0;
6664 weapons[i].smallrotation2 = 10;
6673 if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6675 if (animCurrent != animTarget)
6677 if (skeleton.free == 2)
6686 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6689 static float distance;
6690 static float olddistance;
6691 static int intersecting;
6692 static int firstintersecting;
6695 static XYZ start, end;
6696 static float slopethreshold = -.4;
6698 firstintersecting = -1;
6702 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6705 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6706 for (i = 0; i < 4; i++) {
6707 for (j = 0; j < model->TriangleNum; j++) {
6708 if (model->facenormals[j].y <= slopethreshold) {
6710 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)));
6711 if (distance < radius) {
6712 point = *p1 - model->facenormals[j] * distance;
6713 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]]))
6716 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6717 &model->vertex[model->Triangles[j].vertex[1]],
6720 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6721 &model->vertex[model->Triangles[j].vertex[2]],
6724 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6725 &model->vertex[model->Triangles[j].vertex[2]],
6728 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6732 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)) {
6733 p1->y = point.y + radius;
6734 if ((animTarget == jumpdownanim || isFlip())) {
6735 if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4))
6738 if (animTarget == jumpupanim) {
6740 animTarget = getIdle();
6747 pause_sound(whooshsound);
6748 OPENAL_SetVolume(channels[whooshsound], 0);
6751 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6754 animTarget = getLanding();
6755 emit_sound_at(landsound, coords, 128.);
6758 addEnvSound(coords);
6765 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6766 olddistance = distance;
6767 firstintersecting = j;
6772 for (j = 0; j < model->TriangleNum; j++) {
6773 if (model->facenormals[j].y > slopethreshold) {
6776 start.y -= radius / 4;
6777 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6778 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6779 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6780 distance = abs((model->facenormals[j].x * start.x)
6781 + (model->facenormals[j].y * start.y)
6782 + (model->facenormals[j].z * start.z)
6783 - ((model->facenormals[j].x * v0.x)
6784 + (model->facenormals[j].y * v0.y)
6785 + (model->facenormals[j].z * v0.z)));
6786 if (distance < radius * .5) {
6787 point = start - model->facenormals[j] * distance;
6788 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6791 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6793 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6795 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6797 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6798 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6800 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6801 if (findLengthfast(&start) < findLengthfast(&velocity))
6804 *p1 += model->facenormals[j] * (distance - radius * .5);
6807 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6808 olddistance = distance;
6809 firstintersecting = j;
6816 *p = DoRotation(*p, 0, *rotate, 0);
6819 *p1 = DoRotation(*p1, 0, *rotate, 0);
6821 return firstintersecting;
6824 void Person::takeWeapon(int weaponId)
6827 weapons[weaponId].owner = id;
6828 if (num_weapons > 0) {
6829 weaponids[num_weapons] = weaponids[0];
6832 weaponids[0] = weaponId;
6835 void Person::addClothes()
6837 if (numclothes > 0) {
6838 for (int i = 0; i < numclothes; i++) {
6845 bool Person::addClothes(const int& clothesId)
6848 const std::string fileName = clothes[clothesId];
6850 GLubyte* array = &skeleton.skinText[0];
6854 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6859 float tintr = clothestintr[clothesId];
6860 float tintg = clothestintg[clothesId];
6861 float tintb = clothestintb[clothesId];
6863 if (tintr > 1) tintr = 1;
6864 if (tintg > 1) tintg = 1;
6865 if (tintb > 1) tintb = 1;
6867 if (tintr < 0) tintr = 0;
6868 if (tintg < 0) tintg = 0;
6869 if (tintb < 0) tintb = 0;
6871 int bytesPerPixel = texture.bpp / 8;
6875 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6876 if (bytesPerPixel == 3)
6878 else if ((i + 1) % 4 == 0)
6879 alphanum = texture.data[i];
6880 if ((i + 1) % 4 || bytesPerPixel == 3) {
6882 texture.data[i] *= tintr;
6884 texture.data[i] *= tintg;
6886 texture.data[i] *= tintb;
6887 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);