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"
30 extern float multiplier;
31 extern Terrain terrain;
33 extern int environment;
35 extern FRUSTUM frustum;
37 extern float realmultiplier;
39 extern float slomodelay;
40 extern bool cellophane;
41 extern float texdetail;
42 extern float realtexdetail;
43 extern GLubyte bloodText[512 * 512 * 3];
44 extern GLubyte wolfbloodText[512 * 512 * 3];
45 extern int bloodtoggle;
46 extern Objects objects;
47 extern bool autoslomo;
48 extern float camerashake;
50 extern float viewdistance;
51 extern float blackout;
52 extern int difficulty;
54 extern float fadestart;
56 extern bool winfreeze;
57 extern bool showpoints;
58 extern bool immediate;
59 extern int tutoriallevel;
60 extern float smoketex;
61 extern int tutorialstage;
62 extern bool reversaltrain;
63 extern bool canattack;
65 extern float damagedealt;
67 extern float hostiletime;
69 extern bool gamestarted;
71 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
84 howactive(typeactive),
86 superruntoggle(false),
87 lastattack(0), lastattack2(0), lastattack3(0),
88 currentoffset(), targetoffset(), offset(),
120 rabbitkickenabled(false),
132 superpermanentdamage(0),
146 bleedx(0), bleedy(0),
150 headyaw(0), headpitch(0),
151 targetheadyaw(0), targetheadpitch(0),
162 normalsupdatedelay(0),
165 forwardkeydown(false),
166 forwardstogglekeydown(false),
171 jumptogglekeydown(false),
172 crouchkeydown(false),
173 crouchtogglekeydown(false),
175 drawtogglekeydown(false),
177 throwtogglekeydown(false),
178 attackkeydown(false),
183 crouchkeydowntime(0),
197 whichdirection(false),
198 whichdirectiondelay(0),
199 avoidsomething(false),
208 lefthandmorphness(0),
209 righthandmorphness(0),
213 targetlefthandmorphness(0),
214 targetrighthandmorphness(0),
215 targetheadmorphness(0),
216 targetchestmorphness(0),
217 targettailmorphness(0),
218 lefthandmorphstart(0), lefthandmorphend(0),
219 righthandmorphstart(0), righthandmorphend(0),
220 headmorphstart(0), headmorphend(0),
221 chestmorphstart(0), chestmorphend(0),
222 tailmorphstart(0), tailmorphend(0),
225 highreversaldelay(0),
228 creature(rabbittype),
275 finalpathfindpoint(0),
276 targetpathfindpoint(0),
277 lastpathfindpoint(0),
278 lastpathfindpoint2(0),
279 lastpathfindpoint3(0),
280 lastpathfindpoint4(0),
297 neckspurtparticledelay(0),
301 rabbitkickragdoll(false),
309 /* Read a person in tfile. Throws an error if it’s not valid */
310 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
313 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
315 funpackf(tfile, "Bi", &howactive);
317 howactive = typeactive;
320 funpackf(tfile, "Bf", &scale);
325 funpackf(tfile, "Bb", &immobile);
330 funpackf(tfile, "Bf", &yaw);
335 if (num_weapons < 0 || num_weapons > 5) {
336 throw InvalidPersonException();
338 if (num_weapons > 0 && num_weapons < 5) {
339 for (int j = 0; j < num_weapons; j++) {
340 weaponids[j] = weapons.size();
342 funpackf(tfile, "Bi", &type);
343 weapons.push_back(Weapon(type, id));
346 funpackf(tfile, "Bi", &numwaypoints);
347 for (int j = 0; j < numwaypoints; j++) {
348 funpackf(tfile, "Bf", &waypoints[j].x);
349 funpackf(tfile, "Bf", &waypoints[j].y);
350 funpackf(tfile, "Bf", &waypoints[j].z);
352 funpackf(tfile, "Bi", &waypointtype[j]);
354 waypointtype[j] = wpkeepwalking;
358 funpackf(tfile, "Bi", &waypoint);
359 if (waypoint > (numwaypoints - 1)) {
363 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
364 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
365 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
366 funpackf(tfile, "Bf Bf", &power, &speedmult);
368 float headprop, legprop, armprop, bodyprop;
371 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
379 if (creature == wolftype) {
380 proportionhead = 1.1 * headprop;
381 proportionbody = 1.1 * bodyprop;
382 proportionarms = 1.1 * armprop;
383 proportionlegs = 1.1 * legprop;
384 } else if (creature == rabbittype) {
385 proportionhead = 1.2 * headprop;
386 proportionbody = 1.05 * bodyprop;
387 proportionarms = 1.00 * armprop;
388 proportionlegs = 1.1 * legprop;
389 proportionlegs.y = 1.05 * legprop;
392 funpackf(tfile, "Bi", &numclothes);
393 for (int k = 0; k < numclothes; k++) {
395 funpackf(tfile, "Bi", &templength);
396 for (int l = 0; l < templength; l++)
397 funpackf(tfile, "Bb", &clothes[k][l]);
398 clothes[k][templength] = '\0';
399 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
406 * GameTick/doPlayerCollisions
408 void Person::CheckKick()
411 && (animTarget == rabbitkickanim
413 && victim != this->shared_from_this()
415 && animCurrent == rabbitkickanim)
416 && distsq(&coords, &victim->coords) < 1.2
417 && !victim->skeleton.free))
420 if (animation[victim->animTarget].height != lowheight) {
421 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
422 XYZ relative = velocity;
424 Normalise(&relative);
428 if (tutoriallevel != 1)
429 emit_sound_at(heavyimpactsound, victim->coords);
431 for (int i = 0; i < victim->skeleton.num_joints; i++) {
432 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
435 victim->DoDamage(100 * damagemult / victim->protectionhigh);
441 animTarget = backflipanim;
443 velocity = facing * -10;
447 resume_stream(whooshsound);
449 award_bonus(id, cannon);
450 } else if (victim->isCrouch()) {
451 animTarget = rabbitkickreversedanim;
452 animCurrent = rabbitkickreversedanim;
453 victim->animCurrent = rabbitkickreversalanim;
454 victim->animTarget = rabbitkickreversalanim;
460 victim->oldcoords = victim->coords;
461 coords = victim->coords;
462 victim->targetyaw = targetyaw;
463 victim->victim = this->shared_from_this();
470 * GameTick/doPlayerCollisions - spread fire between players
471 * GameTick/doDebugKeys - press f to ignite
472 * Person::DoStuff - spread fire from lit campfires and bushes
474 void Person::CatchFire()
476 XYZ flatfacing, flatvelocity;
478 for (int i = 0; i < 10; i++) {
479 howmany = abs(Random() % (skeleton.num_joints));
481 flatvelocity = skeleton.joints[howmany].velocity;
482 flatfacing = skeleton.joints[howmany].position * scale + coords;
484 flatvelocity = velocity;
485 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
487 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
492 emit_sound_at(firestartsound, coords);
494 emit_stream_at(stream_firesound, coords);
502 * idle animation for this creature (depending on status)
504 int Person::getIdle()
506 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
508 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
509 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
510 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
511 victim->id < Person::players.size())) {
512 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
513 if (creature == rabbittype)
514 return fightidleanim;
515 if (creature == wolftype)
518 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
519 if (weapons[weaponids[weaponactive]].getType() == knife)
520 return knifefightidleanim;
521 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
522 return swordfightidlebothanim;
523 if (weapons[weaponids[weaponactive]].getType() == sword)
524 return swordfightidleanim;
525 if (weapons[weaponids[weaponactive]].getType() == staff)
526 return swordfightidleanim;
528 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
529 return fightsidestep;
531 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
533 if (howactive == typesitting) return sitanim;
534 if (howactive == typesittingwall) return sitwallanim;
535 if (howactive == typesleeping) return sleepanim;
536 if (howactive == typedead1) return dead1anim;
537 if (howactive == typedead2) return dead2anim;
538 if (howactive == typedead3) return dead3anim;
539 if (howactive == typedead4) return dead4anim;
540 if (creature == rabbittype) return bounceidleanim;
541 if (creature == wolftype) return wolfidle;
546 * crouch animation for this creature
548 int Person::getCrouch()
550 if (creature == rabbittype)
552 if (creature == wolftype)
553 return wolfcrouchanim;
558 * running animation for this creature (can be upright or all fours)
562 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
564 if (creature == wolftype && (!superruntoggle))
567 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
568 return rabbitrunninganim;
569 if (creature == wolftype && (superruntoggle))
570 return wolfrunninganim;
576 int Person::getStop()
578 if (creature == rabbittype)
580 if (creature == wolftype)
587 int Person::getLanding()
589 if (creature == rabbittype)
591 if (creature == wolftype)
598 int Person::getLandhard()
600 if (creature == rabbittype)
602 if (creature == wolftype)
603 return wolflandhardanim;
610 * Person::DoAnimations
613 SolidHitBonus(int playerid)
615 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
616 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
618 award_bonus(playerid, solidhit);
622 * spawns blood effects
624 void Person::DoBlood(float howmuch, int which)
626 // FIXME: should abstract out inputs
627 static int bleedxint, bleedyint;
629 if (bloodtoggle && tutoriallevel != 1) {
630 if (bleeding <= 0 && spurt) {
632 for (int i = 0; i < 3; i++) {
633 // emit blood particles
636 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
637 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
638 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
639 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
642 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
643 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
644 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
645 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
648 if (Random() % 2 == 0) // 50% chance
649 for (int i = 0; i < 3; i++) {
650 if (Random() % 2 != 0) {
651 // emit teeth particles
654 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
655 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
658 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
659 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
663 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
665 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
667 Sprite::setLastSpriteSpecial(3); // sets it to teeth
672 // FIXME: manipulating attributes
673 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
676 if (creature == rabbittype)
677 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) {
678 bleedxint = abs(Random() % 512);
679 bleedyint = abs(Random() % 512);
681 if (creature == wolftype)
682 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) {
683 bleedxint = abs(Random() % 512);
684 bleedyint = abs(Random() % 512);
688 bleedy /= realtexdetail;
689 bleedx /= realtexdetail;
690 direction = abs(Random() % 2) * 2 - 1;
699 * spawns big blood effects and ???
700 * modifies character's skin texture
702 void Person::DoBloodBig(float howmuch, int which)
704 static int bleedxint, bleedyint, i, j;
706 if (howmuch && id == 0)
709 if (tutoriallevel != 1 || id == 0)
710 if (aitype != playercontrolled && howmuch > 0) {
714 if (creature == wolftype) {
715 int i = abs(Random() % 2);
717 whichsound = snarlsound;
719 whichsound = snarl2sound;
721 if (creature == rabbittype) {
722 int i = abs(Random() % 2);
724 whichsound = rabbitpainsound;
725 if (i == 1 && howmuch >= 2)
726 whichsound = rabbitpain1sound;
729 if (whichsound != -1) {
730 emit_sound_at(whichsound, coords);
735 if (id == 0 && howmuch > 0) {
739 if (bloodtoggle && decals && tutoriallevel != 1) {
740 if (bleeding <= 0 && spurt) {
742 for (int i = 0; i < 3; i++) {
743 // emit blood particles
744 // FIXME: copypaste from above
747 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
748 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
749 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
750 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
753 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
754 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
755 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
756 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
761 // weird texture manipulation code follows.
762 // looks like this is painting blood onto the character's skin texture
763 // FIXME: surely there's a better way
765 int offsetx = 0, offsety = 0;
767 offsety = Random() % 40;
768 offsetx = abs(Random() % 60);
770 if (which == 190 || which == 185) {
771 offsety = Random() % 40;
772 offsetx = abs(Random() % 100) - 20;
775 offsety = Random() % 10;
776 offsetx = Random() % 10;
779 offsety = Random() % 20;
780 offsetx = Random() % 20;
782 if (which == 220 || which == 215) {
792 if (creature == rabbittype)
793 for (i = 0; i < 512; i++) {
794 for (j = 0; j < 512; j++) {
795 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
796 if (i < startx) startx = i;
797 if (j < starty) starty = j;
798 if (i > endx) endx = i;
799 if (j > endy) endy = j;
803 if (creature == wolftype)
804 for (i = 0; i < 512; i++) {
805 for (j = 0; j < 512; j++) {
806 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
807 if (i < startx) startx = i;
808 if (j < starty) starty = j;
809 if (i > endx) endx = i;
810 if (j > endy) endy = j;
820 if (startx < 0) startx = 0;
821 if (starty < 0) starty = 0;
822 if (endx > 512 - 1) endx = 512 - 1;
823 if (endy > 512 - 1) endy = 512 - 1;
824 if (endx < startx) endx = startx;
825 if (endy < starty) endy = starty;
827 startx /= realtexdetail;
828 starty /= realtexdetail;
829 endx /= realtexdetail;
830 endy /= realtexdetail;
832 int texdetailint = realtexdetail;
834 if (creature == rabbittype)
835 for (i = startx; i < endx; i++) {
836 for (j = starty; j < endy; j++) {
837 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) {
838 color = Random() % 85 + 170;
839 where = i * skeleton.skinsize * 3 + j * 3;
840 if (skeleton.skinText[where + 0] > color / 2)
841 skeleton.skinText[where + 0] = color / 2;
842 skeleton.skinText[where + 1] = 0;
843 skeleton.skinText[where + 2] = 0;
847 if (creature == wolftype)
848 for (i = startx; i < endx; i++) {
849 for (j = starty; j < endy; j++) {
850 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) {
851 color = Random() % 85 + 170;
852 where = i * skeleton.skinsize * 3 + j * 3;
853 if (skeleton.skinText[where + 0] > color / 2)
854 skeleton.skinText[where + 0] = color / 2;
855 skeleton.skinText[where + 1] = 0;
856 skeleton.skinText[where + 2] = 0;
860 skeleton.drawmodel.textureptr.bind();
865 if (creature == rabbittype)
866 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) {
867 bleedxint = abs(Random() % 512);
868 bleedyint = abs(Random() % 512);
870 if (creature == wolftype)
871 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) {
872 bleedxint = abs(Random() % 512);
873 bleedyint = abs(Random() % 512);
875 bleedy = bleedxint + offsetx;
876 bleedx = bleedyint + offsety;
877 bleedy /= realtexdetail;
878 bleedx /= realtexdetail;
883 if (bleedx > skeleton.skinsize - 1)
884 bleedx = skeleton.skinsize - 1;
885 if (bleedy > skeleton.skinsize - 1)
886 bleedy = skeleton.skinsize - 1;
887 direction = abs(Random() % 2) * 2 - 1;
890 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
891 deathbleeding += bleeding;
892 bloodloss += bleeding * 3;
894 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
895 if (abs(Random() % 2) == 0) {
896 aitype = gethelptype;
899 aitype = attacktypecutoff;
907 * similar to DoBloodBig
909 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
913 static XYZ startpoint, endpoint, colpoint, movepoint;
914 static float rotationpoint;
916 static XYZ p1, p2, p3, p0;
919 float coordsx, coordsy;
922 if (bloodtoggle && decals && tutoriallevel != 1) {
925 where = DoRotation(where, 0, -yaw, 0);
933 // ray testing for a tri in the character model
934 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
935 if (whichtri != -1) {
936 // low level geometry math
938 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
939 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
940 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
942 bary.x = distsq(&p0, &p1);
943 bary.y = distsq(&p0, &p2);
944 bary.z = distsq(&p0, &p3);
946 total = bary.x + bary.y + bary.z;
955 total = bary.x + bary.y + bary.z;
961 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
962 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
963 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
964 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
965 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
966 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
967 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;
968 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;
970 if (bleeding <= 0 && spurt) {
972 for (int i = 0; i < 3; i++) {
973 // emit blood particles
974 // FIXME: more copypaste code
977 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
978 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
979 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
980 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
983 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
984 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
985 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
986 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
991 // texture manipulation follows
993 int offsetx = 0, offsety = 0;
994 offsetx = (1 + coordsy) * 512 - 291;
995 offsety = coordsx * 512 - 437;
1002 if (creature == rabbittype)
1003 for (i = 0; i < 512; i++) {
1004 for (j = 0; j < 512; j++) {
1005 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1006 if (i < startx) startx = i;
1007 if (j < starty) starty = j;
1008 if (i > endx) endx = i;
1009 if (j > endy) endy = j;
1013 if (creature == wolftype)
1014 for (i = 0; i < 512; i++) {
1015 for (j = 0; j < 512; j++) {
1016 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1017 if (i < startx) startx = i;
1018 if (j < starty) starty = j;
1019 if (i > endx) endx = i;
1020 if (j > endy) endy = j;
1029 if (startx < 0) startx = 0;
1030 if (starty < 0) starty = 0;
1031 if (endx > 512 - 1) endx = 512 - 1;
1032 if (endy > 512 - 1) endy = 512 - 1;
1033 if (endx < startx) endx = startx;
1034 if (endy < starty) endy = starty;
1036 startx /= realtexdetail;
1037 starty /= realtexdetail;
1038 endx /= realtexdetail;
1039 endy /= realtexdetail;
1041 int texdetailint = realtexdetail;
1043 if (creature == rabbittype)
1044 for (i = startx; i < endx; i++) {
1045 for (j = starty; j < endy; j++) {
1046 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) {
1047 color = Random() % 85 + 170;
1048 where = i * skeleton.skinsize * 3 + j * 3;
1049 if (skeleton.skinText[where + 0] > color / 2)
1050 skeleton.skinText[where + 0] = color / 2;
1051 skeleton.skinText[where + 1] = 0;
1052 skeleton.skinText[where + 2] = 0;
1053 } 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) {
1054 color = Random() % 85 + 170;
1055 where = i * skeleton.skinsize * 3 + j * 3;
1056 if (skeleton.skinText[where + 0] > color / 2)
1057 skeleton.skinText[where + 0] = color / 2;
1058 skeleton.skinText[where + 1] = 0;
1059 skeleton.skinText[where + 2] = 0;
1063 if (creature == wolftype)
1064 for (i = startx; i < endx; i++) {
1065 for (j = starty; j < endy; j++) {
1066 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) {
1067 color = Random() % 85 + 170;
1068 where = i * skeleton.skinsize * 3 + j * 3;
1069 if (skeleton.skinText[where + 0] > color / 2)
1070 skeleton.skinText[where + 0] = color / 2;
1071 skeleton.skinText[where + 1] = 0;
1072 skeleton.skinText[where + 2] = 0;
1073 } 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) {
1074 color = Random() % 85 + 170;
1075 where = i * skeleton.skinsize * 3 + j * 3;
1076 if (skeleton.skinText[where + 0] > color / 2)
1077 skeleton.skinText[where + 0] = color / 2;
1078 skeleton.skinText[where + 1] = 0;
1079 skeleton.skinText[where + 2] = 0;
1083 skeleton.drawmodel.textureptr.bind();
1086 bleedy = (1 + coordsy) * 512;
1087 bleedx = coordsx * 512;
1088 bleedy /= realtexdetail;
1089 bleedx /= realtexdetail;
1094 if (bleedx > skeleton.skinsize - 1)
1095 bleedx = skeleton.skinsize - 1;
1096 if (bleedy > skeleton.skinsize - 1)
1097 bleedy = skeleton.skinsize - 1;
1098 direction = abs(Random() % 2) * 2 - 1;
1103 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1104 deathbleeding += bleeding;
1105 bloodloss += bleeding * 3;
1107 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1108 if (abs(Random() % 2) == 0) {
1109 aitype = gethelptype;
1112 aitype = attacktypecutoff;
1123 * guessing this performs a reversal
1125 void Person::Reverse()
1127 if (!((victim->aitype == playercontrolled
1129 || staggerdelay <= 0)
1130 && victim->animTarget != jumpupanim
1131 && victim->animTarget != jumpdownanim
1132 && (tutoriallevel != 1 || cananger)
1136 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1137 && (victim->id != 0 || difficulty >= 2)
1138 && (creature != wolftype || victim->creature == wolftype))
1141 if (animTarget == sweepanim) {
1142 animTarget = sweepreversedanim;
1143 animCurrent = sweepreversedanim;
1144 victim->animCurrent = sweepreversalanim;
1145 victim->animTarget = sweepreversalanim;
1147 if (animTarget == spinkickanim) {
1148 animTarget = spinkickreversedanim;
1149 animCurrent = spinkickreversedanim;
1150 victim->animCurrent = spinkickreversalanim;
1151 victim->animTarget = spinkickreversalanim;
1153 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1154 if (animTarget == rabbittacklinganim) {
1157 victim->frameCurrent = 6;
1158 victim->frameTarget = 7;
1160 animTarget = upunchreversedanim;
1161 animCurrent = upunchreversedanim;
1162 victim->animCurrent = upunchreversalanim;
1163 victim->animTarget = upunchreversalanim;
1165 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1166 if (victim->weaponactive != -1) {
1167 victim->throwtogglekeydown = 1;
1168 XYZ tempVelocity = victim->velocity * .2;
1169 if (tempVelocity.x == 0)
1170 tempVelocity.x = .1;
1171 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1172 victim->num_weapons--;
1173 if (victim->num_weapons) {
1174 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1175 if (victim->weaponstuck == victim->num_weapons)
1176 victim->weaponstuck = 0;
1179 victim->weaponactive = -1;
1180 for (unsigned j = 0; j < Person::players.size(); j++) {
1181 Person::players[j]->wentforweapon = 0;
1185 animTarget = staffhitreversedanim;
1186 animCurrent = staffhitreversedanim;
1187 victim->animCurrent = staffhitreversalanim;
1188 victim->animTarget = staffhitreversalanim;
1190 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1191 if (victim->weaponactive != -1) {
1192 victim->throwtogglekeydown = 1;
1193 XYZ tempVelocity = victim->velocity * .2;
1194 if (tempVelocity.x == 0)
1195 tempVelocity.x = .1;
1196 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1197 victim->num_weapons--;
1198 if (victim->num_weapons) {
1199 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1200 if (victim->weaponstuck == victim->num_weapons)
1201 victim->weaponstuck = 0;
1204 victim->weaponactive = -1;
1205 for (unsigned j = 0; j < Person::players.size(); j++) {
1206 Person::players[j]->wentforweapon = 0;
1209 animTarget = staffspinhitreversedanim;
1210 animCurrent = staffspinhitreversedanim;
1211 victim->animCurrent = staffspinhitreversalanim;
1212 victim->animTarget = staffspinhitreversalanim;
1214 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1215 if (victim->weaponactive != -1) {
1216 victim->throwtogglekeydown = 1;
1217 XYZ tempVelocity = victim->velocity * .2;
1218 if (tempVelocity.x == 0)
1219 tempVelocity.x = .1;
1220 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1221 victim->num_weapons--;
1222 if (victim->num_weapons) {
1223 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1224 if (victim->weaponstuck == victim->num_weapons)
1225 victim->weaponstuck = 0;
1228 victim->weaponactive = -1;
1229 for (unsigned j = 0; j < Person::players.size(); j++) {
1230 Person::players[j]->wentforweapon = 0;
1233 animTarget = swordslashreversedanim;
1234 animCurrent = swordslashreversedanim;
1235 victim->animCurrent = swordslashreversalanim;
1236 victim->animTarget = swordslashreversalanim;
1238 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1239 if (victim->weaponactive != -1) {
1240 victim->throwtogglekeydown = 1;
1241 XYZ tempVelocity = victim->velocity * .2;
1242 if (tempVelocity.x == 0)
1243 tempVelocity.x = .1;
1244 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1245 victim->num_weapons--;
1246 if (victim->num_weapons) {
1247 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1248 if (victim->weaponstuck == victim->num_weapons)
1249 victim->weaponstuck = 0;
1252 victim->weaponactive = -1;
1253 for (unsigned j = 0; j < Person::players.size(); j++) {
1254 Person::players[j]->wentforweapon = 0;
1257 animTarget = knifeslashreversedanim;
1258 animCurrent = knifeslashreversedanim;
1259 victim->animCurrent = knifeslashreversalanim;
1260 victim->animTarget = knifeslashreversalanim;
1262 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1263 victim->targettilt2 = targettilt2;
1264 victim->frameCurrent = frameCurrent;
1265 victim->frameTarget = frameTarget;
1266 victim->target = target;
1267 victim->velocity = 0;
1268 victim->oldcoords = victim->coords;
1269 victim->coords = coords;
1270 victim->targetyaw = targetyaw;
1271 victim->yaw = targetyaw;
1272 victim->victim = this->shared_from_this();
1274 if (animTarget == winduppunchanim) {
1275 animTarget = winduppunchblockedanim;
1276 victim->animTarget = blockhighleftanim;
1277 victim->frameTarget = 1;
1278 victim->target = .5;
1279 victim->victim = this->shared_from_this();
1280 victim->targetyaw = targetyaw + 180;
1282 if (animTarget == wolfslapanim) {
1283 animTarget = winduppunchblockedanim;
1284 victim->animTarget = blockhighleftanim;
1285 victim->frameTarget = 1;
1286 victim->target = .5;
1287 victim->victim = this->shared_from_this();
1288 victim->targetyaw = targetyaw + 180;
1290 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1291 animTarget = swordslashparriedanim;
1292 parriedrecently = .4;
1293 victim->parriedrecently = 0;
1294 victim->animTarget = swordslashparryanim;
1295 victim->frameTarget = 1;
1296 victim->target = .5;
1297 victim->victim = this->shared_from_this();
1298 victim->targetyaw = targetyaw + 180;
1300 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1301 if (victim->weaponactive != -1) {
1302 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1303 if (weapons[victim->weaponids[0]].getType() == staff)
1304 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1305 if (weapons[weaponids[0]].getType() == staff)
1306 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1307 emit_sound_at(swordstaffsound, victim->coords);
1309 emit_sound_at(metalhitsound, victim->coords);
1313 victim->Puff(righthand);
1315 victim->frameTarget = 0;
1316 victim->animTarget = staggerbackhighanim;
1317 victim->targetyaw = targetyaw + 180;
1319 aim = DoRotation(facing, 0, 90, 0) * 21;
1321 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1322 victim->num_weapons--;
1323 if (victim->num_weapons) {
1324 victim->weaponids[0] = victim->weaponids[num_weapons];
1325 if (victim->weaponstuck == victim->num_weapons)
1326 victim->weaponstuck = 0;
1328 victim->weaponactive = -1;
1329 for (unsigned i = 0; i < Person::players.size(); i++) {
1330 Person::players[i]->wentforweapon = 0;
1334 if (abs(Random() % 20) == 0) {
1335 if (weaponactive != -1) {
1336 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1337 if (weapons[victim->weaponids[0]].getType() == staff)
1338 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1339 if (weapons[weaponids[0]].getType() == staff)
1340 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1342 emit_sound_at(swordstaffsound, coords);
1344 emit_sound_at(metalhitsound, coords);
1352 animTarget = staggerbackhighanim;
1353 targetyaw = targetyaw + 180;
1355 aim = DoRotation(facing, 0, 90, 0) * 21;
1357 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1360 weaponids[0] = weaponids[num_weapons];
1361 if (weaponstuck == num_weapons)
1365 for (unsigned i = 0; i < Person::players.size(); i++) {
1366 Person::players[i]->wentforweapon = 0;
1373 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1374 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1375 victim->animTarget = dodgebackanim;
1376 victim->frameTarget = 0;
1380 rotatetarget = coords - victim->coords;
1381 Normalise(&rotatetarget);
1382 victim->targetyaw = -asin(0 - rotatetarget.x);
1383 victim->targetyaw *= 360 / 6.28;
1384 if (rotatetarget.z < 0)
1385 victim->targetyaw = 180 - victim->targetyaw;
1387 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1389 victim->lastattack3 = victim->lastattack2;
1390 victim->lastattack2 = victim->lastattack;
1391 victim->lastattack = victim->animTarget;
1393 victim->animTarget = sweepanim;
1394 victim->frameTarget = 0;
1398 rotatetarget = coords - victim->coords;
1399 Normalise(&rotatetarget);
1400 victim->targetyaw = -asin(0 - rotatetarget.x);
1401 victim->targetyaw *= 360 / 6.28;
1402 if (rotatetarget.z < 0)
1403 victim->targetyaw = 180 - victim->targetyaw;
1405 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1407 victim->lastattack3 = victim->lastattack2;
1408 victim->lastattack2 = victim->lastattack;
1409 victim->lastattack = victim->animTarget;
1414 victim->velocity = 0;
1416 if (aitype != playercontrolled)
1418 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1420 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1422 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1425 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1432 void Person::DoDamage(float howmuch)
1434 // subtract health (temporary?)
1435 if (tutoriallevel != 1)
1436 damage += howmuch / power;
1439 damagedealt += howmuch / power;
1441 damagetaken += howmuch / power;
1444 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1447 if (tutoriallevel != 1)
1448 permanentdamage += howmuch / 2 / power;
1449 if (tutoriallevel != 1)
1450 superpermanentdamage += howmuch / 4 / power;
1452 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1454 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1458 camerashake += howmuch / 100;
1459 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1460 blackout = damage / damagetolerance;
1465 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1466 aitype = attacktypecutoff;
1467 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1468 if (abs(Random() % 2) == 0) {
1469 aitype = gethelptype;
1472 aitype = attacktypecutoff;
1476 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1479 for (int i = 0; i < skeleton.num_joints; i++) {
1480 if (skeleton.free) {
1481 flatvelocity2 = skeleton.joints[i].velocity;
1482 flatfacing2 = skeleton.joints[i].position * scale + coords;
1484 flatvelocity2 = velocity;
1485 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1487 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1488 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1489 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1490 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1491 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1492 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1495 emit_sound_at(splattersound, coords);
1500 if (!dead && creature == wolftype) {
1501 award_bonus(0, Wolfbonus);
1508 if (tutoriallevel != 1 || id == 0)
1509 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1510 int whichsound = -1;
1512 if (creature == wolftype) {
1513 int i = abs(Random() % 2);
1515 whichsound = snarlsound;
1517 whichsound = snarl2sound;
1519 if (creature == rabbittype) {
1520 int i = abs(Random() % 2);
1522 whichsound = rabbitpainsound;
1523 if (i == 1 && damage > damagetolerance)
1524 whichsound = rabbitpain1sound;
1527 if (whichsound != -1) {
1528 emit_sound_at(whichsound, coords);
1529 addEnvSound(coords);
1536 * calculate/animate head facing direction?
1538 void Person::DoHead()
1540 static XYZ rotatearound;
1542 static float lookspeed = 500;
1544 if (!freeze && !winfreeze) {
1547 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1548 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1550 while (targetheadyaw > 180)targetheadyaw -= 360;
1551 while (targetheadyaw < -180)targetheadyaw += 360;
1553 if (targetheadyaw > 160)
1554 targetheadpitch = targetheadpitch * -1;
1555 if (targetheadyaw < -160)
1556 targetheadpitch = targetheadpitch * -1;
1557 if (targetheadyaw > 160)
1558 targetheadyaw = targetheadyaw - 180;
1559 if (targetheadyaw < -160)
1560 targetheadyaw = targetheadyaw + 180;
1562 if (targetheadpitch > 120)
1563 targetheadpitch = 120;
1564 if (targetheadpitch < -120)
1565 targetheadpitch = -120;
1566 if (targetheadyaw > 120)
1567 targetheadyaw = 120;
1568 if (targetheadyaw < -120)
1569 targetheadyaw = -120;
1572 targetheadpitch = 0;
1574 if (targetheadyaw > 80)
1576 if (targetheadyaw < -80)
1577 targetheadyaw = -80;
1578 if (targetheadpitch > 50)
1579 targetheadpitch = 50;
1580 if (targetheadpitch < -50)
1581 targetheadpitch = -50;
1584 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1585 headyaw = targetheadyaw;
1586 else if (headyaw > targetheadyaw) {
1587 headyaw -= multiplier * lookspeed;
1588 } else if (headyaw < targetheadyaw) {
1589 headyaw += multiplier * lookspeed;
1592 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1593 headpitch = targetheadpitch;
1594 else if (headpitch > targetheadpitch) {
1595 headpitch -= multiplier * lookspeed / 2;
1596 } else if (headpitch < targetheadpitch) {
1597 headpitch += multiplier * lookspeed / 2;
1600 rotatearound = jointPos(neck);
1601 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1605 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1606 facing = DoRotation(facing, headpitch * .4, 0, 0);
1607 facing = DoRotation(facing, 0, headyaw * .4, 0);
1610 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1611 facing = DoRotation(facing, headpitch * .8, 0, 0);
1612 facing = DoRotation(facing, 0, headyaw * .8, 0);
1615 if (animTarget == walkanim) {
1616 facing = DoRotation(facing, headpitch * .6, 0, 0);
1617 facing = DoRotation(facing, 0, headyaw * .6, 0);
1620 skeleton.specialforward[0] = facing;
1621 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1622 for (int i = 0; i < skeleton.num_muscles; i++) {
1623 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1624 skeleton.FindRotationMuscle(i, animTarget);
1631 * ragdolls character?
1633 void Person::RagDoll(bool checkcollision)
1638 if (!skeleton.free) {
1641 if (id == 0 && isFlip())
1648 facing = DoRotation(facing, 0, yaw, 0);
1650 skeleton.freetime = 0;
1652 skeleton.longdead = 0;
1655 skeleton.broken = 0;
1656 skeleton.spinny = 1;
1658 skeleton.freefall = 1;
1660 if (!isnormal(velocity.x)) velocity.x = 0;
1661 if (!isnormal(velocity.y)) velocity.y = 0;
1662 if (!isnormal(velocity.z)) velocity.z = 0;
1663 if (!isnormal(yaw)) yaw = 0;
1664 if (!isnormal(coords.x)) coords = 0;
1665 if (!isnormal(tilt)) tilt = 0;
1666 if (!isnormal(tilt2)) tilt2 = 0;
1668 for (int i = 0; i < skeleton.num_joints; i++) {
1669 skeleton.joints[i].delay = 0;
1670 skeleton.joints[i].locked = 0;
1671 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1672 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1673 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1674 skeleton.joints[i].position.y += .1;
1675 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1676 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1679 for (int i = 0; i < skeleton.num_joints; i++) {
1680 skeleton.joints[i].velocity = 0;
1681 skeleton.joints[i].velchange = 0;
1683 skeleton.DoConstraints(&coords, &scale);
1684 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1685 skeleton.DoConstraints(&coords, &scale);
1686 skeleton.DoConstraints(&coords, &scale);
1687 skeleton.DoConstraints(&coords, &scale);
1688 skeleton.DoConstraints(&coords, &scale);
1691 speed = animation[animTarget].speed[frameTarget] * 2;
1692 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1693 speed = animation[animCurrent].speed[frameCurrent] * 2;
1696 speed = transspeed * 2;
1700 for (int i = 0; i < skeleton.num_joints; i++) {
1701 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1702 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);
1704 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1705 change.x = (float)(Random() % 100) / 100;
1706 change.y = (float)(Random() % 100) / 100;
1707 change.z = (float)(Random() % 100) / 100;
1708 skeleton.joints[i].velocity += change;
1709 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1711 change.x = (float)(Random() % 100) / 100;
1712 change.y = (float)(Random() % 100) / 100;
1713 change.z = (float)(Random() % 100) / 100;
1714 skeleton.joints[i].velchange += change;
1715 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1718 if (checkcollision) {
1725 for (j = 0; j < skeleton.num_joints; j++) {
1726 average += skeleton.joints[j].position;
1730 coords += average * scale;
1731 for (j = 0; j < skeleton.num_joints; j++) {
1732 skeleton.joints[j].position -= average;
1735 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1736 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1737 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1738 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1739 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1742 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1743 coords.x = lowpoint.x;
1744 coords.z = lowpoint.z;
1753 for (int i = 0; i < skeleton.num_joints; i++) {
1754 velocity += skeleton.joints[i].velocity * scale;
1756 velocity /= skeleton.num_joints;
1759 if (Random() % 2 == 0) {
1760 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1761 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1762 weapons[weaponids[0]].velocity.x += .01;
1765 weaponids[0] = weaponids[num_weapons];
1766 if (weaponstuck == num_weapons)
1770 for (unsigned i = 0; i < Person::players.size(); i++) {
1771 Person::players[i]->wentforweapon = 0;
1776 animTarget = bounceidleanim;
1777 animCurrent = bounceidleanim;
1787 void Person::FootLand(bodyparts whichfoot, float opacity)
1789 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1790 cerr << "FootLand called on wrong bodypart" << endl;
1793 static XYZ terrainlight;
1794 static XYZ footvel, footpoint;
1795 if (opacity >= 1 || skiddelay <= 0) {
1798 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1799 if (distsq(&footpoint, &viewer))
1800 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1801 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1802 footvel = velocity / 5;
1805 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1806 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1807 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1808 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1809 if (environment == snowyenvironment) {
1810 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1812 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1814 } else if (environment == grassyenvironment) {
1815 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1816 } else if (environment == desertenvironment) {
1817 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1819 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1823 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1824 footvel = velocity / 5;
1827 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1828 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1829 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1836 * make a puff effect at a body part (dust effect?)
1838 void Person::Puff(int whichlabel)
1840 static XYZ footvel, footpoint;
1843 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1844 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1848 * I think I added this in an attempt to clean up code
1850 void Person::setAnimation(int animation)
1852 animTarget = animation;
1861 void Person::DoAnimations()
1863 if (!skeleton.free) {
1864 static float oldtarget;
1866 if (isIdle() && animCurrent != getIdle())
1867 normalsupdatedelay = 0;
1869 if (animTarget == tempanim || animCurrent == tempanim) {
1870 animation[tempanim] = tempanimation;
1872 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1878 vel[0] = velocity.x;
1879 vel[1] = velocity.y;
1880 vel[2] = velocity.z;
1883 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1884 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1886 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1888 if (!crouchkeydown && velocity.y >= -15)
1891 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1896 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1898 if (normaldotproduct(targfacing, velocity) >= -.3)
1899 animTarget = flipanim;
1901 animTarget = backflipanim;
1902 crouchtogglekeydown = 1;
1910 if (animation[animTarget].attack != reversed)
1912 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1913 crouchtogglekeydown = 0;
1914 if (aitype == playercontrolled)
1917 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1920 crouchtogglekeydown = 1;
1924 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1926 normalsupdatedelay = 0;
1930 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1932 emit_sound_at(fireendsound, coords);
1933 pause_sound(stream_firesound);
1937 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1938 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1940 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1941 if (normaldotproduct(victim->facing, facing) > 0)
1942 victim->animTarget = rabbittackledbackanim;
1944 victim->animTarget = rabbittackledfrontanim;
1945 victim->frameTarget = 2;
1948 victim->targetyaw = yaw;
1949 if (victim->aitype == gethelptype)
1950 victim->DoDamage(victim->damagetolerance - victim->damage);
1951 //victim->DoDamage(30);
1952 if (creature == wolftype) {
1954 emit_sound_at(clawslicesound, victim->coords);
1956 victim->DoBloodBig(1 / victim->armorhead, 210);
1958 award_bonus(id, TackleBonus,
1959 victim->aitype == gethelptype ? 50 : 0);
1963 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1964 if (weapons[weaponids[0]].getType() == knife) {
1965 if (weaponactive == -1)
1967 else if (weaponactive == 0)
1970 if (weaponactive == -1) {
1971 emit_sound_at(knifesheathesound, coords);
1973 if (weaponactive != -1) {
1974 emit_sound_at(knifedrawsound, coords, 128);
1977 drawtogglekeydown = 1;
1980 if (tutoriallevel != 1 || id == 0)
1981 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1984 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1985 if (animation[animTarget].label[frameTarget] == 1)
1986 whichsound = footstepsound;
1988 whichsound = footstepsound2;
1989 if (animation[animTarget].label[frameTarget] == 1)
1990 FootLand(leftfoot, 1);
1991 if (animation[animTarget].label[frameTarget] == 2)
1992 FootLand(rightfoot, 1);
1993 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1994 FootLand(rightfoot, 1);
1995 FootLand(leftfoot, 1);
1999 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2000 if (animation[animTarget].label[frameTarget] == 1)
2001 whichsound = footstepsound3;
2003 whichsound = footstepsound4;
2007 if (animation[animTarget].label[frameTarget] == 1)
2008 whichsound = footstepsound3;
2010 whichsound = footstepsound4;
2012 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2013 if (animation[animTarget].attack != neutral) {
2014 unsigned r = abs(Random() % 3);
2016 whichsound = lowwhooshsound;
2018 whichsound = midwhooshsound;
2020 whichsound = highwhooshsound;
2022 if (animation[animTarget].attack == neutral)
2023 whichsound = movewhooshsound;
2024 } else if (animation[animTarget].label[frameTarget] == 4)
2025 whichsound = knifeswishsound;
2026 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2027 whichsound = landsound2;
2029 emit_sound_at(whichsound, coords, 256.);
2032 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2033 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2034 addEnvSound(coords, 15);
2036 addEnvSound(coords, 6);
2040 if (animation[animTarget].label[frameTarget] == 3) {
2042 emit_sound_at(whichsound, coords, 128.);
2047 if (tutoriallevel != 1 || id == 0)
2048 if (speechdelay <= 0)
2049 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2050 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2051 int whichsound = -1;
2052 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2053 if (animation[animTarget].attack != neutral) {
2054 unsigned r = abs(Random() % 4);
2055 if (creature == rabbittype) {
2056 if (r == 0) whichsound = rabbitattacksound;
2057 if (r == 1) whichsound = rabbitattack2sound;
2058 if (r == 2) whichsound = rabbitattack3sound;
2059 if (r == 3) whichsound = rabbitattack4sound;
2061 if (creature == wolftype) {
2062 if (r == 0) whichsound = barksound;
2063 if (r == 1) whichsound = bark2sound;
2064 if (r == 2) whichsound = bark3sound;
2065 if (r == 3) whichsound = barkgrowlsound;
2071 if (whichsound != -1) {
2072 emit_sound_at(whichsound, coords);
2078 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2079 FootLand(leftfoot, 1);
2080 FootLand(rightfoot, 1);
2084 currentoffset = targetoffset;
2085 frameTarget = frameCurrent;
2086 animCurrent = animTarget;
2089 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2090 for (unsigned i = 0; i < weapons.size(); i++) {
2091 if (weapons[i].owner == -1)
2092 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2093 if (distsq(&coords, &weapons[i].position) >= 1) {
2094 if (weapons[i].getType() != staff) {
2095 emit_sound_at(knifedrawsound, coords, 128.);
2104 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2105 for (unsigned i = 0; i < weapons.size(); i++) {
2106 bool willwork = true;
2107 if (weapons[i].owner != -1)
2108 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2109 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2110 if (Person::players[weapons[i].owner]->num_weapons > 1)
2112 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2113 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2114 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2115 bool fleshstuck = false;
2116 if (weapons[i].owner != -1)
2117 if (victim->weaponstuck != -1) {
2118 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2123 emit_sound_at(fleshstabremovesound, coords, 128.);
2125 if (weapons[i].getType() != staff) {
2126 emit_sound_at(knifedrawsound, coords, 128.);
2129 if (weapons[i].owner != -1) {
2130 victim = Person::players[weapons[i].owner];
2131 if (victim->num_weapons == 1)
2132 victim->num_weapons = 0;
2134 victim->num_weapons = 1;
2136 //victim->weaponactive=-1;
2137 victim->skeleton.longdead = 0;
2138 victim->skeleton.free = 1;
2139 victim->skeleton.broken = 0;
2141 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2142 victim->skeleton.joints[j].velchange = 0;
2143 victim->skeleton.joints[j].locked = 0;
2149 Normalise(&relative);
2150 XYZ footvel, footpoint;
2152 footpoint = weapons[i].position;
2153 if (victim->weaponstuck != -1) {
2154 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2156 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2157 weapons[i].bloody = 2;
2158 weapons[i].blooddrip = 5;
2159 victim->weaponstuck = -1;
2162 if (victim->num_weapons > 0) {
2163 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2164 victim->weaponstuck = 0;
2165 if (victim->weaponids[0] == int(i))
2166 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2169 victim->jointVel(abdomen) += relative * 6;
2170 victim->jointVel(neck) += relative * 6;
2171 victim->jointVel(rightshoulder) += relative * 6;
2172 victim->jointVel(leftshoulder) += relative * 6;
2180 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2181 if (weaponactive == -1)
2183 else if (weaponactive == 0) {
2185 if (num_weapons == 2) {
2187 buffer = weaponids[0];
2188 weaponids[0] = weaponids[1];
2189 weaponids[1] = buffer;
2192 if (weaponactive == -1) {
2193 emit_sound_at(knifesheathesound, coords, 128.);
2195 if (weaponactive != -1) {
2196 emit_sound_at(knifedrawsound, coords, 128.);
2201 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2202 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2203 Normalise(&rotatetarget);
2204 targetyaw = -asin(0 - rotatetarget.x);
2205 targetyaw *= 360 / 6.28;
2206 if (rotatetarget.z < 0)
2207 targetyaw = 180 - targetyaw;
2209 if (animTarget == walljumprightkickanim)
2211 if (animTarget == walljumpleftkickanim)
2217 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2220 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2225 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2226 animTarget = rabbittackleanim;
2228 emit_sound_at(jumpsound, coords);
2236 targetloc = velocity;
2237 Normalise(&targetloc);
2238 targetloc += coords;
2239 for (unsigned i = 0; i < Person::players.size(); i++) {
2241 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2242 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2246 if (closestid != -1)
2247 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2249 victim = Person::players[closestid];
2250 coords = victim->coords;
2251 animCurrent = rabbittacklinganim;
2252 animTarget = rabbittacklinganim;
2256 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2257 rotatetarget = coords - victim->coords;
2258 Normalise(&rotatetarget);
2259 targetyaw = -asin(0 - rotatetarget.x);
2260 targetyaw *= 360 / 6.28;
2261 if (rotatetarget.z < 0)
2262 targetyaw = 180 - targetyaw;
2264 if (animTarget != rabbitrunninganim) {
2265 emit_sound_at(jumpsound, coords, 128.);
2271 float damagemult = 1 * power;
2272 if (creature == wolftype)
2273 damagemult = 2.5 * power;
2275 damagemult /= victim->damagetolerance / 200;
2277 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2278 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2279 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2283 if (Random() % 2 || creature == wolftype) {
2286 if (creature == wolftype)
2289 if (tutoriallevel != 1) {
2290 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2292 if (creature == wolftype) {
2293 emit_sound_at(clawslicesound, victim->coords, 128.);
2295 victim->DoBloodBig(2 / victim->armorhead, 175);
2299 relative = victim->coords - coords;
2301 Normalise(&relative);
2302 relative = DoRotation(relative, 0, -90, 0);
2303 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2304 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2306 victim->jointVel(head) += relative * damagemult * 200;
2308 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2314 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2315 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2319 if (Random() % 2 || creature == wolftype) {
2321 if (creature == wolftype)
2324 emit_sound_at(whooshhitsound, victim->coords);
2325 if (creature == wolftype) {
2326 emit_sound_at(clawslicesound, victim->coords, 128.);
2328 victim->DoBloodBig(2, 175);
2332 relative = victim->coords - coords;
2334 Normalise(&relative);
2336 Normalise(&relative);
2337 relative = DoRotation(relative, 0, 90, 0);
2338 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2339 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2341 victim->jointVel(head) += relative * damagemult * 100;
2343 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2347 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2348 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2354 if (tutoriallevel != 1) {
2355 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2357 if (creature == wolftype) {
2358 emit_sound_at(clawslicesound, victim->coords, 128.);
2360 victim->DoBloodBig(2 / victim->armorhead, 175);
2366 Normalise(&relative);
2367 relative = DoRotation(relative, 0, -90, 0);
2368 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2369 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2371 victim->jointVel(head) += relative * damagemult * 200;
2373 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2375 if (victim->damage > victim->damagetolerance)
2376 award_bonus(id, style);
2382 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2383 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2389 if (tutoriallevel != 1) {
2390 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2392 if (creature == wolftype) {
2393 emit_sound_at(clawslicesound, victim->coords, 128.);
2395 victim->DoBloodBig(2 / victim->armorhead, 175);
2401 Normalise(&relative);
2402 relative = DoRotation(relative, 0, 90, 0);
2403 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2404 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2406 victim->jointVel(head) += relative * damagemult * 200;
2408 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2410 if (victim->damage > victim->damagetolerance)
2411 award_bonus(id, style);
2417 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2418 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2426 emit_sound_at(whooshhitsound, victim->coords);
2429 relative = victim->coords - coords;
2431 Normalise(&relative);
2432 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2433 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2435 victim->jointVel(head) += relative * damagemult * 100;
2437 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2441 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2442 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2446 emit_sound_at(whooshhitsound, victim->coords, 128.);
2448 victim->skeleton.longdead = 0;
2449 victim->skeleton.free = 1;
2450 victim->skeleton.broken = 0;
2451 victim->skeleton.spinny = 1;
2453 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2454 victim->skeleton.joints[i].velchange = 0;
2455 victim->skeleton.joints[i].delay = 0;
2456 victim->skeleton.joints[i].locked = 0;
2457 //victim->skeleton.joints[i].velocity=0;
2463 Normalise(&relative);
2464 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2465 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2466 victim->skeleton.joints[i].position.y += relative.y * .3;
2467 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2468 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2470 victim->Puff(abdomen);
2471 victim->jointVel(abdomen).y = relative.y * 400;
2475 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2476 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2480 if (tutoriallevel != 1) {
2481 emit_sound_at(heavyimpactsound, coords, 128.);
2484 relative = victim->coords - coords;
2486 Normalise(&relative);
2487 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2488 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2490 victim->Puff(abdomen);
2491 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2495 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2496 victim->jointVel(abdomen) += relative * damagemult * 300;
2500 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2501 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2505 if (tutoriallevel != 1) {
2506 emit_sound_at(thudsound, coords);
2509 victim->skeleton.longdead = 0;
2510 victim->skeleton.free = 1;
2511 victim->skeleton.broken = 0;
2512 victim->skeleton.spinny = 1;
2514 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2515 victim->skeleton.joints[i].velchange = 0;
2516 //victim->skeleton.joints[i].delay=0;
2517 victim->skeleton.joints[i].locked = 0;
2520 relative = victim->coords - coords;
2521 Normalise(&relative);
2523 Normalise(&relative);
2524 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2525 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2530 victim->Puff(abdomen);
2531 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2532 victim->jointVel(abdomen) += relative * damagemult * 200;
2541 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2544 if (!victim->skeleton.free)
2548 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2549 emit_sound_at(knifesheathesound, coords, 128.);
2552 if (victim && hasvictim) {
2553 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2555 XYZ where, startpoint, endpoint, movepoint, colpoint;
2556 float rotationpoint;
2558 if (weapons[weaponids[weaponactive]].getType() == knife) {
2559 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2560 where -= victim->coords;
2561 if (!victim->skeleton.free)
2562 where = DoRotation(where, 0, -victim->yaw, 0);
2565 startpoint.y += 100;
2569 if (weapons[weaponids[weaponactive]].getType() == sword) {
2570 where = weapons[weaponids[weaponactive]].position;
2571 where -= victim->coords;
2572 if (!victim->skeleton.free)
2573 where = DoRotation(where, 0, -victim->yaw, 0);
2575 where = weapons[weaponids[weaponactive]].tippoint;
2576 where -= victim->coords;
2577 if (!victim->skeleton.free)
2578 where = DoRotation(where, 0, -victim->yaw, 0);
2581 if (weapons[weaponids[weaponactive]].getType() == staff) {
2582 where = weapons[weaponids[weaponactive]].position;
2583 where -= victim->coords;
2584 if (!victim->skeleton.free)
2585 where = DoRotation(where, 0, -victim->yaw, 0);
2587 where = weapons[weaponids[weaponactive]].tippoint;
2588 where -= victim->coords;
2589 if (!victim->skeleton.free)
2590 where = DoRotation(where, 0, -victim->yaw, 0);
2595 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2597 if (whichtri != -1) {
2598 if (victim->dead != 2) {
2599 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2601 award_bonus(id, FinishedBonus);
2604 weapons[weaponids[weaponactive]].bloody = 2;
2606 victim->skeleton.longdead = 0;
2607 victim->skeleton.free = 1;
2608 victim->skeleton.broken = 0;
2610 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2611 victim->skeleton.joints[i].velchange = 0;
2612 victim->skeleton.joints[i].locked = 0;
2613 //victim->skeleton.joints[i].velocity=0;
2615 emit_sound_at(fleshstabsound, coords, 128);
2618 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2619 weapons[weaponids[weaponactive]].blooddrip += 5;
2620 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2622 if (whichtri == -1) {
2624 emit_sound_at(knifesheathesound, coords, 128.);
2630 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2632 emit_sound_at(knifedrawsound, coords, 128);
2635 if (victim && hasvictim) {
2636 XYZ footvel, footpoint;
2638 emit_sound_at(fleshstabremovesound, coords, 128.);
2641 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2643 if (weapons[weaponids[weaponactive]].getType() == sword) {
2644 XYZ where, startpoint, endpoint, movepoint;
2645 float rotationpoint;
2648 where = weapons[weaponids[weaponactive]].position;
2649 where -= victim->coords;
2650 if (!victim->skeleton.free)
2651 where = DoRotation(where, 0, -victim->yaw, 0);
2653 where = weapons[weaponids[weaponactive]].tippoint;
2654 where -= victim->coords;
2655 if (!victim->skeleton.free)
2656 where = DoRotation(where, 0, -victim->yaw, 0);
2661 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2662 footpoint += victim->coords;
2664 if (whichtri == -1) {
2665 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2668 if (weapons[weaponids[weaponactive]].getType() == staff) {
2669 XYZ where, startpoint, endpoint, movepoint;
2670 float rotationpoint;
2673 where = weapons[weaponids[weaponactive]].position;
2674 where -= victim->coords;
2675 if (!victim->skeleton.free)
2676 where = DoRotation(where, 0, -victim->yaw, 0);
2678 where = weapons[weaponids[weaponactive]].tippoint;
2679 where -= victim->coords;
2680 if (!victim->skeleton.free)
2681 where = DoRotation(where, 0, -victim->yaw, 0);
2686 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2687 footpoint += victim->coords;
2689 if (whichtri == -1) {
2690 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2693 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2695 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2696 victim->skeleton.longdead = 0;
2697 victim->skeleton.free = 1;
2698 victim->skeleton.broken = 0;
2700 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2701 victim->skeleton.joints[i].velchange = 0;
2702 victim->skeleton.joints[i].locked = 0;
2703 //victim->skeleton.joints[i].velocity=0;
2709 Normalise(&relative);
2710 //victim->Puff(abdomen);
2712 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2714 if (victim->bloodloss < victim->damagetolerance) {
2715 victim->bloodloss += 1000;
2719 victim->jointVel(abdomen) += relative * damagemult * 20;
2723 if (!hasvictim && onterrain) {
2724 weapons[weaponids[weaponactive]].bloody = 0;
2725 weapons[weaponids[weaponactive]].blooddrip = 0;
2729 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2730 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2738 if (tutoriallevel != 1) {
2739 emit_sound_at(heavyimpactsound, victim->coords, 128);
2744 relative = victim->coords - coords;
2746 Normalise(&relative);
2747 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2748 victim->skeleton.joints[i].velocity = relative * 30;
2750 victim->jointVel(head) += relative * damagemult * 150;
2752 victim->frameTarget = 0;
2753 victim->animTarget = staggerbackhardanim;
2754 victim->targetyaw = targetyaw + 180;
2756 victim->stunned = 1;
2759 victim->Puff(abdomen);
2760 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2767 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2768 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2772 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2773 if (tutoriallevel != 1) {
2774 emit_sound_at(thudsound, victim->coords);
2776 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2777 if (tutoriallevel != 1) {
2778 emit_sound_at(whooshhitsound, victim->coords);
2781 if (tutoriallevel != 1) {
2782 emit_sound_at(heavyimpactsound, victim->coords);
2786 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2789 relative = victim->coords - coords;
2791 Normalise(&relative);
2793 Normalise(&relative);
2794 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2795 victim->skeleton.joints[i].velocity = relative * 5;
2797 victim->jointVel(abdomen) += relative * damagemult * 400;
2799 victim->frameTarget = 0;
2800 victim->animTarget = staggerbackhardanim;
2801 victim->targetyaw = targetyaw + 180;
2803 victim->stunned = 1;
2805 victim->Puff(abdomen);
2806 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2812 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2813 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2814 if (victim->id == 0)
2816 emit_sound_at(landsound2, victim->coords);
2822 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2823 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2824 if (victim->id == 0)
2827 if (weaponactive != -1) {
2828 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2829 if (weapons[victim->weaponids[0]].getType() == staff)
2830 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2831 if (weapons[weaponids[0]].getType() == staff)
2832 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2834 emit_sound_at(swordstaffsound, victim->coords);
2836 emit_sound_at(metalhitsound, victim->coords);
2844 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2845 if (weaponactive != -1) {
2848 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);
2850 weapons[weaponids[0]].thrown(aim * 50);
2853 weaponids[0] = weaponids[num_weapons];
2859 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2861 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2863 if (tutoriallevel != 1)
2864 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2866 award_bonus(id, Slicebonus);
2867 if (tutoriallevel != 1) {
2868 emit_sound_at(knifeslicesound, victim->coords);
2870 //victim->jointVel(abdomen)+=relative*damagemult*200;
2871 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2872 if (victim->id != 0 || difficulty == 2) {
2873 victim->frameTarget = 0;
2874 victim->animTarget = staggerbackhardanim;
2875 victim->targetyaw = targetyaw + 180;
2879 victim->lowreversaldelay = 0;
2880 victim->highreversaldelay = 0;
2881 if (aitype != playercontrolled)
2882 weaponmissdelay = .6;
2884 if (tutoriallevel != 1)
2885 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2886 weapons[weaponids[weaponactive]].bloody = 1;
2887 if (tutoriallevel != 1)
2888 weapons[weaponids[weaponactive]].blooddrip += 3;
2890 XYZ footvel, footpoint;
2892 if (skeleton.free) {
2893 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2895 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2897 if (tutoriallevel != 1) {
2899 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2900 footvel = DoRotation(facing, 0, 90, 0) * .8;
2902 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2903 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2904 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2905 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2907 if (tutoriallevel == 1) {
2908 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2910 victim->DoDamage(damagemult * 0);
2913 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2914 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2915 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2916 award_bonus(id, Slashbonus);
2918 if (tutoriallevel != 1) {
2919 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2920 victim->DoBloodBig(2 / victim->armorhigh, 190);
2922 victim->DoBloodBig(2 / victim->armorhigh, 185);
2923 victim->deathbleeding = 1;
2924 emit_sound_at(swordslicesound, victim->coords);
2926 //victim->jointVel(abdomen)+=relative*damagemult*200;
2927 if (tutoriallevel != 1) {
2928 victim->frameTarget = 0;
2929 victim->animTarget = staggerbackhardanim;
2930 victim->targetyaw = targetyaw + 180;
2934 if (tutoriallevel != 1) {
2935 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2936 weapons[weaponids[weaponactive]].bloody = 1;
2937 weapons[weaponids[weaponactive]].blooddrip += 3;
2939 float bloodlossamount;
2940 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2941 victim->bloodloss += bloodlossamount / victim->armorhigh;
2942 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2943 victim->DoDamage(damagemult * 0);
2945 XYZ footvel, footpoint;
2947 if (skeleton.free) {
2948 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2950 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2953 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2954 footvel = DoRotation(facing, 0, 90, 0) * .8;
2956 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2957 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2958 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2959 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2962 if (victim->weaponactive != -1) {
2963 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2964 if (weapons[victim->weaponids[0]].getType() == staff)
2965 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2966 if (weapons[weaponids[0]].getType() == staff)
2967 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2969 emit_sound_at(swordstaffsound, victim->coords);
2971 emit_sound_at(metalhitsound, victim->coords);
2977 victim->Puff(righthand);
2979 victim->frameTarget = 0;
2980 victim->animTarget = staggerbackhighanim;
2981 victim->targetyaw = targetyaw + 180;
2983 aim = DoRotation(facing, 0, 90, 0) * 21;
2985 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2986 victim->num_weapons--;
2987 if (victim->num_weapons) {
2988 victim->weaponids[0] = victim->weaponids[num_weapons];
2989 if (victim->weaponstuck == victim->num_weapons)
2990 victim->weaponstuck = 0;
2992 victim->weaponactive = -1;
2993 for (unsigned i = 0; i < Person::players.size(); i++) {
2994 Person::players[i]->wentforweapon = 0;
3001 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3002 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3003 if (tutoriallevel != 1) {
3004 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3008 if (Random() % 2 || creature == wolftype) {
3011 emit_sound_at(staffheadsound, victim->coords);
3015 relative = victim->coords - coords;
3017 Normalise(&relative);
3018 relative = DoRotation(relative, 0, 90, 0);
3020 Normalise(&relative);
3021 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3022 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3024 victim->jointVel(head) += relative * damagemult * 230;
3025 victim->jointVel(neck) += relative * damagemult * 230;
3027 if (tutoriallevel != 1) {
3028 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3030 award_bonus(id, solidhit, 30);
3035 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3036 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3037 if (tutoriallevel != 1) {
3038 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3042 if (Random() % 2 || creature == wolftype) {
3045 emit_sound_at(staffheadsound, victim->coords);
3049 relative = victim->coords - coords;
3051 Normalise(&relative);
3052 relative = DoRotation(relative, 0, -90, 0);
3053 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3054 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3056 victim->jointVel(head) += relative * damagemult * 220;
3057 victim->jointVel(neck) += relative * damagemult * 220;
3059 if (tutoriallevel != 1) {
3060 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3062 award_bonus(id, solidhit, 60);
3067 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3068 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3070 if (tutoriallevel != 1) {
3072 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3075 if (Random() % 2 || creature == wolftype) {
3078 emit_sound_at(staffbodysound, victim->coords);
3080 victim->skeleton.longdead = 0;
3081 victim->skeleton.free = 1;
3082 victim->skeleton.broken = 0;
3084 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3085 victim->skeleton.joints[i].velchange = 0;
3086 victim->skeleton.joints[i].locked = 0;
3087 //victim->skeleton.joints[i].velocity=0;
3094 Normalise(&relative);
3095 if (!victim->dead) {
3096 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3097 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3099 victim->jointVel(abdomen) += relative * damagemult * 40;
3102 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3103 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3106 victim->Puff(abdomen);
3107 if (tutoriallevel != 1) {
3108 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3110 if (!victim->dead) {
3111 award_bonus(id, solidhit, 40);
3117 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3118 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3123 relative = victim->coords - coords;
3125 Normalise(&relative);
3129 if (animation[victim->animTarget].height == lowheight) {
3135 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3136 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3138 victim->jointVel(head) += relative * damagemult * 200;
3139 if (tutoriallevel != 1) {
3140 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3143 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3144 if (victim->howactive == typesleeping)
3145 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3146 if (creature == wolftype) {
3147 emit_sound_at(clawslicesound, victim->coords, 128.);
3149 victim->DoBloodBig(2 / victim->armorhead, 175);
3152 if (victim->damage >= victim->damagetolerance)
3154 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3155 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3157 victim->jointVel(abdomen) += relative * damagemult * 200;
3158 victim->frameTarget = 0;
3159 victim->animTarget = staggerbackhighanim;
3160 victim->targetyaw = targetyaw + 180;
3162 if (tutoriallevel != 1) {
3163 emit_sound_at(landsound2, victim->coords, 128.);
3165 victim->Puff(abdomen);
3166 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3167 if (creature == wolftype) {
3168 emit_sound_at(clawslicesound, victim->coords, 128.);
3170 victim->DoBloodBig(2 / victim->armorhigh, 170);
3177 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3178 if ((victim->animTarget != jumpupanim) &&
3179 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3180 (victim != this->shared_from_this())) {
3184 if (tutoriallevel != 1) {
3185 emit_sound_at(landsound2, victim->coords, 128.);
3188 relative = victim->coords - coords;
3190 Normalise(&relative);
3192 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3195 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3196 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3198 relative = DoRotation(relative, 0, -90, 0);
3200 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3201 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)
3202 victim->skeleton.joints[i].velocity = relative * 80;
3204 victim->Puff(rightankle);
3205 victim->Puff(leftankle);
3206 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3208 if (victim->damage >= victim->damagetolerance)
3210 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3211 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3213 relative = DoRotation(relative, 0, -90, 0);
3214 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3215 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)
3216 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3218 victim->jointVel(abdomen) += relative * damagemult * 200;
3219 victim->frameTarget = 0;
3220 victim->animTarget = staggerbackhighanim;
3221 victim->targetyaw = targetyaw + 180;
3223 if (tutoriallevel != 1) {
3224 emit_sound_at(landsound2, victim->coords, 128.);
3226 victim->Puff(abdomen);
3227 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3235 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3236 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3244 if (tutoriallevel != 1) {
3245 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3247 if (creature == wolftype) {
3248 emit_sound_at(clawslicesound, victim->coords, 128);
3250 victim->DoBloodBig(2 / victim->armorhigh, 170);
3254 relative = victim->coords - oldcoords;
3256 Normalise(&relative);
3257 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3258 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3260 victim->jointVel(abdomen) += relative * damagemult * 200;
3261 victim->Puff(abdomen);
3262 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3264 award_bonus(id, Reversal);
3267 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3268 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3269 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3270 takeWeapon(victim->weaponids[victim->weaponactive]);
3271 victim->num_weapons--;
3272 if (victim->num_weapons > 0) {
3273 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3275 victim->weaponactive = -1;
3280 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3288 emit_sound_at(whooshhitsound, victim->coords, 128.);
3291 relative = victim->coords - oldcoords;
3293 Normalise(&relative);
3294 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3295 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3297 victim->jointVel(abdomen) += relative * damagemult * 200;
3299 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3302 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3311 award_bonus(id, staffreversebonus);
3313 if (tutoriallevel != 1) {
3314 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3317 award_bonus(id, staffreversebonus); // Huh, again?
3320 relative = victim->coords - oldcoords;
3322 Normalise(&relative);
3323 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3324 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3326 victim->jointVel(abdomen) += relative * damagemult * 200;
3328 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3331 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3337 Normalise(&relative);
3339 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3340 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3342 victim->jointVel(lefthand) *= .1;
3343 victim->jointVel(leftwrist) *= .2;
3344 victim->jointVel(leftelbow) *= .5;
3345 victim->jointVel(leftshoulder) *= .7;
3346 victim->jointVel(righthand) *= .1;
3347 victim->jointVel(rightwrist) *= .2;
3348 victim->jointVel(rightelbow) *= .5;
3349 victim->jointVel(rightshoulder) *= .7;
3351 victim->Puff(abdomen);
3352 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3354 award_bonus(id, Reversal);
3358 if (weaponactive != -1 || creature == wolftype)
3360 if (creature == rabbittype && weaponactive != -1)
3361 if (weapons[weaponids[0]].getType() == staff)
3364 if (weaponactive != -1) {
3365 victim->DoBloodBig(2 / victim->armorhigh, 225);
3366 emit_sound_at(knifeslicesound, victim->coords);
3367 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3368 weapons[weaponids[weaponactive]].bloody = 1;
3369 weapons[weaponids[weaponactive]].blooddrip += 3;
3371 if (weaponactive == -1 && creature == wolftype) {
3372 emit_sound_at(clawslicesound, victim->coords, 128.);
3374 victim->DoBloodBig(2 / victim->armorhigh, 175);
3381 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3387 Normalise(&relative);
3389 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3390 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3392 victim->jointVel(lefthand) *= .1 - 1;
3393 victim->jointVel(leftwrist) *= .2 - 1;
3394 victim->jointVel(leftelbow) *= .5 - 1;
3395 victim->jointVel(leftshoulder) *= .7 - 1;
3396 victim->jointVel(righthand) *= .1 - 1;
3397 victim->jointVel(rightwrist) *= .2 - 1;
3398 victim->jointVel(rightelbow) *= .5 - 1;
3399 victim->jointVel(rightshoulder) *= .7 - 1;
3401 award_bonus(id, swordreversebonus);
3404 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3412 if (tutoriallevel != 1) {
3413 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3417 relative = victim->coords - oldcoords;
3419 Normalise(&relative);
3420 relative = DoRotation(relative, 0, -90, 0);
3421 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3422 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3424 victim->jointVel(abdomen) += relative * damagemult * 200;
3425 victim->Puff(abdomen);
3426 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3428 award_bonus(id, Reversal);
3431 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3434 victim->skeleton.spinny = 0;
3436 relative = facing * -1;
3438 Normalise(&relative);
3439 if (victim->id == 0)
3441 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3442 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3444 victim->damage = victim->damagetolerance;
3445 victim->permanentdamage = victim->damagetolerance - 1;
3448 if (weaponactive != -1 || creature == wolftype)
3450 if (creature == rabbittype && weaponactive != -1)
3451 if (weapons[weaponids[0]].getType() == staff)
3454 if (weaponactive != -1) {
3455 victim->DoBloodBig(200, 225);
3456 emit_sound_at(knifeslicesound, victim->coords);
3458 weapons[weaponids[weaponactive]].bloody = 2;
3459 weapons[weaponids[weaponactive]].blooddrip += 5;
3462 if (creature == wolftype && weaponactive == -1) {
3463 emit_sound_at(clawslicesound, victim->coords, 128.);
3465 victim->DoBloodBig(2, 175);
3468 award_bonus(id, spinecrusher);
3471 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3472 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3474 if (animTarget == knifefollowanim)
3475 victim->DoBloodBig(200, 210);
3476 if (animTarget == knifesneakattackanim) {
3477 XYZ footvel, footpoint;
3479 footpoint = weapons[weaponids[0]].tippoint;
3481 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3482 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3483 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3484 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3485 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3486 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3487 victim->DoBloodBig(200, 195);
3488 award_bonus(id, tracheotomy);
3490 if (animTarget == knifefollowanim) {
3491 award_bonus(id, Stabbonus);
3492 XYZ footvel, footpoint;
3494 footpoint = weapons[weaponids[0]].tippoint;
3496 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3497 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3498 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3499 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3500 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3501 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3504 victim->bloodloss += 10000;
3505 victim->velocity = 0;
3506 emit_sound_at(fleshstabsound, victim->coords);
3508 weapons[weaponids[weaponactive]].bloody = 2;
3509 weapons[weaponids[weaponactive]].blooddrip += 5;
3513 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3515 victim->velocity = 0;
3516 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3517 victim->skeleton.joints[i].velocity = 0;
3519 if (animTarget == knifefollowanim) {
3521 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3522 victim->skeleton.joints[i].velocity = 0;
3525 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3526 emit_sound_at(fleshstabremovesound, victim->coords);
3528 weapons[weaponids[weaponactive]].bloody = 2;
3529 weapons[weaponids[weaponactive]].blooddrip += 5;
3531 XYZ footvel, footpoint;
3533 footpoint = weapons[weaponids[0]].tippoint;
3535 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3536 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3537 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3544 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3545 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3546 award_bonus(id, backstab);
3550 XYZ footvel, footpoint;
3552 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3554 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3555 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3556 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3557 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3558 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3559 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3560 victim->DoBloodBig(200, 180);
3561 victim->DoBloodBig(200, 215);
3562 victim->bloodloss += 10000;
3563 victim->velocity = 0;
3564 emit_sound_at(fleshstabsound, victim->coords);
3566 weapons[weaponids[weaponactive]].bloody = 2;
3567 weapons[weaponids[weaponactive]].blooddrip += 5;
3571 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3573 victim->velocity = 0;
3574 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3575 victim->skeleton.joints[i].velocity = 0;
3577 if (weaponactive != -1) {
3578 emit_sound_at(fleshstabremovesound, victim->coords);
3580 weapons[weaponids[weaponactive]].bloody = 2;
3581 weapons[weaponids[weaponactive]].blooddrip += 5;
3583 XYZ footvel, footpoint;
3585 footpoint = weapons[weaponids[0]].tippoint;
3587 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3588 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3589 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3590 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3591 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3592 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3596 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3604 if (weaponactive == -1) {
3605 if (tutoriallevel != 1) {
3606 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3611 if (weaponactive != -1 || creature == wolftype)
3613 if (creature == rabbittype && weaponactive != -1)
3614 if (weapons[weaponids[0]].getType() == staff)
3617 if (weaponactive != -1) {
3618 victim->DoBloodBig(2 / victim->armorhead, 225);
3619 emit_sound_at(knifeslicesound, victim->coords);
3620 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3621 weapons[weaponids[weaponactive]].bloody = 1;
3622 weapons[weaponids[weaponactive]].blooddrip += 3;
3624 if (weaponactive == -1 && creature == wolftype) {
3625 emit_sound_at(clawslicesound, victim->coords, 128.);
3627 victim->DoBloodBig(2 / victim->armorhead, 175);
3631 award_bonus(id, Reversal);
3636 relative = facing * -1;
3638 Normalise(&relative);
3639 relative = DoRotation(relative, 0, 90, 0);
3641 Normalise(&relative);
3642 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3643 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3645 victim->jointVel(head) += relative * damagemult * 200;
3646 if (victim->damage < victim->damagetolerance - 100)
3647 victim->velocity = relative * 200;
3648 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3649 victim->velocity = 0;
3652 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3656 relative = facing * -1;
3658 Normalise(&relative);
3659 relative = DoRotation(relative, 0, 90, 0);
3661 Normalise(&relative);
3662 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3663 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3665 victim->jointVel(head) += relative * damagemult * 200;
3668 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3669 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3670 award_bonus(id, reverseko);
3676 if (frameTarget > animation[animCurrent].numframes - 1) {
3679 animTarget = getIdle();
3680 FootLand(leftfoot, 1);
3681 FootLand(rightfoot, 1);
3683 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3684 animTarget = rollanim;
3686 emit_sound_at(movewhooshsound, coords, 128.);
3688 if (animCurrent == staggerbackhighanim) {
3689 animTarget = getIdle();
3691 if (animCurrent == staggerbackhardanim) {
3692 animTarget = getIdle();
3694 if (animCurrent == removeknifeanim) {
3695 animTarget = getIdle();
3697 if (animCurrent == crouchremoveknifeanim) {
3698 animTarget = getCrouch();
3700 if (animCurrent == backhandspringanim) {
3701 animTarget = getIdle();
3703 if (animCurrent == dodgebackanim) {
3704 animTarget = getIdle();
3706 if (animCurrent == drawleftanim) {
3707 animTarget = getIdle();
3709 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3710 animTarget = getIdle();
3711 if (animCurrent == crouchdrawrightanim) {
3712 animTarget = getCrouch();
3714 if (weaponactive == -1)
3716 else if (weaponactive == 0) {
3718 if (num_weapons == 2) {
3720 buffer = weaponids[0];
3721 weaponids[0] = weaponids[1];
3722 weaponids[1] = buffer;
3726 if (weaponactive == -1) {
3727 emit_sound_at(knifesheathesound, coords, 128.);
3729 if (weaponactive != -1) {
3730 emit_sound_at(knifedrawsound, coords, 128.);
3733 if (animCurrent == rollanim) {
3734 animTarget = getCrouch();
3735 FootLand(leftfoot, 1);
3736 FootLand(rightfoot, 1);
3739 if (animTarget == walljumprightkickanim) {
3742 if (animTarget == walljumpleftkickanim) {
3745 animTarget = jumpdownanim;
3747 if (animCurrent == climbanim) {
3748 animTarget = getCrouch();
3750 coords += facing * .1;
3751 if (!isnormal(coords.x))
3762 if (animTarget == rabbitkickreversalanim) {
3763 animTarget = getCrouch();
3766 if (animTarget == jumpreversalanim) {
3767 animTarget = getCrouch();
3770 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3771 if (attackkeydown && animTarget != walljumpfrontanim) {
3773 float closestdist = -1;
3775 if (Person::players.size() > 1)
3776 for (unsigned i = 0; i < Person::players.size(); i++) {
3777 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3778 distance = distsq(&Person::players[i]->coords, &coords);
3779 if (closestdist == -1 || distance < closestdist) {
3780 closestdist = distance;
3785 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3786 victim = Person::players[closest];
3787 animTarget = walljumprightkickanim;
3789 XYZ rotatetarget = victim->coords - coords;
3790 Normalise(&rotatetarget);
3791 yaw = -asin(0 - rotatetarget.x);
3793 if (rotatetarget.z < 0)
3795 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3796 velocity = (victim->coords - coords) * 4;
3801 if (animTarget == walljumpbackanim) {
3802 animTarget = backflipanim;
3804 velocity = facing * -8;
3807 resume_stream(whooshsound);
3809 if (animTarget == walljumprightanim) {
3810 animTarget = rightflipanim;
3814 velocity = DoRotation(facing, 0, 30, 0) * -8;
3817 if (animTarget == walljumpfrontanim) {
3818 animTarget = frontflipanim;
3822 velocity = facing * 8;
3826 resume_stream(whooshsound);
3828 if (animTarget == walljumpleftanim) {
3829 if (attackkeydown) {
3831 float closestdist = -1;
3833 if (Person::players.size() > 1)
3834 for (unsigned i = 0; i < Person::players.size(); i++) {
3835 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3836 distance = distsq(&Person::players[i]->coords, &coords);
3837 if (closestdist == -1 || distance < closestdist) {
3838 closestdist = distance;
3843 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3844 victim = Person::players[closest];
3845 animTarget = walljumpleftkickanim;
3847 XYZ rotatetarget = victim->coords - coords;
3848 Normalise(&rotatetarget);
3849 yaw = -asin(0 - rotatetarget.x);
3851 if (rotatetarget.z < 0)
3853 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3854 velocity = (victim->coords - coords) * 4;
3859 if (animTarget != walljumpleftkickanim) {
3860 animTarget = leftflipanim;
3864 velocity = DoRotation(facing, 0, -30, 0) * -8;
3868 resume_stream(whooshsound);
3870 if (animTarget == sneakattackanim) {
3871 animCurrent = getCrouch();
3872 animTarget = getCrouch();
3879 transspeed = 1000000;
3880 targetheadyaw += 180;
3881 coords -= facing * .7;
3883 coords.y = terrain.getHeight(coords.x, coords.z);
3887 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3888 animTarget = getIdle();
3891 coords.y = terrain.getHeight(coords.x, coords.z);
3895 if (animCurrent == knifefollowanim) {
3896 animTarget = getIdle();
3899 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3900 float ycoords = oldcoords.y;
3901 animTarget = getStop();
3906 transspeed = 1000000;
3907 targetheadyaw += 180;
3908 if (!isnormal(coords.x))
3910 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3911 oldcoords = coords + facing * .5;
3912 else if (animCurrent == sweepreversalanim)
3913 oldcoords = coords + facing * 1.1;
3914 else if (animCurrent == upunchreversalanim) {
3915 oldcoords = coords + facing * 1.5;
3918 targetheadyaw += 180;
3921 } else if (animCurrent == knifeslashreversalanim) {
3922 oldcoords = coords + facing * .5;
3925 targetheadyaw += 90;
3928 } else if (animCurrent == staffspinhitreversalanim) {
3931 targetheadyaw += 180;
3936 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3938 oldcoords.y = ycoords;
3939 currentoffset = coords - oldcoords;
3945 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3950 if (animation[animTarget].attack == reversed) {
3952 if (animTarget == sweepreversedanim)
3954 animTarget = backhandspringanim;
3956 emit_sound_at(landsound, coords, 128);
3958 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3959 animTarget = rollanim;
3962 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3963 coords.y = oldcoords.y;
3965 if (animCurrent == knifeslashreversedanim) {
3966 animTarget = rollanim;
3971 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3972 coords.y = oldcoords.y;
3976 animTarget = jumpdownanim;
3979 animTarget = getIdle();
3981 animTarget = getIdle();
3982 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3983 animTarget = getIdle();
3985 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3986 coords.y = oldcoords.y;
3987 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3988 targetoffset.y = coords.y;
3990 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3991 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3992 currentoffset.y -= (coords.y - targetoffset.y);
3993 coords.y = targetoffset.y;
3995 normalsupdatedelay = 0;
3997 if (animCurrent == upunchanim) {
3998 animTarget = getStop();
3999 normalsupdatedelay = 0;
4002 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4006 if (num_weapons > 0)
4007 if (weapons[0].getType() == staff)
4013 rabbitkickragdoll = 1;
4015 if (animCurrent == rabbitkickreversedanim) {
4021 skeleton.spinny = 0;
4022 SolidHitBonus(!id); // FIXME: tricky id
4026 animTarget = rollanim;
4029 pause_sound(whooshsound);
4033 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4037 skeleton.spinny = 0;
4039 if (animCurrent == jumpreversedanim) {
4045 skeleton.spinny = 0;
4046 SolidHitBonus(!id); // FIXME: tricky id
4050 animTarget = rollanim;
4051 coords += facing * 2;
4053 pause_sound(whooshsound);
4058 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) {
4059 animTarget = getupfromfrontanim;
4061 } else if (animation[animCurrent].attack == normalattack) {
4062 animTarget = getIdle();
4065 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4066 animTarget = blockhighleftstrikeanim;
4068 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4069 animTarget = getIdle();
4072 if (animCurrent == spinkickanim && victim->skeleton.free) {
4073 if (creature == rabbittype)
4074 animTarget = fightidleanim;
4079 if (isIdle() && !wasIdle())
4080 normalsupdatedelay = 0;
4082 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4083 animTarget = jumpdownanim;
4086 if (!skeleton.free) {
4088 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4089 if (!isRun() || !wasRun()) {
4090 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4091 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4092 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4093 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4095 if (isRun() && wasRun()) {
4097 tempspeed = velspeed;
4098 if (tempspeed < 10 * speedmult)
4099 tempspeed = 10 * speedmult;
4100 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4102 } else if (transspeed)
4103 target += multiplier * transspeed * speed * 2;
4105 if (!isRun() || !wasRun()) {
4106 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4107 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4108 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4109 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4113 if (animCurrent != animTarget)
4114 target = (target + oldtarget) / 2;
4117 frameCurrent = frameTarget;
4121 rot = targetrot * target;
4122 yaw += rot - oldrot;
4128 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4130 for (int i = 0; i < skeleton.num_joints; i++) {
4131 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4134 skeleton.FindForwards();
4136 for (int i = 0; i < skeleton.num_muscles; i++) {
4137 if (skeleton.muscles[i].visible) {
4138 skeleton.FindRotationMuscle(i, animTarget);
4141 for (int i = 0; i < skeleton.num_muscles; i++) {
4142 if (skeleton.muscles[i].visible) {
4143 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4144 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4145 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4146 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4147 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4148 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4153 for (int i = 0; i < skeleton.num_joints; i++) {
4154 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4157 skeleton.FindForwards();
4159 for (int i = 0; i < skeleton.num_muscles; i++) {
4160 if (skeleton.muscles[i].visible) {
4161 skeleton.FindRotationMuscle(i, animTarget);
4164 for (int i = 0; i < skeleton.num_muscles; i++) {
4165 if (skeleton.muscles[i].visible) {
4166 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4167 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4168 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4169 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4170 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4171 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4172 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4173 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4174 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4175 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4176 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4177 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4181 if (frameCurrent >= animation[animCurrent].numframes)
4182 frameCurrent = animation[animCurrent].numframes - 1;
4184 oldanimCurrent = animCurrent;
4185 oldanimTarget = animTarget;
4186 oldframeTarget = frameTarget;
4187 oldframeCurrent = frameCurrent;
4189 for (int i = 0; i < skeleton.num_joints; i++) {
4190 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4191 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4193 offset = currentoffset * (1 - target) + targetoffset * target;
4194 for (int i = 0; i < skeleton.num_muscles; i++) {
4195 if (skeleton.muscles[i].visible) {
4196 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4197 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4198 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4203 if (isLanding() && landhard) {
4206 animTarget = getLandhard();
4219 void Person::DoStuff()
4221 static XYZ terrainnormal;
4222 static XYZ flatfacing;
4223 static XYZ flatvelocity;
4224 static float flatvelspeed;
4228 static int bloodsize;
4229 static int startx, starty, endx, endy;
4230 static GLubyte color;
4231 static XYZ bloodvel;
4233 onfiredelay -= multiplier;
4234 if (onfiredelay < 0 && onfire) {
4235 if (Random() % 2 == 0) {
4241 crouchkeydowntime += multiplier;
4243 crouchkeydowntime = 0;
4244 jumpkeydowntime += multiplier;
4245 if (!jumpkeydown && skeleton.free)
4246 jumpkeydowntime = 0;
4248 if (hostile || damage > 0 || bloodloss > 0)
4251 if (isIdle() || isRun())
4254 if (num_weapons == 1 && weaponactive != -1)
4258 blooddimamount -= multiplier * .3;
4259 speechdelay -= multiplier;
4260 texupdatedelay -= multiplier;
4261 interestdelay -= multiplier;
4262 flamedelay -= multiplier;
4263 parriedrecently -= multiplier;
4265 victim = this->shared_from_this();
4270 speed = 1.1 * speedmult;
4272 speed = 1.0 * speedmult;
4274 rabbitkickragdoll = 0;
4278 if (id != 0 && (creature == rabbittype || difficulty != 2))
4280 if (id != 0 && creature == wolftype && difficulty == 2) {
4282 if (aitype != passivetype) {
4284 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) {
4290 if (animTarget == wolfrunninganim && !superruntoggle) {
4291 animTarget = getRun();
4295 if (weaponactive == -1 && num_weapons > 0) {
4296 if (weapons[weaponids[0]].getType() == staff) {
4302 burnt += multiplier;
4306 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4308 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4314 vel[0] = velocity.x;
4315 vel[1] = velocity.y;
4316 vel[2] = velocity.z;
4319 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4320 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4324 while (flamedelay < 0 && onfire) {
4326 howmany = abs(Random() % (skeleton.num_joints));
4327 if (skeleton.free) {
4328 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4329 flatfacing = skeleton.joints[howmany].position * scale + coords;
4331 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4332 flatvelocity = (coords - oldcoords) / multiplier / 2;
4334 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4337 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4339 howmany = abs(Random() % (skeleton.num_joints));
4340 if (skeleton.free) {
4341 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4342 flatfacing = skeleton.joints[howmany].position * scale + coords;
4344 flatvelocity = (coords - oldcoords) / multiplier / 2;
4345 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4347 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4351 bleeding -= multiplier * .3;
4352 if (bloodtoggle == 2) {
4353 skeleton.drawmodel.textureptr.bind();
4354 if ((bleeding <= 0) && (detail != 2))
4359 if (neckspurtamount > 0) {
4360 neckspurtamount -= multiplier;
4361 neckspurtdelay -= multiplier * 3;
4362 neckspurtparticledelay -= multiplier * 3;
4363 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4366 if (skeleton.free) {
4367 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4368 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4369 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4371 bloodvel.z = 5 * neckspurtamount;
4372 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4373 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4374 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4376 neckspurtparticledelay = .05;
4378 if (neckspurtdelay < 0) {
4383 if (deathbleeding > 0 && dead != 2) {
4384 if (deathbleeding < 5)
4385 bleeddelay -= deathbleeding * multiplier / 4;
4387 bleeddelay -= 5 * multiplier / 4;
4388 if (bleeddelay < 0 && bloodtoggle) {
4393 if (skeleton.free) {
4394 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4395 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4397 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4398 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4402 bloodloss += deathbleeding * multiplier * 80;
4403 deathbleeding -= multiplier * 1.6;
4404 if (deathbleeding < 0)
4406 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4407 if (weaponactive != -1) {
4408 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4409 weapons[weaponids[0]].velocity.x += .01;
4412 weaponids[0] = weaponids[num_weapons];
4413 if (weaponstuck == num_weapons)
4417 for (unsigned i = 0; i < Person::players.size(); i++) {
4418 Person::players[i]->wentforweapon = 0;
4426 if (!dead && creature == wolftype) {
4427 award_bonus(0, Wolfbonus);
4430 if (animTarget == knifefollowedanim && !skeleton.free) {
4431 for (int i = 0; i < skeleton.num_joints; i++) {
4432 skeleton.joints[i].velocity = 0;
4433 skeleton.joints[i].velocity.y = -2;
4436 if (id != 0 && unconscioustime > .1) {
4444 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4445 texupdatedelay = .12;
4447 bloodsize = 5 - realtexdetail;
4451 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4452 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4453 endx = startx + bloodsize;
4454 endy = starty + bloodsize;
4464 if (endx > skeleton.skinsize - 1) {
4465 endx = skeleton.skinsize - 1;
4468 if (endy > skeleton.skinsize - 1) {
4469 endy = skeleton.skinsize - 1;
4477 for (i = startx; i < endx; i++) {
4478 for (j = starty; j < endy; j++) {
4479 if (Random() % 2 == 0) {
4480 color = Random() % 85 + 170;
4481 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4482 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4483 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4484 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4489 skeleton.drawmodel.textureptr.bind();
4493 if (skeleton.free) {
4494 bleedx += 4 * direction / realtexdetail;
4496 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4498 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4500 bleedy -= 4 / realtexdetail;
4502 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4504 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4508 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4509 righthandmorphness = targetrighthandmorphness;
4510 righthandmorphstart = righthandmorphend;
4511 } else if (righthandmorphness > targetrighthandmorphness) {
4512 righthandmorphness -= multiplier * 4;
4513 } else if (righthandmorphness < targetrighthandmorphness) {
4514 righthandmorphness += multiplier * 4;
4517 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4518 lefthandmorphness = targetlefthandmorphness;
4519 lefthandmorphstart = lefthandmorphend;
4520 } else if (lefthandmorphness > targetlefthandmorphness) {
4521 lefthandmorphness -= multiplier * 4;
4522 } else if (lefthandmorphness < targetlefthandmorphness) {
4523 lefthandmorphness += multiplier * 4;
4526 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4527 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4528 tailmorphness = targettailmorphness;
4529 tailmorphstart = tailmorphend;
4530 } else if (tailmorphness > targettailmorphness) {
4531 tailmorphness -= multiplier * 10;
4532 } else if (tailmorphness < targettailmorphness) {
4533 tailmorphness += multiplier * 10;
4537 if (creature == wolftype) {
4538 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4539 tailmorphness = targettailmorphness;
4540 tailmorphstart = tailmorphend;
4541 } else if (tailmorphness > targettailmorphness) {
4542 tailmorphness -= multiplier * 2;
4543 } else if (tailmorphness < targettailmorphness) {
4544 tailmorphness += multiplier * 2;
4548 if (headmorphend == 3 || headmorphstart == 3) {
4549 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4550 headmorphness = targetheadmorphness;
4551 headmorphstart = headmorphend;
4552 } else if (headmorphness > targetheadmorphness) {
4553 headmorphness -= multiplier * 7;
4554 } else if (headmorphness < targetheadmorphness) {
4555 headmorphness += multiplier * 7;
4557 } else if (headmorphend == 5 || headmorphstart == 5) {
4558 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4559 headmorphness = targetheadmorphness;
4560 headmorphstart = headmorphend;
4561 } else if (headmorphness > targetheadmorphness) {
4562 headmorphness -= multiplier * 10;
4563 } else if (headmorphness < targetheadmorphness) {
4564 headmorphness += multiplier * 10;
4567 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4568 headmorphness = targetheadmorphness;
4569 headmorphstart = headmorphend;
4570 } else if (headmorphness > targetheadmorphness) {
4571 headmorphness -= multiplier * 4;
4572 } else if (headmorphness < targetheadmorphness) {
4573 headmorphness += multiplier * 4;
4577 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4578 chestmorphness = targetchestmorphness;
4579 chestmorphstart = chestmorphend;
4580 } else if (chestmorphness > targetchestmorphness) {
4581 chestmorphness -= multiplier;
4582 } else if (chestmorphness < targetchestmorphness) {
4583 chestmorphness += multiplier;
4586 if (dead != 2 && howactive <= typesleeping) {
4587 if (chestmorphstart == 0 && chestmorphend == 0) {
4589 targetchestmorphness = 1;
4592 if (chestmorphstart != 0 && chestmorphend != 0) {
4594 targetchestmorphness = 1;
4596 if (environment == snowyenvironment) {
4599 if (skeleton.free) {
4600 footvel = skeleton.specialforward[0] * -1;
4601 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4603 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4604 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4606 if (animTarget == sleepanim)
4607 footvel = DoRotation(footvel, 0, 90, 0);
4608 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4612 if (!dead && howactive < typesleeping) {
4613 blinkdelay -= multiplier * 2;
4614 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4616 targetheadmorphness = 1;
4618 blinkdelay = (float)(abs(Random() % 40)) / 5;
4620 if (headmorphstart == 3 && headmorphend == 3) {
4622 targetheadmorphness = 1;
4627 twitchdelay -= multiplier * 1.5;
4628 if (animTarget != hurtidleanim) {
4629 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4631 targetheadmorphness = 1;
4633 twitchdelay = (float)(abs(Random() % 40)) / 5;
4635 if (headmorphstart == 5 && headmorphend == 5) {
4637 targetheadmorphness = 1;
4641 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4642 twitchdelay3 -= multiplier * 1;
4643 if (Random() % 2 == 0) {
4644 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4645 righthandmorphness = 0;
4646 targetrighthandmorphness = 1;
4647 righthandmorphend = 1;
4648 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4650 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4651 righthandmorphness = 0;
4652 targetrighthandmorphness = 1;
4653 righthandmorphend = 0;
4656 if (Random() % 2 == 0) {
4657 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4658 lefthandmorphness = 0;
4659 targetlefthandmorphness = 1;
4660 lefthandmorphend = 1;
4661 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4663 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4664 lefthandmorphness = 0;
4665 targetlefthandmorphness = 1;
4666 lefthandmorphend = 0;
4672 if (creature == rabbittype) {
4673 if (howactive < typesleeping)
4674 twitchdelay2 -= multiplier * 1.5;
4676 twitchdelay2 -= multiplier * 0.5;
4677 if (howactive <= typesleeping) {
4678 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4680 targettailmorphness = 1;
4682 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4684 if (tailmorphstart == 1 && tailmorphend == 1) {
4686 targettailmorphness = 1;
4689 if (tailmorphstart == 2 && tailmorphend == 2) {
4691 targettailmorphness = 1;
4698 if (creature == wolftype) {
4699 twitchdelay2 -= multiplier * 1.5;
4700 if (tailmorphend != 0)
4701 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4703 targettailmorphness = 1;
4707 if (tailmorphend != 5)
4708 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4710 targettailmorphness = 1;
4714 if (twitchdelay2 <= 0) {
4715 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4717 targettailmorphness = 1;
4720 if (tailmorphstart == 1 && tailmorphend == 1) {
4722 targettailmorphness = 1;
4725 if (tailmorphstart == 2 && tailmorphend == 2) {
4727 targettailmorphness = 1;
4730 if (tailmorphstart == 3 && tailmorphend == 3) {
4732 targettailmorphness = 1;
4735 if (tailmorphstart == 4 && tailmorphend == 4) {
4737 targettailmorphness = 1;
4744 unconscioustime = 0;
4746 if (dead == 1 || howactive == typesleeping) {
4747 unconscioustime += multiplier;
4748 //If unconscious, close eyes and mouth
4749 if (righthandmorphend != 0)
4750 righthandmorphness = 0;
4751 righthandmorphend = 0;
4752 targetrighthandmorphness = 1;
4754 if (lefthandmorphend != 0)
4755 lefthandmorphness = 0;
4756 lefthandmorphend = 0;
4757 targetlefthandmorphness = 1;
4759 if (headmorphend != 3 && headmorphend != 5)
4762 targetheadmorphness = 1;
4766 if (howactive > typesleeping) {
4769 if (bloodtoggle && !bled) {
4770 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4772 if (bloodtoggle && !bled)
4773 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4774 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4775 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4779 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4784 if (dead == 2 || howactive > typesleeping) {
4785 //If dead, open mouth and hands
4786 if (righthandmorphend != 0)
4787 righthandmorphness = 0;
4788 righthandmorphend = 0;
4789 targetrighthandmorphness = 1;
4791 if (lefthandmorphend != 0)
4792 lefthandmorphness = 0;
4793 lefthandmorphend = 0;
4794 targetlefthandmorphness = 1;
4796 if (headmorphend != 2)
4799 targetheadmorphness = 1;
4802 if (stunned > 0 && !dead && headmorphend != 2) {
4803 if (headmorphend != 4)
4806 targetheadmorphness = 1;
4809 if (damage > damagetolerance && !dead) {
4812 unconscioustime = 0;
4814 if (creature == wolftype) {
4815 award_bonus(0, Wolfbonus);
4820 if (weaponactive != -1) {
4821 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4822 weapons[weaponids[0]].velocity.x += .01;
4825 weaponids[0] = weaponids[num_weapons];
4826 if (weaponstuck == num_weapons)
4830 for (unsigned i = 0; i < Person::players.size(); i++) {
4831 Person::players[i]->wentforweapon = 0;
4837 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4846 damage -= multiplier * 13;
4848 permanentdamage -= multiplier * 4;
4849 if (isIdle() || isCrouch()) {
4851 permanentdamage -= multiplier * 4;
4855 if (permanentdamage < 0)
4856 permanentdamage = 0;
4857 if (superpermanentdamage < 0)
4858 superpermanentdamage = 0;
4859 if (permanentdamage < superpermanentdamage) {
4860 permanentdamage = superpermanentdamage;
4862 if (damage < permanentdamage) {
4863 damage = permanentdamage;
4865 if (dead == 1 && damage < damagetolerance) {
4869 for (int i = 0; i < skeleton.num_joints; i++) {
4870 skeleton.joints[i].velocity = 0;
4873 if (permanentdamage > damagetolerance && dead != 2) {
4876 if (weaponactive != -1) {
4877 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4878 weapons[weaponids[0]].velocity.x += .01;
4881 weaponids[0] = weaponids[num_weapons];
4882 if (weaponstuck == num_weapons)
4886 for (unsigned i = 0; i < Person::players.size(); i++) {
4887 Person::players[i]->wentforweapon = 0;
4893 if (!dead && creature == wolftype) {
4894 award_bonus(0, Wolfbonus);
4897 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4898 award_bonus(id, touchofdeath);
4899 if (id != 0 && unconscioustime > .1) {
4907 emit_sound_at(breaksound, coords);
4910 if (skeleton.free == 1) {
4912 pause_sound(whooshsound);
4915 //If knocked over, open hands and close mouth
4916 if (righthandmorphend != 0)
4917 righthandmorphness = 0;
4918 righthandmorphend = 0;
4919 targetrighthandmorphness = 1;
4921 if (lefthandmorphend != 0)
4922 lefthandmorphness = 0;
4923 lefthandmorphend = 0;
4924 targetlefthandmorphness = 1;
4926 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4927 if (headmorphend != 0)
4930 targetheadmorphness = 1;
4934 skeleton.DoGravity(&scale);
4936 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4937 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4938 award_bonus(id, deepimpact);
4939 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4943 for (j = 0; j < skeleton.num_joints; j++) {
4944 average += skeleton.joints[j].position;
4948 coords += average * scale;
4949 for (j = 0; j < skeleton.num_joints; j++) {
4950 skeleton.joints[j].position -= average;
4952 average /= multiplier;
4955 for (int i = 0; i < skeleton.num_joints; i++) {
4956 velocity += skeleton.joints[i].velocity * scale;
4958 velocity /= skeleton.num_joints;
4960 if (!isnormal(velocity.x) && velocity.x) {
4964 if (findLength(&average) < 10 && dead && skeleton.free) {
4965 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4966 if (skeleton.longdead > 2000) {
4967 if (skeleton.longdead > 6000) {
4969 pause_sound(whooshsound);
4974 if (dead == 2 && bloodloss < damagetolerance) {
4976 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4978 if (bloodtoggle && !bled) {
4979 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4981 if (bloodtoggle && !bled)
4982 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4983 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4984 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4985 float size = .2 * 1.2;
4988 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4992 if (dead == 2 && bloodloss >= damagetolerance) {
4994 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4997 if (bloodtoggle && !bled) {
4998 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5000 if (bloodtoggle && !bled)
5001 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5002 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5003 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5007 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5014 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5015 bool canrecover = 1;
5016 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5017 startpoint = coords;
5020 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5022 if (velocity.y < -30)
5024 for (i = 0; i < objects.numobjects; i++) {
5025 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5026 colviewer = startpoint;
5027 coltarget = endpoint;
5028 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5037 terrainnormal = jointPos(groin) - jointPos(abdomen);
5038 if (joint(groin).locked && joint(abdomen).locked) {
5039 terrainnormal = jointPos(groin) - jointPos(abdomen);
5040 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5042 if (joint(abdomen).locked && joint(neck).locked) {
5043 terrainnormal = jointPos(abdomen) - jointPos(neck);
5044 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5046 if (joint(groin).locked && joint(neck).locked) {
5047 terrainnormal = jointPos(groin) - jointPos(neck);
5048 middle = (jointPos(groin) + jointPos(neck)) / 2;
5050 Normalise(&terrainnormal);
5052 targetyaw = -asin(0 - terrainnormal.x);
5053 targetyaw *= 360 / 6.28;
5054 if (terrainnormal.z < 0)
5055 targetyaw = 180 - targetyaw;
5059 animTarget = flipanim;
5060 crouchtogglekeydown = 1;
5065 animCurrent = tempanim;
5069 for (int i = 0; i < skeleton.num_joints; i++) {
5070 tempanimation.position[i][0] = skeleton.joints[i].position;
5071 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5076 if (findLength(&average) < 10 && !dead && skeleton.free) {
5077 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5078 if (skeleton.longdead > (damage + 500) * 1.5) {
5080 pause_sound(whooshsound);
5086 terrainnormal = jointPos(groin) - jointPos(abdomen);
5087 if (joint(groin).locked && joint(abdomen).locked) {
5088 terrainnormal = jointPos(groin) - jointPos(abdomen);
5089 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5091 if (joint(abdomen).locked && joint(neck).locked) {
5092 terrainnormal = jointPos(abdomen) - jointPos(neck);
5093 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5095 if (joint(groin).locked && joint(neck).locked) {
5096 terrainnormal = jointPos(groin) - jointPos(neck);
5097 middle = (jointPos(groin) + jointPos(neck)) / 2;
5099 Normalise(&terrainnormal);
5101 targetyaw = -asin(0 - terrainnormal.x);
5102 targetyaw *= 360 / 6.28;
5103 if (terrainnormal.z < 0)
5104 targetyaw = 180 - targetyaw;
5107 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5110 if (skeleton.forward.y < 0) {
5111 animTarget = getupfrombackanim;
5115 if (skeleton.forward.y > -.3) {
5116 animTarget = getupfromfrontanim;
5124 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5125 animTarget = rollanim;
5126 targetyaw = lookyaw;
5143 if ( !leftkeydown && !rightkeydown)
5150 if (abs(targettilt2) > 50)
5152 animCurrent = tempanim;
5155 tilt2 = targettilt2;
5157 if (middle.y > 0 && animTarget != rollanim)
5158 targetoffset.y = middle.y + 1;
5160 for (int i = 0; i < skeleton.num_joints; i++) {
5161 tempanimation.position[i][0] = skeleton.joints[i].position;
5162 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5169 if (num_weapons > 0)
5170 if (weapons[0].getType() == staff)
5172 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5173 if (velocity.y > -30) {
5175 tempvelocity = velocity;
5176 Normalise(&tempvelocity);
5177 targetyaw = -asin(0 - tempvelocity.x);
5178 targetyaw *= 360 / 6.28;
5180 targetyaw = 180 - targetyaw;
5184 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5185 animTarget = rollanim;
5188 animTarget = backhandspringanim;
5194 emit_sound_at(movewhooshsound, coords, 128.);
5196 animCurrent = animTarget;
5197 frameCurrent = frameTarget - 1;
5209 if (skeleton.freefall == 0)
5214 if (aitype != passivetype || skeleton.free == 1)
5215 if (findLengthfast(&velocity) > .1)
5216 for (i = 0; i < objects.numobjects; i++) {
5217 if (objects.type[i] == firetype)
5218 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) {
5220 if (!objects.onfire[i]) {
5221 emit_sound_at(firestartsound, objects.position[i]);
5223 objects.onfire[i] = 1;
5226 if (objects.onfire[i]) {
5231 if (objects.type[i] == bushtype)
5232 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) {
5234 if (!objects.onfire[i]) {
5235 emit_sound_at(firestartsound, objects.position[i]);
5237 objects.onfire[i] = 1;
5241 if (objects.onfire[i]) {
5245 if (objects.messedwith[i] <= 0) {
5249 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5252 addEnvSound(coords, 4 * findLength(&velocity));
5256 if (environment == grassyenvironment)
5257 howmany = findLength(&velocity) * 4;
5258 if (environment == snowyenvironment)
5259 howmany = findLength(&velocity) * 2;
5261 if (environment != desertenvironment)
5262 for (j = 0; j < howmany; j++) {
5263 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5264 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5265 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5268 pos.x += float(abs(Random() % 100) - 50) / 200;
5269 pos.y += float(abs(Random() % 100) - 50) / 200;
5270 pos.z += float(abs(Random() % 100) - 50) / 200;
5271 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);
5272 Sprite::setLastSpriteSpecial(1);
5274 howmany = findLength(&velocity) * 4;
5276 if (environment == snowyenvironment)
5277 for (j = 0; j < howmany; j++) {
5278 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5279 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5280 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5283 pos.x += float(abs(Random() % 100) - 50) / 200;
5284 pos.y += float(abs(Random() % 100) - 50) / 200;
5285 pos.z += float(abs(Random() % 100) - 50) / 200;
5286 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5287 Sprite::setLastSpriteSpecial(2);
5290 objects.rotx[i] += velocity.x * multiplier * 6;
5291 objects.roty[i] += velocity.z * multiplier * 6;
5292 objects.messedwith[i] = .5;
5295 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5296 if (objects.pitch[i] == 0)
5299 tempcoord = coords - objects.position[i];
5300 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5301 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5302 tempcoord += objects.position[i];
5304 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]) {
5305 if (objects.messedwith[i] <= 0) {
5309 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5312 addEnvSound(coords, 4 * findLength(&velocity));
5316 if (environment == grassyenvironment)
5317 howmany = findLength(&velocity) * 4;
5318 if (environment == snowyenvironment)
5319 howmany = findLength(&velocity) * 2;
5321 if (environment != desertenvironment)
5322 for (j = 0; j < howmany; j++) {
5323 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5324 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5325 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5327 pos += velocity * .1;
5329 pos.x += float(abs(Random() % 100) - 50) / 150;
5330 pos.y += float(abs(Random() % 100) - 50) / 150;
5331 pos.z += float(abs(Random() % 100) - 50) / 150;
5332 Sprite::MakeSprite(splintersprite, pos, tempvel * .5 + velocity * float(abs(Random() % 100)) / 100, 165 / 255 + float(abs(Random() % 100) - 50) / 400, 0, 0, .2 + float(abs(Random() % 100) - 50) / 1300, 1);
5333 Sprite::setLastSpriteSpecial(1);
5335 howmany = findLength(&velocity) * 4;
5337 if (environment == snowyenvironment)
5338 for (j = 0; j < howmany; j++) {
5339 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5340 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5341 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5343 pos += velocity * .1;
5345 pos.x += float(abs(Random() % 100) - 50) / 150;
5346 pos.y += float(abs(Random() % 100) - 50) / 150;
5347 pos.z += float(abs(Random() % 100) - 50) / 150;
5348 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5349 Sprite::setLastSpriteSpecial(2);
5352 objects.messedwith[i] = .5;
5357 if (!skeleton.free) {
5360 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5363 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5365 if (tutoriallevel == 1 && id != 0)
5367 if (play && aitype != playercontrolled) {
5368 int whichsound = -1;
5369 i = abs(Random() % 4);
5370 if (speechdelay <= 0) {
5371 if (creature == rabbittype) {
5373 whichsound = rabbitchitter;
5375 whichsound = rabbitchitter2;
5377 if (creature == wolftype) {
5379 whichsound = growlsound;
5381 whichsound = growl2sound;
5386 if (whichsound != -1) {
5387 emit_sound_at(whichsound, coords);
5391 if (animTarget == staggerbackhighanim)
5393 if (animTarget == staggerbackhardanim)
5395 staggerdelay -= multiplier;
5396 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5398 if (velocity.y < -30 && animTarget == jumpdownanim)
5400 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5401 animTarget = getIdle();
5405 weaponmissdelay -= multiplier;
5406 highreversaldelay -= multiplier;
5407 lowreversaldelay -= multiplier;
5408 lastcollide -= multiplier;
5409 skiddelay -= multiplier;
5410 if (!isnormal(velocity.x) && velocity.x) {
5413 if (!isnormal(targettilt) && targettilt) {
5416 if (!isnormal(targettilt2) && targettilt2) {
5419 if (!isnormal(targetyaw) && targetyaw) {
5423 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5424 //open hands and close mouth
5425 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5426 righthandmorphness = 0;
5427 righthandmorphend = 0;
5428 targetrighthandmorphness = 1;
5431 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5432 lefthandmorphness = 0;
5433 lefthandmorphend = 0;
5434 targetlefthandmorphness = 1;
5437 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5440 targetheadmorphness = 1;
5444 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) {
5445 //open hands and mouth
5446 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5447 righthandmorphness = 0;
5448 righthandmorphend = 0;
5449 targetrighthandmorphness = 1;
5452 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5453 lefthandmorphness = 0;
5454 lefthandmorphend = 0;
5455 targetlefthandmorphness = 1;
5458 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5461 targetheadmorphness = 1;
5465 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5466 //close hands and mouth
5467 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5468 righthandmorphness = 0;
5469 righthandmorphend = 1;
5470 targetrighthandmorphness = 1;
5473 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5474 lefthandmorphness = 0;
5475 lefthandmorphend = 1;
5476 targetlefthandmorphness = 1;
5479 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5482 targetheadmorphness = 1;
5486 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) {
5487 //close hands and yell
5488 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5489 righthandmorphness = 0;
5490 righthandmorphend = 1;
5491 targetrighthandmorphness = 1;
5494 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5495 lefthandmorphness = 0;
5496 lefthandmorphend = 1;
5497 targetlefthandmorphness = 1;
5500 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5503 targetheadmorphness = 1;
5510 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5511 (victim->aitype != searchtype) && (aitype != passivetype) &&
5512 (aitype != searchtype) && (victim->id < Person::players.size())) {
5513 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5517 if (!dead && animTarget != hurtidleanim)
5518 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5519 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5522 targetheadmorphness = 1;
5526 if (weaponactive != -1) {
5527 if (weapons[weaponids[weaponactive]].getType() != staff) {
5528 righthandmorphstart = 1;
5529 righthandmorphend = 1;
5531 if (weapons[weaponids[weaponactive]].getType() == staff) {
5532 righthandmorphstart = 2;
5533 righthandmorphend = 2;
5535 targetrighthandmorphness = 1;
5538 terrainnormal = terrain.getNormal(coords.x, coords.z);
5540 if (animation[animTarget].attack != reversal) {
5541 if (!isnormal(coords.x))
5549 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5550 facing = flatfacing;
5551 ReflectVector(&facing, terrainnormal);
5554 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5556 targettilt2 = -facing.y * 20;
5561 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5563 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5564 flatvelocity = velocity;
5566 flatvelspeed = findLength(&flatvelocity);
5567 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5568 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5573 if (targettilt > 25)
5575 if (targettilt < -25)
5579 if (targettilt2 > 45)
5581 if (targettilt2 < -45)
5583 if (abs(tilt2 - targettilt2) < multiplier * 400)
5584 tilt2 = targettilt2;
5585 else if (tilt2 > targettilt2) {
5586 tilt2 -= multiplier * 400;
5587 } else if (tilt2 < targettilt2) {
5588 tilt2 += multiplier * 400;
5590 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5597 if (!isnormal(targettilt) && targettilt) {
5600 if (!isnormal(targettilt2) && targettilt2) {
5605 if (animTarget == rabbittackleanim) {
5606 velocity += facing * multiplier * speed * 700 * scale;
5607 velspeed = findLength(&velocity);
5608 if (velspeed > speed * 65 * scale) {
5609 velocity /= velspeed;
5610 velspeed = speed * 65 * scale;
5611 velocity *= velspeed;
5613 velocity.y += gravity * multiplier * 20;
5614 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5615 velspeed = findLength(&velocity);
5616 velocity = flatfacing * velspeed;
5618 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5619 if (isRun() || animTarget == rabbitkickanim) {
5620 velocity += facing * multiplier * speed * 700 * scale;
5621 velspeed = findLength(&velocity);
5622 if (velspeed > speed * 45 * scale) {
5623 velocity /= velspeed;
5624 velspeed = speed * 45 * scale;
5625 velocity *= velspeed;
5627 velocity.y += gravity * multiplier * 20;
5628 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5629 velspeed = findLength(&velocity);
5630 if (velspeed < speed * 30 * scale)
5631 velspeed = speed * 30 * scale;
5632 velocity = flatfacing * velspeed;
5634 } else if (isRun()) {
5635 velocity += facing * multiplier * speed * 700 * scale;
5636 velspeed = findLength(&velocity);
5637 if (creature == rabbittype) {
5638 if (velspeed > speed * 55 * scale) {
5639 velocity /= velspeed;
5640 velspeed = speed * 55 * scale;
5641 velocity *= velspeed;
5644 if (creature == wolftype) {
5645 if (velspeed > speed * 75 * scale) {
5646 velocity /= velspeed;
5647 velspeed = speed * 75 * scale;
5648 velocity *= velspeed;
5651 velocity.y += gravity * multiplier * 20;
5652 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5653 velspeed = findLength(&velocity);
5654 velocity = flatfacing * velspeed;
5657 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5658 velocity += facing * multiplier * speed * 700 * scale;
5659 velspeed = findLength(&velocity);
5660 if (velspeed > speed * 45 * scale) {
5661 velocity /= velspeed;
5662 velspeed = speed * 45 * scale;
5663 velocity *= velspeed;
5665 velocity.y += gravity * multiplier * 20;
5666 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5667 velspeed = findLength(&velocity);
5668 velocity = flatfacing * velspeed;
5671 if (animTarget == sneakanim || animTarget == walkanim) {
5672 velocity += facing * multiplier * speed * 700 * scale;
5673 velspeed = findLength(&velocity);
5674 if (velspeed > speed * 12 * scale) {
5675 velocity /= velspeed;
5676 velspeed = speed * 12 * scale;
5677 velocity *= velspeed;
5679 velocity.y += gravity * multiplier * 20;
5680 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5681 velspeed = findLength(&velocity);
5682 velocity = flatfacing * velspeed;
5685 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5686 velocity += facing * multiplier * speed * 700 * scale;
5687 velspeed = findLength(&velocity);
5688 if (velspeed > speed * 2 * scale) {
5689 velocity /= velspeed;
5690 velspeed = speed * 2 * scale;
5691 velocity *= velspeed;
5693 velocity.y += gravity * multiplier * 20;
5694 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5695 velspeed = findLength(&velocity);
5696 velocity = flatfacing * velspeed;
5700 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5701 velocity -= facing * multiplier * speed * 700 * scale;
5702 velspeed = findLength(&velocity);
5703 if (velspeed > speed * 2 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 2 * scale;
5706 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = flatfacing * velspeed * -1;
5714 if (animTarget == fightsidestep) {
5715 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5716 velspeed = findLength(&velocity);
5717 if (velspeed > speed * 12 * scale) {
5718 velocity /= velspeed;
5719 velspeed = speed * 12 * scale;
5720 velocity *= velspeed;
5722 velocity.y += gravity * multiplier * 20;
5723 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5724 velspeed = findLength(&velocity);
5725 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5728 if (animTarget == staggerbackhighanim) {
5729 coords -= facing * multiplier * speed * 16 * scale;
5732 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5733 coords -= facing * multiplier * speed * 20 * scale;
5737 if (animTarget == backhandspringanim) {
5738 //coords-=facing*multiplier*50*scale;
5739 velocity += facing * multiplier * speed * 700 * scale * -1;
5740 velspeed = findLength(&velocity);
5741 if (velspeed > speed * 50 * scale) {
5742 velocity /= velspeed;
5743 velspeed = speed * 50 * scale;
5744 velocity *= velspeed;
5746 velocity.y += gravity * multiplier * 20;
5747 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5748 velspeed = findLength(&velocity);
5749 velocity = flatfacing * velspeed * -1;
5751 if (animTarget == dodgebackanim) {
5752 //coords-=facing*multiplier*50*scale;
5753 velocity += facing * multiplier * speed * 700 * scale * -1;
5754 velspeed = findLength(&velocity);
5755 if (velspeed > speed * 60 * scale) {
5756 velocity /= velspeed;
5757 velspeed = speed * 60 * scale;
5758 velocity *= velspeed;
5760 velocity.y += gravity * multiplier * 20;
5761 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5762 velspeed = findLength(&velocity);
5763 velocity = flatfacing * velspeed * -1;
5766 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5767 velspeed = findLength(&velocity);
5771 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5772 velocity.y += gravity * multiplier;
5775 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5776 coords += velocity * multiplier;
5778 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5779 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5782 if (animTarget == jumpupanim) {
5784 animTarget = getIdle();
5791 pause_sound(whooshsound);
5792 OPENAL_SetVolume(channels[whooshsound], 0);
5795 if (animTarget == jumpdownanim || isFlip()) {
5796 if (isFlip())jumppower = -4;
5797 animTarget = getLanding();
5798 emit_sound_at(landsound, coords, 128.);
5801 addEnvSound(coords);
5806 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5807 coords.y += gravity * multiplier * 2;
5808 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5809 coords.y = terrain.getHeight(coords.x, coords.z);
5814 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)) {
5815 velspeed = findLength(&velocity);
5817 if (velspeed < multiplier * 300 * scale) {
5820 velocity -= velocity / velspeed * multiplier * 300 * scale;
5821 if (velspeed > 5 && (isLanding() || isLandhard())) {
5822 skiddingdelay += multiplier;
5823 if (skiddelay <= 0) {
5824 FootLand(leftfoot, .5);
5825 FootLand(rightfoot, .5);
5833 velspeed = findLength(&velocity);
5835 if (velspeed < multiplier * 600 * scale) {
5838 velocity -= velocity / velspeed * multiplier * 600 * scale;
5840 if (velspeed > 5 && (isLanding() || isLandhard())) {
5841 skiddingdelay += multiplier;
5842 if (skiddelay <= 0) {
5843 FootLand(leftfoot, .5);
5844 FootLand(rightfoot, .5);
5851 if (skiddingdelay < 0)
5852 skiddingdelay += multiplier;
5853 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5855 if (!onterrain || environment == grassyenvironment) {
5856 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5858 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5862 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5863 terrainnormal = victim->coords - coords;
5864 Normalise(&terrainnormal);
5865 targetyaw = -asin(0 - terrainnormal.x);
5866 targetyaw *= 360 / 6.28;
5867 if (terrainnormal.z < 0)
5868 targetyaw = 180 - targetyaw;
5869 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5872 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5873 targetyaw = victim->targetyaw;
5875 if (animTarget == rabbittacklinganim) {
5876 coords = victim->coords;
5879 skeleton.oldfree = skeleton.free;
5883 midterrain.x = terrain.size * terrain.scale / 2;
5884 midterrain.z = terrain.size * terrain.scale / 2;
5885 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5887 tempposit = coords - midterrain;
5889 Normalise(&tempposit);
5890 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5891 coords.x = tempposit.x + midterrain.x;
5892 coords.z = tempposit.z + midterrain.z;
5898 * inverse kinematics helper function
5900 void IKHelper(Person *p, float interp)
5902 XYZ point, change, change2;
5903 float heightleft, heightright;
5905 // TODO: implement localToWorld and worldToLocal
5906 // but keep in mind it won't be the same math if player is ragdolled or something
5907 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5908 // then comb through code for places where to use it
5910 // point = localToWorld(jointPos(leftfoot))
5911 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5912 // adjust height of foot
5913 heightleft = terrain.getHeight(point.x, point.z) + .04;
5914 point.y = heightleft;
5915 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5916 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5917 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5918 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5919 // move ankle along with foot
5920 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5921 // average knee pos between old and new pos
5922 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5924 // do same as above for right leg
5925 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5926 heightright = terrain.getHeight(point.x, point.z) + .04;
5927 point.y = heightright;
5928 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5929 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5930 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5931 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5932 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5934 // fix up skeleton now that we've moved body parts?
5935 p->skeleton.DoConstraints(&p->coords, &p->scale);
5942 int Person::DrawSkeleton()
5944 int oldplayerdetail;
5945 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5946 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5956 glAlphaFunc(GL_GREATER, 0.0001);
5958 float terrainheight;
5962 if (!isnormal(tilt))
5964 if (!isnormal(tilt2))
5966 oldplayerdetail = playerdetail;
5968 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5971 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5974 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5979 if (playerdetail != oldplayerdetail) {
5981 normalsupdatedelay = 0;
5983 static float updatedelaychange;
5984 static float morphness;
5985 static float framemult;
5987 skeleton.FindForwards();
5988 if (howactive == typesittingwall) {
5989 skeleton.specialforward[1] = 0;
5990 skeleton.specialforward[1].z = 1;
5996 static int weaponattachmuscle;
5997 static int weaponrotatemuscle;
5998 static XYZ weaponpoint;
5999 static int start, endthing;
6000 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6001 if (!isSleeping() && !isSitting()) {
6002 // TODO: give these meaningful names
6003 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6004 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6005 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6006 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6008 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6010 if (creature == wolftype)
6014 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6015 IKHelper(this, target);
6016 if (creature == wolftype)
6017 IKHelper(this, target);
6020 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6021 IKHelper(this, 1 - target);
6022 if (creature == wolftype)
6023 IKHelper(this, 1 - target);
6027 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()))
6030 targetheadyaw = -targetyaw;
6031 targetheadpitch = 0;
6032 if (animation[animTarget].attack == 3)
6033 targetheadyaw += 180;
6035 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6036 skeleton.drawmodel.vertex[i] = 0;
6037 skeleton.drawmodel.vertex[i].y = 999;
6039 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6040 skeleton.drawmodellow.vertex[i] = 0;
6041 skeleton.drawmodellow.vertex[i].y = 999;
6043 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6044 skeleton.drawmodelclothes.vertex[i] = 0;
6045 skeleton.drawmodelclothes.vertex[i].y = 999;
6047 for (int i = 0; i < skeleton.num_muscles; i++) {
6048 // convenience renames
6049 const int p1 = skeleton.muscles[i].parent1->label;
6050 const int p2 = skeleton.muscles[i].parent2->label;
6052 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6057 if (p1 == righthand || p2 == righthand) {
6058 morphness = righthandmorphness;
6059 start = righthandmorphstart;
6060 endthing = righthandmorphend;
6062 if (p1 == lefthand || p2 == lefthand) {
6063 morphness = lefthandmorphness;
6064 start = lefthandmorphstart;
6065 endthing = lefthandmorphend;
6067 if (p1 == head || p2 == head) {
6068 morphness = headmorphness;
6069 start = headmorphstart;
6070 endthing = headmorphend;
6072 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6073 morphness = chestmorphness;
6074 start = chestmorphstart;
6075 endthing = chestmorphend;
6077 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6078 morphness = tailmorphness;
6079 start = tailmorphstart;
6080 endthing = tailmorphend;
6083 skeleton.FindRotationMuscle(i, animTarget);
6084 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6085 glMatrixMode(GL_MODELVIEW);
6089 glRotatef(tilt2, 1, 0, 0);
6091 glRotatef(tilt, 0, 0, 1);
6094 glTranslatef(mid.x, mid.y, mid.z);
6096 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6097 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6099 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6100 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6102 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6103 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6105 if (playerdetail || skeleton.free == 3) {
6106 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6107 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6108 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6109 glMatrixMode(GL_MODELVIEW);
6111 if (p1 == abdomen || p2 == abdomen)
6112 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6113 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6114 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6115 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6116 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6117 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6118 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6119 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6120 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6121 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6122 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6123 if (p1 == head || p2 == head)
6124 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6125 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6126 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6127 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6128 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6129 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6130 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6134 if (!playerdetail || skeleton.free == 3) {
6135 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6136 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6137 glMatrixMode(GL_MODELVIEW);
6139 if (p1 == abdomen || p2 == abdomen)
6140 glTranslatef(v0.x * proportionbody.x,
6141 v0.y * proportionbody.y,
6142 v0.z * proportionbody.z);
6143 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6144 glTranslatef(v0.x * proportionarms.x,
6145 v0.y * proportionarms.y,
6146 v0.z * proportionarms.z);
6147 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6148 glTranslatef(v0.x * proportionlegs.x,
6149 v0.y * proportionlegs.y,
6150 v0.z * proportionlegs.z);
6151 if (p1 == head || p2 == head)
6152 glTranslatef(v0.x * proportionhead.x,
6153 v0.y * proportionhead.y,
6154 v0.z * proportionhead.z);
6156 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6157 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6158 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6159 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6165 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6166 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6168 glMatrixMode(GL_MODELVIEW);
6172 glRotatef(tilt2, 1, 0, 0);
6174 glRotatef(tilt, 0, 0, 1);
6175 glTranslatef(mid.x, mid.y, mid.z);
6176 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6177 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6179 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6180 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6182 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6183 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6185 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6186 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6187 glMatrixMode(GL_MODELVIEW);
6189 if (p1 == abdomen || p2 == abdomen)
6190 glTranslatef(v0.x * proportionbody.x,
6191 v0.y * proportionbody.y,
6192 v0.z * proportionbody.z);
6193 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6194 glTranslatef(v0.x * proportionarms.x,
6195 v0.y * proportionarms.y,
6196 v0.z * proportionarms.z);
6197 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6198 glTranslatef(v0.x * proportionlegs.x,
6199 v0.y * proportionlegs.y,
6200 v0.z * proportionlegs.z);
6201 if (p1 == head || p2 == head)
6202 glTranslatef(v0.x * proportionhead.x,
6203 v0.y * proportionhead.y,
6204 v0.z * proportionhead.z);
6205 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6206 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6207 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6208 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6213 updatedelay = 1 + (float)(Random() % 100) / 1000;
6215 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6216 normalsupdatedelay = 1;
6217 if (playerdetail || skeleton.free == 3)
6218 skeleton.drawmodel.CalculateNormals(0);
6219 if (!playerdetail || skeleton.free == 3)
6220 skeleton.drawmodellow.CalculateNormals(0);
6221 if (skeleton.clothes)
6222 skeleton.drawmodelclothes.CalculateNormals(0);
6224 if (playerdetail || skeleton.free == 3)
6225 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6226 if (!playerdetail || skeleton.free == 3)
6227 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6228 if (skeleton.clothes) {
6229 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6234 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6235 if (updatedelaychange > -realmultiplier * 30)
6236 updatedelaychange = -realmultiplier * 30;
6237 if (updatedelaychange > -framemult * 4)
6238 updatedelaychange = -framemult * 4;
6239 if (skeleton.free == 1)
6240 updatedelaychange *= 6;
6242 updatedelaychange *= 8;
6243 updatedelay += updatedelaychange;
6245 glMatrixMode(GL_MODELVIEW);
6247 glTranslatef(coords.x, coords.y - .02, coords.z);
6248 if (!skeleton.free) {
6249 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6250 glRotatef(yaw, 0, 1, 0);
6254 glColor4f(.4, 1, .4, 1);
6255 glDisable(GL_LIGHTING);
6256 glDisable(GL_TEXTURE_2D);
6259 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6260 XYZ &v0 = skeleton.drawmodel.vertex[i];
6261 glVertex3f(v0.x, v0.y, v0.z);
6267 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6268 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6269 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6270 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6271 glVertex3f(v0.x, v0.y, v0.z);
6272 glVertex3f(v1.x, v1.y, v1.z);
6273 glVertex3f(v1.x, v1.y, v1.z);
6274 glVertex3f(v2.x, v2.y, v2.z);
6275 glVertex3f(v2.x, v2.y, v2.z);
6276 glVertex3f(v0.x, v0.y, v0.z);
6282 terrainlight = terrain.getLighting(coords.x, coords.z);
6283 distance = distsq(&viewer, &coords);
6284 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6288 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6289 if (terrainheight < 1)
6291 if (terrainheight > 1.7)
6292 terrainheight = 1.7;
6294 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6295 glDisable(GL_BLEND);
6296 glAlphaFunc(GL_GREATER, 0.0001);
6297 glEnable(GL_TEXTURE_2D);
6299 glDisable(GL_TEXTURE_2D);
6300 glColor4f(.7, .35, 0, .5);
6302 glEnable(GL_LIGHTING);
6305 if (tutoriallevel && id != 0) {
6306 glColor4f(.7, .7, .7, 0.6);
6308 glEnable(GL_LIGHTING);
6310 if (canattack && cananger)
6311 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6312 glDisable(GL_TEXTURE_2D);
6313 glColor4f(1, 0, 0, 0.8);
6315 glMatrixMode(GL_TEXTURE);
6317 glTranslatef(0, -smoketex, 0);
6318 glTranslatef(-smoketex, 0, 0);
6322 if ((tutoriallevel && id != 0))
6323 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6325 skeleton.drawmodel.draw();
6328 if (!playerdetail) {
6329 if ((tutoriallevel && id != 0))
6330 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6332 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6335 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6336 if (tutoriallevel && id != 0) {
6338 glMatrixMode(GL_MODELVIEW);
6339 glEnable(GL_TEXTURE_2D);
6340 glColor4f(.7, .7, .7, 0.6);
6342 glEnable(GL_LIGHTING);
6344 if (canattack && cananger)
6345 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6346 glDisable(GL_TEXTURE_2D);
6347 glColor4f(1, 0, 0, 0.8);
6349 glMatrixMode(GL_TEXTURE);
6351 glTranslatef(0, -smoketex * .6, 0);
6352 glTranslatef(smoketex * .6, 0, 0);
6355 if ((tutoriallevel && id != 0))
6356 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6358 skeleton.drawmodel.draw();
6361 if (!playerdetail) {
6362 if ((tutoriallevel && id != 0))
6363 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6365 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6370 if (tutoriallevel && id != 0) {
6372 glMatrixMode(GL_MODELVIEW);
6373 glEnable(GL_TEXTURE_2D);
6375 if (skeleton.clothes) {
6379 skeleton.drawmodelclothes.draw();
6381 skeleton.drawmodelclothes.drawimmediate();
6387 if (num_weapons > 0) {
6388 for (k = 0; k < num_weapons; k++) {
6390 if (weaponactive == k) {
6391 if (weapons[i].getType() != staff) {
6392 for (j = 0; j < skeleton.num_muscles; j++) {
6393 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6394 weaponattachmuscle = j;
6397 for (j = 0; j < skeleton.num_muscles; j++) {
6398 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) {
6399 weaponrotatemuscle = j;
6402 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6403 if (creature == wolftype)
6404 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6406 if (weapons[i].getType() == staff) {
6407 for (j = 0; j < skeleton.num_muscles; j++) {
6408 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6409 weaponattachmuscle = j;
6412 for (j = 0; j < skeleton.num_muscles; j++) {
6413 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) {
6414 weaponrotatemuscle = j;
6417 //weaponpoint=jointPos(rightwrist);
6418 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6419 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6420 XYZ tempnormthing, vec1, vec2;
6421 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6422 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6423 CrossProduct(&vec1, &vec2, &tempnormthing);
6424 Normalise(&tempnormthing);
6425 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6426 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6429 if (weaponactive != k && weaponstuck != k) {
6430 if (weapons[i].getType() == knife)
6431 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6432 if (weapons[i].getType() == sword)
6433 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6434 if (weapons[i].getType() == staff)
6435 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6436 for (j = 0; j < skeleton.num_muscles; j++) {
6437 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) {
6438 weaponrotatemuscle = j;
6442 if (weaponstuck == k) {
6443 if (weaponstuckwhere == 0)
6444 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6446 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
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 (skeleton.free) {
6454 weapons[i].position = weaponpoint * scale + coords;
6455 weapons[i].bigrotation = 0;
6456 weapons[i].bigtilt = 0;
6457 weapons[i].bigtilt2 = 0;
6459 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;
6460 weapons[i].bigrotation = yaw;
6461 weapons[i].bigtilt = tilt;
6462 weapons[i].bigtilt2 = tilt2;
6464 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6465 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6466 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6467 if (weaponactive == k) {
6468 if (weapons[i].getType() == knife) {
6469 weapons[i].smallrotation = 180;
6470 weapons[i].smallrotation2 = 0;
6471 if (isCrouch() || wasCrouch()) {
6472 weapons[i].smallrotation2 = 20;
6474 if (animTarget == hurtidleanim) {
6475 weapons[i].smallrotation2 = 50;
6477 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6478 XYZ temppoint1, temppoint2;
6481 temppoint1 = jointPos(righthand);
6482 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6483 distance = findDistance(&temppoint1, &temppoint2);
6484 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6485 weapons[i].rotation2 *= 360 / 6.28;
6488 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6489 weapons[i].rotation1 *= 360 / 6.28;
6490 weapons[i].rotation3 = 0;
6491 weapons[i].smallrotation = -90;
6492 weapons[i].smallrotation2 = 0;
6493 if (temppoint1.x > temppoint2.x)
6494 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6496 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6497 XYZ temppoint1, temppoint2;
6500 temppoint1 = jointPos(righthand);
6501 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6502 distance = findDistance(&temppoint1, &temppoint2);
6503 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6504 weapons[i].rotation2 *= 360 / 6.28;
6507 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6508 weapons[i].rotation1 *= 360 / 6.28;
6509 weapons[i].rotation3 = 0;
6510 weapons[i].smallrotation = 90;
6511 weapons[i].smallrotation2 = 0;
6512 if (temppoint1.x > temppoint2.x)
6513 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6515 if (animTarget == knifethrowanim) {
6516 weapons[i].smallrotation = 90;
6517 //weapons[i].smallrotation2=-90;
6518 weapons[i].smallrotation2 = 0;
6519 weapons[i].rotation1 = 0;
6520 weapons[i].rotation2 = 0;
6521 weapons[i].rotation3 = 0;
6523 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6524 weapons[i].smallrotation = -90;
6525 weapons[i].rotation1 = 0;
6526 weapons[i].rotation2 = 0;
6527 weapons[i].rotation3 = 0;
6530 if (weapons[i].getType() == sword) {
6531 weapons[i].smallrotation = 0;
6532 weapons[i].smallrotation2 = 0;
6533 if (animTarget == knifethrowanim) {
6534 weapons[i].smallrotation = -90;
6535 weapons[i].smallrotation2 = 0;
6536 weapons[i].rotation1 = 0;
6537 weapons[i].rotation2 = 0;
6538 weapons[i].rotation3 = 0;
6540 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)) {
6541 XYZ temppoint1, temppoint2;
6544 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6545 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6546 distance = findDistance(&temppoint1, &temppoint2);
6547 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6548 weapons[i].rotation2 *= 360 / 6.28;
6551 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6552 weapons[i].rotation1 *= 360 / 6.28;
6553 weapons[i].rotation3 = 0;
6554 weapons[i].smallrotation = 90;
6555 weapons[i].smallrotation2 = 0;
6556 if (temppoint1.x > temppoint2.x)
6557 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6560 if (weapons[i].getType() == staff) {
6561 weapons[i].smallrotation = 100;
6562 weapons[i].smallrotation2 = 0;
6563 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6564 XYZ temppoint1, temppoint2;
6567 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6568 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6569 distance = findDistance(&temppoint1, &temppoint2);
6570 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6571 weapons[i].rotation2 *= 360 / 6.28;
6574 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6575 weapons[i].rotation1 *= 360 / 6.28;
6576 weapons[i].rotation3 = 0;
6577 weapons[i].smallrotation = 90;
6578 weapons[i].smallrotation2 = 0;
6579 if (temppoint1.x > temppoint2.x)
6580 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6584 if (weaponactive != k && weaponstuck != k) {
6585 if (weapons[i].getType() == knife) {
6586 weapons[i].smallrotation = -70;
6587 weapons[i].smallrotation2 = 10;
6589 if (weapons[i].getType() == sword) {
6590 weapons[i].smallrotation = -100;
6591 weapons[i].smallrotation2 = -8;
6593 if (weapons[i].getType() == staff) {
6594 weapons[i].smallrotation = -100;
6595 weapons[i].smallrotation2 = -8;
6598 if (weaponstuck == k) {
6599 if (weaponstuckwhere == 0)
6600 weapons[i].smallrotation = 180;
6602 weapons[i].smallrotation = 0;
6603 weapons[i].smallrotation2 = 10;
6612 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6614 if (animCurrent != animTarget)
6616 if (skeleton.free == 2)
6625 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6628 static float distance;
6629 static float olddistance;
6630 static int intersecting;
6631 static int firstintersecting;
6634 static XYZ start, end;
6635 static float slopethreshold = -.4;
6637 firstintersecting = -1;
6641 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6644 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6645 for (i = 0; i < 4; i++) {
6646 for (j = 0; j < model->TriangleNum; j++) {
6647 if (model->facenormals[j].y <= slopethreshold) {
6649 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)));
6650 if (distance < radius) {
6651 point = *p1 - model->facenormals[j] * distance;
6652 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]]))
6655 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6656 &model->vertex[model->Triangles[j].vertex[1]],
6659 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6660 &model->vertex[model->Triangles[j].vertex[2]],
6663 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6664 &model->vertex[model->Triangles[j].vertex[2]],
6667 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6671 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)) {
6672 p1->y = point.y + radius;
6673 if ((animTarget == jumpdownanim || isFlip())) {
6674 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6677 if (animTarget == jumpupanim) {
6679 animTarget = getIdle();
6686 pause_sound(whooshsound);
6687 OPENAL_SetVolume(channels[whooshsound], 0);
6690 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6693 animTarget = getLanding();
6694 emit_sound_at(landsound, coords, 128.);
6697 addEnvSound(coords);
6704 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6705 olddistance = distance;
6706 firstintersecting = j;
6711 for (j = 0; j < model->TriangleNum; j++) {
6712 if (model->facenormals[j].y > slopethreshold) {
6715 start.y -= radius / 4;
6716 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6717 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6718 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6719 distance = abs((model->facenormals[j].x * start.x)
6720 + (model->facenormals[j].y * start.y)
6721 + (model->facenormals[j].z * start.z)
6722 - ((model->facenormals[j].x * v0.x)
6723 + (model->facenormals[j].y * v0.y)
6724 + (model->facenormals[j].z * v0.z)));
6725 if (distance < radius * .5) {
6726 point = start - model->facenormals[j] * distance;
6727 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6730 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6732 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6734 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6736 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6737 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6739 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6740 if (findLengthfast(&start) < findLengthfast(&velocity))
6743 *p1 += model->facenormals[j] * (distance - radius * .5);
6746 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6747 olddistance = distance;
6748 firstintersecting = j;
6755 *p = DoRotation(*p, 0, *rotate, 0);
6758 *p1 = DoRotation(*p1, 0, *rotate, 0);
6760 return firstintersecting;
6763 void Person::takeWeapon(int weaponId)
6766 weapons[weaponId].owner = id;
6767 if (num_weapons > 0) {
6768 weaponids[num_weapons] = weaponids[0];
6771 weaponids[0] = weaponId;
6774 void Person::addClothes()
6776 if (numclothes > 0) {
6777 for (int i = 0; i < numclothes; i++) {
6784 bool Person::addClothes(const int& clothesId)
6787 const char* fileName = clothes[clothesId];
6789 GLubyte* array = &skeleton.skinText[0];
6793 bool opened = load_image(fileName, texture);
6798 float tintr = clothestintr[clothesId];
6799 float tintg = clothestintg[clothesId];
6800 float tintb = clothestintb[clothesId];
6802 if (tintr > 1) tintr = 1;
6803 if (tintg > 1) tintg = 1;
6804 if (tintb > 1) tintb = 1;
6806 if (tintr < 0) tintr = 0;
6807 if (tintg < 0) tintg = 0;
6808 if (tintb < 0) tintb = 0;
6810 int bytesPerPixel = texture.bpp / 8;
6814 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6815 if (bytesPerPixel == 3)
6817 else if ((i + 1) % 4 == 0)
6818 alphanum = texture.data[i];
6819 if ((i + 1) % 4 || bytesPerPixel == 3) {
6821 texture.data[i] *= tintr;
6823 texture.data[i] *= tintg;
6825 texture.data[i] *= tintb;
6826 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);