2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 extern float multiplier;
30 extern Terrain terrain;
32 extern int environment;
34 extern FRUSTUM frustum;
36 extern float realmultiplier;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
61 extern bool tilt2weird;
62 extern bool tiltweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
76 extern float damagedealt;
78 extern float hostiletime;
80 extern int indialogue;
82 extern bool gamestarted;
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
97 howactive(typeactive),
99 superruntoggle(false),
100 lastattack(0), lastattack2(0), lastattack3(0),
101 currentoffset(), targetoffset(), offset(),
134 rabbitkickenabled(false),
146 superpermanentdamage(0),
158 backwardsanim(false),
163 bleedx(0), bleedy(0),
167 headyaw(0), headpitch(0),
168 targetheadyaw(0), targetheadpitch(0),
179 normalsupdatedelay(0),
182 forwardkeydown(false),
183 forwardstogglekeydown(false),
188 jumptogglekeydown(false),
189 crouchkeydown(false),
190 crouchtogglekeydown(false),
192 drawtogglekeydown(false),
194 throwtogglekeydown(false),
195 attackkeydown(false),
200 crouchkeydowntime(0),
215 whichdirection(false),
216 whichdirectiondelay(0),
217 avoidsomething(false),
226 lefthandmorphness(0),
227 righthandmorphness(0),
231 targetlefthandmorphness(0),
232 targetrighthandmorphness(0),
233 targetheadmorphness(0),
234 targetchestmorphness(0),
235 targettailmorphness(0),
236 lefthandmorphstart(0), lefthandmorphend(0),
237 righthandmorphstart(0), righthandmorphend(0),
238 headmorphstart(0), headmorphend(0),
239 chestmorphstart(0), chestmorphend(0),
240 tailmorphstart(0), tailmorphend(0),
243 highreversaldelay(0),
247 creature(rabbittype),
290 hastempwaypoint(false),
298 finalpathfindpoint(0),
299 targetpathfindpoint(0),
300 lastpathfindpoint(0),
301 lastpathfindpoint2(0),
302 lastpathfindpoint3(0),
303 lastpathfindpoint4(0),
321 neckspurtparticledelay(0),
325 rabbitkickragdoll(false),
341 * GameTick/doPlayerCollisions
343 void Person::CheckKick()
346 && (animTarget == rabbitkickanim
348 && victim != this->shared_from_this()
350 && animCurrent == rabbitkickanim)
351 && distsq(&coords, &victim->coords) < 1.2
352 && !victim->skeleton.free))
355 if (animation[victim->animTarget].height != lowheight) {
356 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
357 XYZ relative = velocity;
359 Normalise(&relative);
363 if (tutoriallevel != 1)
364 emit_sound_at(heavyimpactsound, victim->coords);
366 for (int i = 0; i < victim->skeleton.num_joints; i++) {
367 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
370 victim->DoDamage(100 * damagemult / victim->protectionhigh);
376 animTarget = backflipanim;
378 velocity = facing * -10;
382 resume_stream(whooshsound);
384 award_bonus(id, cannon);
385 } else if (victim->isCrouch()) {
386 animTarget = rabbitkickreversedanim;
387 animCurrent = rabbitkickreversedanim;
388 victim->animCurrent = rabbitkickreversalanim;
389 victim->animTarget = rabbitkickreversalanim;
395 victim->oldcoords = victim->coords;
396 coords = victim->coords;
397 victim->targetyaw = targetyaw;
398 victim->victim = this->shared_from_this();
405 * GameTick/doPlayerCollisions - spread fire between players
406 * GameTick/doDebugKeys - press f to ignite
407 * Person::DoStuff - spread fire from lit campfires and bushes
409 void Person::CatchFire()
411 XYZ flatfacing, flatvelocity;
413 for (int i = 0; i < 10; i++) {
414 howmany = abs(Random() % (skeleton.num_joints));
416 flatvelocity = skeleton.joints[howmany].velocity;
417 flatfacing = skeleton.joints[howmany].position * scale + coords;
419 flatvelocity = velocity;
420 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
422 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
427 emit_sound_at(firestartsound, coords);
429 emit_stream_at(stream_firesound, coords);
437 * idle animation for this creature (depending on status)
439 int Person::getIdle()
441 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
443 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
444 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
445 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
446 victim->id < Person::players.size())) {
447 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
448 if (creature == rabbittype)
449 return fightidleanim;
450 if (creature == wolftype)
453 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
454 if (weapons[weaponids[weaponactive]].getType() == knife)
455 return knifefightidleanim;
456 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
457 return swordfightidlebothanim;
458 if (weapons[weaponids[weaponactive]].getType() == sword)
459 return swordfightidleanim;
460 if (weapons[weaponids[weaponactive]].getType() == staff)
461 return swordfightidleanim;
463 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
464 return fightsidestep;
466 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
468 if (howactive == typesitting) return sitanim;
469 if (howactive == typesittingwall) return sitwallanim;
470 if (howactive == typesleeping) return sleepanim;
471 if (howactive == typedead1) return dead1anim;
472 if (howactive == typedead2) return dead2anim;
473 if (howactive == typedead3) return dead3anim;
474 if (howactive == typedead4) return dead4anim;
475 if (creature == rabbittype) return bounceidleanim;
476 if (creature == wolftype) return wolfidle;
481 * crouch animation for this creature
483 int Person::getCrouch()
485 if (creature == rabbittype)
487 if (creature == wolftype)
488 return wolfcrouchanim;
493 * running animation for this creature (can be upright or all fours)
497 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
499 if (creature == wolftype && (!superruntoggle))
502 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
503 return rabbitrunninganim;
504 if (creature == wolftype && (superruntoggle))
505 return wolfrunninganim;
511 int Person::getStop()
513 if (creature == rabbittype)
515 if (creature == wolftype)
522 int Person::getLanding()
524 if (creature == rabbittype)
526 if (creature == wolftype)
533 int Person::getLandhard()
535 if (creature == rabbittype)
537 if (creature == wolftype)
538 return wolflandhardanim;
545 * Person::DoAnimations
548 SolidHitBonus(int playerid)
550 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
551 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
553 award_bonus(playerid, solidhit);
557 * spawns blood effects
559 void Person::DoBlood(float howmuch, int which)
561 // FIXME: should abstract out inputs
562 static int bleedxint, bleedyint;
564 if (bloodtoggle && tutoriallevel != 1) {
565 if (bleeding <= 0 && spurt) {
567 for (int i = 0; i < 3; i++) {
568 // emit blood particles
571 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
572 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
573 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
574 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
577 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
578 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
579 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
580 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
583 if (Random() % 2 == 0) // 50% chance
584 for (int i = 0; i < 3; i++) {
585 if (Random() % 2 != 0) {
586 // emit teeth particles
589 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
590 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
593 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
594 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
598 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
600 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
602 Sprite::setLastSpriteSpecial(3); // sets it to teeth
607 // FIXME: manipulating attributes
608 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
611 if (creature == rabbittype)
612 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) {
613 bleedxint = abs(Random() % 512);
614 bleedyint = abs(Random() % 512);
616 if (creature == wolftype)
617 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) {
618 bleedxint = abs(Random() % 512);
619 bleedyint = abs(Random() % 512);
623 bleedy /= realtexdetail;
624 bleedx /= realtexdetail;
625 direction = abs(Random() % 2) * 2 - 1;
634 * spawns big blood effects and ???
635 * modifies character's skin texture
637 void Person::DoBloodBig(float howmuch, int which)
639 static int bleedxint, bleedyint, i, j;
641 if (howmuch && id == 0)
644 if (tutoriallevel != 1 || id == 0)
645 if (aitype != playercontrolled && howmuch > 0) {
649 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
650 if (creature == wolftype) {
651 int i = abs(Random() % 2);
653 whichsound = snarlsound;
655 whichsound = snarl2sound;
656 envsound[numenvsounds] = coords;
657 envsoundvol[numenvsounds] = 16;
658 envsoundlife[numenvsounds] = .4;
661 if (creature == rabbittype) {
662 int i = abs(Random() % 2);
664 whichsound = rabbitpainsound;
665 if (i == 1 && howmuch >= 2)
666 whichsound = rabbitpain1sound;
667 envsound[numenvsounds] = coords;
668 envsoundvol[numenvsounds] = 16;
669 envsoundlife[numenvsounds] = .4;
673 if (whichsound != -1)
674 emit_sound_at(whichsound, coords);
677 if (id == 0 && howmuch > 0) {
678 // FIXME: manipulating attributes
686 if (bloodtoggle && decals && tutoriallevel != 1) {
687 if (bleeding <= 0 && spurt) {
689 for (int i = 0; i < 3; i++) {
690 // emit blood particles
691 // FIXME: copypaste from above
694 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
695 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
696 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
697 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
700 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
701 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
702 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
703 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
708 // weird texture manipulation code follows.
709 // looks like this is painting blood onto the character's skin texture
710 // FIXME: surely there's a better way
712 int offsetx = 0, offsety = 0;
714 offsety = Random() % 40;
715 offsetx = abs(Random() % 60);
717 if (which == 190 || which == 185) {
718 offsety = Random() % 40;
719 offsetx = abs(Random() % 100) - 20;
722 offsety = Random() % 10;
723 offsetx = Random() % 10;
726 offsety = Random() % 20;
727 offsetx = Random() % 20;
729 if (which == 220 || which == 215) {
739 if (creature == rabbittype)
740 for (i = 0; i < 512; i++) {
741 for (j = 0; j < 512; j++) {
742 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
743 if (i < startx) startx = i;
744 if (j < starty) starty = j;
745 if (i > endx) endx = i;
746 if (j > endy) endy = j;
750 if (creature == wolftype)
751 for (i = 0; i < 512; i++) {
752 for (j = 0; j < 512; j++) {
753 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
754 if (i < startx) startx = i;
755 if (j < starty) starty = j;
756 if (i > endx) endx = i;
757 if (j > endy) endy = j;
767 if (startx < 0) startx = 0;
768 if (starty < 0) starty = 0;
769 if (endx > 512 - 1) endx = 512 - 1;
770 if (endy > 512 - 1) endy = 512 - 1;
771 if (endx < startx) endx = startx;
772 if (endy < starty) endy = starty;
774 startx /= realtexdetail;
775 starty /= realtexdetail;
776 endx /= realtexdetail;
777 endy /= realtexdetail;
779 int texdetailint = realtexdetail;
781 if (creature == rabbittype)
782 for (i = startx; i < endx; i++) {
783 for (j = starty; j < endy; j++) {
784 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) {
785 color = Random() % 85 + 170;
786 where = i * skeleton.skinsize * 3 + j * 3;
787 if (skeleton.skinText[where + 0] > color / 2)
788 skeleton.skinText[where + 0] = color / 2;
789 skeleton.skinText[where + 1] = 0;
790 skeleton.skinText[where + 2] = 0;
794 if (creature == wolftype)
795 for (i = startx; i < endx; i++) {
796 for (j = starty; j < endy; j++) {
797 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) {
798 color = Random() % 85 + 170;
799 where = i * skeleton.skinsize * 3 + j * 3;
800 if (skeleton.skinText[where + 0] > color / 2)
801 skeleton.skinText[where + 0] = color / 2;
802 skeleton.skinText[where + 1] = 0;
803 skeleton.skinText[where + 2] = 0;
807 skeleton.drawmodel.textureptr.bind();
812 if (creature == rabbittype)
813 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) {
814 bleedxint = abs(Random() % 512);
815 bleedyint = abs(Random() % 512);
817 if (creature == wolftype)
818 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) {
819 bleedxint = abs(Random() % 512);
820 bleedyint = abs(Random() % 512);
822 bleedy = bleedxint + offsetx;
823 bleedx = bleedyint + offsety;
824 bleedy /= realtexdetail;
825 bleedx /= realtexdetail;
830 if (bleedx > skeleton.skinsize - 1)
831 bleedx = skeleton.skinsize - 1;
832 if (bleedy > skeleton.skinsize - 1)
833 bleedy = skeleton.skinsize - 1;
834 direction = abs(Random() % 2) * 2 - 1;
837 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
838 deathbleeding += bleeding;
839 bloodloss += bleeding * 3;
841 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
842 if (abs(Random() % 2) == 0) {
843 aitype = gethelptype;
846 aitype = attacktypecutoff;
854 * similar to DoBloodBig
856 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
860 static XYZ startpoint, endpoint, colpoint, movepoint;
861 static float rotationpoint;
863 static XYZ p1, p2, p3, p0;
866 float coordsx, coordsy;
869 if (bloodtoggle && decals && tutoriallevel != 1) {
872 where = DoRotation(where, 0, -yaw, 0);
880 // ray testing for a tri in the character model
881 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
882 if (whichtri != -1) {
883 // low level geometry math
885 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
886 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
887 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
889 bary.x = distsq(&p0, &p1);
890 bary.y = distsq(&p0, &p2);
891 bary.z = distsq(&p0, &p3);
893 total = bary.x + bary.y + bary.z;
902 total = bary.x + bary.y + bary.z;
908 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
909 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
910 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
911 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
912 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
913 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
914 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;
915 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;
917 if (bleeding <= 0 && spurt) {
919 for (int i = 0; i < 3; i++) {
920 // emit blood particles
921 // FIXME: more copypaste code
924 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
925 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
926 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
927 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
930 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
931 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
932 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
933 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
938 // texture manipulation follows
940 int offsetx = 0, offsety = 0;
941 offsetx = (1 + coordsy) * 512 - 291;
942 offsety = coordsx * 512 - 437;
949 if (creature == rabbittype)
950 for (i = 0; i < 512; i++) {
951 for (j = 0; j < 512; j++) {
952 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
953 if (i < startx) startx = i;
954 if (j < starty) starty = j;
955 if (i > endx) endx = i;
956 if (j > endy) endy = j;
960 if (creature == wolftype)
961 for (i = 0; i < 512; i++) {
962 for (j = 0; j < 512; j++) {
963 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
964 if (i < startx) startx = i;
965 if (j < starty) starty = j;
966 if (i > endx) endx = i;
967 if (j > endy) endy = j;
976 if (startx < 0) startx = 0;
977 if (starty < 0) starty = 0;
978 if (endx > 512 - 1) endx = 512 - 1;
979 if (endy > 512 - 1) endy = 512 - 1;
980 if (endx < startx) endx = startx;
981 if (endy < starty) endy = starty;
983 startx /= realtexdetail;
984 starty /= realtexdetail;
985 endx /= realtexdetail;
986 endy /= realtexdetail;
988 int texdetailint = realtexdetail;
990 if (creature == rabbittype)
991 for (i = startx; i < endx; i++) {
992 for (j = starty; j < endy; j++) {
993 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) {
994 color = Random() % 85 + 170;
995 where = i * skeleton.skinsize * 3 + j * 3;
996 if (skeleton.skinText[where + 0] > color / 2)
997 skeleton.skinText[where + 0] = color / 2;
998 skeleton.skinText[where + 1] = 0;
999 skeleton.skinText[where + 2] = 0;
1000 } 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) {
1001 color = Random() % 85 + 170;
1002 where = i * skeleton.skinsize * 3 + j * 3;
1003 if (skeleton.skinText[where + 0] > color / 2)
1004 skeleton.skinText[where + 0] = color / 2;
1005 skeleton.skinText[where + 1] = 0;
1006 skeleton.skinText[where + 2] = 0;
1010 if (creature == wolftype)
1011 for (i = startx; i < endx; i++) {
1012 for (j = starty; j < endy; j++) {
1013 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) {
1014 color = Random() % 85 + 170;
1015 where = i * skeleton.skinsize * 3 + j * 3;
1016 if (skeleton.skinText[where + 0] > color / 2)
1017 skeleton.skinText[where + 0] = color / 2;
1018 skeleton.skinText[where + 1] = 0;
1019 skeleton.skinText[where + 2] = 0;
1020 } 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) {
1021 color = Random() % 85 + 170;
1022 where = i * skeleton.skinsize * 3 + j * 3;
1023 if (skeleton.skinText[where + 0] > color / 2)
1024 skeleton.skinText[where + 0] = color / 2;
1025 skeleton.skinText[where + 1] = 0;
1026 skeleton.skinText[where + 2] = 0;
1030 skeleton.drawmodel.textureptr.bind();
1033 bleedy = (1 + coordsy) * 512;
1034 bleedx = coordsx * 512;
1035 bleedy /= realtexdetail;
1036 bleedx /= realtexdetail;
1041 if (bleedx > skeleton.skinsize - 1)
1042 bleedx = skeleton.skinsize - 1;
1043 if (bleedy > skeleton.skinsize - 1)
1044 bleedy = skeleton.skinsize - 1;
1045 direction = abs(Random() % 2) * 2 - 1;
1050 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1051 deathbleeding += bleeding;
1052 bloodloss += bleeding * 3;
1054 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1055 if (abs(Random() % 2) == 0) {
1056 aitype = gethelptype;
1059 aitype = attacktypecutoff;
1070 * guessing this performs a reversal
1072 void Person::Reverse()
1074 if (!((victim->aitype == playercontrolled
1076 || staggerdelay <= 0)
1077 && victim->animTarget != jumpupanim
1078 && victim->animTarget != jumpdownanim
1079 && (tutoriallevel != 1 || cananger)
1083 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1084 && (victim->id != 0 || difficulty >= 2)
1085 && (creature != wolftype || victim->creature == wolftype))
1088 if (animTarget == sweepanim) {
1089 animTarget = sweepreversedanim;
1090 animCurrent = sweepreversedanim;
1091 victim->animCurrent = sweepreversalanim;
1092 victim->animTarget = sweepreversalanim;
1094 if (animTarget == spinkickanim) {
1095 animTarget = spinkickreversedanim;
1096 animCurrent = spinkickreversedanim;
1097 victim->animCurrent = spinkickreversalanim;
1098 victim->animTarget = spinkickreversalanim;
1100 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1101 if (animTarget == rabbittacklinganim) {
1104 victim->frameCurrent = 6;
1105 victim->frameTarget = 7;
1107 animTarget = upunchreversedanim;
1108 animCurrent = upunchreversedanim;
1109 victim->animCurrent = upunchreversalanim;
1110 victim->animTarget = upunchreversalanim;
1112 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1113 if (victim->weaponactive != -1) {
1114 victim->throwtogglekeydown = 1;
1115 XYZ tempVelocity = victim->velocity * .2;
1116 if (tempVelocity.x == 0)
1117 tempVelocity.x = .1;
1118 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1119 victim->num_weapons--;
1120 if (victim->num_weapons) {
1121 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1122 if (victim->weaponstuck == victim->num_weapons)
1123 victim->weaponstuck = 0;
1126 victim->weaponactive = -1;
1127 for (unsigned j = 0; j < Person::players.size(); j++) {
1128 Person::players[j]->wentforweapon = 0;
1132 animTarget = staffhitreversedanim;
1133 animCurrent = staffhitreversedanim;
1134 victim->animCurrent = staffhitreversalanim;
1135 victim->animTarget = staffhitreversalanim;
1137 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1138 if (victim->weaponactive != -1) {
1139 victim->throwtogglekeydown = 1;
1140 XYZ tempVelocity = victim->velocity * .2;
1141 if (tempVelocity.x == 0)
1142 tempVelocity.x = .1;
1143 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1144 victim->num_weapons--;
1145 if (victim->num_weapons) {
1146 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1147 if (victim->weaponstuck == victim->num_weapons)
1148 victim->weaponstuck = 0;
1151 victim->weaponactive = -1;
1152 for (unsigned j = 0; j < Person::players.size(); j++) {
1153 Person::players[j]->wentforweapon = 0;
1156 animTarget = staffspinhitreversedanim;
1157 animCurrent = staffspinhitreversedanim;
1158 victim->animCurrent = staffspinhitreversalanim;
1159 victim->animTarget = staffspinhitreversalanim;
1161 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1162 if (victim->weaponactive != -1) {
1163 victim->throwtogglekeydown = 1;
1164 XYZ tempVelocity = victim->velocity * .2;
1165 if (tempVelocity.x == 0)
1166 tempVelocity.x = .1;
1167 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1168 victim->num_weapons--;
1169 if (victim->num_weapons) {
1170 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1171 if (victim->weaponstuck == victim->num_weapons)
1172 victim->weaponstuck = 0;
1175 victim->weaponactive = -1;
1176 for (unsigned j = 0; j < Person::players.size(); j++) {
1177 Person::players[j]->wentforweapon = 0;
1180 animTarget = swordslashreversedanim;
1181 animCurrent = swordslashreversedanim;
1182 victim->animCurrent = swordslashreversalanim;
1183 victim->animTarget = swordslashreversalanim;
1185 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1186 if (victim->weaponactive != -1) {
1187 victim->throwtogglekeydown = 1;
1188 XYZ tempVelocity = victim->velocity * .2;
1189 if (tempVelocity.x == 0)
1190 tempVelocity.x = .1;
1191 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1192 victim->num_weapons--;
1193 if (victim->num_weapons) {
1194 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1195 if (victim->weaponstuck == victim->num_weapons)
1196 victim->weaponstuck = 0;
1199 victim->weaponactive = -1;
1200 for (unsigned j = 0; j < Person::players.size(); j++) {
1201 Person::players[j]->wentforweapon = 0;
1204 animTarget = knifeslashreversedanim;
1205 animCurrent = knifeslashreversedanim;
1206 victim->animCurrent = knifeslashreversalanim;
1207 victim->animTarget = knifeslashreversalanim;
1209 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1210 victim->targettilt2 = targettilt2;
1211 victim->frameCurrent = frameCurrent;
1212 victim->frameTarget = frameTarget;
1213 victim->target = target;
1214 victim->velocity = 0;
1215 victim->oldcoords = victim->coords;
1216 victim->coords = coords;
1217 victim->targetyaw = targetyaw;
1218 victim->yaw = targetyaw;
1219 victim->victim = this->shared_from_this();
1221 if (animTarget == winduppunchanim) {
1222 animTarget = winduppunchblockedanim;
1223 victim->animTarget = blockhighleftanim;
1224 victim->frameTarget = 1;
1225 victim->target = .5;
1226 victim->victim = this->shared_from_this();
1227 victim->targetyaw = targetyaw + 180;
1229 if (animTarget == wolfslapanim) {
1230 animTarget = winduppunchblockedanim;
1231 victim->animTarget = blockhighleftanim;
1232 victim->frameTarget = 1;
1233 victim->target = .5;
1234 victim->victim = this->shared_from_this();
1235 victim->targetyaw = targetyaw + 180;
1237 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1238 animTarget = swordslashparriedanim;
1239 parriedrecently = .4;
1240 victim->parriedrecently = 0;
1241 victim->animTarget = swordslashparryanim;
1242 victim->frameTarget = 1;
1243 victim->target = .5;
1244 victim->victim = this->shared_from_this();
1245 victim->targetyaw = targetyaw + 180;
1247 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1248 if (victim->weaponactive != -1) {
1249 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1250 if (weapons[victim->weaponids[0]].getType() == staff)
1251 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1252 if (weapons[weaponids[0]].getType() == staff)
1253 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1254 emit_sound_at(swordstaffsound, victim->coords);
1256 emit_sound_at(metalhitsound, victim->coords);
1260 victim->Puff(righthand);
1262 victim->frameTarget = 0;
1263 victim->animTarget = staggerbackhighanim;
1264 victim->targetyaw = targetyaw + 180;
1266 aim = DoRotation(facing, 0, 90, 0) * 21;
1268 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1269 victim->num_weapons--;
1270 if (victim->num_weapons) {
1271 victim->weaponids[0] = victim->weaponids[num_weapons];
1272 if (victim->weaponstuck == victim->num_weapons)
1273 victim->weaponstuck = 0;
1275 victim->weaponactive = -1;
1276 for (unsigned i = 0; i < Person::players.size(); i++) {
1277 Person::players[i]->wentforweapon = 0;
1281 if (abs(Random() % 20) == 0) {
1282 if (weaponactive != -1) {
1283 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1284 if (weapons[victim->weaponids[0]].getType() == staff)
1285 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1286 if (weapons[weaponids[0]].getType() == staff)
1287 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1289 emit_sound_at(swordstaffsound, coords);
1291 emit_sound_at(metalhitsound, coords);
1299 animTarget = staggerbackhighanim;
1300 targetyaw = targetyaw + 180;
1302 aim = DoRotation(facing, 0, 90, 0) * 21;
1304 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1307 weaponids[0] = weaponids[num_weapons];
1308 if (weaponstuck == num_weapons)
1312 for (unsigned i = 0; i < Person::players.size(); i++) {
1313 Person::players[i]->wentforweapon = 0;
1320 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1321 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1322 victim->animTarget = dodgebackanim;
1323 victim->frameTarget = 0;
1327 rotatetarget = coords - victim->coords;
1328 Normalise(&rotatetarget);
1329 victim->targetyaw = -asin(0 - rotatetarget.x);
1330 victim->targetyaw *= 360 / 6.28;
1331 if (rotatetarget.z < 0)
1332 victim->targetyaw = 180 - victim->targetyaw;
1334 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1336 victim->lastattack3 = victim->lastattack2;
1337 victim->lastattack2 = victim->lastattack;
1338 victim->lastattack = victim->animTarget;
1340 victim->animTarget = sweepanim;
1341 victim->frameTarget = 0;
1345 rotatetarget = coords - victim->coords;
1346 Normalise(&rotatetarget);
1347 victim->targetyaw = -asin(0 - rotatetarget.x);
1348 victim->targetyaw *= 360 / 6.28;
1349 if (rotatetarget.z < 0)
1350 victim->targetyaw = 180 - victim->targetyaw;
1352 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1354 victim->lastattack3 = victim->lastattack2;
1355 victim->lastattack2 = victim->lastattack;
1356 victim->lastattack = victim->animTarget;
1361 victim->velocity = 0;
1363 if (aitype != playercontrolled)
1365 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1367 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1369 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1372 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1379 void Person::DoDamage(float howmuch)
1381 // subtract health (temporary?)
1382 if (tutoriallevel != 1)
1383 damage += howmuch / power;
1386 damagedealt += howmuch / power;
1388 damagetaken += howmuch / power;
1391 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1394 if (tutoriallevel != 1)
1395 permanentdamage += howmuch / 2 / power;
1396 if (tutoriallevel != 1)
1397 superpermanentdamage += howmuch / 4 / power;
1399 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1401 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1405 camerashake += howmuch / 100;
1406 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1407 blackout = damage / damagetolerance;
1412 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1413 aitype = attacktypecutoff;
1414 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1415 if (abs(Random() % 2) == 0) {
1416 aitype = gethelptype;
1419 aitype = attacktypecutoff;
1423 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1426 for (int i = 0; i < skeleton.num_joints; i++) {
1427 if (skeleton.free) {
1428 flatvelocity2 = skeleton.joints[i].velocity;
1429 flatfacing2 = skeleton.joints[i].position * scale + coords;
1431 flatvelocity2 = velocity;
1432 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1434 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1435 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1436 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1437 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1438 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1439 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1442 emit_sound_at(splattersound, coords);
1447 if (!dead && creature == wolftype) {
1448 award_bonus(0, Wolfbonus);
1455 if (tutoriallevel != 1 || id == 0)
1456 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1457 int whichsound = -1;
1459 if (creature == wolftype) {
1460 int i = abs(Random() % 2);
1462 whichsound = snarlsound;
1464 whichsound = snarl2sound;
1465 envsound[numenvsounds] = coords;
1466 envsoundvol[numenvsounds] = 16;
1467 envsoundlife[numenvsounds] = .4;
1470 if (creature == rabbittype) {
1471 int i = abs(Random() % 2);
1473 whichsound = rabbitpainsound;
1474 if (i == 1 && damage > damagetolerance)
1475 whichsound = rabbitpain1sound;
1476 envsound[numenvsounds] = coords;
1477 envsoundvol[numenvsounds] = 16;
1478 envsoundlife[numenvsounds] = .4;
1482 if (whichsound != -1) {
1483 emit_sound_at(whichsound, coords);
1490 * calculate/animate head facing direction?
1492 void Person::DoHead()
1494 static XYZ rotatearound;
1496 static float lookspeed = 500;
1498 if (!freeze && !winfreeze) {
1501 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1502 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1504 while (targetheadyaw > 180)targetheadyaw -= 360;
1505 while (targetheadyaw < -180)targetheadyaw += 360;
1507 if (targetheadyaw > 160)
1508 targetheadpitch = targetheadpitch * -1;
1509 if (targetheadyaw < -160)
1510 targetheadpitch = targetheadpitch * -1;
1511 if (targetheadyaw > 160)
1512 targetheadyaw = targetheadyaw - 180;
1513 if (targetheadyaw < -160)
1514 targetheadyaw = targetheadyaw + 180;
1516 if (targetheadpitch > 120)
1517 targetheadpitch = 120;
1518 if (targetheadpitch < -120)
1519 targetheadpitch = -120;
1520 if (targetheadyaw > 120)
1521 targetheadyaw = 120;
1522 if (targetheadyaw < -120)
1523 targetheadyaw = -120;
1526 targetheadpitch = 0;
1528 if (targetheadyaw > 80)
1530 if (targetheadyaw < -80)
1531 targetheadyaw = -80;
1532 if (targetheadpitch > 50)
1533 targetheadpitch = 50;
1534 if (targetheadpitch < -50)
1535 targetheadpitch = -50;
1538 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1539 headyaw = targetheadyaw;
1540 else if (headyaw > targetheadyaw) {
1541 headyaw -= multiplier * lookspeed;
1542 } else if (headyaw < targetheadyaw) {
1543 headyaw += multiplier * lookspeed;
1546 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1547 headpitch = targetheadpitch;
1548 else if (headpitch > targetheadpitch) {
1549 headpitch -= multiplier * lookspeed / 2;
1550 } else if (headpitch < targetheadpitch) {
1551 headpitch += multiplier * lookspeed / 2;
1554 rotatearound = jointPos(neck);
1555 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1559 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1560 facing = DoRotation(facing, headpitch * .4, 0, 0);
1561 facing = DoRotation(facing, 0, headyaw * .4, 0);
1564 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1565 facing = DoRotation(facing, headpitch * .8, 0, 0);
1566 facing = DoRotation(facing, 0, headyaw * .8, 0);
1569 if (animTarget == walkanim) {
1570 facing = DoRotation(facing, headpitch * .6, 0, 0);
1571 facing = DoRotation(facing, 0, headyaw * .6, 0);
1574 skeleton.specialforward[0] = facing;
1575 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1576 for (int i = 0; i < skeleton.num_muscles; i++) {
1577 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1578 skeleton.FindRotationMuscle(i, animTarget);
1585 * ragdolls character?
1587 void Person::RagDoll(bool checkcollision)
1592 if (!skeleton.free) {
1595 if (id == 0 && isFlip())
1602 facing = DoRotation(facing, 0, yaw, 0);
1604 skeleton.freetime = 0;
1606 skeleton.longdead = 0;
1609 skeleton.broken = 0;
1610 skeleton.spinny = 1;
1612 skeleton.freefall = 1;
1614 if (!isnormal(velocity.x)) velocity.x = 0;
1615 if (!isnormal(velocity.y)) velocity.y = 0;
1616 if (!isnormal(velocity.z)) velocity.z = 0;
1617 if (!isnormal(yaw)) yaw = 0;
1618 if (!isnormal(coords.x)) coords = 0;
1619 if (!isnormal(tilt)) tilt = 0;
1620 if (!isnormal(tilt2)) tilt2 = 0;
1622 for (int i = 0; i < skeleton.num_joints; i++) {
1623 skeleton.joints[i].delay = 0;
1624 skeleton.joints[i].locked = 0;
1625 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1626 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1627 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1628 skeleton.joints[i].position.y += .1;
1629 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1630 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1633 for (int i = 0; i < skeleton.num_joints; i++) {
1634 skeleton.joints[i].velocity = 0;
1635 skeleton.joints[i].velchange = 0;
1637 skeleton.DoConstraints(&coords, &scale);
1638 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1639 skeleton.DoConstraints(&coords, &scale);
1640 skeleton.DoConstraints(&coords, &scale);
1641 skeleton.DoConstraints(&coords, &scale);
1642 skeleton.DoConstraints(&coords, &scale);
1645 speed = animation[animTarget].speed[frameTarget] * 2;
1646 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1647 speed = animation[animCurrent].speed[frameCurrent] * 2;
1650 speed = transspeed * 2;
1654 for (int i = 0; i < skeleton.num_joints; i++) {
1655 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1656 skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((animation[animTarget].position[i][frameTarget] - animation[animCurrent].position[i][frameCurrent]) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1658 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1659 change.x = (float)(Random() % 100) / 100;
1660 change.y = (float)(Random() % 100) / 100;
1661 change.z = (float)(Random() % 100) / 100;
1662 skeleton.joints[i].velocity += change;
1663 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1665 change.x = (float)(Random() % 100) / 100;
1666 change.y = (float)(Random() % 100) / 100;
1667 change.z = (float)(Random() % 100) / 100;
1668 skeleton.joints[i].velchange += change;
1669 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1672 if (checkcollision) {
1679 for (j = 0; j < skeleton.num_joints; j++) {
1680 average += skeleton.joints[j].position;
1684 coords += average * scale;
1685 for (j = 0; j < skeleton.num_joints; j++) {
1686 skeleton.joints[j].position -= average;
1689 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1690 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1691 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1692 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1693 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1696 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1697 coords.x = lowpoint.x;
1698 coords.z = lowpoint.z;
1707 for (int i = 0; i < skeleton.num_joints; i++) {
1708 velocity += skeleton.joints[i].velocity * scale;
1710 velocity /= skeleton.num_joints;
1713 if (Random() % 2 == 0) {
1714 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1715 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1716 weapons[weaponids[0]].velocity.x += .01;
1719 weaponids[0] = weaponids[num_weapons];
1720 if (weaponstuck == num_weapons)
1724 for (unsigned i = 0; i < Person::players.size(); i++) {
1725 Person::players[i]->wentforweapon = 0;
1730 animTarget = bounceidleanim;
1731 animCurrent = bounceidleanim;
1741 void Person::FootLand(int which, float opacity)
1743 static XYZ terrainlight;
1744 static XYZ footvel, footpoint;
1745 if (opacity >= 1 || skiddelay <= 0)
1749 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1751 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1752 //footpoint.y=coords.y;
1753 if (distsq(&footpoint, &viewer))
1754 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1755 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1756 footvel = velocity / 5;
1760 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1762 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1763 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1764 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1765 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1766 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1767 if (opacity >= 1 || detail == 2)
1769 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1770 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1771 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1772 footvel = velocity / 5;
1776 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1778 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1779 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1780 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1781 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1782 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1783 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1784 footvel = velocity / 5;
1788 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1790 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1791 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1792 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1793 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1794 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1795 if (opacity >= 1 || detail == 2)
1797 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1798 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1799 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1800 footvel = velocity / 5;
1804 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1806 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1807 //footpoint.y=coords.y;
1808 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1809 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1814 * make a puff effect at a body part (dust effect?)
1816 void Person::Puff(int whichlabel)
1818 static XYZ footvel, footpoint;
1821 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1822 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1826 * I think I added this in an attempt to clean up code
1828 void Person::setAnimation(int animation)
1830 animTarget = animation;
1839 void Person::DoAnimations()
1841 if (!skeleton.free) {
1842 static float oldtarget;
1844 if (isIdle() && animCurrent != getIdle())
1845 normalsupdatedelay = 0;
1847 if (animTarget == tempanim || animCurrent == tempanim) {
1848 animation[tempanim] = tempanimation;
1850 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1856 vel[0] = velocity.x;
1857 vel[1] = velocity.y;
1858 vel[2] = velocity.z;
1861 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1862 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1864 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1866 if (!crouchkeydown && velocity.y >= -15)
1869 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1874 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1876 if (normaldotproduct(targfacing, velocity) >= -.3)
1877 animTarget = flipanim;
1879 animTarget = backflipanim;
1880 crouchtogglekeydown = 1;
1888 if (animation[animTarget].attack != reversed)
1890 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1891 crouchtogglekeydown = 0;
1892 if (aitype == playercontrolled)
1895 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1898 crouchtogglekeydown = 1;
1902 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1904 normalsupdatedelay = 0;
1908 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1910 emit_sound_at(fireendsound, coords);
1911 pause_sound(stream_firesound);
1915 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1916 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1918 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1919 if (normaldotproduct(victim->facing, facing) > 0)
1920 victim->animTarget = rabbittackledbackanim;
1922 victim->animTarget = rabbittackledfrontanim;
1923 victim->frameTarget = 2;
1926 victim->targetyaw = yaw;
1927 if (victim->aitype == gethelptype)
1928 victim->DoDamage(victim->damagetolerance - victim->damage);
1929 //victim->DoDamage(30);
1930 if (creature == wolftype) {
1932 emit_sound_at(clawslicesound, victim->coords);
1934 victim->DoBloodBig(1 / victim->armorhead, 210);
1936 award_bonus(id, TackleBonus,
1937 victim->aitype == gethelptype ? 50 : 0);
1941 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1942 if (weapons[weaponids[0]].getType() == knife) {
1943 if (weaponactive == -1)
1945 else if (weaponactive == 0)
1948 if (weaponactive == -1) {
1949 emit_sound_at(knifesheathesound, coords);
1951 if (weaponactive != -1) {
1952 emit_sound_at(knifedrawsound, coords, 128);
1955 drawtogglekeydown = 1;
1958 if (tutoriallevel != 1 || id == 0)
1959 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1962 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1963 if (animation[animTarget].label[frameTarget] == 1)
1964 whichsound = footstepsound;
1966 whichsound = footstepsound2;
1967 if (animation[animTarget].label[frameTarget] == 1)
1969 if (animation[animTarget].label[frameTarget] == 2)
1971 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1977 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1978 if (animation[animTarget].label[frameTarget] == 1)
1979 whichsound = footstepsound3;
1981 whichsound = footstepsound4;
1985 if (animation[animTarget].label[frameTarget] == 1)
1986 whichsound = footstepsound3;
1988 whichsound = footstepsound4;
1990 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1991 if (animation[animTarget].attack != neutral) {
1992 unsigned r = abs(Random() % 3);
1994 whichsound = lowwhooshsound;
1996 whichsound = midwhooshsound;
1998 whichsound = highwhooshsound;
2000 if (animation[animTarget].attack == neutral)
2001 whichsound = movewhooshsound;
2002 } else if (animation[animTarget].label[frameTarget] == 4)
2003 whichsound = knifeswishsound;
2004 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2005 whichsound = landsound2;
2007 emit_sound_at(whichsound, coords, 256.);
2010 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2011 envsound[numenvsounds] = coords;
2012 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
2013 envsoundvol[numenvsounds] = 15;
2015 envsoundvol[numenvsounds] = 6;
2016 envsoundlife[numenvsounds] = .4;
2020 if (animation[animTarget].label[frameTarget] == 3) {
2022 emit_sound_at(whichsound, coords, 128.);
2027 if (tutoriallevel != 1 || id == 0)
2028 if (speechdelay <= 0)
2029 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2030 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2031 int whichsound = -1;
2032 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2033 if (animation[animTarget].attack != neutral) {
2034 unsigned r = abs(Random() % 4);
2035 if (creature == rabbittype) {
2036 if (r == 0) whichsound = rabbitattacksound;
2037 if (r == 1) whichsound = rabbitattack2sound;
2038 if (r == 2) whichsound = rabbitattack3sound;
2039 if (r == 3) whichsound = rabbitattack4sound;
2041 if (creature == wolftype) {
2042 if (r == 0) whichsound = barksound;
2043 if (r == 1) whichsound = bark2sound;
2044 if (r == 2) whichsound = bark3sound;
2045 if (r == 3) whichsound = barkgrowlsound;
2051 if (whichsound != -1) {
2052 emit_sound_at(whichsound, coords);
2058 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2064 currentoffset = targetoffset;
2065 frameTarget = frameCurrent;
2066 animCurrent = animTarget;
2069 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2070 for (unsigned i = 0; i < weapons.size(); i++) {
2071 if (weapons[i].owner == -1)
2072 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2073 if (distsq(&coords, &weapons[i].position) >= 1) {
2074 if (weapons[i].getType() != staff) {
2075 emit_sound_at(knifedrawsound, coords, 128.);
2084 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2085 for (unsigned i = 0; i < weapons.size(); i++) {
2086 bool willwork = true;
2087 if (weapons[i].owner != -1)
2088 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2089 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2090 if (Person::players[weapons[i].owner]->num_weapons > 1)
2092 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2093 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2094 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2095 bool fleshstuck = false;
2096 if (weapons[i].owner != -1)
2097 if (victim->weaponstuck != -1) {
2098 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2103 emit_sound_at(fleshstabremovesound, coords, 128.);
2105 if (weapons[i].getType() != staff) {
2106 emit_sound_at(knifedrawsound, coords, 128.);
2109 if (weapons[i].owner != -1) {
2110 victim = Person::players[weapons[i].owner];
2111 if (victim->num_weapons == 1)
2112 victim->num_weapons = 0;
2114 victim->num_weapons = 1;
2116 //victim->weaponactive=-1;
2117 victim->skeleton.longdead = 0;
2118 victim->skeleton.free = 1;
2119 victim->skeleton.broken = 0;
2121 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2122 victim->skeleton.joints[j].velchange = 0;
2123 victim->skeleton.joints[j].locked = 0;
2129 Normalise(&relative);
2130 XYZ footvel, footpoint;
2132 footpoint = weapons[i].position;
2133 if (victim->weaponstuck != -1) {
2134 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2136 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2137 weapons[i].bloody = 2;
2138 weapons[i].blooddrip = 5;
2139 victim->weaponstuck = -1;
2142 if (victim->num_weapons > 0) {
2143 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2144 victim->weaponstuck = 0;
2145 if (victim->weaponids[0] == int(i))
2146 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2149 victim->jointVel(abdomen) += relative * 6;
2150 victim->jointVel(neck) += relative * 6;
2151 victim->jointVel(rightshoulder) += relative * 6;
2152 victim->jointVel(leftshoulder) += relative * 6;
2160 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2161 if (weaponactive == -1)
2163 else if (weaponactive == 0) {
2165 if (num_weapons == 2) {
2167 buffer = weaponids[0];
2168 weaponids[0] = weaponids[1];
2169 weaponids[1] = buffer;
2172 if (weaponactive == -1) {
2173 emit_sound_at(knifesheathesound, coords, 128.);
2175 if (weaponactive != -1) {
2176 emit_sound_at(knifedrawsound, coords, 128.);
2181 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2182 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2183 Normalise(&rotatetarget);
2184 targetyaw = -asin(0 - rotatetarget.x);
2185 targetyaw *= 360 / 6.28;
2186 if (rotatetarget.z < 0)
2187 targetyaw = 180 - targetyaw;
2189 if (animTarget == walljumprightkickanim)
2191 if (animTarget == walljumpleftkickanim)
2197 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2200 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2205 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2206 animTarget = rabbittackleanim;
2208 emit_sound_at(jumpsound, coords);
2216 targetloc = velocity;
2217 Normalise(&targetloc);
2218 targetloc += coords;
2219 for (unsigned i = 0; i < Person::players.size(); i++) {
2221 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2222 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2226 if (closestid != -1)
2227 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2229 victim = Person::players[closestid];
2230 coords = victim->coords;
2231 animCurrent = rabbittacklinganim;
2232 animTarget = rabbittacklinganim;
2236 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2237 rotatetarget = coords - victim->coords;
2238 Normalise(&rotatetarget);
2239 targetyaw = -asin(0 - rotatetarget.x);
2240 targetyaw *= 360 / 6.28;
2241 if (rotatetarget.z < 0)
2242 targetyaw = 180 - targetyaw;
2244 if (animTarget != rabbitrunninganim) {
2245 emit_sound_at(jumpsound, coords, 128.);
2251 float damagemult = 1 * power;
2252 if (creature == wolftype)
2253 damagemult = 2.5 * power;
2255 damagemult /= victim->damagetolerance / 200;
2257 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2258 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2259 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2263 if (Random() % 2 || creature == wolftype) {
2266 if (creature == wolftype)
2269 if (tutoriallevel != 1) {
2270 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2272 if (creature == wolftype) {
2273 emit_sound_at(clawslicesound, victim->coords, 128.);
2275 victim->DoBloodBig(2 / victim->armorhead, 175);
2279 relative = victim->coords - coords;
2281 Normalise(&relative);
2282 relative = DoRotation(relative, 0, -90, 0);
2283 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2284 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2286 victim->jointVel(head) += relative * damagemult * 200;
2289 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2295 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2296 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2300 if (Random() % 2 || creature == wolftype) {
2302 if (creature == wolftype)
2305 emit_sound_at(whooshhitsound, victim->coords);
2306 if (creature == wolftype) {
2307 emit_sound_at(clawslicesound, victim->coords, 128.);
2309 victim->DoBloodBig(2, 175);
2313 relative = victim->coords - coords;
2315 Normalise(&relative);
2317 Normalise(&relative);
2318 relative = DoRotation(relative, 0, 90, 0);
2319 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2320 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2322 victim->jointVel(head) += relative * damagemult * 100;
2325 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2329 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2330 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2336 if (tutoriallevel != 1) {
2337 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2339 if (creature == wolftype) {
2340 emit_sound_at(clawslicesound, victim->coords, 128.);
2342 victim->DoBloodBig(2 / victim->armorhead, 175);
2348 Normalise(&relative);
2349 relative = DoRotation(relative, 0, -90, 0);
2350 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2351 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2353 victim->jointVel(head) += relative * damagemult * 200;
2356 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2358 if (victim->damage > victim->damagetolerance)
2359 award_bonus(id, style);
2365 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2366 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2372 if (tutoriallevel != 1) {
2373 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2375 if (creature == wolftype) {
2376 emit_sound_at(clawslicesound, victim->coords, 128.);
2378 victim->DoBloodBig(2 / victim->armorhead, 175);
2384 Normalise(&relative);
2385 relative = DoRotation(relative, 0, 90, 0);
2386 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2387 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2389 victim->jointVel(head) += relative * damagemult * 200;
2392 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2394 if (victim->damage > victim->damagetolerance)
2395 award_bonus(id, style);
2401 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2402 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2410 emit_sound_at(whooshhitsound, victim->coords);
2413 relative = victim->coords - coords;
2415 Normalise(&relative);
2416 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2417 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2419 victim->jointVel(head) += relative * damagemult * 100;
2422 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2426 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2427 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2431 emit_sound_at(whooshhitsound, victim->coords, 128.);
2433 victim->skeleton.longdead = 0;
2434 victim->skeleton.free = 1;
2435 victim->skeleton.broken = 0;
2436 victim->skeleton.spinny = 1;
2438 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2439 victim->skeleton.joints[i].velchange = 0;
2440 victim->skeleton.joints[i].delay = 0;
2441 victim->skeleton.joints[i].locked = 0;
2442 //victim->skeleton.joints[i].velocity=0;
2448 Normalise(&relative);
2449 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2450 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2451 victim->skeleton.joints[i].position.y += relative.y * .3;
2452 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2453 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2455 victim->Puff(abdomen);
2456 victim->jointVel(abdomen).y = relative.y * 400;
2460 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2461 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2465 if (tutoriallevel != 1) {
2466 emit_sound_at(heavyimpactsound, coords, 128.);
2469 relative = victim->coords - coords;
2471 Normalise(&relative);
2472 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2473 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2475 victim->Puff(abdomen);
2476 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2480 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2481 victim->jointVel(abdomen) += relative * damagemult * 300;
2485 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2486 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2490 if (tutoriallevel != 1) {
2491 emit_sound_at(thudsound, coords);
2494 victim->skeleton.longdead = 0;
2495 victim->skeleton.free = 1;
2496 victim->skeleton.broken = 0;
2497 victim->skeleton.spinny = 1;
2499 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2500 victim->skeleton.joints[i].velchange = 0;
2501 //victim->skeleton.joints[i].delay=0;
2502 victim->skeleton.joints[i].locked = 0;
2505 relative = victim->coords - coords;
2506 Normalise(&relative);
2508 Normalise(&relative);
2509 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2510 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2515 victim->Puff(abdomen);
2516 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2517 victim->jointVel(abdomen) += relative * damagemult * 200;
2526 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2529 if (!victim->skeleton.free)
2533 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2534 emit_sound_at(knifesheathesound, coords, 128.);
2537 if (victim && hasvictim) {
2538 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2540 XYZ where, startpoint, endpoint, movepoint, colpoint;
2541 float rotationpoint;
2543 if (weapons[weaponids[weaponactive]].getType() == knife) {
2544 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2545 where -= victim->coords;
2546 if (!victim->skeleton.free)
2547 where = DoRotation(where, 0, -victim->yaw, 0);
2550 startpoint.y += 100;
2554 if (weapons[weaponids[weaponactive]].getType() == sword) {
2555 where = weapons[weaponids[weaponactive]].position;
2556 where -= victim->coords;
2557 if (!victim->skeleton.free)
2558 where = DoRotation(where, 0, -victim->yaw, 0);
2560 where = weapons[weaponids[weaponactive]].tippoint;
2561 where -= victim->coords;
2562 if (!victim->skeleton.free)
2563 where = DoRotation(where, 0, -victim->yaw, 0);
2566 if (weapons[weaponids[weaponactive]].getType() == staff) {
2567 where = weapons[weaponids[weaponactive]].position;
2568 where -= victim->coords;
2569 if (!victim->skeleton.free)
2570 where = DoRotation(where, 0, -victim->yaw, 0);
2572 where = weapons[weaponids[weaponactive]].tippoint;
2573 where -= victim->coords;
2574 if (!victim->skeleton.free)
2575 where = DoRotation(where, 0, -victim->yaw, 0);
2580 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2582 if (whichtri != -1) {
2583 if (victim->dead != 2) {
2584 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2586 award_bonus(id, FinishedBonus);
2589 weapons[weaponids[weaponactive]].bloody = 2;
2591 victim->skeleton.longdead = 0;
2592 victim->skeleton.free = 1;
2593 victim->skeleton.broken = 0;
2595 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2596 victim->skeleton.joints[i].velchange = 0;
2597 victim->skeleton.joints[i].locked = 0;
2598 //victim->skeleton.joints[i].velocity=0;
2600 emit_sound_at(fleshstabsound, coords, 128);
2603 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2604 weapons[weaponids[weaponactive]].blooddrip += 5;
2605 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2607 if (whichtri == -1) {
2609 emit_sound_at(knifesheathesound, coords, 128.);
2615 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2617 emit_sound_at(knifedrawsound, coords, 128);
2620 if (victim && hasvictim) {
2621 XYZ footvel, footpoint;
2623 emit_sound_at(fleshstabremovesound, coords, 128.);
2626 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2628 if (weapons[weaponids[weaponactive]].getType() == sword) {
2629 XYZ where, startpoint, endpoint, movepoint;
2630 float rotationpoint;
2633 where = weapons[weaponids[weaponactive]].position;
2634 where -= victim->coords;
2635 if (!victim->skeleton.free)
2636 where = DoRotation(where, 0, -victim->yaw, 0);
2638 where = weapons[weaponids[weaponactive]].tippoint;
2639 where -= victim->coords;
2640 if (!victim->skeleton.free)
2641 where = DoRotation(where, 0, -victim->yaw, 0);
2646 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2647 footpoint += victim->coords;
2649 if (whichtri == -1) {
2650 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2653 if (weapons[weaponids[weaponactive]].getType() == staff) {
2654 XYZ where, startpoint, endpoint, movepoint;
2655 float rotationpoint;
2658 where = weapons[weaponids[weaponactive]].position;
2659 where -= victim->coords;
2660 if (!victim->skeleton.free)
2661 where = DoRotation(where, 0, -victim->yaw, 0);
2663 where = weapons[weaponids[weaponactive]].tippoint;
2664 where -= victim->coords;
2665 if (!victim->skeleton.free)
2666 where = DoRotation(where, 0, -victim->yaw, 0);
2671 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2672 footpoint += victim->coords;
2674 if (whichtri == -1) {
2675 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2678 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2680 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2681 victim->skeleton.longdead = 0;
2682 victim->skeleton.free = 1;
2683 victim->skeleton.broken = 0;
2685 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2686 victim->skeleton.joints[i].velchange = 0;
2687 victim->skeleton.joints[i].locked = 0;
2688 //victim->skeleton.joints[i].velocity=0;
2694 Normalise(&relative);
2695 //victim->Puff(abdomen);
2697 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2699 if (victim->bloodloss < victim->damagetolerance) {
2700 victim->bloodloss += 1000;
2704 victim->jointVel(abdomen) += relative * damagemult * 20;
2708 if (!hasvictim && onterrain) {
2709 weapons[weaponids[weaponactive]].bloody = 0;
2710 weapons[weaponids[weaponactive]].blooddrip = 0;
2714 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2715 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2723 if (tutoriallevel != 1) {
2724 emit_sound_at(heavyimpactsound, victim->coords, 128);
2729 relative = victim->coords - coords;
2731 Normalise(&relative);
2732 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2733 victim->skeleton.joints[i].velocity = relative * 30;
2735 victim->jointVel(head) += relative * damagemult * 150;
2737 victim->frameTarget = 0;
2738 victim->animTarget = staggerbackhardanim;
2739 victim->targetyaw = targetyaw + 180;
2741 victim->stunned = 1;
2744 victim->Puff(abdomen);
2745 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2752 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2753 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2757 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2758 if (tutoriallevel != 1) {
2759 emit_sound_at(thudsound, victim->coords);
2761 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2762 if (tutoriallevel != 1) {
2763 emit_sound_at(whooshhitsound, victim->coords);
2766 if (tutoriallevel != 1) {
2767 emit_sound_at(heavyimpactsound, victim->coords);
2771 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2774 relative = victim->coords - coords;
2776 Normalise(&relative);
2778 Normalise(&relative);
2779 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2780 victim->skeleton.joints[i].velocity = relative * 5;
2782 victim->jointVel(abdomen) += relative * damagemult * 400;
2784 victim->frameTarget = 0;
2785 victim->animTarget = staggerbackhardanim;
2786 victim->targetyaw = targetyaw + 180;
2788 victim->stunned = 1;
2790 victim->Puff(abdomen);
2791 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2797 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2798 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2799 if (victim->id == 0)
2801 emit_sound_at(landsound2, victim->coords);
2807 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2808 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2809 if (victim->id == 0)
2812 if (weaponactive != -1) {
2813 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2814 if (weapons[victim->weaponids[0]].getType() == staff)
2815 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2816 if (weapons[weaponids[0]].getType() == staff)
2817 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2819 emit_sound_at(swordstaffsound, victim->coords);
2821 emit_sound_at(metalhitsound, victim->coords);
2829 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2830 if (weaponactive != -1) {
2833 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);
2835 weapons[weaponids[0]].thrown(aim * 50);
2838 weaponids[0] = weaponids[num_weapons];
2844 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2846 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2848 if (tutoriallevel != 1)
2849 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2851 award_bonus(id, Slicebonus);
2852 if (tutoriallevel != 1) {
2853 emit_sound_at(knifeslicesound, victim->coords);
2855 //victim->jointVel(abdomen)+=relative*damagemult*200;
2856 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2857 if (victim->id != 0 || difficulty == 2) {
2858 victim->frameTarget = 0;
2859 victim->animTarget = staggerbackhardanim;
2860 victim->targetyaw = targetyaw + 180;
2864 victim->lowreversaldelay = 0;
2865 victim->highreversaldelay = 0;
2866 if (aitype != playercontrolled)
2867 weaponmissdelay = .6;
2869 if (tutoriallevel != 1)
2870 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2871 weapons[weaponids[weaponactive]].bloody = 1;
2872 if (tutoriallevel != 1)
2873 weapons[weaponids[weaponactive]].blooddrip += 3;
2875 XYZ footvel, footpoint;
2877 if (skeleton.free) {
2878 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2880 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2882 if (tutoriallevel != 1) {
2884 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2885 footvel = DoRotation(facing, 0, 90, 0) * .8;
2887 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2888 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2889 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2890 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2892 if (tutoriallevel == 1) {
2893 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2895 victim->DoDamage(damagemult * 0);
2898 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2899 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2900 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2901 award_bonus(id, Slashbonus);
2903 if (tutoriallevel != 1) {
2904 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2905 victim->DoBloodBig(2 / victim->armorhigh, 190);
2907 victim->DoBloodBig(2 / victim->armorhigh, 185);
2908 victim->deathbleeding = 1;
2909 emit_sound_at(swordslicesound, victim->coords);
2911 //victim->jointVel(abdomen)+=relative*damagemult*200;
2912 if (tutoriallevel != 1) {
2913 victim->frameTarget = 0;
2914 victim->animTarget = staggerbackhardanim;
2915 victim->targetyaw = targetyaw + 180;
2919 if (tutoriallevel != 1) {
2920 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2921 weapons[weaponids[weaponactive]].bloody = 1;
2922 weapons[weaponids[weaponactive]].blooddrip += 3;
2924 float bloodlossamount;
2925 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2926 victim->bloodloss += bloodlossamount / victim->armorhigh;
2927 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2928 victim->DoDamage(damagemult * 0);
2930 XYZ footvel, footpoint;
2932 if (skeleton.free) {
2933 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2935 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2938 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2939 footvel = DoRotation(facing, 0, 90, 0) * .8;
2941 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2942 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2943 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2944 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2947 if (victim->weaponactive != -1) {
2948 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2949 if (weapons[victim->weaponids[0]].getType() == staff)
2950 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2951 if (weapons[weaponids[0]].getType() == staff)
2952 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2954 emit_sound_at(swordstaffsound, victim->coords);
2956 emit_sound_at(metalhitsound, victim->coords);
2962 victim->Puff(righthand);
2964 victim->frameTarget = 0;
2965 victim->animTarget = staggerbackhighanim;
2966 victim->targetyaw = targetyaw + 180;
2968 aim = DoRotation(facing, 0, 90, 0) * 21;
2970 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2971 victim->num_weapons--;
2972 if (victim->num_weapons) {
2973 victim->weaponids[0] = victim->weaponids[num_weapons];
2974 if (victim->weaponstuck == victim->num_weapons)
2975 victim->weaponstuck = 0;
2977 victim->weaponactive = -1;
2978 for (unsigned i = 0; i < Person::players.size(); i++) {
2979 Person::players[i]->wentforweapon = 0;
2986 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2987 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2988 if (tutoriallevel != 1) {
2989 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2993 if (Random() % 2 || creature == wolftype) {
2996 emit_sound_at(staffheadsound, victim->coords);
3000 relative = victim->coords - coords;
3002 Normalise(&relative);
3003 relative = DoRotation(relative, 0, 90, 0);
3005 Normalise(&relative);
3006 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3007 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3009 victim->jointVel(head) += relative * damagemult * 230;
3010 victim->jointVel(neck) += relative * damagemult * 230;
3013 if (tutoriallevel != 1) {
3014 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3016 award_bonus(id, solidhit, 30);
3021 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3022 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3023 if (tutoriallevel != 1) {
3024 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3028 if (Random() % 2 || creature == wolftype) {
3031 emit_sound_at(staffheadsound, victim->coords);
3035 relative = victim->coords - coords;
3037 Normalise(&relative);
3038 relative = DoRotation(relative, 0, -90, 0);
3039 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3040 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3042 victim->jointVel(head) += relative * damagemult * 220;
3043 victim->jointVel(neck) += relative * damagemult * 220;
3046 if (tutoriallevel != 1) {
3047 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3049 award_bonus(id, solidhit, 60);
3054 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3055 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3057 if (tutoriallevel != 1) {
3059 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3062 if (Random() % 2 || creature == wolftype) {
3065 emit_sound_at(staffbodysound, victim->coords);
3067 victim->skeleton.longdead = 0;
3068 victim->skeleton.free = 1;
3069 victim->skeleton.broken = 0;
3071 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3072 victim->skeleton.joints[i].velchange = 0;
3073 victim->skeleton.joints[i].locked = 0;
3074 //victim->skeleton.joints[i].velocity=0;
3080 /*relative=victim->coords-coords;
3082 Normalise(&relative);
3083 relative=DoRotation(relative,0,90,0);*/
3085 Normalise(&relative);
3086 if (!victim->dead) {
3087 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3088 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3091 victim->jointVel(abdomen) += relative * damagemult * 40;
3094 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3095 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3098 //victim->jointVel(abdomen)+=relative*damagemult*20;
3100 victim->Puff(abdomen);
3101 if (tutoriallevel != 1) {
3102 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3104 if (!victim->dead) {
3105 award_bonus(id, solidhit, 40);
3111 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3112 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3117 relative = victim->coords - coords;
3119 Normalise(&relative);
3123 if (animation[victim->animTarget].height == lowheight) {
3129 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3130 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3132 victim->jointVel(head) += relative * damagemult * 200;
3133 if (tutoriallevel != 1) {
3134 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3137 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3138 if (victim->howactive == typesleeping)
3139 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3140 if (creature == wolftype) {
3141 emit_sound_at(clawslicesound, victim->coords, 128.);
3143 victim->DoBloodBig(2 / victim->armorhead, 175);
3146 if (victim->damage >= victim->damagetolerance)
3148 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3149 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3151 victim->jointVel(abdomen) += relative * damagemult * 200;
3152 victim->frameTarget = 0;
3153 victim->animTarget = staggerbackhighanim;
3154 victim->targetyaw = targetyaw + 180;
3156 if (tutoriallevel != 1) {
3157 emit_sound_at(landsound2, victim->coords, 128.);
3159 victim->Puff(abdomen);
3160 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3161 if (creature == wolftype) {
3162 emit_sound_at(clawslicesound, victim->coords, 128.);
3164 victim->DoBloodBig(2 / victim->armorhigh, 170);
3171 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3172 if ((victim->animTarget != jumpupanim) &&
3173 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3174 (victim != this->shared_from_this())) {
3178 if (tutoriallevel != 1) {
3179 emit_sound_at(landsound2, victim->coords, 128.);
3182 relative = victim->coords - coords;
3184 Normalise(&relative);
3186 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3189 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3190 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3192 relative = DoRotation(relative, 0, -90, 0);
3194 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3195 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)
3196 victim->skeleton.joints[i].velocity = relative * 80;
3198 victim->Puff(rightankle);
3199 victim->Puff(leftankle);
3200 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3202 if (victim->damage >= victim->damagetolerance)
3204 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3205 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3207 relative = DoRotation(relative, 0, -90, 0);
3208 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3209 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)
3210 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3212 victim->jointVel(abdomen) += relative * damagemult * 200;
3213 victim->frameTarget = 0;
3214 victim->animTarget = staggerbackhighanim;
3215 victim->targetyaw = targetyaw + 180;
3217 if (tutoriallevel != 1) {
3218 emit_sound_at(landsound2, victim->coords, 128.);
3220 victim->Puff(abdomen);
3221 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3229 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3230 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3238 if (tutoriallevel != 1) {
3239 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3241 if (creature == wolftype) {
3242 emit_sound_at(clawslicesound, victim->coords, 128);
3244 victim->DoBloodBig(2 / victim->armorhigh, 170);
3248 relative = victim->coords - oldcoords;
3250 Normalise(&relative);
3251 //relative=DoRotation(relative,0,-90,0);
3252 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3253 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3255 victim->jointVel(abdomen) += relative * damagemult * 200;
3257 victim->Puff(abdomen);
3258 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3260 award_bonus(id, Reversal);
3263 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3264 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3265 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3266 takeWeapon(victim->weaponids[victim->weaponactive]);
3267 victim->num_weapons--;
3268 if (victim->num_weapons > 0) {
3269 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3271 victim->weaponactive = -1;
3276 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3284 emit_sound_at(whooshhitsound, victim->coords, 128.);
3287 relative = victim->coords - oldcoords;
3289 Normalise(&relative);
3290 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3291 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3293 victim->jointVel(abdomen) += relative * damagemult * 200;
3295 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3298 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3307 award_bonus(id, staffreversebonus);
3309 if (tutoriallevel != 1) {
3310 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3313 award_bonus(id, staffreversebonus); // Huh, again?
3316 relative = victim->coords - oldcoords;
3318 Normalise(&relative);
3319 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3320 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3322 victim->jointVel(abdomen) += relative * damagemult * 200;
3324 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3327 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3333 Normalise(&relative);
3335 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3336 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3338 victim->jointVel(lefthand) *= .1;
3339 victim->jointVel(leftwrist) *= .2;
3340 victim->jointVel(leftelbow) *= .5;
3341 victim->jointVel(leftshoulder) *= .7;
3342 victim->jointVel(righthand) *= .1;
3343 victim->jointVel(rightwrist) *= .2;
3344 victim->jointVel(rightelbow) *= .5;
3345 victim->jointVel(rightshoulder) *= .7;
3347 victim->Puff(abdomen);
3348 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3350 award_bonus(id, Reversal);
3354 if (weaponactive != -1 || creature == wolftype)
3356 if (creature == rabbittype && weaponactive != -1)
3357 if (weapons[weaponids[0]].getType() == staff)
3360 if (weaponactive != -1) {
3361 victim->DoBloodBig(2 / victim->armorhigh, 225);
3362 emit_sound_at(knifeslicesound, victim->coords);
3363 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3364 weapons[weaponids[weaponactive]].bloody = 1;
3365 weapons[weaponids[weaponactive]].blooddrip += 3;
3367 if (weaponactive == -1 && creature == wolftype) {
3369 emit_sound_at(clawslicesound, victim->coords, 128.);
3371 victim->DoBloodBig(2 / victim->armorhigh, 175);
3378 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3384 Normalise(&relative);
3386 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3387 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3389 victim->jointVel(lefthand) *= .1 - 1;
3390 victim->jointVel(leftwrist) *= .2 - 1;
3391 victim->jointVel(leftelbow) *= .5 - 1;
3392 victim->jointVel(leftshoulder) *= .7 - 1;
3393 victim->jointVel(righthand) *= .1 - 1;
3394 victim->jointVel(rightwrist) *= .2 - 1;
3395 victim->jointVel(rightelbow) *= .5 - 1;
3396 victim->jointVel(rightshoulder) *= .7 - 1;
3398 award_bonus(id, swordreversebonus);
3401 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3409 if (tutoriallevel != 1) {
3410 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3414 relative = victim->coords - oldcoords;
3416 Normalise(&relative);
3417 relative = DoRotation(relative, 0, -90, 0);
3418 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3419 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3421 victim->jointVel(abdomen) += relative * damagemult * 200;
3422 victim->Puff(abdomen);
3423 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3425 award_bonus(id, Reversal);
3428 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3431 victim->skeleton.spinny = 0;
3433 relative = facing * -1;
3435 Normalise(&relative);
3436 if (victim->id == 0)
3438 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3439 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3441 victim->damage = victim->damagetolerance;
3442 victim->permanentdamage = victim->damagetolerance - 1;
3445 if (weaponactive != -1 || creature == wolftype)
3447 if (creature == rabbittype && weaponactive != -1)
3448 if (weapons[weaponids[0]].getType() == staff)
3451 if (weaponactive != -1) {
3452 victim->DoBloodBig(200, 225);
3453 emit_sound_at(knifeslicesound, victim->coords);
3455 weapons[weaponids[weaponactive]].bloody = 2;
3456 weapons[weaponids[weaponactive]].blooddrip += 5;
3459 if (creature == wolftype && weaponactive == -1) {
3460 emit_sound_at(clawslicesound, victim->coords, 128.);
3462 victim->DoBloodBig(2, 175);
3465 award_bonus(id, spinecrusher);
3468 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3469 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3471 if (animTarget == knifefollowanim)
3472 victim->DoBloodBig(200, 210);
3473 if (animTarget == knifesneakattackanim) {
3474 XYZ footvel, footpoint;
3476 footpoint = weapons[weaponids[0]].tippoint;
3478 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3479 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3480 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3481 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3482 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3483 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3484 victim->DoBloodBig(200, 195);
3485 award_bonus(id, tracheotomy);
3487 if (animTarget == knifefollowanim) {
3488 award_bonus(id, Stabbonus);
3489 XYZ footvel, footpoint;
3491 footpoint = weapons[weaponids[0]].tippoint;
3493 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3494 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3495 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3496 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3497 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3498 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3501 victim->bloodloss += 10000;
3502 victim->velocity = 0;
3503 emit_sound_at(fleshstabsound, victim->coords);
3505 weapons[weaponids[weaponactive]].bloody = 2;
3506 weapons[weaponids[weaponactive]].blooddrip += 5;
3510 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3512 victim->velocity = 0;
3513 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3514 victim->skeleton.joints[i].velocity = 0;
3516 if (animTarget == knifefollowanim) {
3518 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3519 victim->skeleton.joints[i].velocity = 0;
3522 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3523 emit_sound_at(fleshstabremovesound, victim->coords);
3525 weapons[weaponids[weaponactive]].bloody = 2;
3526 weapons[weaponids[weaponactive]].blooddrip += 5;
3528 XYZ footvel, footpoint;
3530 footpoint = weapons[weaponids[0]].tippoint;
3532 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3533 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3534 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3535 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3536 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3537 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3541 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3542 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3543 award_bonus(id, backstab);
3547 XYZ footvel, footpoint;
3549 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3551 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3552 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3553 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3554 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3555 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3556 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3557 victim->DoBloodBig(200, 180);
3558 victim->DoBloodBig(200, 215);
3559 victim->bloodloss += 10000;
3560 victim->velocity = 0;
3561 emit_sound_at(fleshstabsound, victim->coords);
3563 weapons[weaponids[weaponactive]].bloody = 2;
3564 weapons[weaponids[weaponactive]].blooddrip += 5;
3568 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3570 victim->velocity = 0;
3571 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3572 victim->skeleton.joints[i].velocity = 0;
3574 if (weaponactive != -1) {
3575 emit_sound_at(fleshstabremovesound, victim->coords);
3577 weapons[weaponids[weaponactive]].bloody = 2;
3578 weapons[weaponids[weaponactive]].blooddrip += 5;
3580 XYZ footvel, footpoint;
3582 footpoint = weapons[weaponids[0]].tippoint;
3584 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3585 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3586 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3587 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3588 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3589 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3593 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3601 if (weaponactive == -1) {
3602 if (tutoriallevel != 1) {
3603 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3608 if (weaponactive != -1 || creature == wolftype)
3610 if (creature == rabbittype && weaponactive != -1)
3611 if (weapons[weaponids[0]].getType() == staff)
3614 if (weaponactive != -1) {
3615 victim->DoBloodBig(2 / victim->armorhead, 225);
3616 emit_sound_at(knifeslicesound, victim->coords);
3617 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3618 weapons[weaponids[weaponactive]].bloody = 1;
3619 weapons[weaponids[weaponactive]].blooddrip += 3;
3621 if (weaponactive == -1 && creature == wolftype) {
3622 emit_sound_at(clawslicesound, victim->coords, 128.);
3624 victim->DoBloodBig(2 / victim->armorhead, 175);
3628 award_bonus(id, Reversal);
3633 relative = facing * -1;
3635 Normalise(&relative);
3636 relative = DoRotation(relative, 0, 90, 0);
3638 Normalise(&relative);
3639 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3640 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3642 victim->jointVel(head) += relative * damagemult * 200;
3643 if (victim->damage < victim->damagetolerance - 100)
3644 victim->velocity = relative * 200;
3645 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3646 victim->velocity = 0;
3649 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3653 relative = facing * -1;
3655 Normalise(&relative);
3656 relative = DoRotation(relative, 0, 90, 0);
3658 Normalise(&relative);
3659 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3660 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3662 victim->jointVel(head) += relative * damagemult * 200;
3665 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3666 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3667 award_bonus(id, reverseko);
3673 if (frameTarget > animation[animCurrent].numframes - 1) {
3676 animTarget = getIdle();
3680 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3681 animTarget = rollanim;
3683 emit_sound_at(movewhooshsound, coords, 128.);
3685 if (animCurrent == staggerbackhighanim) {
3686 animTarget = getIdle();
3688 if (animCurrent == staggerbackhardanim) {
3689 animTarget = getIdle();
3691 if (animCurrent == removeknifeanim) {
3692 animTarget = getIdle();
3694 if (animCurrent == crouchremoveknifeanim) {
3695 animTarget = getCrouch();
3697 if (animCurrent == backhandspringanim) {
3698 animTarget = getIdle();
3700 if (animCurrent == dodgebackanim) {
3701 animTarget = getIdle();
3703 if (animCurrent == drawleftanim) {
3704 animTarget = getIdle();
3706 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3707 animTarget = getIdle();
3708 if (animCurrent == crouchdrawrightanim) {
3709 animTarget = getCrouch();
3711 if (weaponactive == -1)
3713 else if (weaponactive == 0) {
3715 if (num_weapons == 2) {
3717 buffer = weaponids[0];
3718 weaponids[0] = weaponids[1];
3719 weaponids[1] = buffer;
3723 if (weaponactive == -1) {
3724 emit_sound_at(knifesheathesound, coords, 128.);
3726 if (weaponactive != -1) {
3727 emit_sound_at(knifedrawsound, coords, 128.);
3730 if (animCurrent == rollanim) {
3731 animTarget = getCrouch();
3736 if (animTarget == walljumprightkickanim) {
3739 if (animTarget == walljumpleftkickanim) {
3742 animTarget = jumpdownanim;
3744 if (animCurrent == climbanim) {
3745 animTarget = getCrouch();
3747 coords += facing * .1;
3748 if (!isnormal(coords.x))
3759 if (animTarget == rabbitkickreversalanim) {
3760 animTarget = getCrouch();
3763 if (animTarget == jumpreversalanim) {
3764 animTarget = getCrouch();
3767 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3768 if (attackkeydown && animTarget != walljumpfrontanim) {
3770 float closestdist = -1;
3772 if (Person::players.size() > 1)
3773 for (unsigned i = 0; i < Person::players.size(); i++) {
3774 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3775 distance = distsq(&Person::players[i]->coords, &coords);
3776 if (closestdist == -1 || distance < closestdist) {
3777 closestdist = distance;
3782 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3783 victim = Person::players[closest];
3784 animTarget = walljumprightkickanim;
3786 XYZ rotatetarget = victim->coords - coords;
3787 Normalise(&rotatetarget);
3788 yaw = -asin(0 - rotatetarget.x);
3790 if (rotatetarget.z < 0)
3792 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3793 velocity = (victim->coords - coords) * 4;
3798 if (animTarget == walljumpbackanim) {
3799 animTarget = backflipanim;
3801 velocity = facing * -8;
3804 resume_stream(whooshsound);
3806 if (animTarget == walljumprightanim) {
3807 animTarget = rightflipanim;
3811 velocity = DoRotation(facing, 0, 30, 0) * -8;
3814 if (animTarget == walljumpfrontanim) {
3815 animTarget = frontflipanim;
3819 velocity = facing * 8;
3823 resume_stream(whooshsound);
3825 if (animTarget == walljumpleftanim) {
3826 if (attackkeydown) {
3828 float closestdist = -1;
3830 if (Person::players.size() > 1)
3831 for (unsigned i = 0; i < Person::players.size(); i++) {
3832 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3833 distance = distsq(&Person::players[i]->coords, &coords);
3834 if (closestdist == -1 || distance < closestdist) {
3835 closestdist = distance;
3840 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3841 victim = Person::players[closest];
3842 animTarget = walljumpleftkickanim;
3844 XYZ rotatetarget = victim->coords - coords;
3845 Normalise(&rotatetarget);
3846 yaw = -asin(0 - rotatetarget.x);
3848 if (rotatetarget.z < 0)
3850 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3851 velocity = (victim->coords - coords) * 4;
3856 if (animTarget != walljumpleftkickanim) {
3857 animTarget = leftflipanim;
3861 velocity = DoRotation(facing, 0, -30, 0) * -8;
3865 resume_stream(whooshsound);
3867 if (animTarget == sneakattackanim) {
3868 animCurrent = getCrouch();
3869 animTarget = getCrouch();
3876 transspeed = 1000000;
3877 targetheadyaw += 180;
3878 coords -= facing * .7;
3880 coords.y = terrain.getHeight(coords.x, coords.z);
3884 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3885 animTarget = getIdle();
3888 coords.y = terrain.getHeight(coords.x, coords.z);
3892 if (animCurrent == knifefollowanim) {
3893 animTarget = getIdle();
3896 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3897 float ycoords = oldcoords.y;
3898 animTarget = getStop();
3903 transspeed = 1000000;
3904 targetheadyaw += 180;
3905 if (!isnormal(coords.x))
3907 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3908 oldcoords = coords + facing * .5;
3909 else if (animCurrent == sweepreversalanim)
3910 oldcoords = coords + facing * 1.1;
3911 else if (animCurrent == upunchreversalanim) {
3912 oldcoords = coords + facing * 1.5;
3915 targetheadyaw += 180;
3918 } else if (animCurrent == knifeslashreversalanim) {
3919 oldcoords = coords + facing * .5;
3922 targetheadyaw += 90;
3925 } else if (animCurrent == staffspinhitreversalanim) {
3928 targetheadyaw += 180;
3933 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3935 oldcoords.y = ycoords;
3936 currentoffset = coords - oldcoords;
3942 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3947 if (animation[animTarget].attack == reversed) {
3949 if (animTarget == sweepreversedanim)
3951 animTarget = backhandspringanim;
3953 emit_sound_at(landsound, coords, 128);
3955 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3956 animTarget = rollanim;
3959 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3960 coords.y = oldcoords.y;
3962 if (animCurrent == knifeslashreversedanim) {
3963 animTarget = rollanim;
3968 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3969 coords.y = oldcoords.y;
3973 animTarget = jumpdownanim;
3976 animTarget = getIdle();
3978 animTarget = getIdle();
3979 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3980 animTarget = getIdle();
3982 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3983 coords.y = oldcoords.y;
3984 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3985 targetoffset.y = coords.y;
3987 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3988 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3989 currentoffset.y -= (coords.y - targetoffset.y);
3990 coords.y = targetoffset.y;
3992 normalsupdatedelay = 0;
3994 if (animCurrent == upunchanim) {
3995 animTarget = getStop();
3996 normalsupdatedelay = 0;
3999 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4003 if (num_weapons > 0)
4004 if (weapons[0].getType() == staff)
4010 rabbitkickragdoll = 1;
4012 if (animCurrent == rabbitkickreversedanim) {
4018 skeleton.spinny = 0;
4019 SolidHitBonus(!id); // FIXME: tricky id
4023 animTarget = rollanim;
4026 pause_sound(whooshsound);
4030 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4034 skeleton.spinny = 0;
4036 if (animCurrent == jumpreversedanim) {
4042 skeleton.spinny = 0;
4043 SolidHitBonus(!id); // FIXME: tricky id
4047 animTarget = rollanim;
4048 coords += facing * 2;
4050 pause_sound(whooshsound);
4055 if (animation[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) {
4056 animTarget = getupfromfrontanim;
4058 } else if (animation[animCurrent].attack == normalattack) {
4059 animTarget = getIdle();
4062 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4063 animTarget = blockhighleftstrikeanim;
4065 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4066 animTarget = getIdle();
4069 if (animCurrent == spinkickanim && victim->skeleton.free) {
4070 if (creature == rabbittype)
4071 animTarget = fightidleanim;
4076 if (isIdle() && !wasIdle())
4077 normalsupdatedelay = 0;
4079 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4080 animTarget = jumpdownanim;
4083 if (!skeleton.free) {
4085 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4086 if (!isRun() || !wasRun()) {
4087 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4088 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4089 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4090 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4092 if (isRun() && wasRun()) {
4094 tempspeed = velspeed;
4095 if (tempspeed < 10 * speedmult)
4096 tempspeed = 10 * speedmult;
4097 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4099 } else if (transspeed)
4100 target += multiplier * transspeed * speed * 2;
4102 if (!isRun() || !wasRun()) {
4103 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4104 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4105 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4106 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4110 if (animCurrent != animTarget)
4111 target = (target + oldtarget) / 2;
4114 frameCurrent = frameTarget;
4118 rot = targetrot * target;
4119 yaw += rot - oldrot;
4125 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4127 for (int i = 0; i < skeleton.num_joints; i++) {
4128 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4131 skeleton.FindForwards();
4133 for (int i = 0; i < skeleton.num_muscles; i++) {
4134 if (skeleton.muscles[i].visible) {
4135 skeleton.FindRotationMuscle(i, animTarget);
4138 for (int i = 0; i < skeleton.num_muscles; i++) {
4139 if (skeleton.muscles[i].visible) {
4140 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4141 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4142 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4143 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4144 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4145 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4150 for (int i = 0; i < skeleton.num_joints; i++) {
4151 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4154 skeleton.FindForwards();
4156 for (int i = 0; i < skeleton.num_muscles; i++) {
4157 if (skeleton.muscles[i].visible) {
4158 skeleton.FindRotationMuscle(i, animTarget);
4161 for (int i = 0; i < skeleton.num_muscles; i++) {
4162 if (skeleton.muscles[i].visible) {
4163 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4164 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4165 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4166 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4167 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4168 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4169 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4170 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4171 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4172 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4173 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4174 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4178 if (frameCurrent >= animation[animCurrent].numframes)
4179 frameCurrent = animation[animCurrent].numframes - 1;
4181 oldanimCurrent = animCurrent;
4182 oldanimTarget = animTarget;
4183 oldframeTarget = frameTarget;
4184 oldframeCurrent = frameCurrent;
4186 for (int i = 0; i < skeleton.num_joints; i++) {
4187 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4188 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4190 offset = currentoffset * (1 - target) + targetoffset * target;
4191 for (int i = 0; i < skeleton.num_muscles; i++) {
4192 if (skeleton.muscles[i].visible) {
4193 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4194 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4195 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4200 if (isLanding() && landhard) {
4203 animTarget = getLandhard();
4216 void Person::DoStuff()
4218 static XYZ terrainnormal;
4219 static XYZ flatfacing;
4220 static XYZ flatvelocity;
4221 static float flatvelspeed;
4225 static int bloodsize;
4226 static int startx, starty, endx, endy;
4227 static GLubyte color;
4228 static XYZ bloodvel;
4230 onfiredelay -= multiplier;
4231 if (onfiredelay < 0 && onfire) {
4232 if (Random() % 2 == 0) {
4238 crouchkeydowntime += multiplier;
4240 crouchkeydowntime = 0;
4241 jumpkeydowntime += multiplier;
4242 if (!jumpkeydown && skeleton.free)
4243 jumpkeydowntime = 0;
4245 if (hostile || damage > 0 || bloodloss > 0)
4248 if (isIdle() || isRun())
4251 if (num_weapons == 1 && weaponactive != -1)
4255 blooddimamount -= multiplier * .3;
4256 speechdelay -= multiplier;
4257 texupdatedelay -= multiplier;
4258 interestdelay -= multiplier;
4259 flamedelay -= multiplier;
4260 parriedrecently -= multiplier;
4262 victim = this->shared_from_this();
4267 speed = 1.1 * speedmult;
4269 speed = 1.0 * speedmult;
4271 rabbitkickragdoll = 0;
4275 if (id != 0 && (creature == rabbittype || difficulty != 2))
4277 if (id != 0 && creature == wolftype && difficulty == 2) {
4279 if (aitype != passivetype) {
4281 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) {
4287 if (animTarget == wolfrunninganim && !superruntoggle) {
4288 animTarget = getRun();
4292 if (weaponactive == -1 && num_weapons > 0) {
4293 if (weapons[weaponids[0]].getType() == staff) {
4299 burnt += multiplier;
4303 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4305 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4311 vel[0] = velocity.x;
4312 vel[1] = velocity.y;
4313 vel[2] = velocity.z;
4316 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4317 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4321 while (flamedelay < 0 && onfire) {
4323 howmany = abs(Random() % (skeleton.num_joints));
4324 if (skeleton.free) {
4325 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4326 flatfacing = skeleton.joints[howmany].position * scale + coords;
4328 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4329 flatvelocity = (coords - oldcoords) / multiplier / 2;
4331 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4334 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4336 howmany = abs(Random() % (skeleton.num_joints));
4337 if (skeleton.free) {
4338 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4339 flatfacing = skeleton.joints[howmany].position * scale + coords;
4341 flatvelocity = (coords - oldcoords) / multiplier / 2;
4342 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4344 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4348 bleeding -= multiplier * .3;
4349 if (bloodtoggle == 2) {
4350 skeleton.drawmodel.textureptr.bind();
4351 if ((bleeding <= 0) && (detail != 2))
4356 if (neckspurtamount > 0) {
4357 neckspurtamount -= multiplier;
4358 neckspurtdelay -= multiplier * 3;
4359 neckspurtparticledelay -= multiplier * 3;
4360 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4363 if (skeleton.free) {
4364 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4365 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4366 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4368 bloodvel.z = 5 * neckspurtamount;
4369 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4370 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4371 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4373 neckspurtparticledelay = .05;
4375 if (neckspurtdelay < 0) {
4380 if (deathbleeding > 0 && dead != 2) {
4381 if (deathbleeding < 5)
4382 bleeddelay -= deathbleeding * multiplier / 4;
4384 bleeddelay -= 5 * multiplier / 4;
4385 if (bleeddelay < 0 && bloodtoggle) {
4390 if (skeleton.free) {
4391 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4392 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4394 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4395 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4399 bloodloss += deathbleeding * multiplier * 80;
4400 deathbleeding -= multiplier * 1.6;
4401 if (deathbleeding < 0)
4403 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4404 if (weaponactive != -1) {
4405 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4406 weapons[weaponids[0]].velocity.x += .01;
4409 weaponids[0] = weaponids[num_weapons];
4410 if (weaponstuck == num_weapons)
4414 for (unsigned i = 0; i < Person::players.size(); i++) {
4415 Person::players[i]->wentforweapon = 0;
4427 if (!dead && creature == wolftype) {
4428 award_bonus(0, Wolfbonus);
4431 if (animTarget == knifefollowedanim && !skeleton.free) {
4432 for (int i = 0; i < skeleton.num_joints; i++) {
4433 skeleton.joints[i].velocity = 0;
4434 skeleton.joints[i].velocity.y = -2;
4437 if (id != 0 && unconscioustime > .1) {
4445 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4446 texupdatedelay = .12;
4448 bloodsize = 5 - realtexdetail;
4452 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4453 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4454 endx = startx + bloodsize;
4455 endy = starty + bloodsize;
4465 if (endx > skeleton.skinsize - 1) {
4466 endx = skeleton.skinsize - 1;
4469 if (endy > skeleton.skinsize - 1) {
4470 endy = skeleton.skinsize - 1;
4478 for (i = startx; i < endx; i++) {
4479 for (j = starty; j < endy; j++) {
4480 if (Random() % 2 == 0) {
4481 color = Random() % 85 + 170;
4482 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4483 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4484 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4485 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4490 skeleton.drawmodel.textureptr.bind();
4494 if (skeleton.free) {
4495 bleedx += 4 * direction / realtexdetail;
4497 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4499 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4501 bleedy -= 4 / realtexdetail;
4503 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4505 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4509 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4510 righthandmorphness = targetrighthandmorphness;
4511 righthandmorphstart = righthandmorphend;
4512 } else if (righthandmorphness > targetrighthandmorphness) {
4513 righthandmorphness -= multiplier * 4;
4514 } else if (righthandmorphness < targetrighthandmorphness) {
4515 righthandmorphness += multiplier * 4;
4518 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4519 lefthandmorphness = targetlefthandmorphness;
4520 lefthandmorphstart = lefthandmorphend;
4521 } else if (lefthandmorphness > targetlefthandmorphness) {
4522 lefthandmorphness -= multiplier * 4;
4523 } else if (lefthandmorphness < targetlefthandmorphness) {
4524 lefthandmorphness += multiplier * 4;
4527 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4528 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4529 tailmorphness = targettailmorphness;
4530 tailmorphstart = tailmorphend;
4531 } else if (tailmorphness > targettailmorphness) {
4532 tailmorphness -= multiplier * 10;
4533 } else if (tailmorphness < targettailmorphness) {
4534 tailmorphness += multiplier * 10;
4538 if (creature == wolftype) {
4539 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4540 tailmorphness = targettailmorphness;
4541 tailmorphstart = tailmorphend;
4542 } else if (tailmorphness > targettailmorphness) {
4543 tailmorphness -= multiplier * 2;
4544 } else if (tailmorphness < targettailmorphness) {
4545 tailmorphness += multiplier * 2;
4549 if (headmorphend == 3 || headmorphstart == 3) {
4550 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4551 headmorphness = targetheadmorphness;
4552 headmorphstart = headmorphend;
4553 } else if (headmorphness > targetheadmorphness) {
4554 headmorphness -= multiplier * 7;
4555 } else if (headmorphness < targetheadmorphness) {
4556 headmorphness += multiplier * 7;
4558 } else if (headmorphend == 5 || headmorphstart == 5) {
4559 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4560 headmorphness = targetheadmorphness;
4561 headmorphstart = headmorphend;
4562 } else if (headmorphness > targetheadmorphness) {
4563 headmorphness -= multiplier * 10;
4564 } else if (headmorphness < targetheadmorphness) {
4565 headmorphness += multiplier * 10;
4568 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4569 headmorphness = targetheadmorphness;
4570 headmorphstart = headmorphend;
4571 } else if (headmorphness > targetheadmorphness) {
4572 headmorphness -= multiplier * 4;
4573 } else if (headmorphness < targetheadmorphness) {
4574 headmorphness += multiplier * 4;
4578 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4579 chestmorphness = targetchestmorphness;
4580 chestmorphstart = chestmorphend;
4581 } else if (chestmorphness > targetchestmorphness) {
4582 chestmorphness -= multiplier;
4583 } else if (chestmorphness < targetchestmorphness) {
4584 chestmorphness += multiplier;
4587 if (dead != 2 && howactive <= typesleeping) {
4588 if (chestmorphstart == 0 && chestmorphend == 0) {
4590 targetchestmorphness = 1;
4593 if (chestmorphstart != 0 && chestmorphend != 0) {
4595 targetchestmorphness = 1;
4597 if (environment == snowyenvironment) {
4600 if (skeleton.free) {
4601 footvel = skeleton.specialforward[0] * -1;
4602 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4604 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4605 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4607 if (animTarget == sleepanim)
4608 footvel = DoRotation(footvel, 0, 90, 0);
4609 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4613 if (!dead && howactive < typesleeping) {
4614 blinkdelay -= multiplier * 2;
4615 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4617 targetheadmorphness = 1;
4619 blinkdelay = (float)(abs(Random() % 40)) / 5;
4621 if (headmorphstart == 3 && headmorphend == 3) {
4623 targetheadmorphness = 1;
4628 twitchdelay -= multiplier * 1.5;
4629 if (animTarget != hurtidleanim) {
4630 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4632 targetheadmorphness = 1;
4634 twitchdelay = (float)(abs(Random() % 40)) / 5;
4636 if (headmorphstart == 5 && headmorphend == 5) {
4638 targetheadmorphness = 1;
4642 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4643 twitchdelay3 -= multiplier * 1;
4644 if (Random() % 2 == 0) {
4645 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4646 righthandmorphness = 0;
4647 targetrighthandmorphness = 1;
4648 righthandmorphend = 1;
4649 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4651 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4652 righthandmorphness = 0;
4653 targetrighthandmorphness = 1;
4654 righthandmorphend = 0;
4657 if (Random() % 2 == 0) {
4658 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4659 lefthandmorphness = 0;
4660 targetlefthandmorphness = 1;
4661 lefthandmorphend = 1;
4662 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4664 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4665 lefthandmorphness = 0;
4666 targetlefthandmorphness = 1;
4667 lefthandmorphend = 0;
4673 if (creature == rabbittype) {
4674 if (howactive < typesleeping)
4675 twitchdelay2 -= multiplier * 1.5;
4677 twitchdelay2 -= multiplier * 0.5;
4678 if (howactive <= typesleeping) {
4679 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4681 targettailmorphness = 1;
4683 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4685 if (tailmorphstart == 1 && tailmorphend == 1) {
4687 targettailmorphness = 1;
4690 if (tailmorphstart == 2 && tailmorphend == 2) {
4692 targettailmorphness = 1;
4699 if (creature == wolftype) {
4700 twitchdelay2 -= multiplier * 1.5;
4701 if (tailmorphend != 0)
4702 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4704 targettailmorphness = 1;
4708 if (tailmorphend != 5)
4709 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4711 targettailmorphness = 1;
4715 if (twitchdelay2 <= 0) {
4716 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4718 targettailmorphness = 1;
4721 if (tailmorphstart == 1 && tailmorphend == 1) {
4723 targettailmorphness = 1;
4726 if (tailmorphstart == 2 && tailmorphend == 2) {
4728 targettailmorphness = 1;
4731 if (tailmorphstart == 3 && tailmorphend == 3) {
4733 targettailmorphness = 1;
4736 if (tailmorphstart == 4 && tailmorphend == 4) {
4738 targettailmorphness = 1;
4745 unconscioustime = 0;
4747 if (dead == 1 || howactive == typesleeping) {
4748 unconscioustime += multiplier;
4749 //If unconscious, close eyes and mouth
4750 if (righthandmorphend != 0)
4751 righthandmorphness = 0;
4752 righthandmorphend = 0;
4753 targetrighthandmorphness = 1;
4755 if (lefthandmorphend != 0)
4756 lefthandmorphness = 0;
4757 lefthandmorphend = 0;
4758 targetlefthandmorphness = 1;
4760 if (headmorphend != 3 && headmorphend != 5)
4763 targetheadmorphness = 1;
4767 if (howactive > typesleeping) {
4770 if (bloodtoggle && !bled) {
4771 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4773 if (bloodtoggle && !bled)
4774 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4775 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4776 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4780 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4785 if (dead == 2 || howactive > typesleeping) {
4786 //If dead, open mouth and hands
4787 if (righthandmorphend != 0)
4788 righthandmorphness = 0;
4789 righthandmorphend = 0;
4790 targetrighthandmorphness = 1;
4792 if (lefthandmorphend != 0)
4793 lefthandmorphness = 0;
4794 lefthandmorphend = 0;
4795 targetlefthandmorphness = 1;
4797 if (headmorphend != 2)
4800 targetheadmorphness = 1;
4803 if (stunned > 0 && !dead && headmorphend != 2) {
4804 if (headmorphend != 4)
4807 targetheadmorphness = 1;
4810 if (damage > damagetolerance && !dead) {
4813 unconscioustime = 0;
4815 if (creature == wolftype) {
4816 award_bonus(0, Wolfbonus);
4821 if (weaponactive != -1) {
4822 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4823 weapons[weaponids[0]].velocity.x += .01;
4826 weaponids[0] = weaponids[num_weapons];
4827 if (weaponstuck == num_weapons)
4831 for (unsigned i = 0; i < Person::players.size(); i++) {
4832 Person::players[i]->wentforweapon = 0;
4838 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4847 damage -= multiplier * 13;
4849 permanentdamage -= multiplier * 4;
4850 if (isIdle() || isCrouch()) {
4852 permanentdamage -= multiplier * 4;
4856 if (permanentdamage < 0)
4857 permanentdamage = 0;
4858 if (superpermanentdamage < 0)
4859 superpermanentdamage = 0;
4860 if (permanentdamage < superpermanentdamage) {
4861 permanentdamage = superpermanentdamage;
4863 if (damage < permanentdamage) {
4864 damage = permanentdamage;
4866 if (dead == 1 && damage < damagetolerance) {
4870 for (int i = 0; i < skeleton.num_joints; i++) {
4871 skeleton.joints[i].velocity = 0;
4874 if (permanentdamage > damagetolerance && dead != 2) {
4877 if (weaponactive != -1) {
4878 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4879 weapons[weaponids[0]].velocity.x += .01;
4882 weaponids[0] = weaponids[num_weapons];
4883 if (weaponstuck == num_weapons)
4887 for (unsigned i = 0; i < Person::players.size(); i++) {
4888 Person::players[i]->wentforweapon = 0;
4894 if (!dead && creature == wolftype) {
4895 award_bonus(0, Wolfbonus);
4898 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4899 award_bonus(id, touchofdeath);
4900 if (id != 0 && unconscioustime > .1) {
4908 emit_sound_at(breaksound, coords);
4911 if (skeleton.free == 1) {
4913 pause_sound(whooshsound);
4916 //If knocked over, open hands and close mouth
4917 if (righthandmorphend != 0)
4918 righthandmorphness = 0;
4919 righthandmorphend = 0;
4920 targetrighthandmorphness = 1;
4922 if (lefthandmorphend != 0)
4923 lefthandmorphness = 0;
4924 lefthandmorphend = 0;
4925 targetlefthandmorphness = 1;
4927 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4928 if (headmorphend != 0)
4931 targetheadmorphness = 1;
4935 skeleton.DoGravity(&scale);
4937 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4938 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4939 award_bonus(id, deepimpact);
4940 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4944 for (j = 0; j < skeleton.num_joints; j++) {
4945 average += skeleton.joints[j].position;
4949 coords += average * scale;
4950 for (j = 0; j < skeleton.num_joints; j++) {
4951 skeleton.joints[j].position -= average;
4953 average /= multiplier;
4956 for (int i = 0; i < skeleton.num_joints; i++) {
4957 velocity += skeleton.joints[i].velocity * scale;
4959 velocity /= skeleton.num_joints;
4961 if (!isnormal(velocity.x) && velocity.x) {
4965 if (findLength(&average) < 10 && dead && skeleton.free) {
4966 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4967 if (skeleton.longdead > 2000) {
4968 if (skeleton.longdead > 6000) {
4970 pause_sound(whooshsound);
4975 if (dead == 2 && bloodloss < damagetolerance) {
4977 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4979 if (bloodtoggle && !bled) {
4980 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4982 if (bloodtoggle && !bled)
4983 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4984 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4985 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4986 float size = .2 * 1.2;
4989 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4993 if (dead == 2 && bloodloss >= damagetolerance) {
4995 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4998 if (bloodtoggle && !bled) {
4999 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5001 if (bloodtoggle && !bled)
5002 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5003 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5004 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5008 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5015 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5016 bool canrecover = 1;
5017 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5018 startpoint = coords;
5021 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5023 if (velocity.y < -30)
5025 for (i = 0; i < objects.numobjects; i++) {
5026 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5027 colviewer = startpoint;
5028 coltarget = endpoint;
5029 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5038 terrainnormal = jointPos(groin) - jointPos(abdomen);
5039 if (joint(groin).locked && joint(abdomen).locked) {
5040 terrainnormal = jointPos(groin) - jointPos(abdomen);
5041 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5043 if (joint(abdomen).locked && joint(neck).locked) {
5044 terrainnormal = jointPos(abdomen) - jointPos(neck);
5045 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5047 if (joint(groin).locked && joint(neck).locked) {
5048 terrainnormal = jointPos(groin) - jointPos(neck);
5049 middle = (jointPos(groin) + jointPos(neck)) / 2;
5051 Normalise(&terrainnormal);
5053 targetyaw = -asin(0 - terrainnormal.x);
5054 targetyaw *= 360 / 6.28;
5055 if (terrainnormal.z < 0)
5056 targetyaw = 180 - targetyaw;
5060 animTarget = flipanim;
5061 crouchtogglekeydown = 1;
5066 animCurrent = tempanim;
5070 for (int i = 0; i < skeleton.num_joints; i++) {
5071 tempanimation.position[i][0] = skeleton.joints[i].position;
5072 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5077 if (findLength(&average) < 10 && !dead && skeleton.free) {
5078 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5079 if (skeleton.longdead > (damage + 500) * 1.5) {
5081 pause_sound(whooshsound);
5087 terrainnormal = jointPos(groin) - jointPos(abdomen);
5088 if (joint(groin).locked && joint(abdomen).locked) {
5089 terrainnormal = jointPos(groin) - jointPos(abdomen);
5090 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5092 if (joint(abdomen).locked && joint(neck).locked) {
5093 terrainnormal = jointPos(abdomen) - jointPos(neck);
5094 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5096 if (joint(groin).locked && joint(neck).locked) {
5097 terrainnormal = jointPos(groin) - jointPos(neck);
5098 middle = (jointPos(groin) + jointPos(neck)) / 2;
5100 Normalise(&terrainnormal);
5102 targetyaw = -asin(0 - terrainnormal.x);
5103 targetyaw *= 360 / 6.28;
5104 if (terrainnormal.z < 0)
5105 targetyaw = 180 - targetyaw;
5108 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5111 if (skeleton.forward.y < 0) {
5112 animTarget = getupfrombackanim;
5116 if (skeleton.forward.y > -.3) {
5117 animTarget = getupfromfrontanim;
5125 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5126 animTarget = rollanim;
5127 targetyaw = lookyaw;
5144 if ( !leftkeydown && !rightkeydown)
5151 if (abs(targettilt2) > 50)
5153 animCurrent = tempanim;
5156 tilt2 = targettilt2;
5158 if (middle.y > 0 && animTarget != rollanim)
5159 targetoffset.y = middle.y + 1;
5161 for (int i = 0; i < skeleton.num_joints; i++) {
5162 tempanimation.position[i][0] = skeleton.joints[i].position;
5163 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5170 if (num_weapons > 0)
5171 if (weapons[0].getType() == staff)
5173 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5174 if (velocity.y > -30) {
5176 tempvelocity = velocity;
5177 Normalise(&tempvelocity);
5178 targetyaw = -asin(0 - tempvelocity.x);
5179 targetyaw *= 360 / 6.28;
5181 targetyaw = 180 - targetyaw;
5185 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5186 animTarget = rollanim;
5189 animTarget = backhandspringanim;
5195 emit_sound_at(movewhooshsound, coords, 128.);
5197 animCurrent = animTarget;
5198 frameCurrent = frameTarget - 1;
5210 if (skeleton.freefall == 0)
5215 if (aitype != passivetype || skeleton.free == 1)
5216 if (findLengthfast(&velocity) > .1)
5217 for (i = 0; i < objects.numobjects; i++) {
5218 if (objects.type[i] == firetype)
5219 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5221 if (!objects.onfire[i]) {
5222 emit_sound_at(firestartsound, objects.position[i]);
5224 objects.onfire[i] = 1;
5227 if (objects.onfire[i]) {
5232 if (objects.type[i] == bushtype)
5233 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5235 if (!objects.onfire[i]) {
5236 emit_sound_at(firestartsound, objects.position[i]);
5238 objects.onfire[i] = 1;
5242 if (objects.onfire[i]) {
5246 if (objects.messedwith[i] <= 0) {
5250 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5253 envsound[numenvsounds] = coords;
5254 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5255 envsoundlife[numenvsounds] = .4;
5260 if (environment == grassyenvironment)
5261 howmany = findLength(&velocity) * 4;
5262 if (environment == snowyenvironment)
5263 howmany = findLength(&velocity) * 2;
5265 if (environment != desertenvironment)
5266 for (j = 0; j < howmany; j++) {
5267 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5268 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5269 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5272 pos.x += float(abs(Random() % 100) - 50) / 200;
5273 pos.y += float(abs(Random() % 100) - 50) / 200;
5274 pos.z += float(abs(Random() % 100) - 50) / 200;
5275 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);
5276 Sprite::setLastSpriteSpecial(1);
5278 howmany = findLength(&velocity) * 4;
5280 if (environment == snowyenvironment)
5281 for (j = 0; j < howmany; j++) {
5282 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5283 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5284 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5287 pos.x += float(abs(Random() % 100) - 50) / 200;
5288 pos.y += float(abs(Random() % 100) - 50) / 200;
5289 pos.z += float(abs(Random() % 100) - 50) / 200;
5290 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5291 Sprite::setLastSpriteSpecial(2);
5294 objects.rotx[i] += velocity.x * multiplier * 6;
5295 objects.roty[i] += velocity.z * multiplier * 6;
5296 objects.messedwith[i] = .5;
5299 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5300 if (objects.pitch[i] == 0)
5303 tempcoord = coords - objects.position[i];
5304 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5305 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5306 tempcoord += objects.position[i];
5308 if (distsqflat(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 8 && distsq(&tempcoord, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 300 && tempcoord.y > objects.position[i].y + 3 * objects.scale[i]) {
5309 if (objects.messedwith[i] <= 0) {
5313 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5316 envsound[numenvsounds] = coords;
5317 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5318 envsoundlife[numenvsounds] = .4;
5323 if (environment == grassyenvironment)
5324 howmany = findLength(&velocity) * 4;
5325 if (environment == snowyenvironment)
5326 howmany = findLength(&velocity) * 2;
5328 if (environment != desertenvironment)
5329 for (j = 0; j < howmany; j++) {
5330 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5331 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5332 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5334 pos += velocity * .1;
5336 pos.x += float(abs(Random() % 100) - 50) / 150;
5337 pos.y += float(abs(Random() % 100) - 50) / 150;
5338 pos.z += float(abs(Random() % 100) - 50) / 150;
5339 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);
5340 Sprite::setLastSpriteSpecial(1);
5342 howmany = findLength(&velocity) * 4;
5344 if (environment == snowyenvironment)
5345 for (j = 0; j < howmany; j++) {
5346 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5347 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5348 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5350 pos += velocity * .1;
5352 pos.x += float(abs(Random() % 100) - 50) / 150;
5353 pos.y += float(abs(Random() % 100) - 50) / 150;
5354 pos.z += float(abs(Random() % 100) - 50) / 150;
5355 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5356 Sprite::setLastSpriteSpecial(2);
5359 objects.messedwith[i] = .5;
5364 if (!skeleton.free) {
5367 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5370 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5372 if (tutoriallevel == 1 && id != 0)
5374 if (play && aitype != playercontrolled) {
5375 int whichsound = -1;
5376 i = abs(Random() % 4);
5377 if (speechdelay <= 0) {
5378 if (creature == rabbittype) {
5380 whichsound = rabbitchitter;
5382 whichsound = rabbitchitter2;
5384 if (creature == wolftype) {
5386 whichsound = growlsound;
5388 whichsound = growl2sound;
5393 if (whichsound != -1) {
5394 emit_sound_at(whichsound, coords);
5398 if (animTarget == staggerbackhighanim)
5400 if (animTarget == staggerbackhardanim)
5402 staggerdelay -= multiplier;
5403 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5405 if (velocity.y < -30 && animTarget == jumpdownanim)
5407 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5408 animTarget = getIdle();
5412 weaponmissdelay -= multiplier;
5413 highreversaldelay -= multiplier;
5414 lowreversaldelay -= multiplier;
5415 lastcollide -= multiplier;
5416 skiddelay -= multiplier;
5417 if (!isnormal(velocity.x) && velocity.x) {
5420 if (!isnormal(targettilt) && targettilt) {
5423 if (!isnormal(targettilt2) && targettilt2) {
5426 if (!isnormal(targetyaw) && targetyaw) {
5430 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5431 //open hands and close mouth
5432 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5433 righthandmorphness = 0;
5434 righthandmorphend = 0;
5435 targetrighthandmorphness = 1;
5438 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5439 lefthandmorphness = 0;
5440 lefthandmorphend = 0;
5441 targetlefthandmorphness = 1;
5444 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5447 targetheadmorphness = 1;
5451 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) {
5452 //open hands and mouth
5453 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5454 righthandmorphness = 0;
5455 righthandmorphend = 0;
5456 targetrighthandmorphness = 1;
5459 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5460 lefthandmorphness = 0;
5461 lefthandmorphend = 0;
5462 targetlefthandmorphness = 1;
5465 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5468 targetheadmorphness = 1;
5472 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5473 //close hands and mouth
5474 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5475 righthandmorphness = 0;
5476 righthandmorphend = 1;
5477 targetrighthandmorphness = 1;
5480 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5481 lefthandmorphness = 0;
5482 lefthandmorphend = 1;
5483 targetlefthandmorphness = 1;
5486 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5489 targetheadmorphness = 1;
5493 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) {
5494 //close hands and yell
5495 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5496 righthandmorphness = 0;
5497 righthandmorphend = 1;
5498 targetrighthandmorphness = 1;
5501 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5502 lefthandmorphness = 0;
5503 lefthandmorphend = 1;
5504 targetlefthandmorphness = 1;
5507 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5510 targetheadmorphness = 1;
5517 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5518 (victim->aitype != searchtype) && (aitype != passivetype) &&
5519 (aitype != searchtype) && (victim->id < Person::players.size())) {
5520 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5524 if (!dead && animTarget != hurtidleanim)
5525 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5526 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5529 targetheadmorphness = 1;
5533 if (weaponactive != -1) {
5534 if (weapons[weaponids[weaponactive]].getType() != staff) {
5535 righthandmorphstart = 1;
5536 righthandmorphend = 1;
5538 if (weapons[weaponids[weaponactive]].getType() == staff) {
5539 righthandmorphstart = 2;
5540 righthandmorphend = 2;
5542 targetrighthandmorphness = 1;
5545 terrainnormal = terrain.getNormal(coords.x, coords.z);
5547 if (animation[animTarget].attack != reversal) {
5548 if (!isnormal(coords.x))
5556 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5557 facing = flatfacing;
5558 ReflectVector(&facing, terrainnormal);
5561 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5563 targettilt2 = -facing.y * 20;
5568 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5570 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5571 flatvelocity = velocity;
5573 flatvelspeed = findLength(&flatvelocity);
5574 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5575 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5580 if (targettilt > 25)
5582 if (targettilt < -25)
5586 if (targettilt2 > 45)
5588 if (targettilt2 < -45)
5590 if (abs(tilt2 - targettilt2) < multiplier * 400)
5591 tilt2 = targettilt2;
5592 else if (tilt2 > targettilt2) {
5593 tilt2 -= multiplier * 400;
5594 } else if (tilt2 < targettilt2) {
5595 tilt2 += multiplier * 400;
5597 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5604 if (!isnormal(targettilt) && targettilt) {
5607 if (!isnormal(targettilt2) && targettilt2) {
5612 if (animTarget == rabbittackleanim) {
5613 velocity += facing * multiplier * speed * 700 * scale;
5614 velspeed = findLength(&velocity);
5615 if (velspeed > speed * 65 * scale) {
5616 velocity /= velspeed;
5617 velspeed = speed * 65 * scale;
5618 velocity *= velspeed;
5620 velocity.y += gravity * multiplier * 20;
5621 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5622 velspeed = findLength(&velocity);
5623 velocity = flatfacing * velspeed;
5625 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5626 if (isRun() || animTarget == rabbitkickanim) {
5627 velocity += facing * multiplier * speed * 700 * scale;
5628 velspeed = findLength(&velocity);
5629 if (velspeed > speed * 45 * scale) {
5630 velocity /= velspeed;
5631 velspeed = speed * 45 * scale;
5632 velocity *= velspeed;
5634 velocity.y += gravity * multiplier * 20;
5635 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5636 velspeed = findLength(&velocity);
5637 if (velspeed < speed * 30 * scale)
5638 velspeed = speed * 30 * scale;
5639 velocity = flatfacing * velspeed;
5641 } else if (isRun()) {
5642 velocity += facing * multiplier * speed * 700 * scale;
5643 velspeed = findLength(&velocity);
5644 if (creature == rabbittype) {
5645 if (velspeed > speed * 55 * scale) {
5646 velocity /= velspeed;
5647 velspeed = speed * 55 * scale;
5648 velocity *= velspeed;
5651 if (creature == wolftype) {
5652 if (velspeed > speed * 75 * scale) {
5653 velocity /= velspeed;
5654 velspeed = speed * 75 * scale;
5655 velocity *= velspeed;
5658 velocity.y += gravity * multiplier * 20;
5659 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5660 velspeed = findLength(&velocity);
5661 velocity = flatfacing * velspeed;
5664 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5665 velocity += facing * multiplier * speed * 700 * scale;
5666 velspeed = findLength(&velocity);
5667 if (velspeed > speed * 45 * scale) {
5668 velocity /= velspeed;
5669 velspeed = speed * 45 * scale;
5670 velocity *= velspeed;
5672 velocity.y += gravity * multiplier * 20;
5673 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5674 velspeed = findLength(&velocity);
5675 velocity = flatfacing * velspeed;
5678 if (animTarget == sneakanim || animTarget == walkanim) {
5679 velocity += facing * multiplier * speed * 700 * scale;
5680 velspeed = findLength(&velocity);
5681 if (velspeed > speed * 12 * scale) {
5682 velocity /= velspeed;
5683 velspeed = speed * 12 * scale;
5684 velocity *= velspeed;
5686 velocity.y += gravity * multiplier * 20;
5687 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5688 velspeed = findLength(&velocity);
5689 velocity = flatfacing * velspeed;
5692 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5693 velocity += facing * multiplier * speed * 700 * scale;
5694 velspeed = findLength(&velocity);
5695 if (velspeed > speed * 2 * scale) {
5696 velocity /= velspeed;
5697 velspeed = speed * 2 * scale;
5698 velocity *= velspeed;
5700 velocity.y += gravity * multiplier * 20;
5701 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5702 velspeed = findLength(&velocity);
5703 velocity = flatfacing * velspeed;
5707 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5708 velocity -= facing * multiplier * speed * 700 * scale;
5709 velspeed = findLength(&velocity);
5710 if (velspeed > speed * 2 * scale) {
5711 velocity /= velspeed;
5712 velspeed = speed * 2 * scale;
5713 velocity *= velspeed;
5715 velocity.y += gravity * multiplier * 20;
5716 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5717 velspeed = findLength(&velocity);
5718 velocity = flatfacing * velspeed * -1;
5721 if (animTarget == fightsidestep) {
5722 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5723 velspeed = findLength(&velocity);
5724 if (velspeed > speed * 12 * scale) {
5725 velocity /= velspeed;
5726 velspeed = speed * 12 * scale;
5727 velocity *= velspeed;
5729 velocity.y += gravity * multiplier * 20;
5730 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5731 velspeed = findLength(&velocity);
5732 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5735 if (animTarget == staggerbackhighanim) {
5736 coords -= facing * multiplier * speed * 16 * scale;
5739 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5740 coords -= facing * multiplier * speed * 20 * scale;
5744 if (animTarget == backhandspringanim) {
5745 //coords-=facing*multiplier*50*scale;
5746 velocity += facing * multiplier * speed * 700 * scale * -1;
5747 velspeed = findLength(&velocity);
5748 if (velspeed > speed * 50 * scale) {
5749 velocity /= velspeed;
5750 velspeed = speed * 50 * scale;
5751 velocity *= velspeed;
5753 velocity.y += gravity * multiplier * 20;
5754 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5755 velspeed = findLength(&velocity);
5756 velocity = flatfacing * velspeed * -1;
5758 if (animTarget == dodgebackanim) {
5759 //coords-=facing*multiplier*50*scale;
5760 velocity += facing * multiplier * speed * 700 * scale * -1;
5761 velspeed = findLength(&velocity);
5762 if (velspeed > speed * 60 * scale) {
5763 velocity /= velspeed;
5764 velspeed = speed * 60 * scale;
5765 velocity *= velspeed;
5767 velocity.y += gravity * multiplier * 20;
5768 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5769 velspeed = findLength(&velocity);
5770 velocity = flatfacing * velspeed * -1;
5773 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5774 velspeed = findLength(&velocity);
5778 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5779 velocity.y += gravity * multiplier;
5782 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5783 coords += velocity * multiplier;
5785 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5786 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5789 if (animTarget == jumpupanim) {
5791 animTarget = getIdle();
5798 pause_sound(whooshsound);
5799 OPENAL_SetVolume(channels[whooshsound], 0);
5802 if (animTarget == jumpdownanim || isFlip()) {
5803 if (isFlip())jumppower = -4;
5804 animTarget = getLanding();
5805 emit_sound_at(landsound, coords, 128.);
5808 envsound[numenvsounds] = coords;
5809 envsoundvol[numenvsounds] = 16;
5810 envsoundlife[numenvsounds] = .4;
5816 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5817 coords.y += gravity * multiplier * 2;
5818 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5819 coords.y = terrain.getHeight(coords.x, coords.z);
5824 if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || animation[animTarget].attack || (animTarget == rollanim && animation[animTarget].label[frameTarget] == 6)) {
5825 velspeed = findLength(&velocity);
5827 if (velspeed < multiplier * 300 * scale) {
5830 velocity -= velocity / velspeed * multiplier * 300 * scale;
5831 if (velspeed > 5 && (isLanding() || isLandhard())) {
5832 skiddingdelay += multiplier;
5833 if (skiddelay <= 0) {
5843 velspeed = findLength(&velocity);
5845 if (velspeed < multiplier * 600 * scale) {
5848 velocity -= velocity / velspeed * multiplier * 600 * scale;
5850 if (velspeed > 5 && (isLanding() || isLandhard())) {
5851 skiddingdelay += multiplier;
5852 if (skiddelay <= 0) {
5861 if (skiddingdelay < 0)
5862 skiddingdelay += multiplier;
5863 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5865 if (!onterrain || environment == grassyenvironment) {
5866 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5868 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5872 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5873 terrainnormal = victim->coords - coords;
5874 Normalise(&terrainnormal);
5875 targetyaw = -asin(0 - terrainnormal.x);
5876 targetyaw *= 360 / 6.28;
5877 if (terrainnormal.z < 0)
5878 targetyaw = 180 - targetyaw;
5879 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5882 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5883 targetyaw = victim->targetyaw;
5885 if (animTarget == rabbittacklinganim) {
5886 coords = victim->coords;
5889 skeleton.oldfree = skeleton.free;
5893 midterrain.x = terrain.size * terrain.scale / 2;
5894 midterrain.z = terrain.size * terrain.scale / 2;
5895 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5897 tempposit = coords - midterrain;
5899 Normalise(&tempposit);
5900 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5901 coords.x = tempposit.x + midterrain.x;
5902 coords.z = tempposit.z + midterrain.z;
5908 * inverse kinematics helper function
5910 void IKHelper(Person *p, float interp)
5912 XYZ point, change, change2;
5913 float heightleft, heightright;
5915 // TODO: implement localToWorld and worldToLocal
5916 // but keep in mind it won't be the same math if player is ragdolled or something
5917 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5918 // then comb through code for places where to use it
5920 // point = localToWorld(jointPos(leftfoot))
5921 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5922 // adjust height of foot
5923 heightleft = terrain.getHeight(point.x, point.z) + .04;
5924 point.y = heightleft;
5925 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5926 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5927 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5928 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5929 // move ankle along with foot
5930 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5931 // average knee pos between old and new pos
5932 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5934 // do same as above for right leg
5935 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5936 heightright = terrain.getHeight(point.x, point.z) + .04;
5937 point.y = heightright;
5938 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5939 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5940 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5941 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5942 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5944 // fix up skeleton now that we've moved body parts?
5945 p->skeleton.DoConstraints(&p->coords, &p->scale);
5952 int Person::DrawSkeleton()
5954 int oldplayerdetail;
5955 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5956 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5966 glAlphaFunc(GL_GREATER, 0.0001);
5968 float terrainheight;
5972 if (!isnormal(tilt))
5974 if (!isnormal(tilt2))
5976 oldplayerdetail = playerdetail;
5978 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5981 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5984 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5989 if (playerdetail != oldplayerdetail) {
5991 normalsupdatedelay = 0;
5993 static float updatedelaychange;
5994 static float morphness;
5995 static float framemult;
5997 skeleton.FindForwards();
5998 if (howactive == typesittingwall) {
5999 skeleton.specialforward[1] = 0;
6000 skeleton.specialforward[1].z = 1;
6006 static int weaponattachmuscle;
6007 static int weaponrotatemuscle;
6008 static XYZ weaponpoint;
6009 static int start, endthing;
6010 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6011 if (!isSleeping() && !isSitting()) {
6012 // TODO: give these meaningful names
6013 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6014 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6015 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6016 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6018 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6020 if (creature == wolftype)
6024 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6025 IKHelper(this, target);
6026 if (creature == wolftype)
6027 IKHelper(this, target);
6030 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6031 IKHelper(this, 1 - target);
6032 if (creature == wolftype)
6033 IKHelper(this, 1 - target);
6037 if (!skeleton.free && (!animation[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || animation[animTarget].label[frameTarget] == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping()))
6040 targetheadyaw = -targetyaw;
6041 targetheadpitch = 0;
6042 if (animation[animTarget].attack == 3)
6043 targetheadyaw += 180;
6045 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6046 skeleton.drawmodel.vertex[i] = 0;
6047 skeleton.drawmodel.vertex[i].y = 999;
6049 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6050 skeleton.drawmodellow.vertex[i] = 0;
6051 skeleton.drawmodellow.vertex[i].y = 999;
6053 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6054 skeleton.drawmodelclothes.vertex[i] = 0;
6055 skeleton.drawmodelclothes.vertex[i].y = 999;
6057 for (int i = 0; i < skeleton.num_muscles; i++) {
6058 // convenience renames
6059 const int p1 = skeleton.muscles[i].parent1->label;
6060 const int p2 = skeleton.muscles[i].parent2->label;
6062 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6067 if (p1 == righthand || p2 == righthand) {
6068 morphness = righthandmorphness;
6069 start = righthandmorphstart;
6070 endthing = righthandmorphend;
6072 if (p1 == lefthand || p2 == lefthand) {
6073 morphness = lefthandmorphness;
6074 start = lefthandmorphstart;
6075 endthing = lefthandmorphend;
6077 if (p1 == head || p2 == head) {
6078 morphness = headmorphness;
6079 start = headmorphstart;
6080 endthing = headmorphend;
6082 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6083 morphness = chestmorphness;
6084 start = chestmorphstart;
6085 endthing = chestmorphend;
6087 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6088 morphness = tailmorphness;
6089 start = tailmorphstart;
6090 endthing = tailmorphend;
6093 skeleton.FindRotationMuscle(i, animTarget);
6094 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6095 glMatrixMode(GL_MODELVIEW);
6099 glRotatef(tilt2, 1, 0, 0);
6101 glRotatef(tilt, 0, 0, 1);
6104 glTranslatef(mid.x, mid.y, mid.z);
6106 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6107 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6109 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6110 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6112 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6113 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6115 if (playerdetail || skeleton.free == 3) {
6116 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6117 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6118 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6119 glMatrixMode(GL_MODELVIEW);
6121 if (p1 == abdomen || p2 == abdomen)
6122 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6123 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6124 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6125 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6126 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6127 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6128 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6129 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6130 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6131 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6132 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6133 if (p1 == head || p2 == head)
6134 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6135 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6136 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6137 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6138 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6139 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6140 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6144 if (!playerdetail || skeleton.free == 3) {
6145 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6146 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6147 glMatrixMode(GL_MODELVIEW);
6149 if (p1 == abdomen || p2 == abdomen)
6150 glTranslatef(v0.x * proportionbody.x,
6151 v0.y * proportionbody.y,
6152 v0.z * proportionbody.z);
6153 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6154 glTranslatef(v0.x * proportionarms.x,
6155 v0.y * proportionarms.y,
6156 v0.z * proportionarms.z);
6157 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6158 glTranslatef(v0.x * proportionlegs.x,
6159 v0.y * proportionlegs.y,
6160 v0.z * proportionlegs.z);
6161 if (p1 == head || p2 == head)
6162 glTranslatef(v0.x * proportionhead.x,
6163 v0.y * proportionhead.y,
6164 v0.z * proportionhead.z);
6166 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6167 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6168 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6169 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6175 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6176 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6178 glMatrixMode(GL_MODELVIEW);
6182 glRotatef(tilt2, 1, 0, 0);
6184 glRotatef(tilt, 0, 0, 1);
6185 glTranslatef(mid.x, mid.y, mid.z);
6186 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6187 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6189 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6190 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6192 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6193 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6195 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6196 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6197 glMatrixMode(GL_MODELVIEW);
6199 if (p1 == abdomen || p2 == abdomen)
6200 glTranslatef(v0.x * proportionbody.x,
6201 v0.y * proportionbody.y,
6202 v0.z * proportionbody.z);
6203 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6204 glTranslatef(v0.x * proportionarms.x,
6205 v0.y * proportionarms.y,
6206 v0.z * proportionarms.z);
6207 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6208 glTranslatef(v0.x * proportionlegs.x,
6209 v0.y * proportionlegs.y,
6210 v0.z * proportionlegs.z);
6211 if (p1 == head || p2 == head)
6212 glTranslatef(v0.x * proportionhead.x,
6213 v0.y * proportionhead.y,
6214 v0.z * proportionhead.z);
6215 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6216 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6217 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6218 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6223 updatedelay = 1 + (float)(Random() % 100) / 1000;
6225 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6226 normalsupdatedelay = 1;
6227 if (playerdetail || skeleton.free == 3)
6228 skeleton.drawmodel.CalculateNormals(0);
6229 if (!playerdetail || skeleton.free == 3)
6230 skeleton.drawmodellow.CalculateNormals(0);
6231 if (skeleton.clothes)
6232 skeleton.drawmodelclothes.CalculateNormals(0);
6234 if (playerdetail || skeleton.free == 3)
6235 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6236 if (!playerdetail || skeleton.free == 3)
6237 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6238 if (skeleton.clothes) {
6239 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6244 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6245 if (updatedelaychange > -realmultiplier * 30)
6246 updatedelaychange = -realmultiplier * 30;
6247 if (updatedelaychange > -framemult * 4)
6248 updatedelaychange = -framemult * 4;
6249 if (skeleton.free == 1)
6250 updatedelaychange *= 6;
6252 updatedelaychange *= 8;
6253 updatedelay += updatedelaychange;
6255 glMatrixMode(GL_MODELVIEW);
6257 glTranslatef(coords.x, coords.y - .02, coords.z);
6258 if (!skeleton.free) {
6259 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6260 glRotatef(yaw, 0, 1, 0);
6264 glColor4f(.4, 1, .4, 1);
6265 glDisable(GL_LIGHTING);
6266 glDisable(GL_TEXTURE_2D);
6269 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6270 XYZ &v0 = skeleton.drawmodel.vertex[i];
6271 glVertex3f(v0.x, v0.y, v0.z);
6277 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6278 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6279 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6280 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6281 glVertex3f(v0.x, v0.y, v0.z);
6282 glVertex3f(v1.x, v1.y, v1.z);
6283 glVertex3f(v1.x, v1.y, v1.z);
6284 glVertex3f(v2.x, v2.y, v2.z);
6285 glVertex3f(v2.x, v2.y, v2.z);
6286 glVertex3f(v0.x, v0.y, v0.z);
6292 terrainlight = terrain.getLighting(coords.x, coords.z);
6293 distance = distsq(&viewer, &coords);
6294 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6298 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6299 if (terrainheight < 1)
6301 if (terrainheight > 1.7)
6302 terrainheight = 1.7;
6305 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6306 glDisable(GL_BLEND);
6307 glAlphaFunc(GL_GREATER, 0.0001);
6308 glEnable(GL_TEXTURE_2D);
6310 glDisable(GL_TEXTURE_2D);
6311 glColor4f(.7, .35, 0, .5);
6313 glEnable(GL_LIGHTING);
6316 if (tutoriallevel && id != 0) {
6317 glColor4f(.7, .7, .7, 0.6);
6319 glEnable(GL_LIGHTING);
6321 if (canattack && cananger)
6322 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6323 glDisable(GL_TEXTURE_2D);
6324 glColor4f(1, 0, 0, 0.8);
6326 glMatrixMode(GL_TEXTURE);
6328 glTranslatef(0, -smoketex, 0);
6329 glTranslatef(-smoketex, 0, 0);
6333 if ((tutoriallevel && id != 0))
6334 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6336 skeleton.drawmodel.draw();
6339 if (!playerdetail) {
6340 if ((tutoriallevel && id != 0))
6341 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6343 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6346 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6347 if (tutoriallevel && id != 0) {
6349 glMatrixMode(GL_MODELVIEW);
6350 glEnable(GL_TEXTURE_2D);
6351 glColor4f(.7, .7, .7, 0.6);
6353 glEnable(GL_LIGHTING);
6355 if (canattack && cananger)
6356 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6357 glDisable(GL_TEXTURE_2D);
6358 glColor4f(1, 0, 0, 0.8);
6360 glMatrixMode(GL_TEXTURE);
6362 glTranslatef(0, -smoketex * .6, 0);
6363 glTranslatef(smoketex * .6, 0, 0);
6366 if ((tutoriallevel && id != 0))
6367 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6369 skeleton.drawmodel.draw();
6372 if (!playerdetail) {
6373 if ((tutoriallevel && id != 0))
6374 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6376 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6381 if (tutoriallevel && id != 0) {
6383 glMatrixMode(GL_MODELVIEW);
6384 glEnable(GL_TEXTURE_2D);
6386 if (skeleton.clothes) {
6390 skeleton.drawmodelclothes.draw();
6392 skeleton.drawmodelclothes.drawimmediate();
6398 if (num_weapons > 0) {
6399 for (k = 0; k < num_weapons; k++) {
6401 if (weaponactive == k) {
6402 if (weapons[i].getType() != staff) {
6403 for (j = 0; j < skeleton.num_muscles; j++) {
6404 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6405 weaponattachmuscle = j;
6408 for (j = 0; j < skeleton.num_muscles; j++) {
6409 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].numvertices > 0) {
6410 weaponrotatemuscle = j;
6413 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6414 if (creature == wolftype)
6415 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6417 if (weapons[i].getType() == staff) {
6418 for (j = 0; j < skeleton.num_muscles; j++) {
6419 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6420 weaponattachmuscle = j;
6423 for (j = 0; j < skeleton.num_muscles; j++) {
6424 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].numvertices > 0) {
6425 weaponrotatemuscle = j;
6428 //weaponpoint=jointPos(rightwrist);
6429 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6430 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6431 XYZ tempnormthing, vec1, vec2;
6432 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6433 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6434 CrossProduct(&vec1, &vec2, &tempnormthing);
6435 Normalise(&tempnormthing);
6436 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6437 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6440 if (weaponactive != k && weaponstuck != k) {
6441 if (weapons[i].getType() == knife)
6442 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6443 if (weapons[i].getType() == sword)
6444 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6445 if (weapons[i].getType() == staff)
6446 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6447 for (j = 0; j < skeleton.num_muscles; j++) {
6448 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].numvertices > 0) {
6449 weaponrotatemuscle = j;
6453 if (weaponstuck == k) {
6454 if (weaponstuckwhere == 0)
6455 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6457 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6458 for (j = 0; j < skeleton.num_muscles; j++) {
6459 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].numvertices > 0) {
6460 weaponrotatemuscle = j;
6464 if (skeleton.free) {
6465 weapons[i].position = weaponpoint * scale + coords;
6466 weapons[i].bigrotation = 0;
6467 weapons[i].bigtilt = 0;
6468 weapons[i].bigtilt2 = 0;
6470 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;
6471 weapons[i].bigrotation = yaw;
6472 weapons[i].bigtilt = tilt;
6473 weapons[i].bigtilt2 = tilt2;
6475 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6476 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6477 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6478 if (weaponactive == k) {
6479 if (weapons[i].getType() == knife) {
6480 weapons[i].smallrotation = 180;
6481 weapons[i].smallrotation2 = 0;
6482 if (isCrouch() || wasCrouch()) {
6483 weapons[i].smallrotation2 = 20;
6485 if (animTarget == hurtidleanim) {
6486 weapons[i].smallrotation2 = 50;
6488 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6489 XYZ temppoint1, temppoint2;
6492 temppoint1 = jointPos(righthand);
6493 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6494 distance = findDistance(&temppoint1, &temppoint2);
6495 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6496 weapons[i].rotation2 *= 360 / 6.28;
6499 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6500 weapons[i].rotation1 *= 360 / 6.28;
6501 weapons[i].rotation3 = 0;
6502 weapons[i].smallrotation = -90;
6503 weapons[i].smallrotation2 = 0;
6504 if (temppoint1.x > temppoint2.x)
6505 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6507 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6508 XYZ temppoint1, temppoint2;
6511 temppoint1 = jointPos(righthand);
6512 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6513 distance = findDistance(&temppoint1, &temppoint2);
6514 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6515 weapons[i].rotation2 *= 360 / 6.28;
6518 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6519 weapons[i].rotation1 *= 360 / 6.28;
6520 weapons[i].rotation3 = 0;
6521 weapons[i].smallrotation = 90;
6522 weapons[i].smallrotation2 = 0;
6523 if (temppoint1.x > temppoint2.x)
6524 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6526 if (animTarget == knifethrowanim) {
6527 weapons[i].smallrotation = 90;
6528 //weapons[i].smallrotation2=-90;
6529 weapons[i].smallrotation2 = 0;
6530 weapons[i].rotation1 = 0;
6531 weapons[i].rotation2 = 0;
6532 weapons[i].rotation3 = 0;
6534 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6535 weapons[i].smallrotation = -90;
6536 weapons[i].rotation1 = 0;
6537 weapons[i].rotation2 = 0;
6538 weapons[i].rotation3 = 0;
6541 if (weapons[i].getType() == sword) {
6542 weapons[i].smallrotation = 0;
6543 weapons[i].smallrotation2 = 0;
6544 if (animTarget == knifethrowanim) {
6545 weapons[i].smallrotation = -90;
6546 weapons[i].smallrotation2 = 0;
6547 weapons[i].rotation1 = 0;
6548 weapons[i].rotation2 = 0;
6549 weapons[i].rotation3 = 0;
6551 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)) {
6552 XYZ temppoint1, temppoint2;
6555 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6556 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6557 distance = findDistance(&temppoint1, &temppoint2);
6558 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6559 weapons[i].rotation2 *= 360 / 6.28;
6562 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6563 weapons[i].rotation1 *= 360 / 6.28;
6564 weapons[i].rotation3 = 0;
6565 weapons[i].smallrotation = 90;
6566 weapons[i].smallrotation2 = 0;
6567 if (temppoint1.x > temppoint2.x)
6568 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6571 if (weapons[i].getType() == staff) {
6572 weapons[i].smallrotation = 100;
6573 weapons[i].smallrotation2 = 0;
6574 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6575 XYZ temppoint1, temppoint2;
6578 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6579 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6580 distance = findDistance(&temppoint1, &temppoint2);
6581 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6582 weapons[i].rotation2 *= 360 / 6.28;
6585 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6586 weapons[i].rotation1 *= 360 / 6.28;
6587 weapons[i].rotation3 = 0;
6588 weapons[i].smallrotation = 90;
6589 weapons[i].smallrotation2 = 0;
6590 if (temppoint1.x > temppoint2.x)
6591 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6595 if (weaponactive != k && weaponstuck != k) {
6596 if (weapons[i].getType() == knife) {
6597 weapons[i].smallrotation = -70;
6598 weapons[i].smallrotation2 = 10;
6600 if (weapons[i].getType() == sword) {
6601 weapons[i].smallrotation = -100;
6602 weapons[i].smallrotation2 = -8;
6604 if (weapons[i].getType() == staff) {
6605 weapons[i].smallrotation = -100;
6606 weapons[i].smallrotation2 = -8;
6609 if (weaponstuck == k) {
6610 if (weaponstuckwhere == 0)
6611 weapons[i].smallrotation = 180;
6613 weapons[i].smallrotation = 0;
6614 weapons[i].smallrotation2 = 10;
6623 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6625 if (animCurrent != animTarget)
6627 if (skeleton.free == 2)
6636 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6639 static float distance;
6640 static float olddistance;
6641 static int intersecting;
6642 static int firstintersecting;
6645 static XYZ start, end;
6646 static float slopethreshold = -.4;
6648 firstintersecting = -1;
6652 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6655 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6656 for (i = 0; i < 4; i++) {
6657 for (j = 0; j < model->TriangleNum; j++) {
6658 if (model->facenormals[j].y <= slopethreshold) {
6660 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)));
6661 if (distance < radius) {
6662 point = *p1 - model->facenormals[j] * distance;
6663 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]]))
6666 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6667 &model->vertex[model->Triangles[j].vertex[1]],
6670 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6671 &model->vertex[model->Triangles[j].vertex[2]],
6674 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6675 &model->vertex[model->Triangles[j].vertex[2]],
6678 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6682 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)) {
6683 p1->y = point.y + radius;
6684 if ((animTarget == jumpdownanim || isFlip())) {
6685 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6688 if (animTarget == jumpupanim) {
6690 animTarget = getIdle();
6697 pause_sound(whooshsound);
6698 OPENAL_SetVolume(channels[whooshsound], 0);
6701 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6704 animTarget = getLanding();
6705 emit_sound_at(landsound, coords, 128.);
6708 envsound[numenvsounds] = coords;
6709 envsoundvol[numenvsounds] = 16;
6710 envsoundlife[numenvsounds] = .4;
6718 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6719 olddistance = distance;
6720 firstintersecting = j;
6725 for (j = 0; j < model->TriangleNum; j++) {
6726 if (model->facenormals[j].y > slopethreshold) {
6729 start.y -= radius / 4;
6730 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6731 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6732 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6733 distance = abs((model->facenormals[j].x * start.x)
6734 + (model->facenormals[j].y * start.y)
6735 + (model->facenormals[j].z * start.z)
6736 - ((model->facenormals[j].x * v0.x)
6737 + (model->facenormals[j].y * v0.y)
6738 + (model->facenormals[j].z * v0.z)));
6739 if (distance < radius * .5) {
6740 point = start - model->facenormals[j] * distance;
6741 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6744 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6746 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6748 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6750 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6751 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6753 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6754 if (findLengthfast(&start) < findLengthfast(&velocity))
6757 *p1 += model->facenormals[j] * (distance - radius * .5);
6760 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6761 olddistance = distance;
6762 firstintersecting = j;
6769 *p = DoRotation(*p, 0, *rotate, 0);
6772 *p1 = DoRotation(*p1, 0, *rotate, 0);
6774 return firstintersecting;
6777 void Person::takeWeapon(int weaponId)
6780 weapons[weaponId].owner = id;
6781 if (num_weapons > 0) {
6782 weaponids[num_weapons] = weaponids[0];
6785 weaponids[0] = weaponId;
6788 void Person::addClothes()
6790 if (numclothes > 0) {
6791 for (int i = 0; i < numclothes; i++) {
6798 bool Person::addClothes(const int& clothesId)
6801 const char* fileName = clothes[clothesId];
6803 GLubyte* array = &skeleton.skinText[0];
6807 bool opened = load_image(fileName, texture);
6812 float tintr = clothestintr[clothesId];
6813 float tintg = clothestintg[clothesId];
6814 float tintb = clothestintb[clothesId];
6816 if (tintr > 1) tintr = 1;
6817 if (tintg > 1) tintg = 1;
6818 if (tintb > 1) tintb = 1;
6820 if (tintr < 0) tintr = 0;
6821 if (tintg < 0) tintg = 0;
6822 if (tintb < 0) tintb = 0;
6824 int bytesPerPixel = texture.bpp / 8;
6828 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6829 if (bytesPerPixel == 3)
6831 else if ((i + 1) % 4 == 0)
6832 alphanum = texture.data[i];
6833 if ((i + 1) % 4 || bytesPerPixel == 3) {
6835 texture.data[i] *= tintr;
6837 texture.data[i] *= tintg;
6839 texture.data[i] *= tintb;
6840 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);