2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 #include "Utils/Folders.h"
31 extern float multiplier;
32 extern Terrain terrain;
34 extern int environment;
36 extern FRUSTUM frustum;
38 extern float realmultiplier;
40 extern float slomodelay;
41 extern bool cellophane;
42 extern float texdetail;
43 extern float realtexdetail;
44 extern GLubyte bloodText[512 * 512 * 3];
45 extern GLubyte wolfbloodText[512 * 512 * 3];
46 extern int bloodtoggle;
47 extern Objects objects;
48 extern bool autoslomo;
49 extern float camerashake;
51 extern float viewdistance;
52 extern float blackout;
53 extern int difficulty;
55 extern float fadestart;
57 extern bool winfreeze;
58 extern bool showpoints;
59 extern bool immediate;
60 extern int tutoriallevel;
61 extern float smoketex;
62 extern int tutorialstage;
63 extern bool reversaltrain;
64 extern bool canattack;
66 extern float damagedealt;
68 extern float hostiletime;
70 extern bool gamestarted;
72 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
85 howactive(typeactive),
87 superruntoggle(false),
88 lastattack(0), lastattack2(0), lastattack3(0),
89 currentoffset(), targetoffset(), offset(),
121 rabbitkickenabled(false),
133 superpermanentdamage(0),
147 bleedx(0), bleedy(0),
151 headyaw(0), headpitch(0),
152 targetheadyaw(0), targetheadpitch(0),
163 normalsupdatedelay(0),
166 forwardkeydown(false),
167 forwardstogglekeydown(false),
172 jumptogglekeydown(false),
173 crouchkeydown(false),
174 crouchtogglekeydown(false),
176 drawtogglekeydown(false),
178 throwtogglekeydown(false),
179 attackkeydown(false),
184 crouchkeydowntime(0),
198 whichdirection(false),
199 whichdirectiondelay(0),
200 avoidsomething(false),
209 lefthandmorphness(0),
210 righthandmorphness(0),
214 targetlefthandmorphness(0),
215 targetrighthandmorphness(0),
216 targetheadmorphness(0),
217 targetchestmorphness(0),
218 targettailmorphness(0),
219 lefthandmorphstart(0), lefthandmorphend(0),
220 righthandmorphstart(0), righthandmorphend(0),
221 headmorphstart(0), headmorphend(0),
222 chestmorphstart(0), chestmorphend(0),
223 tailmorphstart(0), tailmorphend(0),
226 highreversaldelay(0),
229 creature(rabbittype),
276 finalpathfindpoint(0),
277 targetpathfindpoint(0),
278 lastpathfindpoint(0),
279 lastpathfindpoint2(0),
280 lastpathfindpoint3(0),
281 lastpathfindpoint4(0),
298 neckspurtparticledelay(0),
302 rabbitkickragdoll(false),
310 /* Read a person in tfile. Throws an error if it’s not valid */
311 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
314 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
316 funpackf(tfile, "Bi", &howactive);
318 howactive = typeactive;
321 funpackf(tfile, "Bf", &scale);
326 funpackf(tfile, "Bb", &immobile);
331 funpackf(tfile, "Bf", &yaw);
336 if (num_weapons < 0 || num_weapons > 5) {
337 throw InvalidPersonException();
339 if (num_weapons > 0 && num_weapons < 5) {
340 for (int j = 0; j < num_weapons; j++) {
341 weaponids[j] = weapons.size();
343 funpackf(tfile, "Bi", &type);
344 weapons.push_back(Weapon(type, id));
347 funpackf(tfile, "Bi", &numwaypoints);
348 for (int j = 0; j < numwaypoints; j++) {
349 funpackf(tfile, "Bf", &waypoints[j].x);
350 funpackf(tfile, "Bf", &waypoints[j].y);
351 funpackf(tfile, "Bf", &waypoints[j].z);
353 funpackf(tfile, "Bi", &waypointtype[j]);
355 waypointtype[j] = wpkeepwalking;
359 funpackf(tfile, "Bi", &waypoint);
360 if (waypoint > (numwaypoints - 1)) {
364 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
365 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
366 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
367 funpackf(tfile, "Bf Bf", &power, &speedmult);
369 float headprop, legprop, armprop, bodyprop;
372 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
380 if (creature == wolftype) {
381 proportionhead = 1.1 * headprop;
382 proportionbody = 1.1 * bodyprop;
383 proportionarms = 1.1 * armprop;
384 proportionlegs = 1.1 * legprop;
385 } else if (creature == rabbittype) {
386 proportionhead = 1.2 * headprop;
387 proportionbody = 1.05 * bodyprop;
388 proportionarms = 1.00 * armprop;
389 proportionlegs = 1.1 * legprop;
390 proportionlegs.y = 1.05 * legprop;
393 funpackf(tfile, "Bi", &numclothes);
394 for (int k = 0; k < numclothes; k++) {
396 funpackf(tfile, "Bi", &templength);
397 for (int l = 0; l < templength; l++)
398 funpackf(tfile, "Bb", &clothes[k][l]);
399 clothes[k][templength] = '\0';
400 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
407 * GameTick/doPlayerCollisions
409 void Person::CheckKick()
412 && (animTarget == rabbitkickanim
414 && victim != this->shared_from_this()
416 && animCurrent == rabbitkickanim)
417 && distsq(&coords, &victim->coords) < 1.2
418 && !victim->skeleton.free))
421 if (animation[victim->animTarget].height != lowheight) {
422 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
423 XYZ relative = velocity;
425 Normalise(&relative);
429 if (tutoriallevel != 1)
430 emit_sound_at(heavyimpactsound, victim->coords);
432 for (int i = 0; i < victim->skeleton.num_joints; i++) {
433 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
436 victim->DoDamage(100 * damagemult / victim->protectionhigh);
442 animTarget = backflipanim;
444 velocity = facing * -10;
448 resume_stream(whooshsound);
450 award_bonus(id, cannon);
451 } else if (victim->isCrouch()) {
452 animTarget = rabbitkickreversedanim;
453 animCurrent = rabbitkickreversedanim;
454 victim->animCurrent = rabbitkickreversalanim;
455 victim->animTarget = rabbitkickreversalanim;
461 victim->oldcoords = victim->coords;
462 coords = victim->coords;
463 victim->targetyaw = targetyaw;
464 victim->victim = this->shared_from_this();
471 * GameTick/doPlayerCollisions - spread fire between players
472 * GameTick/doDebugKeys - press f to ignite
473 * Person::DoStuff - spread fire from lit campfires and bushes
475 void Person::CatchFire()
477 XYZ flatfacing, flatvelocity;
479 for (int i = 0; i < 10; i++) {
480 howmany = abs(Random() % (skeleton.num_joints));
482 flatvelocity = skeleton.joints[howmany].velocity;
483 flatfacing = skeleton.joints[howmany].position * scale + coords;
485 flatvelocity = velocity;
486 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
488 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
493 emit_sound_at(firestartsound, coords);
495 emit_stream_at(stream_firesound, coords);
503 * idle animation for this creature (depending on status)
505 int Person::getIdle()
507 if (Dialog::inDialog() && (howactive == typeactive) && (creature == rabbittype))
509 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
510 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
511 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
512 victim->id < Person::players.size())) {
513 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
514 if (creature == rabbittype)
515 return fightidleanim;
516 if (creature == wolftype)
519 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
520 if (weapons[weaponids[weaponactive]].getType() == knife)
521 return knifefightidleanim;
522 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
523 return swordfightidlebothanim;
524 if (weapons[weaponids[weaponactive]].getType() == sword)
525 return swordfightidleanim;
526 if (weapons[weaponids[weaponactive]].getType() == staff)
527 return swordfightidleanim;
529 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
530 return fightsidestep;
532 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
534 if (howactive == typesitting) return sitanim;
535 if (howactive == typesittingwall) return sitwallanim;
536 if (howactive == typesleeping) return sleepanim;
537 if (howactive == typedead1) return dead1anim;
538 if (howactive == typedead2) return dead2anim;
539 if (howactive == typedead3) return dead3anim;
540 if (howactive == typedead4) return dead4anim;
541 if (creature == rabbittype) return bounceidleanim;
542 if (creature == wolftype) return wolfidle;
547 * crouch animation for this creature
549 int Person::getCrouch()
551 if (creature == rabbittype)
553 if (creature == wolftype)
554 return wolfcrouchanim;
559 * running animation for this creature (can be upright or all fours)
563 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
565 if (creature == wolftype && (!superruntoggle))
568 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
569 return rabbitrunninganim;
570 if (creature == wolftype && (superruntoggle))
571 return wolfrunninganim;
577 int Person::getStop()
579 if (creature == rabbittype)
581 if (creature == wolftype)
588 int Person::getLanding()
590 if (creature == rabbittype)
592 if (creature == wolftype)
599 int Person::getLandhard()
601 if (creature == rabbittype)
603 if (creature == wolftype)
604 return wolflandhardanim;
611 * Person::DoAnimations
614 SolidHitBonus(int playerid)
616 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
617 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
619 award_bonus(playerid, solidhit);
623 * spawns blood effects
625 void Person::DoBlood(float howmuch, int which)
627 // FIXME: should abstract out inputs
628 static int bleedxint, bleedyint;
630 if (bloodtoggle && tutoriallevel != 1) {
631 if (bleeding <= 0 && spurt) {
633 for (int i = 0; i < 3; i++) {
634 // emit blood particles
637 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
638 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
639 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
640 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
643 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
644 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
645 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
646 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
649 if (Random() % 2 == 0) // 50% chance
650 for (int i = 0; i < 3; i++) {
651 if (Random() % 2 != 0) {
652 // emit teeth particles
655 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
656 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
659 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
660 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
664 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
666 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
668 Sprite::setLastSpriteSpecial(3); // sets it to teeth
673 // FIXME: manipulating attributes
674 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
677 if (creature == rabbittype)
678 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) {
679 bleedxint = abs(Random() % 512);
680 bleedyint = abs(Random() % 512);
682 if (creature == wolftype)
683 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) {
684 bleedxint = abs(Random() % 512);
685 bleedyint = abs(Random() % 512);
689 bleedy /= realtexdetail;
690 bleedx /= realtexdetail;
691 direction = abs(Random() % 2) * 2 - 1;
700 * spawns big blood effects and ???
701 * modifies character's skin texture
703 void Person::DoBloodBig(float howmuch, int which)
705 static int bleedxint, bleedyint, i, j;
707 if (howmuch && id == 0)
710 if (tutoriallevel != 1 || id == 0)
711 if (aitype != playercontrolled && howmuch > 0) {
715 if (creature == wolftype) {
716 int i = abs(Random() % 2);
718 whichsound = snarlsound;
720 whichsound = snarl2sound;
722 if (creature == rabbittype) {
723 int i = abs(Random() % 2);
725 whichsound = rabbitpainsound;
726 if (i == 1 && howmuch >= 2)
727 whichsound = rabbitpain1sound;
730 if (whichsound != -1) {
731 emit_sound_at(whichsound, coords);
736 if (id == 0 && howmuch > 0) {
740 if (bloodtoggle && decals && tutoriallevel != 1) {
741 if (bleeding <= 0 && spurt) {
743 for (int i = 0; i < 3; i++) {
744 // emit blood particles
745 // FIXME: copypaste from above
748 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
749 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
750 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
751 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
754 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
755 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
756 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
757 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
762 // weird texture manipulation code follows.
763 // looks like this is painting blood onto the character's skin texture
764 // FIXME: surely there's a better way
766 int offsetx = 0, offsety = 0;
768 offsety = Random() % 40;
769 offsetx = abs(Random() % 60);
771 if (which == 190 || which == 185) {
772 offsety = Random() % 40;
773 offsetx = abs(Random() % 100) - 20;
776 offsety = Random() % 10;
777 offsetx = Random() % 10;
780 offsety = Random() % 20;
781 offsetx = Random() % 20;
783 if (which == 220 || which == 215) {
793 if (creature == rabbittype)
794 for (i = 0; i < 512; i++) {
795 for (j = 0; j < 512; j++) {
796 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
797 if (i < startx) startx = i;
798 if (j < starty) starty = j;
799 if (i > endx) endx = i;
800 if (j > endy) endy = j;
804 if (creature == wolftype)
805 for (i = 0; i < 512; i++) {
806 for (j = 0; j < 512; j++) {
807 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
808 if (i < startx) startx = i;
809 if (j < starty) starty = j;
810 if (i > endx) endx = i;
811 if (j > endy) endy = j;
821 if (startx < 0) startx = 0;
822 if (starty < 0) starty = 0;
823 if (endx > 512 - 1) endx = 512 - 1;
824 if (endy > 512 - 1) endy = 512 - 1;
825 if (endx < startx) endx = startx;
826 if (endy < starty) endy = starty;
828 startx /= realtexdetail;
829 starty /= realtexdetail;
830 endx /= realtexdetail;
831 endy /= realtexdetail;
833 int texdetailint = realtexdetail;
835 if (creature == rabbittype)
836 for (i = startx; i < endx; i++) {
837 for (j = starty; j < endy; j++) {
838 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) {
839 color = Random() % 85 + 170;
840 where = i * skeleton.skinsize * 3 + j * 3;
841 if (skeleton.skinText[where + 0] > color / 2)
842 skeleton.skinText[where + 0] = color / 2;
843 skeleton.skinText[where + 1] = 0;
844 skeleton.skinText[where + 2] = 0;
848 if (creature == wolftype)
849 for (i = startx; i < endx; i++) {
850 for (j = starty; j < endy; j++) {
851 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) {
852 color = Random() % 85 + 170;
853 where = i * skeleton.skinsize * 3 + j * 3;
854 if (skeleton.skinText[where + 0] > color / 2)
855 skeleton.skinText[where + 0] = color / 2;
856 skeleton.skinText[where + 1] = 0;
857 skeleton.skinText[where + 2] = 0;
861 skeleton.drawmodel.textureptr.bind();
866 if (creature == rabbittype)
867 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) {
868 bleedxint = abs(Random() % 512);
869 bleedyint = abs(Random() % 512);
871 if (creature == wolftype)
872 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) {
873 bleedxint = abs(Random() % 512);
874 bleedyint = abs(Random() % 512);
876 bleedy = bleedxint + offsetx;
877 bleedx = bleedyint + offsety;
878 bleedy /= realtexdetail;
879 bleedx /= realtexdetail;
884 if (bleedx > skeleton.skinsize - 1)
885 bleedx = skeleton.skinsize - 1;
886 if (bleedy > skeleton.skinsize - 1)
887 bleedy = skeleton.skinsize - 1;
888 direction = abs(Random() % 2) * 2 - 1;
891 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
892 deathbleeding += bleeding;
893 bloodloss += bleeding * 3;
895 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
896 if (abs(Random() % 2) == 0) {
897 aitype = gethelptype;
900 aitype = attacktypecutoff;
908 * similar to DoBloodBig
910 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
914 static XYZ startpoint, endpoint, colpoint, movepoint;
915 static float rotationpoint;
917 static XYZ p1, p2, p3, p0;
920 float coordsx, coordsy;
923 if (bloodtoggle && decals && tutoriallevel != 1) {
926 where = DoRotation(where, 0, -yaw, 0);
934 // ray testing for a tri in the character model
935 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
936 if (whichtri != -1) {
937 // low level geometry math
939 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
940 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
941 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
943 bary.x = distsq(&p0, &p1);
944 bary.y = distsq(&p0, &p2);
945 bary.z = distsq(&p0, &p3);
947 total = bary.x + bary.y + bary.z;
956 total = bary.x + bary.y + bary.z;
962 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
963 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
964 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
965 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
966 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
967 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
968 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;
969 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;
971 if (bleeding <= 0 && spurt) {
973 for (int i = 0; i < 3; i++) {
974 // emit blood particles
975 // FIXME: more copypaste code
978 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
979 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
980 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
981 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
984 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
985 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
986 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
987 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
992 // texture manipulation follows
994 int offsetx = 0, offsety = 0;
995 offsetx = (1 + coordsy) * 512 - 291;
996 offsety = coordsx * 512 - 437;
1003 if (creature == rabbittype)
1004 for (i = 0; i < 512; i++) {
1005 for (j = 0; j < 512; j++) {
1006 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1007 if (i < startx) startx = i;
1008 if (j < starty) starty = j;
1009 if (i > endx) endx = i;
1010 if (j > endy) endy = j;
1014 if (creature == wolftype)
1015 for (i = 0; i < 512; i++) {
1016 for (j = 0; j < 512; j++) {
1017 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1018 if (i < startx) startx = i;
1019 if (j < starty) starty = j;
1020 if (i > endx) endx = i;
1021 if (j > endy) endy = j;
1030 if (startx < 0) startx = 0;
1031 if (starty < 0) starty = 0;
1032 if (endx > 512 - 1) endx = 512 - 1;
1033 if (endy > 512 - 1) endy = 512 - 1;
1034 if (endx < startx) endx = startx;
1035 if (endy < starty) endy = starty;
1037 startx /= realtexdetail;
1038 starty /= realtexdetail;
1039 endx /= realtexdetail;
1040 endy /= realtexdetail;
1042 int texdetailint = realtexdetail;
1044 if (creature == rabbittype)
1045 for (i = startx; i < endx; i++) {
1046 for (j = starty; j < endy; j++) {
1047 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) {
1048 color = Random() % 85 + 170;
1049 where = i * skeleton.skinsize * 3 + j * 3;
1050 if (skeleton.skinText[where + 0] > color / 2)
1051 skeleton.skinText[where + 0] = color / 2;
1052 skeleton.skinText[where + 1] = 0;
1053 skeleton.skinText[where + 2] = 0;
1054 } 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) {
1055 color = Random() % 85 + 170;
1056 where = i * skeleton.skinsize * 3 + j * 3;
1057 if (skeleton.skinText[where + 0] > color / 2)
1058 skeleton.skinText[where + 0] = color / 2;
1059 skeleton.skinText[where + 1] = 0;
1060 skeleton.skinText[where + 2] = 0;
1064 if (creature == wolftype)
1065 for (i = startx; i < endx; i++) {
1066 for (j = starty; j < endy; j++) {
1067 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) {
1068 color = Random() % 85 + 170;
1069 where = i * skeleton.skinsize * 3 + j * 3;
1070 if (skeleton.skinText[where + 0] > color / 2)
1071 skeleton.skinText[where + 0] = color / 2;
1072 skeleton.skinText[where + 1] = 0;
1073 skeleton.skinText[where + 2] = 0;
1074 } 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) {
1075 color = Random() % 85 + 170;
1076 where = i * skeleton.skinsize * 3 + j * 3;
1077 if (skeleton.skinText[where + 0] > color / 2)
1078 skeleton.skinText[where + 0] = color / 2;
1079 skeleton.skinText[where + 1] = 0;
1080 skeleton.skinText[where + 2] = 0;
1084 skeleton.drawmodel.textureptr.bind();
1087 bleedy = (1 + coordsy) * 512;
1088 bleedx = coordsx * 512;
1089 bleedy /= realtexdetail;
1090 bleedx /= realtexdetail;
1095 if (bleedx > skeleton.skinsize - 1)
1096 bleedx = skeleton.skinsize - 1;
1097 if (bleedy > skeleton.skinsize - 1)
1098 bleedy = skeleton.skinsize - 1;
1099 direction = abs(Random() % 2) * 2 - 1;
1104 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1105 deathbleeding += bleeding;
1106 bloodloss += bleeding * 3;
1108 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1109 if (abs(Random() % 2) == 0) {
1110 aitype = gethelptype;
1113 aitype = attacktypecutoff;
1124 * guessing this performs a reversal
1126 void Person::Reverse()
1128 if (!((victim->aitype == playercontrolled
1130 || staggerdelay <= 0)
1131 && victim->animTarget != jumpupanim
1132 && victim->animTarget != jumpdownanim
1133 && (tutoriallevel != 1 || cananger)
1137 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1138 && (victim->id != 0 || difficulty >= 2)
1139 && (creature != wolftype || victim->creature == wolftype))
1142 if (animTarget == sweepanim) {
1143 animTarget = sweepreversedanim;
1144 animCurrent = sweepreversedanim;
1145 victim->animCurrent = sweepreversalanim;
1146 victim->animTarget = sweepreversalanim;
1148 if (animTarget == spinkickanim) {
1149 animTarget = spinkickreversedanim;
1150 animCurrent = spinkickreversedanim;
1151 victim->animCurrent = spinkickreversalanim;
1152 victim->animTarget = spinkickreversalanim;
1154 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1155 if (animTarget == rabbittacklinganim) {
1158 victim->frameCurrent = 6;
1159 victim->frameTarget = 7;
1161 animTarget = upunchreversedanim;
1162 animCurrent = upunchreversedanim;
1163 victim->animCurrent = upunchreversalanim;
1164 victim->animTarget = upunchreversalanim;
1166 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1167 if (victim->weaponactive != -1) {
1168 victim->throwtogglekeydown = 1;
1169 XYZ tempVelocity = victim->velocity * .2;
1170 if (tempVelocity.x == 0)
1171 tempVelocity.x = .1;
1172 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1173 victim->num_weapons--;
1174 if (victim->num_weapons) {
1175 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1176 if (victim->weaponstuck == victim->num_weapons)
1177 victim->weaponstuck = 0;
1180 victim->weaponactive = -1;
1181 for (unsigned j = 0; j < Person::players.size(); j++) {
1182 Person::players[j]->wentforweapon = 0;
1186 animTarget = staffhitreversedanim;
1187 animCurrent = staffhitreversedanim;
1188 victim->animCurrent = staffhitreversalanim;
1189 victim->animTarget = staffhitreversalanim;
1191 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1192 if (victim->weaponactive != -1) {
1193 victim->throwtogglekeydown = 1;
1194 XYZ tempVelocity = victim->velocity * .2;
1195 if (tempVelocity.x == 0)
1196 tempVelocity.x = .1;
1197 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1198 victim->num_weapons--;
1199 if (victim->num_weapons) {
1200 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1201 if (victim->weaponstuck == victim->num_weapons)
1202 victim->weaponstuck = 0;
1205 victim->weaponactive = -1;
1206 for (unsigned j = 0; j < Person::players.size(); j++) {
1207 Person::players[j]->wentforweapon = 0;
1210 animTarget = staffspinhitreversedanim;
1211 animCurrent = staffspinhitreversedanim;
1212 victim->animCurrent = staffspinhitreversalanim;
1213 victim->animTarget = staffspinhitreversalanim;
1215 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1216 if (victim->weaponactive != -1) {
1217 victim->throwtogglekeydown = 1;
1218 XYZ tempVelocity = victim->velocity * .2;
1219 if (tempVelocity.x == 0)
1220 tempVelocity.x = .1;
1221 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1222 victim->num_weapons--;
1223 if (victim->num_weapons) {
1224 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1225 if (victim->weaponstuck == victim->num_weapons)
1226 victim->weaponstuck = 0;
1229 victim->weaponactive = -1;
1230 for (unsigned j = 0; j < Person::players.size(); j++) {
1231 Person::players[j]->wentforweapon = 0;
1234 animTarget = swordslashreversedanim;
1235 animCurrent = swordslashreversedanim;
1236 victim->animCurrent = swordslashreversalanim;
1237 victim->animTarget = swordslashreversalanim;
1239 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1240 if (victim->weaponactive != -1) {
1241 victim->throwtogglekeydown = 1;
1242 XYZ tempVelocity = victim->velocity * .2;
1243 if (tempVelocity.x == 0)
1244 tempVelocity.x = .1;
1245 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1246 victim->num_weapons--;
1247 if (victim->num_weapons) {
1248 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1249 if (victim->weaponstuck == victim->num_weapons)
1250 victim->weaponstuck = 0;
1253 victim->weaponactive = -1;
1254 for (unsigned j = 0; j < Person::players.size(); j++) {
1255 Person::players[j]->wentforweapon = 0;
1258 animTarget = knifeslashreversedanim;
1259 animCurrent = knifeslashreversedanim;
1260 victim->animCurrent = knifeslashreversalanim;
1261 victim->animTarget = knifeslashreversalanim;
1263 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1264 victim->targettilt2 = targettilt2;
1265 victim->frameCurrent = frameCurrent;
1266 victim->frameTarget = frameTarget;
1267 victim->target = target;
1268 victim->velocity = 0;
1269 victim->oldcoords = victim->coords;
1270 victim->coords = coords;
1271 victim->targetyaw = targetyaw;
1272 victim->yaw = targetyaw;
1273 victim->victim = this->shared_from_this();
1275 if (animTarget == winduppunchanim) {
1276 animTarget = winduppunchblockedanim;
1277 victim->animTarget = blockhighleftanim;
1278 victim->frameTarget = 1;
1279 victim->target = .5;
1280 victim->victim = this->shared_from_this();
1281 victim->targetyaw = targetyaw + 180;
1283 if (animTarget == wolfslapanim) {
1284 animTarget = winduppunchblockedanim;
1285 victim->animTarget = blockhighleftanim;
1286 victim->frameTarget = 1;
1287 victim->target = .5;
1288 victim->victim = this->shared_from_this();
1289 victim->targetyaw = targetyaw + 180;
1291 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1292 animTarget = swordslashparriedanim;
1293 parriedrecently = .4;
1294 victim->parriedrecently = 0;
1295 victim->animTarget = swordslashparryanim;
1296 victim->frameTarget = 1;
1297 victim->target = .5;
1298 victim->victim = this->shared_from_this();
1299 victim->targetyaw = targetyaw + 180;
1301 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1302 if (victim->weaponactive != -1) {
1303 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1304 if (weapons[victim->weaponids[0]].getType() == staff)
1305 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1306 if (weapons[weaponids[0]].getType() == staff)
1307 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1308 emit_sound_at(swordstaffsound, victim->coords);
1310 emit_sound_at(metalhitsound, victim->coords);
1314 victim->Puff(righthand);
1316 victim->frameTarget = 0;
1317 victim->animTarget = staggerbackhighanim;
1318 victim->targetyaw = targetyaw + 180;
1320 aim = DoRotation(facing, 0, 90, 0) * 21;
1322 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1323 victim->num_weapons--;
1324 if (victim->num_weapons) {
1325 victim->weaponids[0] = victim->weaponids[num_weapons];
1326 if (victim->weaponstuck == victim->num_weapons)
1327 victim->weaponstuck = 0;
1329 victim->weaponactive = -1;
1330 for (unsigned i = 0; i < Person::players.size(); i++) {
1331 Person::players[i]->wentforweapon = 0;
1335 if (abs(Random() % 20) == 0) {
1336 if (weaponactive != -1) {
1337 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1338 if (weapons[victim->weaponids[0]].getType() == staff)
1339 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1340 if (weapons[weaponids[0]].getType() == staff)
1341 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1343 emit_sound_at(swordstaffsound, coords);
1345 emit_sound_at(metalhitsound, coords);
1353 animTarget = staggerbackhighanim;
1354 targetyaw = targetyaw + 180;
1356 aim = DoRotation(facing, 0, 90, 0) * 21;
1358 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1361 weaponids[0] = weaponids[num_weapons];
1362 if (weaponstuck == num_weapons)
1366 for (unsigned i = 0; i < Person::players.size(); i++) {
1367 Person::players[i]->wentforweapon = 0;
1374 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1375 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1376 victim->animTarget = dodgebackanim;
1377 victim->frameTarget = 0;
1381 rotatetarget = coords - victim->coords;
1382 Normalise(&rotatetarget);
1383 victim->targetyaw = -asin(0 - rotatetarget.x);
1384 victim->targetyaw *= 360 / 6.28;
1385 if (rotatetarget.z < 0)
1386 victim->targetyaw = 180 - victim->targetyaw;
1388 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1390 victim->lastattack3 = victim->lastattack2;
1391 victim->lastattack2 = victim->lastattack;
1392 victim->lastattack = victim->animTarget;
1394 victim->animTarget = sweepanim;
1395 victim->frameTarget = 0;
1399 rotatetarget = coords - victim->coords;
1400 Normalise(&rotatetarget);
1401 victim->targetyaw = -asin(0 - rotatetarget.x);
1402 victim->targetyaw *= 360 / 6.28;
1403 if (rotatetarget.z < 0)
1404 victim->targetyaw = 180 - victim->targetyaw;
1406 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1408 victim->lastattack3 = victim->lastattack2;
1409 victim->lastattack2 = victim->lastattack;
1410 victim->lastattack = victim->animTarget;
1415 victim->velocity = 0;
1417 if (aitype != playercontrolled)
1419 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1421 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1423 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1426 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1433 void Person::DoDamage(float howmuch)
1435 // subtract health (temporary?)
1436 if (tutoriallevel != 1)
1437 damage += howmuch / power;
1440 damagedealt += howmuch / power;
1442 damagetaken += howmuch / power;
1445 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1448 if (tutoriallevel != 1)
1449 permanentdamage += howmuch / 2 / power;
1450 if (tutoriallevel != 1)
1451 superpermanentdamage += howmuch / 4 / power;
1453 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1455 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1459 camerashake += howmuch / 100;
1460 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1461 blackout = damage / damagetolerance;
1466 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1467 aitype = attacktypecutoff;
1468 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1469 if (abs(Random() % 2) == 0) {
1470 aitype = gethelptype;
1473 aitype = attacktypecutoff;
1477 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1480 for (int i = 0; i < skeleton.num_joints; i++) {
1481 if (skeleton.free) {
1482 flatvelocity2 = skeleton.joints[i].velocity;
1483 flatfacing2 = skeleton.joints[i].position * scale + coords;
1485 flatvelocity2 = velocity;
1486 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1488 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1489 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1490 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1491 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1492 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1493 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1496 emit_sound_at(splattersound, coords);
1501 if (!dead && creature == wolftype) {
1502 award_bonus(0, Wolfbonus);
1509 if (tutoriallevel != 1 || id == 0)
1510 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1511 int whichsound = -1;
1513 if (creature == wolftype) {
1514 int i = abs(Random() % 2);
1516 whichsound = snarlsound;
1518 whichsound = snarl2sound;
1520 if (creature == rabbittype) {
1521 int i = abs(Random() % 2);
1523 whichsound = rabbitpainsound;
1524 if (i == 1 && damage > damagetolerance)
1525 whichsound = rabbitpain1sound;
1528 if (whichsound != -1) {
1529 emit_sound_at(whichsound, coords);
1530 addEnvSound(coords);
1537 * calculate/animate head facing direction?
1539 void Person::DoHead()
1541 static XYZ rotatearound;
1543 static float lookspeed = 500;
1545 if (!freeze && !winfreeze) {
1548 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1549 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1551 while (targetheadyaw > 180)targetheadyaw -= 360;
1552 while (targetheadyaw < -180)targetheadyaw += 360;
1554 if (targetheadyaw > 160)
1555 targetheadpitch = targetheadpitch * -1;
1556 if (targetheadyaw < -160)
1557 targetheadpitch = targetheadpitch * -1;
1558 if (targetheadyaw > 160)
1559 targetheadyaw = targetheadyaw - 180;
1560 if (targetheadyaw < -160)
1561 targetheadyaw = targetheadyaw + 180;
1563 if (targetheadpitch > 120)
1564 targetheadpitch = 120;
1565 if (targetheadpitch < -120)
1566 targetheadpitch = -120;
1567 if (targetheadyaw > 120)
1568 targetheadyaw = 120;
1569 if (targetheadyaw < -120)
1570 targetheadyaw = -120;
1573 targetheadpitch = 0;
1575 if (targetheadyaw > 80)
1577 if (targetheadyaw < -80)
1578 targetheadyaw = -80;
1579 if (targetheadpitch > 50)
1580 targetheadpitch = 50;
1581 if (targetheadpitch < -50)
1582 targetheadpitch = -50;
1585 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1586 headyaw = targetheadyaw;
1587 else if (headyaw > targetheadyaw) {
1588 headyaw -= multiplier * lookspeed;
1589 } else if (headyaw < targetheadyaw) {
1590 headyaw += multiplier * lookspeed;
1593 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1594 headpitch = targetheadpitch;
1595 else if (headpitch > targetheadpitch) {
1596 headpitch -= multiplier * lookspeed / 2;
1597 } else if (headpitch < targetheadpitch) {
1598 headpitch += multiplier * lookspeed / 2;
1601 rotatearound = jointPos(neck);
1602 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1606 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1607 facing = DoRotation(facing, headpitch * .4, 0, 0);
1608 facing = DoRotation(facing, 0, headyaw * .4, 0);
1611 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1612 facing = DoRotation(facing, headpitch * .8, 0, 0);
1613 facing = DoRotation(facing, 0, headyaw * .8, 0);
1616 if (animTarget == walkanim) {
1617 facing = DoRotation(facing, headpitch * .6, 0, 0);
1618 facing = DoRotation(facing, 0, headyaw * .6, 0);
1621 skeleton.specialforward[0] = facing;
1622 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1623 for (int i = 0; i < skeleton.num_muscles; i++) {
1624 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1625 skeleton.FindRotationMuscle(i, animTarget);
1632 * ragdolls character?
1634 void Person::RagDoll(bool checkcollision)
1639 if (!skeleton.free) {
1642 if (id == 0 && isFlip())
1649 facing = DoRotation(facing, 0, yaw, 0);
1651 skeleton.freetime = 0;
1653 skeleton.longdead = 0;
1656 skeleton.broken = 0;
1657 skeleton.spinny = 1;
1659 skeleton.freefall = 1;
1661 if (!isnormal(velocity.x)) velocity.x = 0;
1662 if (!isnormal(velocity.y)) velocity.y = 0;
1663 if (!isnormal(velocity.z)) velocity.z = 0;
1664 if (!isnormal(yaw)) yaw = 0;
1665 if (!isnormal(coords.x)) coords = 0;
1666 if (!isnormal(tilt)) tilt = 0;
1667 if (!isnormal(tilt2)) tilt2 = 0;
1669 for (int i = 0; i < skeleton.num_joints; i++) {
1670 skeleton.joints[i].delay = 0;
1671 skeleton.joints[i].locked = 0;
1672 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1673 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1674 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1675 skeleton.joints[i].position.y += .1;
1676 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1677 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1680 for (int i = 0; i < skeleton.num_joints; i++) {
1681 skeleton.joints[i].velocity = 0;
1682 skeleton.joints[i].velchange = 0;
1684 skeleton.DoConstraints(&coords, &scale);
1685 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1686 skeleton.DoConstraints(&coords, &scale);
1687 skeleton.DoConstraints(&coords, &scale);
1688 skeleton.DoConstraints(&coords, &scale);
1689 skeleton.DoConstraints(&coords, &scale);
1692 speed = animation[animTarget].speed[frameTarget] * 2;
1693 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1694 speed = animation[animCurrent].speed[frameCurrent] * 2;
1697 speed = transspeed * 2;
1701 for (int i = 0; i < skeleton.num_joints; i++) {
1702 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1703 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);
1705 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1706 change.x = (float)(Random() % 100) / 100;
1707 change.y = (float)(Random() % 100) / 100;
1708 change.z = (float)(Random() % 100) / 100;
1709 skeleton.joints[i].velocity += change;
1710 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1712 change.x = (float)(Random() % 100) / 100;
1713 change.y = (float)(Random() % 100) / 100;
1714 change.z = (float)(Random() % 100) / 100;
1715 skeleton.joints[i].velchange += change;
1716 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1719 if (checkcollision) {
1726 for (j = 0; j < skeleton.num_joints; j++) {
1727 average += skeleton.joints[j].position;
1731 coords += average * scale;
1732 for (j = 0; j < skeleton.num_joints; j++) {
1733 skeleton.joints[j].position -= average;
1736 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1737 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1738 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1739 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1740 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1743 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1744 coords.x = lowpoint.x;
1745 coords.z = lowpoint.z;
1754 for (int i = 0; i < skeleton.num_joints; i++) {
1755 velocity += skeleton.joints[i].velocity * scale;
1757 velocity /= skeleton.num_joints;
1760 if (Random() % 2 == 0) {
1761 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1762 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1763 weapons[weaponids[0]].velocity.x += .01;
1766 weaponids[0] = weaponids[num_weapons];
1767 if (weaponstuck == num_weapons)
1771 for (unsigned i = 0; i < Person::players.size(); i++) {
1772 Person::players[i]->wentforweapon = 0;
1777 animTarget = bounceidleanim;
1778 animCurrent = bounceidleanim;
1788 void Person::FootLand(bodyparts whichfoot, float opacity)
1790 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1791 cerr << "FootLand called on wrong bodypart" << endl;
1794 static XYZ terrainlight;
1795 static XYZ footvel, footpoint;
1796 if (opacity >= 1 || skiddelay <= 0) {
1799 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1800 if (distsq(&footpoint, &viewer))
1801 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1802 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1803 footvel = velocity / 5;
1806 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1807 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1808 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1809 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1810 if (environment == snowyenvironment) {
1811 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1813 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1815 } else if (environment == grassyenvironment) {
1816 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1817 } else if (environment == desertenvironment) {
1818 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1820 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1824 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1825 footvel = velocity / 5;
1828 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1829 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1830 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1837 * make a puff effect at a body part (dust effect?)
1839 void Person::Puff(int whichlabel)
1841 static XYZ footvel, footpoint;
1844 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1845 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1849 * I think I added this in an attempt to clean up code
1851 void Person::setAnimation(int animation)
1853 animTarget = animation;
1862 void Person::DoAnimations()
1864 if (!skeleton.free) {
1865 static float oldtarget;
1867 if (isIdle() && animCurrent != getIdle())
1868 normalsupdatedelay = 0;
1870 if (animTarget == tempanim || animCurrent == tempanim) {
1871 animation[tempanim] = tempanimation;
1873 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1879 vel[0] = velocity.x;
1880 vel[1] = velocity.y;
1881 vel[2] = velocity.z;
1884 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1885 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1887 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1889 if (!crouchkeydown && velocity.y >= -15)
1892 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1897 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1899 if (normaldotproduct(targfacing, velocity) >= -.3)
1900 animTarget = flipanim;
1902 animTarget = backflipanim;
1903 crouchtogglekeydown = 1;
1911 if (animation[animTarget].attack != reversed)
1913 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1914 crouchtogglekeydown = 0;
1915 if (aitype == playercontrolled)
1918 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1921 crouchtogglekeydown = 1;
1925 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1927 normalsupdatedelay = 0;
1931 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1933 emit_sound_at(fireendsound, coords);
1934 pause_sound(stream_firesound);
1938 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1939 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1941 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1942 if (normaldotproduct(victim->facing, facing) > 0)
1943 victim->animTarget = rabbittackledbackanim;
1945 victim->animTarget = rabbittackledfrontanim;
1946 victim->frameTarget = 2;
1949 victim->targetyaw = yaw;
1950 if (victim->aitype == gethelptype)
1951 victim->DoDamage(victim->damagetolerance - victim->damage);
1952 //victim->DoDamage(30);
1953 if (creature == wolftype) {
1955 emit_sound_at(clawslicesound, victim->coords);
1957 victim->DoBloodBig(1 / victim->armorhead, 210);
1959 award_bonus(id, TackleBonus,
1960 victim->aitype == gethelptype ? 50 : 0);
1964 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1965 if (weapons[weaponids[0]].getType() == knife) {
1966 if (weaponactive == -1)
1968 else if (weaponactive == 0)
1971 if (weaponactive == -1) {
1972 emit_sound_at(knifesheathesound, coords);
1974 if (weaponactive != -1) {
1975 emit_sound_at(knifedrawsound, coords, 128);
1978 drawtogglekeydown = 1;
1981 if (tutoriallevel != 1 || id == 0)
1982 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1985 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1986 if (animation[animTarget].label[frameTarget] == 1)
1987 whichsound = footstepsound;
1989 whichsound = footstepsound2;
1990 if (animation[animTarget].label[frameTarget] == 1)
1991 FootLand(leftfoot, 1);
1992 if (animation[animTarget].label[frameTarget] == 2)
1993 FootLand(rightfoot, 1);
1994 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1995 FootLand(rightfoot, 1);
1996 FootLand(leftfoot, 1);
2000 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2001 if (animation[animTarget].label[frameTarget] == 1)
2002 whichsound = footstepsound3;
2004 whichsound = footstepsound4;
2008 if (animation[animTarget].label[frameTarget] == 1)
2009 whichsound = footstepsound3;
2011 whichsound = footstepsound4;
2013 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2014 if (animation[animTarget].attack != neutral) {
2015 unsigned r = abs(Random() % 3);
2017 whichsound = lowwhooshsound;
2019 whichsound = midwhooshsound;
2021 whichsound = highwhooshsound;
2023 if (animation[animTarget].attack == neutral)
2024 whichsound = movewhooshsound;
2025 } else if (animation[animTarget].label[frameTarget] == 4)
2026 whichsound = knifeswishsound;
2027 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2028 whichsound = landsound2;
2030 emit_sound_at(whichsound, coords, 256.);
2033 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2034 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2035 addEnvSound(coords, 15);
2037 addEnvSound(coords, 6);
2041 if (animation[animTarget].label[frameTarget] == 3) {
2043 emit_sound_at(whichsound, coords, 128.);
2048 if (tutoriallevel != 1 || id == 0)
2049 if (speechdelay <= 0)
2050 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2051 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2052 int whichsound = -1;
2053 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2054 if (animation[animTarget].attack != neutral) {
2055 unsigned r = abs(Random() % 4);
2056 if (creature == rabbittype) {
2057 if (r == 0) whichsound = rabbitattacksound;
2058 if (r == 1) whichsound = rabbitattack2sound;
2059 if (r == 2) whichsound = rabbitattack3sound;
2060 if (r == 3) whichsound = rabbitattack4sound;
2062 if (creature == wolftype) {
2063 if (r == 0) whichsound = barksound;
2064 if (r == 1) whichsound = bark2sound;
2065 if (r == 2) whichsound = bark3sound;
2066 if (r == 3) whichsound = barkgrowlsound;
2072 if (whichsound != -1) {
2073 emit_sound_at(whichsound, coords);
2079 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2080 FootLand(leftfoot, 1);
2081 FootLand(rightfoot, 1);
2085 currentoffset = targetoffset;
2086 frameTarget = frameCurrent;
2087 animCurrent = animTarget;
2090 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2091 for (unsigned i = 0; i < weapons.size(); i++) {
2092 if (weapons[i].owner == -1)
2093 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2094 if (distsq(&coords, &weapons[i].position) >= 1) {
2095 if (weapons[i].getType() != staff) {
2096 emit_sound_at(knifedrawsound, coords, 128.);
2105 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2106 for (unsigned i = 0; i < weapons.size(); i++) {
2107 bool willwork = true;
2108 if (weapons[i].owner != -1)
2109 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2110 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2111 if (Person::players[weapons[i].owner]->num_weapons > 1)
2113 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2114 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2115 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2116 bool fleshstuck = false;
2117 if (weapons[i].owner != -1)
2118 if (victim->weaponstuck != -1) {
2119 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2124 emit_sound_at(fleshstabremovesound, coords, 128.);
2126 if (weapons[i].getType() != staff) {
2127 emit_sound_at(knifedrawsound, coords, 128.);
2130 if (weapons[i].owner != -1) {
2131 victim = Person::players[weapons[i].owner];
2132 if (victim->num_weapons == 1)
2133 victim->num_weapons = 0;
2135 victim->num_weapons = 1;
2137 //victim->weaponactive=-1;
2138 victim->skeleton.longdead = 0;
2139 victim->skeleton.free = 1;
2140 victim->skeleton.broken = 0;
2142 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2143 victim->skeleton.joints[j].velchange = 0;
2144 victim->skeleton.joints[j].locked = 0;
2150 Normalise(&relative);
2151 XYZ footvel, footpoint;
2153 footpoint = weapons[i].position;
2154 if (victim->weaponstuck != -1) {
2155 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2157 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2158 weapons[i].bloody = 2;
2159 weapons[i].blooddrip = 5;
2160 victim->weaponstuck = -1;
2163 if (victim->num_weapons > 0) {
2164 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2165 victim->weaponstuck = 0;
2166 if (victim->weaponids[0] == int(i))
2167 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2170 victim->jointVel(abdomen) += relative * 6;
2171 victim->jointVel(neck) += relative * 6;
2172 victim->jointVel(rightshoulder) += relative * 6;
2173 victim->jointVel(leftshoulder) += relative * 6;
2181 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2182 if (weaponactive == -1)
2184 else if (weaponactive == 0) {
2186 if (num_weapons == 2) {
2188 buffer = weaponids[0];
2189 weaponids[0] = weaponids[1];
2190 weaponids[1] = buffer;
2193 if (weaponactive == -1) {
2194 emit_sound_at(knifesheathesound, coords, 128.);
2196 if (weaponactive != -1) {
2197 emit_sound_at(knifedrawsound, coords, 128.);
2202 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2203 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2204 Normalise(&rotatetarget);
2205 targetyaw = -asin(0 - rotatetarget.x);
2206 targetyaw *= 360 / 6.28;
2207 if (rotatetarget.z < 0)
2208 targetyaw = 180 - targetyaw;
2210 if (animTarget == walljumprightkickanim)
2212 if (animTarget == walljumpleftkickanim)
2218 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2221 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2226 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2227 animTarget = rabbittackleanim;
2229 emit_sound_at(jumpsound, coords);
2237 targetloc = velocity;
2238 Normalise(&targetloc);
2239 targetloc += coords;
2240 for (unsigned i = 0; i < Person::players.size(); i++) {
2242 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2243 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2247 if (closestid != -1)
2248 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2250 victim = Person::players[closestid];
2251 coords = victim->coords;
2252 animCurrent = rabbittacklinganim;
2253 animTarget = rabbittacklinganim;
2257 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2258 rotatetarget = coords - victim->coords;
2259 Normalise(&rotatetarget);
2260 targetyaw = -asin(0 - rotatetarget.x);
2261 targetyaw *= 360 / 6.28;
2262 if (rotatetarget.z < 0)
2263 targetyaw = 180 - targetyaw;
2265 if (animTarget != rabbitrunninganim) {
2266 emit_sound_at(jumpsound, coords, 128.);
2272 float damagemult = 1 * power;
2273 if (creature == wolftype)
2274 damagemult = 2.5 * power;
2276 damagemult /= victim->damagetolerance / 200;
2278 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2279 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2280 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2284 if (Random() % 2 || creature == wolftype) {
2287 if (creature == wolftype)
2290 if (tutoriallevel != 1) {
2291 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2293 if (creature == wolftype) {
2294 emit_sound_at(clawslicesound, victim->coords, 128.);
2296 victim->DoBloodBig(2 / victim->armorhead, 175);
2300 relative = victim->coords - coords;
2302 Normalise(&relative);
2303 relative = DoRotation(relative, 0, -90, 0);
2304 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2305 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2307 victim->jointVel(head) += relative * damagemult * 200;
2309 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2315 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2316 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2320 if (Random() % 2 || creature == wolftype) {
2322 if (creature == wolftype)
2325 emit_sound_at(whooshhitsound, victim->coords);
2326 if (creature == wolftype) {
2327 emit_sound_at(clawslicesound, victim->coords, 128.);
2329 victim->DoBloodBig(2, 175);
2333 relative = victim->coords - coords;
2335 Normalise(&relative);
2337 Normalise(&relative);
2338 relative = DoRotation(relative, 0, 90, 0);
2339 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2340 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2342 victim->jointVel(head) += relative * damagemult * 100;
2344 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2348 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2349 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2355 if (tutoriallevel != 1) {
2356 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2358 if (creature == wolftype) {
2359 emit_sound_at(clawslicesound, victim->coords, 128.);
2361 victim->DoBloodBig(2 / victim->armorhead, 175);
2367 Normalise(&relative);
2368 relative = DoRotation(relative, 0, -90, 0);
2369 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2370 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2372 victim->jointVel(head) += relative * damagemult * 200;
2374 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2376 if (victim->damage > victim->damagetolerance)
2377 award_bonus(id, style);
2383 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2384 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2390 if (tutoriallevel != 1) {
2391 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2393 if (creature == wolftype) {
2394 emit_sound_at(clawslicesound, victim->coords, 128.);
2396 victim->DoBloodBig(2 / victim->armorhead, 175);
2402 Normalise(&relative);
2403 relative = DoRotation(relative, 0, 90, 0);
2404 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2405 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2407 victim->jointVel(head) += relative * damagemult * 200;
2409 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2411 if (victim->damage > victim->damagetolerance)
2412 award_bonus(id, style);
2418 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2419 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2427 emit_sound_at(whooshhitsound, victim->coords);
2430 relative = victim->coords - coords;
2432 Normalise(&relative);
2433 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2434 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2436 victim->jointVel(head) += relative * damagemult * 100;
2438 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2442 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2443 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2447 emit_sound_at(whooshhitsound, victim->coords, 128.);
2449 victim->skeleton.longdead = 0;
2450 victim->skeleton.free = 1;
2451 victim->skeleton.broken = 0;
2452 victim->skeleton.spinny = 1;
2454 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2455 victim->skeleton.joints[i].velchange = 0;
2456 victim->skeleton.joints[i].delay = 0;
2457 victim->skeleton.joints[i].locked = 0;
2458 //victim->skeleton.joints[i].velocity=0;
2464 Normalise(&relative);
2465 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2466 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2467 victim->skeleton.joints[i].position.y += relative.y * .3;
2468 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2469 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2471 victim->Puff(abdomen);
2472 victim->jointVel(abdomen).y = relative.y * 400;
2476 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2477 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2481 if (tutoriallevel != 1) {
2482 emit_sound_at(heavyimpactsound, coords, 128.);
2485 relative = victim->coords - coords;
2487 Normalise(&relative);
2488 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2489 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2491 victim->Puff(abdomen);
2492 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2496 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2497 victim->jointVel(abdomen) += relative * damagemult * 300;
2501 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2502 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2506 if (tutoriallevel != 1) {
2507 emit_sound_at(thudsound, coords);
2510 victim->skeleton.longdead = 0;
2511 victim->skeleton.free = 1;
2512 victim->skeleton.broken = 0;
2513 victim->skeleton.spinny = 1;
2515 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2516 victim->skeleton.joints[i].velchange = 0;
2517 //victim->skeleton.joints[i].delay=0;
2518 victim->skeleton.joints[i].locked = 0;
2521 relative = victim->coords - coords;
2522 Normalise(&relative);
2524 Normalise(&relative);
2525 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2526 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2531 victim->Puff(abdomen);
2532 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2533 victim->jointVel(abdomen) += relative * damagemult * 200;
2542 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2545 if (!victim->skeleton.free)
2549 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2550 emit_sound_at(knifesheathesound, coords, 128.);
2553 if (victim && hasvictim) {
2554 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2556 XYZ where, startpoint, endpoint, movepoint, colpoint;
2557 float rotationpoint;
2559 if (weapons[weaponids[weaponactive]].getType() == knife) {
2560 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2561 where -= victim->coords;
2562 if (!victim->skeleton.free)
2563 where = DoRotation(where, 0, -victim->yaw, 0);
2566 startpoint.y += 100;
2570 if (weapons[weaponids[weaponactive]].getType() == sword) {
2571 where = weapons[weaponids[weaponactive]].position;
2572 where -= victim->coords;
2573 if (!victim->skeleton.free)
2574 where = DoRotation(where, 0, -victim->yaw, 0);
2576 where = weapons[weaponids[weaponactive]].tippoint;
2577 where -= victim->coords;
2578 if (!victim->skeleton.free)
2579 where = DoRotation(where, 0, -victim->yaw, 0);
2582 if (weapons[weaponids[weaponactive]].getType() == staff) {
2583 where = weapons[weaponids[weaponactive]].position;
2584 where -= victim->coords;
2585 if (!victim->skeleton.free)
2586 where = DoRotation(where, 0, -victim->yaw, 0);
2588 where = weapons[weaponids[weaponactive]].tippoint;
2589 where -= victim->coords;
2590 if (!victim->skeleton.free)
2591 where = DoRotation(where, 0, -victim->yaw, 0);
2596 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2598 if (whichtri != -1) {
2599 if (victim->dead != 2) {
2600 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2602 award_bonus(id, FinishedBonus);
2605 weapons[weaponids[weaponactive]].bloody = 2;
2607 victim->skeleton.longdead = 0;
2608 victim->skeleton.free = 1;
2609 victim->skeleton.broken = 0;
2611 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2612 victim->skeleton.joints[i].velchange = 0;
2613 victim->skeleton.joints[i].locked = 0;
2614 //victim->skeleton.joints[i].velocity=0;
2616 emit_sound_at(fleshstabsound, coords, 128);
2619 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2620 weapons[weaponids[weaponactive]].blooddrip += 5;
2621 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2623 if (whichtri == -1) {
2625 emit_sound_at(knifesheathesound, coords, 128.);
2631 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2633 emit_sound_at(knifedrawsound, coords, 128);
2636 if (victim && hasvictim) {
2637 XYZ footvel, footpoint;
2639 emit_sound_at(fleshstabremovesound, coords, 128.);
2642 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2644 if (weapons[weaponids[weaponactive]].getType() == sword) {
2645 XYZ where, startpoint, endpoint, movepoint;
2646 float rotationpoint;
2649 where = weapons[weaponids[weaponactive]].position;
2650 where -= victim->coords;
2651 if (!victim->skeleton.free)
2652 where = DoRotation(where, 0, -victim->yaw, 0);
2654 where = weapons[weaponids[weaponactive]].tippoint;
2655 where -= victim->coords;
2656 if (!victim->skeleton.free)
2657 where = DoRotation(where, 0, -victim->yaw, 0);
2662 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2663 footpoint += victim->coords;
2665 if (whichtri == -1) {
2666 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2669 if (weapons[weaponids[weaponactive]].getType() == staff) {
2670 XYZ where, startpoint, endpoint, movepoint;
2671 float rotationpoint;
2674 where = weapons[weaponids[weaponactive]].position;
2675 where -= victim->coords;
2676 if (!victim->skeleton.free)
2677 where = DoRotation(where, 0, -victim->yaw, 0);
2679 where = weapons[weaponids[weaponactive]].tippoint;
2680 where -= victim->coords;
2681 if (!victim->skeleton.free)
2682 where = DoRotation(where, 0, -victim->yaw, 0);
2687 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2688 footpoint += victim->coords;
2690 if (whichtri == -1) {
2691 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2694 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2696 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2697 victim->skeleton.longdead = 0;
2698 victim->skeleton.free = 1;
2699 victim->skeleton.broken = 0;
2701 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2702 victim->skeleton.joints[i].velchange = 0;
2703 victim->skeleton.joints[i].locked = 0;
2704 //victim->skeleton.joints[i].velocity=0;
2710 Normalise(&relative);
2711 //victim->Puff(abdomen);
2713 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2715 if (victim->bloodloss < victim->damagetolerance) {
2716 victim->bloodloss += 1000;
2720 victim->jointVel(abdomen) += relative * damagemult * 20;
2724 if (!hasvictim && onterrain) {
2725 weapons[weaponids[weaponactive]].bloody = 0;
2726 weapons[weaponids[weaponactive]].blooddrip = 0;
2730 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2731 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2739 if (tutoriallevel != 1) {
2740 emit_sound_at(heavyimpactsound, victim->coords, 128);
2745 relative = victim->coords - coords;
2747 Normalise(&relative);
2748 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2749 victim->skeleton.joints[i].velocity = relative * 30;
2751 victim->jointVel(head) += relative * damagemult * 150;
2753 victim->frameTarget = 0;
2754 victim->animTarget = staggerbackhardanim;
2755 victim->targetyaw = targetyaw + 180;
2757 victim->stunned = 1;
2760 victim->Puff(abdomen);
2761 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2768 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2769 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2773 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2774 if (tutoriallevel != 1) {
2775 emit_sound_at(thudsound, victim->coords);
2777 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2778 if (tutoriallevel != 1) {
2779 emit_sound_at(whooshhitsound, victim->coords);
2782 if (tutoriallevel != 1) {
2783 emit_sound_at(heavyimpactsound, victim->coords);
2787 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2790 relative = victim->coords - coords;
2792 Normalise(&relative);
2794 Normalise(&relative);
2795 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2796 victim->skeleton.joints[i].velocity = relative * 5;
2798 victim->jointVel(abdomen) += relative * damagemult * 400;
2800 victim->frameTarget = 0;
2801 victim->animTarget = staggerbackhardanim;
2802 victim->targetyaw = targetyaw + 180;
2804 victim->stunned = 1;
2806 victim->Puff(abdomen);
2807 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2813 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2814 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2815 if (victim->id == 0)
2817 emit_sound_at(landsound2, victim->coords);
2823 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2824 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2825 if (victim->id == 0)
2828 if (weaponactive != -1) {
2829 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2830 if (weapons[victim->weaponids[0]].getType() == staff)
2831 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2832 if (weapons[weaponids[0]].getType() == staff)
2833 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2835 emit_sound_at(swordstaffsound, victim->coords);
2837 emit_sound_at(metalhitsound, victim->coords);
2845 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2846 if (weaponactive != -1) {
2849 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);
2851 weapons[weaponids[0]].thrown(aim * 50);
2854 weaponids[0] = weaponids[num_weapons];
2860 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2862 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2864 if (tutoriallevel != 1)
2865 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2867 award_bonus(id, Slicebonus);
2868 if (tutoriallevel != 1) {
2869 emit_sound_at(knifeslicesound, victim->coords);
2871 //victim->jointVel(abdomen)+=relative*damagemult*200;
2872 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2873 if (victim->id != 0 || difficulty == 2) {
2874 victim->frameTarget = 0;
2875 victim->animTarget = staggerbackhardanim;
2876 victim->targetyaw = targetyaw + 180;
2880 victim->lowreversaldelay = 0;
2881 victim->highreversaldelay = 0;
2882 if (aitype != playercontrolled)
2883 weaponmissdelay = .6;
2885 if (tutoriallevel != 1)
2886 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2887 weapons[weaponids[weaponactive]].bloody = 1;
2888 if (tutoriallevel != 1)
2889 weapons[weaponids[weaponactive]].blooddrip += 3;
2891 XYZ footvel, footpoint;
2893 if (skeleton.free) {
2894 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2896 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2898 if (tutoriallevel != 1) {
2900 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2901 footvel = DoRotation(facing, 0, 90, 0) * .8;
2903 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2904 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2905 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2906 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2908 if (tutoriallevel == 1) {
2909 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2911 victim->DoDamage(damagemult * 0);
2914 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2915 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2916 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2917 award_bonus(id, Slashbonus);
2919 if (tutoriallevel != 1) {
2920 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2921 victim->DoBloodBig(2 / victim->armorhigh, 190);
2923 victim->DoBloodBig(2 / victim->armorhigh, 185);
2924 victim->deathbleeding = 1;
2925 emit_sound_at(swordslicesound, victim->coords);
2927 //victim->jointVel(abdomen)+=relative*damagemult*200;
2928 if (tutoriallevel != 1) {
2929 victim->frameTarget = 0;
2930 victim->animTarget = staggerbackhardanim;
2931 victim->targetyaw = targetyaw + 180;
2935 if (tutoriallevel != 1) {
2936 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2937 weapons[weaponids[weaponactive]].bloody = 1;
2938 weapons[weaponids[weaponactive]].blooddrip += 3;
2940 float bloodlossamount;
2941 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2942 victim->bloodloss += bloodlossamount / victim->armorhigh;
2943 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2944 victim->DoDamage(damagemult * 0);
2946 XYZ footvel, footpoint;
2948 if (skeleton.free) {
2949 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2951 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2954 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2955 footvel = DoRotation(facing, 0, 90, 0) * .8;
2957 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2958 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2959 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2960 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2963 if (victim->weaponactive != -1) {
2964 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2965 if (weapons[victim->weaponids[0]].getType() == staff)
2966 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2967 if (weapons[weaponids[0]].getType() == staff)
2968 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2970 emit_sound_at(swordstaffsound, victim->coords);
2972 emit_sound_at(metalhitsound, victim->coords);
2978 victim->Puff(righthand);
2980 victim->frameTarget = 0;
2981 victim->animTarget = staggerbackhighanim;
2982 victim->targetyaw = targetyaw + 180;
2984 aim = DoRotation(facing, 0, 90, 0) * 21;
2986 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2987 victim->num_weapons--;
2988 if (victim->num_weapons) {
2989 victim->weaponids[0] = victim->weaponids[num_weapons];
2990 if (victim->weaponstuck == victim->num_weapons)
2991 victim->weaponstuck = 0;
2993 victim->weaponactive = -1;
2994 for (unsigned i = 0; i < Person::players.size(); i++) {
2995 Person::players[i]->wentforweapon = 0;
3002 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3003 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3004 if (tutoriallevel != 1) {
3005 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3009 if (Random() % 2 || creature == wolftype) {
3012 emit_sound_at(staffheadsound, victim->coords);
3016 relative = victim->coords - coords;
3018 Normalise(&relative);
3019 relative = DoRotation(relative, 0, 90, 0);
3021 Normalise(&relative);
3022 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3023 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3025 victim->jointVel(head) += relative * damagemult * 230;
3026 victim->jointVel(neck) += relative * damagemult * 230;
3028 if (tutoriallevel != 1) {
3029 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3031 award_bonus(id, solidhit, 30);
3036 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3037 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3038 if (tutoriallevel != 1) {
3039 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3043 if (Random() % 2 || creature == wolftype) {
3046 emit_sound_at(staffheadsound, victim->coords);
3050 relative = victim->coords - coords;
3052 Normalise(&relative);
3053 relative = DoRotation(relative, 0, -90, 0);
3054 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3055 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3057 victim->jointVel(head) += relative * damagemult * 220;
3058 victim->jointVel(neck) += relative * damagemult * 220;
3060 if (tutoriallevel != 1) {
3061 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3063 award_bonus(id, solidhit, 60);
3068 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3069 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3071 if (tutoriallevel != 1) {
3073 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3076 if (Random() % 2 || creature == wolftype) {
3079 emit_sound_at(staffbodysound, victim->coords);
3081 victim->skeleton.longdead = 0;
3082 victim->skeleton.free = 1;
3083 victim->skeleton.broken = 0;
3085 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3086 victim->skeleton.joints[i].velchange = 0;
3087 victim->skeleton.joints[i].locked = 0;
3088 //victim->skeleton.joints[i].velocity=0;
3095 Normalise(&relative);
3096 if (!victim->dead) {
3097 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3098 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3100 victim->jointVel(abdomen) += relative * damagemult * 40;
3103 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3104 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3107 victim->Puff(abdomen);
3108 if (tutoriallevel != 1) {
3109 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3111 if (!victim->dead) {
3112 award_bonus(id, solidhit, 40);
3118 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3119 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3124 relative = victim->coords - coords;
3126 Normalise(&relative);
3130 if (animation[victim->animTarget].height == lowheight) {
3136 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3137 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3139 victim->jointVel(head) += relative * damagemult * 200;
3140 if (tutoriallevel != 1) {
3141 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3144 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3145 if (victim->howactive == typesleeping)
3146 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3147 if (creature == wolftype) {
3148 emit_sound_at(clawslicesound, victim->coords, 128.);
3150 victim->DoBloodBig(2 / victim->armorhead, 175);
3153 if (victim->damage >= victim->damagetolerance)
3155 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3156 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3158 victim->jointVel(abdomen) += relative * damagemult * 200;
3159 victim->frameTarget = 0;
3160 victim->animTarget = staggerbackhighanim;
3161 victim->targetyaw = targetyaw + 180;
3163 if (tutoriallevel != 1) {
3164 emit_sound_at(landsound2, victim->coords, 128.);
3166 victim->Puff(abdomen);
3167 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3168 if (creature == wolftype) {
3169 emit_sound_at(clawslicesound, victim->coords, 128.);
3171 victim->DoBloodBig(2 / victim->armorhigh, 170);
3178 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3179 if ((victim->animTarget != jumpupanim) &&
3180 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3181 (victim != this->shared_from_this())) {
3185 if (tutoriallevel != 1) {
3186 emit_sound_at(landsound2, victim->coords, 128.);
3189 relative = victim->coords - coords;
3191 Normalise(&relative);
3193 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3196 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3197 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3199 relative = DoRotation(relative, 0, -90, 0);
3201 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3202 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)
3203 victim->skeleton.joints[i].velocity = relative * 80;
3205 victim->Puff(rightankle);
3206 victim->Puff(leftankle);
3207 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3209 if (victim->damage >= victim->damagetolerance)
3211 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3212 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3214 relative = DoRotation(relative, 0, -90, 0);
3215 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3216 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)
3217 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3219 victim->jointVel(abdomen) += relative * damagemult * 200;
3220 victim->frameTarget = 0;
3221 victim->animTarget = staggerbackhighanim;
3222 victim->targetyaw = targetyaw + 180;
3224 if (tutoriallevel != 1) {
3225 emit_sound_at(landsound2, victim->coords, 128.);
3227 victim->Puff(abdomen);
3228 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3236 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3237 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3245 if (tutoriallevel != 1) {
3246 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3248 if (creature == wolftype) {
3249 emit_sound_at(clawslicesound, victim->coords, 128);
3251 victim->DoBloodBig(2 / victim->armorhigh, 170);
3255 relative = victim->coords - oldcoords;
3257 Normalise(&relative);
3258 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3259 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3261 victim->jointVel(abdomen) += relative * damagemult * 200;
3262 victim->Puff(abdomen);
3263 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3265 award_bonus(id, Reversal);
3268 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3269 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3270 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3271 takeWeapon(victim->weaponids[victim->weaponactive]);
3272 victim->num_weapons--;
3273 if (victim->num_weapons > 0) {
3274 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3276 victim->weaponactive = -1;
3281 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3289 emit_sound_at(whooshhitsound, victim->coords, 128.);
3292 relative = victim->coords - oldcoords;
3294 Normalise(&relative);
3295 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3296 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3298 victim->jointVel(abdomen) += relative * damagemult * 200;
3300 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3303 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3312 award_bonus(id, staffreversebonus);
3314 if (tutoriallevel != 1) {
3315 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3318 award_bonus(id, staffreversebonus); // Huh, again?
3321 relative = victim->coords - oldcoords;
3323 Normalise(&relative);
3324 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3325 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3327 victim->jointVel(abdomen) += relative * damagemult * 200;
3329 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3332 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3338 Normalise(&relative);
3340 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3341 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3343 victim->jointVel(lefthand) *= .1;
3344 victim->jointVel(leftwrist) *= .2;
3345 victim->jointVel(leftelbow) *= .5;
3346 victim->jointVel(leftshoulder) *= .7;
3347 victim->jointVel(righthand) *= .1;
3348 victim->jointVel(rightwrist) *= .2;
3349 victim->jointVel(rightelbow) *= .5;
3350 victim->jointVel(rightshoulder) *= .7;
3352 victim->Puff(abdomen);
3353 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3355 award_bonus(id, Reversal);
3359 if (weaponactive != -1 || creature == wolftype)
3361 if (creature == rabbittype && weaponactive != -1)
3362 if (weapons[weaponids[0]].getType() == staff)
3365 if (weaponactive != -1) {
3366 victim->DoBloodBig(2 / victim->armorhigh, 225);
3367 emit_sound_at(knifeslicesound, victim->coords);
3368 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3369 weapons[weaponids[weaponactive]].bloody = 1;
3370 weapons[weaponids[weaponactive]].blooddrip += 3;
3372 if (weaponactive == -1 && creature == wolftype) {
3373 emit_sound_at(clawslicesound, victim->coords, 128.);
3375 victim->DoBloodBig(2 / victim->armorhigh, 175);
3382 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3388 Normalise(&relative);
3390 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3391 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3393 victim->jointVel(lefthand) *= .1 - 1;
3394 victim->jointVel(leftwrist) *= .2 - 1;
3395 victim->jointVel(leftelbow) *= .5 - 1;
3396 victim->jointVel(leftshoulder) *= .7 - 1;
3397 victim->jointVel(righthand) *= .1 - 1;
3398 victim->jointVel(rightwrist) *= .2 - 1;
3399 victim->jointVel(rightelbow) *= .5 - 1;
3400 victim->jointVel(rightshoulder) *= .7 - 1;
3402 award_bonus(id, swordreversebonus);
3405 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3413 if (tutoriallevel != 1) {
3414 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3418 relative = victim->coords - oldcoords;
3420 Normalise(&relative);
3421 relative = DoRotation(relative, 0, -90, 0);
3422 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3423 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3425 victim->jointVel(abdomen) += relative * damagemult * 200;
3426 victim->Puff(abdomen);
3427 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3429 award_bonus(id, Reversal);
3432 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3435 victim->skeleton.spinny = 0;
3437 relative = facing * -1;
3439 Normalise(&relative);
3440 if (victim->id == 0)
3442 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3443 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3445 victim->damage = victim->damagetolerance;
3446 victim->permanentdamage = victim->damagetolerance - 1;
3449 if (weaponactive != -1 || creature == wolftype)
3451 if (creature == rabbittype && weaponactive != -1)
3452 if (weapons[weaponids[0]].getType() == staff)
3455 if (weaponactive != -1) {
3456 victim->DoBloodBig(200, 225);
3457 emit_sound_at(knifeslicesound, victim->coords);
3459 weapons[weaponids[weaponactive]].bloody = 2;
3460 weapons[weaponids[weaponactive]].blooddrip += 5;
3463 if (creature == wolftype && weaponactive == -1) {
3464 emit_sound_at(clawslicesound, victim->coords, 128.);
3466 victim->DoBloodBig(2, 175);
3469 award_bonus(id, spinecrusher);
3472 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3473 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3475 if (animTarget == knifefollowanim)
3476 victim->DoBloodBig(200, 210);
3477 if (animTarget == knifesneakattackanim) {
3478 XYZ footvel, footpoint;
3480 footpoint = weapons[weaponids[0]].tippoint;
3482 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3483 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3484 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3485 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3486 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3487 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3488 victim->DoBloodBig(200, 195);
3489 award_bonus(id, tracheotomy);
3491 if (animTarget == knifefollowanim) {
3492 award_bonus(id, Stabbonus);
3493 XYZ footvel, footpoint;
3495 footpoint = weapons[weaponids[0]].tippoint;
3497 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3498 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3499 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3500 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3501 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3502 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3505 victim->bloodloss += 10000;
3506 victim->velocity = 0;
3507 emit_sound_at(fleshstabsound, victim->coords);
3509 weapons[weaponids[weaponactive]].bloody = 2;
3510 weapons[weaponids[weaponactive]].blooddrip += 5;
3514 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3516 victim->velocity = 0;
3517 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3518 victim->skeleton.joints[i].velocity = 0;
3520 if (animTarget == knifefollowanim) {
3522 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3523 victim->skeleton.joints[i].velocity = 0;
3526 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3527 emit_sound_at(fleshstabremovesound, victim->coords);
3529 weapons[weaponids[weaponactive]].bloody = 2;
3530 weapons[weaponids[weaponactive]].blooddrip += 5;
3532 XYZ footvel, footpoint;
3534 footpoint = weapons[weaponids[0]].tippoint;
3536 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3537 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3545 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3546 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3547 award_bonus(id, backstab);
3551 XYZ footvel, footpoint;
3553 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3555 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3556 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3557 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3558 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3559 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3560 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3561 victim->DoBloodBig(200, 180);
3562 victim->DoBloodBig(200, 215);
3563 victim->bloodloss += 10000;
3564 victim->velocity = 0;
3565 emit_sound_at(fleshstabsound, victim->coords);
3567 weapons[weaponids[weaponactive]].bloody = 2;
3568 weapons[weaponids[weaponactive]].blooddrip += 5;
3572 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3574 victim->velocity = 0;
3575 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3576 victim->skeleton.joints[i].velocity = 0;
3578 if (weaponactive != -1) {
3579 emit_sound_at(fleshstabremovesound, victim->coords);
3581 weapons[weaponids[weaponactive]].bloody = 2;
3582 weapons[weaponids[weaponactive]].blooddrip += 5;
3584 XYZ footvel, footpoint;
3586 footpoint = weapons[weaponids[0]].tippoint;
3588 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3589 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3590 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3591 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3592 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3593 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3597 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3605 if (weaponactive == -1) {
3606 if (tutoriallevel != 1) {
3607 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3612 if (weaponactive != -1 || creature == wolftype)
3614 if (creature == rabbittype && weaponactive != -1)
3615 if (weapons[weaponids[0]].getType() == staff)
3618 if (weaponactive != -1) {
3619 victim->DoBloodBig(2 / victim->armorhead, 225);
3620 emit_sound_at(knifeslicesound, victim->coords);
3621 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3622 weapons[weaponids[weaponactive]].bloody = 1;
3623 weapons[weaponids[weaponactive]].blooddrip += 3;
3625 if (weaponactive == -1 && creature == wolftype) {
3626 emit_sound_at(clawslicesound, victim->coords, 128.);
3628 victim->DoBloodBig(2 / victim->armorhead, 175);
3632 award_bonus(id, Reversal);
3637 relative = facing * -1;
3639 Normalise(&relative);
3640 relative = DoRotation(relative, 0, 90, 0);
3642 Normalise(&relative);
3643 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3644 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3646 victim->jointVel(head) += relative * damagemult * 200;
3647 if (victim->damage < victim->damagetolerance - 100)
3648 victim->velocity = relative * 200;
3649 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3650 victim->velocity = 0;
3653 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3657 relative = facing * -1;
3659 Normalise(&relative);
3660 relative = DoRotation(relative, 0, 90, 0);
3662 Normalise(&relative);
3663 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3664 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3666 victim->jointVel(head) += relative * damagemult * 200;
3669 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3670 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3671 award_bonus(id, reverseko);
3677 if (frameTarget > animation[animCurrent].numframes - 1) {
3680 animTarget = getIdle();
3681 FootLand(leftfoot, 1);
3682 FootLand(rightfoot, 1);
3684 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3685 animTarget = rollanim;
3687 emit_sound_at(movewhooshsound, coords, 128.);
3689 if (animCurrent == staggerbackhighanim) {
3690 animTarget = getIdle();
3692 if (animCurrent == staggerbackhardanim) {
3693 animTarget = getIdle();
3695 if (animCurrent == removeknifeanim) {
3696 animTarget = getIdle();
3698 if (animCurrent == crouchremoveknifeanim) {
3699 animTarget = getCrouch();
3701 if (animCurrent == backhandspringanim) {
3702 animTarget = getIdle();
3704 if (animCurrent == dodgebackanim) {
3705 animTarget = getIdle();
3707 if (animCurrent == drawleftanim) {
3708 animTarget = getIdle();
3710 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3711 animTarget = getIdle();
3712 if (animCurrent == crouchdrawrightanim) {
3713 animTarget = getCrouch();
3715 if (weaponactive == -1)
3717 else if (weaponactive == 0) {
3719 if (num_weapons == 2) {
3721 buffer = weaponids[0];
3722 weaponids[0] = weaponids[1];
3723 weaponids[1] = buffer;
3727 if (weaponactive == -1) {
3728 emit_sound_at(knifesheathesound, coords, 128.);
3730 if (weaponactive != -1) {
3731 emit_sound_at(knifedrawsound, coords, 128.);
3734 if (animCurrent == rollanim) {
3735 animTarget = getCrouch();
3736 FootLand(leftfoot, 1);
3737 FootLand(rightfoot, 1);
3740 if (animTarget == walljumprightkickanim) {
3743 if (animTarget == walljumpleftkickanim) {
3746 animTarget = jumpdownanim;
3748 if (animCurrent == climbanim) {
3749 animTarget = getCrouch();
3751 coords += facing * .1;
3752 if (!isnormal(coords.x))
3763 if (animTarget == rabbitkickreversalanim) {
3764 animTarget = getCrouch();
3767 if (animTarget == jumpreversalanim) {
3768 animTarget = getCrouch();
3771 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3772 if (attackkeydown && animTarget != walljumpfrontanim) {
3774 float closestdist = -1;
3776 if (Person::players.size() > 1)
3777 for (unsigned i = 0; i < Person::players.size(); i++) {
3778 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3779 distance = distsq(&Person::players[i]->coords, &coords);
3780 if (closestdist == -1 || distance < closestdist) {
3781 closestdist = distance;
3786 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3787 victim = Person::players[closest];
3788 animTarget = walljumprightkickanim;
3790 XYZ rotatetarget = victim->coords - coords;
3791 Normalise(&rotatetarget);
3792 yaw = -asin(0 - rotatetarget.x);
3794 if (rotatetarget.z < 0)
3796 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3797 velocity = (victim->coords - coords) * 4;
3802 if (animTarget == walljumpbackanim) {
3803 animTarget = backflipanim;
3805 velocity = facing * -8;
3808 resume_stream(whooshsound);
3810 if (animTarget == walljumprightanim) {
3811 animTarget = rightflipanim;
3815 velocity = DoRotation(facing, 0, 30, 0) * -8;
3818 if (animTarget == walljumpfrontanim) {
3819 animTarget = frontflipanim;
3823 velocity = facing * 8;
3827 resume_stream(whooshsound);
3829 if (animTarget == walljumpleftanim) {
3830 if (attackkeydown) {
3832 float closestdist = -1;
3834 if (Person::players.size() > 1)
3835 for (unsigned i = 0; i < Person::players.size(); i++) {
3836 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3837 distance = distsq(&Person::players[i]->coords, &coords);
3838 if (closestdist == -1 || distance < closestdist) {
3839 closestdist = distance;
3844 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3845 victim = Person::players[closest];
3846 animTarget = walljumpleftkickanim;
3848 XYZ rotatetarget = victim->coords - coords;
3849 Normalise(&rotatetarget);
3850 yaw = -asin(0 - rotatetarget.x);
3852 if (rotatetarget.z < 0)
3854 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3855 velocity = (victim->coords - coords) * 4;
3860 if (animTarget != walljumpleftkickanim) {
3861 animTarget = leftflipanim;
3865 velocity = DoRotation(facing, 0, -30, 0) * -8;
3869 resume_stream(whooshsound);
3871 if (animTarget == sneakattackanim) {
3872 animCurrent = getCrouch();
3873 animTarget = getCrouch();
3880 transspeed = 1000000;
3881 targetheadyaw += 180;
3882 coords -= facing * .7;
3884 coords.y = terrain.getHeight(coords.x, coords.z);
3888 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3889 animTarget = getIdle();
3892 coords.y = terrain.getHeight(coords.x, coords.z);
3896 if (animCurrent == knifefollowanim) {
3897 animTarget = getIdle();
3900 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3901 float ycoords = oldcoords.y;
3902 animTarget = getStop();
3907 transspeed = 1000000;
3908 targetheadyaw += 180;
3909 if (!isnormal(coords.x))
3911 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3912 oldcoords = coords + facing * .5;
3913 else if (animCurrent == sweepreversalanim)
3914 oldcoords = coords + facing * 1.1;
3915 else if (animCurrent == upunchreversalanim) {
3916 oldcoords = coords + facing * 1.5;
3919 targetheadyaw += 180;
3922 } else if (animCurrent == knifeslashreversalanim) {
3923 oldcoords = coords + facing * .5;
3926 targetheadyaw += 90;
3929 } else if (animCurrent == staffspinhitreversalanim) {
3932 targetheadyaw += 180;
3937 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3939 oldcoords.y = ycoords;
3940 currentoffset = coords - oldcoords;
3946 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3951 if (animation[animTarget].attack == reversed) {
3953 if (animTarget == sweepreversedanim)
3955 animTarget = backhandspringanim;
3957 emit_sound_at(landsound, coords, 128);
3959 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3960 animTarget = rollanim;
3963 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3964 coords.y = oldcoords.y;
3966 if (animCurrent == knifeslashreversedanim) {
3967 animTarget = rollanim;
3972 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3973 coords.y = oldcoords.y;
3977 animTarget = jumpdownanim;
3980 animTarget = getIdle();
3982 animTarget = getIdle();
3983 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3984 animTarget = getIdle();
3986 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3987 coords.y = oldcoords.y;
3988 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3989 targetoffset.y = coords.y;
3991 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3992 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3993 currentoffset.y -= (coords.y - targetoffset.y);
3994 coords.y = targetoffset.y;
3996 normalsupdatedelay = 0;
3998 if (animCurrent == upunchanim) {
3999 animTarget = getStop();
4000 normalsupdatedelay = 0;
4003 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4007 if (num_weapons > 0)
4008 if (weapons[0].getType() == staff)
4014 rabbitkickragdoll = 1;
4016 if (animCurrent == rabbitkickreversedanim) {
4022 skeleton.spinny = 0;
4023 SolidHitBonus(!id); // FIXME: tricky id
4027 animTarget = rollanim;
4030 pause_sound(whooshsound);
4034 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4038 skeleton.spinny = 0;
4040 if (animCurrent == jumpreversedanim) {
4046 skeleton.spinny = 0;
4047 SolidHitBonus(!id); // FIXME: tricky id
4051 animTarget = rollanim;
4052 coords += facing * 2;
4054 pause_sound(whooshsound);
4059 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) {
4060 animTarget = getupfromfrontanim;
4062 } else if (animation[animCurrent].attack == normalattack) {
4063 animTarget = getIdle();
4066 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4067 animTarget = blockhighleftstrikeanim;
4069 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4070 animTarget = getIdle();
4073 if (animCurrent == spinkickanim && victim->skeleton.free) {
4074 if (creature == rabbittype)
4075 animTarget = fightidleanim;
4080 if (isIdle() && !wasIdle())
4081 normalsupdatedelay = 0;
4083 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4084 animTarget = jumpdownanim;
4087 if (!skeleton.free) {
4089 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4090 if (!isRun() || !wasRun()) {
4091 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4092 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4093 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4094 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4096 if (isRun() && wasRun()) {
4098 tempspeed = velspeed;
4099 if (tempspeed < 10 * speedmult)
4100 tempspeed = 10 * speedmult;
4101 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4103 } else if (transspeed)
4104 target += multiplier * transspeed * speed * 2;
4106 if (!isRun() || !wasRun()) {
4107 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4108 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4109 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4110 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4114 if (animCurrent != animTarget)
4115 target = (target + oldtarget) / 2;
4118 frameCurrent = frameTarget;
4122 rot = targetrot * target;
4123 yaw += rot - oldrot;
4129 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4131 for (int i = 0; i < skeleton.num_joints; i++) {
4132 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4135 skeleton.FindForwards();
4137 for (int i = 0; i < skeleton.num_muscles; i++) {
4138 if (skeleton.muscles[i].visible) {
4139 skeleton.FindRotationMuscle(i, animTarget);
4142 for (int i = 0; i < skeleton.num_muscles; i++) {
4143 if (skeleton.muscles[i].visible) {
4144 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4145 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4146 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4147 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4148 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4149 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4154 for (int i = 0; i < skeleton.num_joints; i++) {
4155 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4158 skeleton.FindForwards();
4160 for (int i = 0; i < skeleton.num_muscles; i++) {
4161 if (skeleton.muscles[i].visible) {
4162 skeleton.FindRotationMuscle(i, animTarget);
4165 for (int i = 0; i < skeleton.num_muscles; i++) {
4166 if (skeleton.muscles[i].visible) {
4167 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4168 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4169 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4170 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4171 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4172 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4173 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4174 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4175 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4176 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4177 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4178 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4182 if (frameCurrent >= animation[animCurrent].numframes)
4183 frameCurrent = animation[animCurrent].numframes - 1;
4185 oldanimCurrent = animCurrent;
4186 oldanimTarget = animTarget;
4187 oldframeTarget = frameTarget;
4188 oldframeCurrent = frameCurrent;
4190 for (int i = 0; i < skeleton.num_joints; i++) {
4191 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4192 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4194 offset = currentoffset * (1 - target) + targetoffset * target;
4195 for (int i = 0; i < skeleton.num_muscles; i++) {
4196 if (skeleton.muscles[i].visible) {
4197 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4198 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4199 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4204 if (isLanding() && landhard) {
4207 animTarget = getLandhard();
4220 void Person::DoStuff()
4222 static XYZ terrainnormal;
4223 static XYZ flatfacing;
4224 static XYZ flatvelocity;
4225 static float flatvelspeed;
4229 static int bloodsize;
4230 static int startx, starty, endx, endy;
4231 static GLubyte color;
4232 static XYZ bloodvel;
4234 onfiredelay -= multiplier;
4235 if (onfiredelay < 0 && onfire) {
4236 if (Random() % 2 == 0) {
4242 crouchkeydowntime += multiplier;
4244 crouchkeydowntime = 0;
4245 jumpkeydowntime += multiplier;
4246 if (!jumpkeydown && skeleton.free)
4247 jumpkeydowntime = 0;
4249 if (hostile || damage > 0 || bloodloss > 0)
4252 if (isIdle() || isRun())
4255 if (num_weapons == 1 && weaponactive != -1)
4259 blooddimamount -= multiplier * .3;
4260 speechdelay -= multiplier;
4261 texupdatedelay -= multiplier;
4262 interestdelay -= multiplier;
4263 flamedelay -= multiplier;
4264 parriedrecently -= multiplier;
4266 victim = this->shared_from_this();
4271 speed = 1.1 * speedmult;
4273 speed = 1.0 * speedmult;
4275 rabbitkickragdoll = 0;
4279 if (id != 0 && (creature == rabbittype || difficulty != 2))
4281 if (id != 0 && creature == wolftype && difficulty == 2) {
4283 if (aitype != passivetype) {
4285 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) {
4291 if (animTarget == wolfrunninganim && !superruntoggle) {
4292 animTarget = getRun();
4296 if (weaponactive == -1 && num_weapons > 0) {
4297 if (weapons[weaponids[0]].getType() == staff) {
4303 burnt += multiplier;
4307 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4309 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4315 vel[0] = velocity.x;
4316 vel[1] = velocity.y;
4317 vel[2] = velocity.z;
4320 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4321 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4325 while (flamedelay < 0 && onfire) {
4327 howmany = abs(Random() % (skeleton.num_joints));
4328 if (skeleton.free) {
4329 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4330 flatfacing = skeleton.joints[howmany].position * scale + coords;
4332 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4333 flatvelocity = (coords - oldcoords) / multiplier / 2;
4335 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4338 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4340 howmany = abs(Random() % (skeleton.num_joints));
4341 if (skeleton.free) {
4342 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4343 flatfacing = skeleton.joints[howmany].position * scale + coords;
4345 flatvelocity = (coords - oldcoords) / multiplier / 2;
4346 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4348 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4352 bleeding -= multiplier * .3;
4353 if (bloodtoggle == 2) {
4354 skeleton.drawmodel.textureptr.bind();
4355 if ((bleeding <= 0) && (detail != 2))
4360 if (neckspurtamount > 0) {
4361 neckspurtamount -= multiplier;
4362 neckspurtdelay -= multiplier * 3;
4363 neckspurtparticledelay -= multiplier * 3;
4364 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4367 if (skeleton.free) {
4368 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4369 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4370 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4372 bloodvel.z = 5 * neckspurtamount;
4373 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4374 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4375 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4377 neckspurtparticledelay = .05;
4379 if (neckspurtdelay < 0) {
4384 if (deathbleeding > 0 && dead != 2) {
4385 if (deathbleeding < 5)
4386 bleeddelay -= deathbleeding * multiplier / 4;
4388 bleeddelay -= 5 * multiplier / 4;
4389 if (bleeddelay < 0 && bloodtoggle) {
4394 if (skeleton.free) {
4395 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4396 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4398 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4399 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4403 bloodloss += deathbleeding * multiplier * 80;
4404 deathbleeding -= multiplier * 1.6;
4405 if (deathbleeding < 0)
4407 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4408 if (weaponactive != -1) {
4409 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4410 weapons[weaponids[0]].velocity.x += .01;
4413 weaponids[0] = weaponids[num_weapons];
4414 if (weaponstuck == num_weapons)
4418 for (unsigned i = 0; i < Person::players.size(); i++) {
4419 Person::players[i]->wentforweapon = 0;
4427 if (!dead && creature == wolftype) {
4428 award_bonus(0, Wolfbonus);
4431 if (animTarget == knifefollowedanim && !skeleton.free) {
4432 for (int i = 0; i < skeleton.num_joints; i++) {
4433 skeleton.joints[i].velocity = 0;
4434 skeleton.joints[i].velocity.y = -2;
4437 if (id != 0 && unconscioustime > .1) {
4445 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4446 texupdatedelay = .12;
4448 bloodsize = 5 - realtexdetail;
4452 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4453 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4454 endx = startx + bloodsize;
4455 endy = starty + bloodsize;
4465 if (endx > skeleton.skinsize - 1) {
4466 endx = skeleton.skinsize - 1;
4469 if (endy > skeleton.skinsize - 1) {
4470 endy = skeleton.skinsize - 1;
4478 for (i = startx; i < endx; i++) {
4479 for (j = starty; j < endy; j++) {
4480 if (Random() % 2 == 0) {
4481 color = Random() % 85 + 170;
4482 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4483 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4484 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4485 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4490 skeleton.drawmodel.textureptr.bind();
4494 if (skeleton.free) {
4495 bleedx += 4 * direction / realtexdetail;
4497 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4499 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4501 bleedy -= 4 / realtexdetail;
4503 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4505 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4509 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4510 righthandmorphness = targetrighthandmorphness;
4511 righthandmorphstart = righthandmorphend;
4512 } else if (righthandmorphness > targetrighthandmorphness) {
4513 righthandmorphness -= multiplier * 4;
4514 } else if (righthandmorphness < targetrighthandmorphness) {
4515 righthandmorphness += multiplier * 4;
4518 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4519 lefthandmorphness = targetlefthandmorphness;
4520 lefthandmorphstart = lefthandmorphend;
4521 } else if (lefthandmorphness > targetlefthandmorphness) {
4522 lefthandmorphness -= multiplier * 4;
4523 } else if (lefthandmorphness < targetlefthandmorphness) {
4524 lefthandmorphness += multiplier * 4;
4527 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4528 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4529 tailmorphness = targettailmorphness;
4530 tailmorphstart = tailmorphend;
4531 } else if (tailmorphness > targettailmorphness) {
4532 tailmorphness -= multiplier * 10;
4533 } else if (tailmorphness < targettailmorphness) {
4534 tailmorphness += multiplier * 10;
4538 if (creature == wolftype) {
4539 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4540 tailmorphness = targettailmorphness;
4541 tailmorphstart = tailmorphend;
4542 } else if (tailmorphness > targettailmorphness) {
4543 tailmorphness -= multiplier * 2;
4544 } else if (tailmorphness < targettailmorphness) {
4545 tailmorphness += multiplier * 2;
4549 if (headmorphend == 3 || headmorphstart == 3) {
4550 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4551 headmorphness = targetheadmorphness;
4552 headmorphstart = headmorphend;
4553 } else if (headmorphness > targetheadmorphness) {
4554 headmorphness -= multiplier * 7;
4555 } else if (headmorphness < targetheadmorphness) {
4556 headmorphness += multiplier * 7;
4558 } else if (headmorphend == 5 || headmorphstart == 5) {
4559 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4560 headmorphness = targetheadmorphness;
4561 headmorphstart = headmorphend;
4562 } else if (headmorphness > targetheadmorphness) {
4563 headmorphness -= multiplier * 10;
4564 } else if (headmorphness < targetheadmorphness) {
4565 headmorphness += multiplier * 10;
4568 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4569 headmorphness = targetheadmorphness;
4570 headmorphstart = headmorphend;
4571 } else if (headmorphness > targetheadmorphness) {
4572 headmorphness -= multiplier * 4;
4573 } else if (headmorphness < targetheadmorphness) {
4574 headmorphness += multiplier * 4;
4578 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4579 chestmorphness = targetchestmorphness;
4580 chestmorphstart = chestmorphend;
4581 } else if (chestmorphness > targetchestmorphness) {
4582 chestmorphness -= multiplier;
4583 } else if (chestmorphness < targetchestmorphness) {
4584 chestmorphness += multiplier;
4587 if (dead != 2 && howactive <= typesleeping) {
4588 if (chestmorphstart == 0 && chestmorphend == 0) {
4590 targetchestmorphness = 1;
4593 if (chestmorphstart != 0 && chestmorphend != 0) {
4595 targetchestmorphness = 1;
4597 if (environment == snowyenvironment) {
4600 if (skeleton.free) {
4601 footvel = skeleton.specialforward[0] * -1;
4602 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4604 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4605 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4607 if (animTarget == sleepanim)
4608 footvel = DoRotation(footvel, 0, 90, 0);
4609 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4613 if (!dead && howactive < typesleeping) {
4614 blinkdelay -= multiplier * 2;
4615 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4617 targetheadmorphness = 1;
4619 blinkdelay = (float)(abs(Random() % 40)) / 5;
4621 if (headmorphstart == 3 && headmorphend == 3) {
4623 targetheadmorphness = 1;
4628 twitchdelay -= multiplier * 1.5;
4629 if (animTarget != hurtidleanim) {
4630 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4632 targetheadmorphness = 1;
4634 twitchdelay = (float)(abs(Random() % 40)) / 5;
4636 if (headmorphstart == 5 && headmorphend == 5) {
4638 targetheadmorphness = 1;
4642 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4643 twitchdelay3 -= multiplier * 1;
4644 if (Random() % 2 == 0) {
4645 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4646 righthandmorphness = 0;
4647 targetrighthandmorphness = 1;
4648 righthandmorphend = 1;
4649 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4651 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4652 righthandmorphness = 0;
4653 targetrighthandmorphness = 1;
4654 righthandmorphend = 0;
4657 if (Random() % 2 == 0) {
4658 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4659 lefthandmorphness = 0;
4660 targetlefthandmorphness = 1;
4661 lefthandmorphend = 1;
4662 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4664 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4665 lefthandmorphness = 0;
4666 targetlefthandmorphness = 1;
4667 lefthandmorphend = 0;
4673 if (creature == rabbittype) {
4674 if (howactive < typesleeping)
4675 twitchdelay2 -= multiplier * 1.5;
4677 twitchdelay2 -= multiplier * 0.5;
4678 if (howactive <= typesleeping) {
4679 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4681 targettailmorphness = 1;
4683 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4685 if (tailmorphstart == 1 && tailmorphend == 1) {
4687 targettailmorphness = 1;
4690 if (tailmorphstart == 2 && tailmorphend == 2) {
4692 targettailmorphness = 1;
4699 if (creature == wolftype) {
4700 twitchdelay2 -= multiplier * 1.5;
4701 if (tailmorphend != 0)
4702 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4704 targettailmorphness = 1;
4708 if (tailmorphend != 5)
4709 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4711 targettailmorphness = 1;
4715 if (twitchdelay2 <= 0) {
4716 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4718 targettailmorphness = 1;
4721 if (tailmorphstart == 1 && tailmorphend == 1) {
4723 targettailmorphness = 1;
4726 if (tailmorphstart == 2 && tailmorphend == 2) {
4728 targettailmorphness = 1;
4731 if (tailmorphstart == 3 && tailmorphend == 3) {
4733 targettailmorphness = 1;
4736 if (tailmorphstart == 4 && tailmorphend == 4) {
4738 targettailmorphness = 1;
4745 unconscioustime = 0;
4747 if (dead == 1 || howactive == typesleeping) {
4748 unconscioustime += multiplier;
4749 //If unconscious, close eyes and mouth
4750 if (righthandmorphend != 0)
4751 righthandmorphness = 0;
4752 righthandmorphend = 0;
4753 targetrighthandmorphness = 1;
4755 if (lefthandmorphend != 0)
4756 lefthandmorphness = 0;
4757 lefthandmorphend = 0;
4758 targetlefthandmorphness = 1;
4760 if (headmorphend != 3 && headmorphend != 5)
4763 targetheadmorphness = 1;
4767 if (howactive > typesleeping) {
4770 if (bloodtoggle && !bled) {
4771 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4773 if (bloodtoggle && !bled)
4774 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4775 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4776 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4780 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4785 if (dead == 2 || howactive > typesleeping) {
4786 //If dead, open mouth and hands
4787 if (righthandmorphend != 0)
4788 righthandmorphness = 0;
4789 righthandmorphend = 0;
4790 targetrighthandmorphness = 1;
4792 if (lefthandmorphend != 0)
4793 lefthandmorphness = 0;
4794 lefthandmorphend = 0;
4795 targetlefthandmorphness = 1;
4797 if (headmorphend != 2)
4800 targetheadmorphness = 1;
4803 if (stunned > 0 && !dead && headmorphend != 2) {
4804 if (headmorphend != 4)
4807 targetheadmorphness = 1;
4810 if (damage > damagetolerance && !dead) {
4813 unconscioustime = 0;
4815 if (creature == wolftype) {
4816 award_bonus(0, Wolfbonus);
4821 if (weaponactive != -1) {
4822 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4823 weapons[weaponids[0]].velocity.x += .01;
4826 weaponids[0] = weaponids[num_weapons];
4827 if (weaponstuck == num_weapons)
4831 for (unsigned i = 0; i < Person::players.size(); i++) {
4832 Person::players[i]->wentforweapon = 0;
4838 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4847 damage -= multiplier * 13;
4849 permanentdamage -= multiplier * 4;
4850 if (isIdle() || isCrouch()) {
4852 permanentdamage -= multiplier * 4;
4856 if (permanentdamage < 0)
4857 permanentdamage = 0;
4858 if (superpermanentdamage < 0)
4859 superpermanentdamage = 0;
4860 if (permanentdamage < superpermanentdamage) {
4861 permanentdamage = superpermanentdamage;
4863 if (damage < permanentdamage) {
4864 damage = permanentdamage;
4866 if (dead == 1 && damage < damagetolerance) {
4870 for (int i = 0; i < skeleton.num_joints; i++) {
4871 skeleton.joints[i].velocity = 0;
4874 if (permanentdamage > damagetolerance && dead != 2) {
4877 if (weaponactive != -1) {
4878 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4879 weapons[weaponids[0]].velocity.x += .01;
4882 weaponids[0] = weaponids[num_weapons];
4883 if (weaponstuck == num_weapons)
4887 for (unsigned i = 0; i < Person::players.size(); i++) {
4888 Person::players[i]->wentforweapon = 0;
4894 if (!dead && creature == wolftype) {
4895 award_bonus(0, Wolfbonus);
4898 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4899 award_bonus(id, touchofdeath);
4900 if (id != 0 && unconscioustime > .1) {
4908 emit_sound_at(breaksound, coords);
4911 if (skeleton.free == 1) {
4913 pause_sound(whooshsound);
4916 //If knocked over, open hands and close mouth
4917 if (righthandmorphend != 0)
4918 righthandmorphness = 0;
4919 righthandmorphend = 0;
4920 targetrighthandmorphness = 1;
4922 if (lefthandmorphend != 0)
4923 lefthandmorphness = 0;
4924 lefthandmorphend = 0;
4925 targetlefthandmorphness = 1;
4927 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4928 if (headmorphend != 0)
4931 targetheadmorphness = 1;
4935 skeleton.DoGravity(&scale);
4937 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4938 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4939 award_bonus(id, deepimpact);
4940 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4944 for (j = 0; j < skeleton.num_joints; j++) {
4945 average += skeleton.joints[j].position;
4949 coords += average * scale;
4950 for (j = 0; j < skeleton.num_joints; j++) {
4951 skeleton.joints[j].position -= average;
4953 average /= multiplier;
4956 for (int i = 0; i < skeleton.num_joints; i++) {
4957 velocity += skeleton.joints[i].velocity * scale;
4959 velocity /= skeleton.num_joints;
4961 if (!isnormal(velocity.x) && velocity.x) {
4965 if (findLength(&average) < 10 && dead && skeleton.free) {
4966 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4967 if (skeleton.longdead > 2000) {
4968 if (skeleton.longdead > 6000) {
4970 pause_sound(whooshsound);
4975 if (dead == 2 && bloodloss < damagetolerance) {
4977 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4979 if (bloodtoggle && !bled) {
4980 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4982 if (bloodtoggle && !bled)
4983 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4984 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4985 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4986 float size = .2 * 1.2;
4989 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4993 if (dead == 2 && bloodloss >= damagetolerance) {
4995 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4998 if (bloodtoggle && !bled) {
4999 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5001 if (bloodtoggle && !bled)
5002 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5003 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5004 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5008 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5015 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5016 bool canrecover = 1;
5017 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5018 startpoint = coords;
5021 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5023 if (velocity.y < -30)
5025 for (i = 0; i < objects.numobjects; i++) {
5026 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5027 colviewer = startpoint;
5028 coltarget = endpoint;
5029 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5038 terrainnormal = jointPos(groin) - jointPos(abdomen);
5039 if (joint(groin).locked && joint(abdomen).locked) {
5040 terrainnormal = jointPos(groin) - jointPos(abdomen);
5041 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5043 if (joint(abdomen).locked && joint(neck).locked) {
5044 terrainnormal = jointPos(abdomen) - jointPos(neck);
5045 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5047 if (joint(groin).locked && joint(neck).locked) {
5048 terrainnormal = jointPos(groin) - jointPos(neck);
5049 middle = (jointPos(groin) + jointPos(neck)) / 2;
5051 Normalise(&terrainnormal);
5053 targetyaw = -asin(0 - terrainnormal.x);
5054 targetyaw *= 360 / 6.28;
5055 if (terrainnormal.z < 0)
5056 targetyaw = 180 - targetyaw;
5060 animTarget = flipanim;
5061 crouchtogglekeydown = 1;
5066 animCurrent = tempanim;
5070 for (int i = 0; i < skeleton.num_joints; i++) {
5071 tempanimation.position[i][0] = skeleton.joints[i].position;
5072 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5077 if (findLength(&average) < 10 && !dead && skeleton.free) {
5078 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5079 if (skeleton.longdead > (damage + 500) * 1.5) {
5081 pause_sound(whooshsound);
5087 terrainnormal = jointPos(groin) - jointPos(abdomen);
5088 if (joint(groin).locked && joint(abdomen).locked) {
5089 terrainnormal = jointPos(groin) - jointPos(abdomen);
5090 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5092 if (joint(abdomen).locked && joint(neck).locked) {
5093 terrainnormal = jointPos(abdomen) - jointPos(neck);
5094 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5096 if (joint(groin).locked && joint(neck).locked) {
5097 terrainnormal = jointPos(groin) - jointPos(neck);
5098 middle = (jointPos(groin) + jointPos(neck)) / 2;
5100 Normalise(&terrainnormal);
5102 targetyaw = -asin(0 - terrainnormal.x);
5103 targetyaw *= 360 / 6.28;
5104 if (terrainnormal.z < 0)
5105 targetyaw = 180 - targetyaw;
5108 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5111 if (skeleton.forward.y < 0) {
5112 animTarget = getupfrombackanim;
5116 if (skeleton.forward.y > -.3) {
5117 animTarget = getupfromfrontanim;
5125 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5126 animTarget = rollanim;
5127 targetyaw = lookyaw;
5144 if ( !leftkeydown && !rightkeydown)
5151 if (abs(targettilt2) > 50)
5153 animCurrent = tempanim;
5156 tilt2 = targettilt2;
5158 if (middle.y > 0 && animTarget != rollanim)
5159 targetoffset.y = middle.y + 1;
5161 for (int i = 0; i < skeleton.num_joints; i++) {
5162 tempanimation.position[i][0] = skeleton.joints[i].position;
5163 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5170 if (num_weapons > 0)
5171 if (weapons[0].getType() == staff)
5173 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5174 if (velocity.y > -30) {
5176 tempvelocity = velocity;
5177 Normalise(&tempvelocity);
5178 targetyaw = -asin(0 - tempvelocity.x);
5179 targetyaw *= 360 / 6.28;
5181 targetyaw = 180 - targetyaw;
5185 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5186 animTarget = rollanim;
5189 animTarget = backhandspringanim;
5195 emit_sound_at(movewhooshsound, coords, 128.);
5197 animCurrent = animTarget;
5198 frameCurrent = frameTarget - 1;
5210 if (skeleton.freefall == 0)
5215 if (aitype != passivetype || skeleton.free == 1)
5216 if (findLengthfast(&velocity) > .1)
5217 for (i = 0; i < objects.numobjects; i++) {
5218 if (objects.type[i] == firetype)
5219 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5221 if (!objects.onfire[i]) {
5222 emit_sound_at(firestartsound, objects.position[i]);
5224 objects.onfire[i] = 1;
5227 if (objects.onfire[i]) {
5232 if (objects.type[i] == bushtype)
5233 if (distsqflat(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 12 && distsq(&coords, &objects.position[i]) < objects.scale[i]*objects.scale[i] * 49) {
5235 if (!objects.onfire[i]) {
5236 emit_sound_at(firestartsound, objects.position[i]);
5238 objects.onfire[i] = 1;
5242 if (objects.onfire[i]) {
5246 if (objects.messedwith[i] <= 0) {
5250 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5253 addEnvSound(coords, 4 * findLength(&velocity));
5257 if (environment == grassyenvironment)
5258 howmany = findLength(&velocity) * 4;
5259 if (environment == snowyenvironment)
5260 howmany = findLength(&velocity) * 2;
5262 if (environment != desertenvironment)
5263 for (j = 0; j < howmany; j++) {
5264 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5265 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5266 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5269 pos.x += float(abs(Random() % 100) - 50) / 200;
5270 pos.y += float(abs(Random() % 100) - 50) / 200;
5271 pos.z += float(abs(Random() % 100) - 50) / 200;
5272 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);
5273 Sprite::setLastSpriteSpecial(1);
5275 howmany = findLength(&velocity) * 4;
5277 if (environment == snowyenvironment)
5278 for (j = 0; j < howmany; j++) {
5279 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5280 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5281 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5284 pos.x += float(abs(Random() % 100) - 50) / 200;
5285 pos.y += float(abs(Random() % 100) - 50) / 200;
5286 pos.z += float(abs(Random() % 100) - 50) / 200;
5287 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5288 Sprite::setLastSpriteSpecial(2);
5291 objects.rotx[i] += velocity.x * multiplier * 6;
5292 objects.roty[i] += velocity.z * multiplier * 6;
5293 objects.messedwith[i] = .5;
5296 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5297 if (objects.pitch[i] == 0)
5300 tempcoord = coords - objects.position[i];
5301 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5302 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5303 tempcoord += objects.position[i];
5305 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]) {
5306 if (objects.messedwith[i] <= 0) {
5310 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5313 addEnvSound(coords, 4 * findLength(&velocity));
5317 if (environment == grassyenvironment)
5318 howmany = findLength(&velocity) * 4;
5319 if (environment == snowyenvironment)
5320 howmany = findLength(&velocity) * 2;
5322 if (environment != desertenvironment)
5323 for (j = 0; j < howmany; j++) {
5324 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5325 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5326 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5328 pos += velocity * .1;
5330 pos.x += float(abs(Random() % 100) - 50) / 150;
5331 pos.y += float(abs(Random() % 100) - 50) / 150;
5332 pos.z += float(abs(Random() % 100) - 50) / 150;
5333 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);
5334 Sprite::setLastSpriteSpecial(1);
5336 howmany = findLength(&velocity) * 4;
5338 if (environment == snowyenvironment)
5339 for (j = 0; j < howmany; j++) {
5340 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5341 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5342 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5344 pos += velocity * .1;
5346 pos.x += float(abs(Random() % 100) - 50) / 150;
5347 pos.y += float(abs(Random() % 100) - 50) / 150;
5348 pos.z += float(abs(Random() % 100) - 50) / 150;
5349 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5350 Sprite::setLastSpriteSpecial(2);
5353 objects.messedwith[i] = .5;
5358 if (!skeleton.free) {
5361 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5364 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5366 if (tutoriallevel == 1 && id != 0)
5368 if (play && aitype != playercontrolled) {
5369 int whichsound = -1;
5370 i = abs(Random() % 4);
5371 if (speechdelay <= 0) {
5372 if (creature == rabbittype) {
5374 whichsound = rabbitchitter;
5376 whichsound = rabbitchitter2;
5378 if (creature == wolftype) {
5380 whichsound = growlsound;
5382 whichsound = growl2sound;
5387 if (whichsound != -1) {
5388 emit_sound_at(whichsound, coords);
5392 if (animTarget == staggerbackhighanim)
5394 if (animTarget == staggerbackhardanim)
5396 staggerdelay -= multiplier;
5397 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5399 if (velocity.y < -30 && animTarget == jumpdownanim)
5401 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5402 animTarget = getIdle();
5406 weaponmissdelay -= multiplier;
5407 highreversaldelay -= multiplier;
5408 lowreversaldelay -= multiplier;
5409 lastcollide -= multiplier;
5410 skiddelay -= multiplier;
5411 if (!isnormal(velocity.x) && velocity.x) {
5414 if (!isnormal(targettilt) && targettilt) {
5417 if (!isnormal(targettilt2) && targettilt2) {
5420 if (!isnormal(targetyaw) && targetyaw) {
5424 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5425 //open hands and close mouth
5426 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5427 righthandmorphness = 0;
5428 righthandmorphend = 0;
5429 targetrighthandmorphness = 1;
5432 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5433 lefthandmorphness = 0;
5434 lefthandmorphend = 0;
5435 targetlefthandmorphness = 1;
5438 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5441 targetheadmorphness = 1;
5445 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) {
5446 //open hands and mouth
5447 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5448 righthandmorphness = 0;
5449 righthandmorphend = 0;
5450 targetrighthandmorphness = 1;
5453 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5454 lefthandmorphness = 0;
5455 lefthandmorphend = 0;
5456 targetlefthandmorphness = 1;
5459 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5462 targetheadmorphness = 1;
5466 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5467 //close hands and mouth
5468 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5469 righthandmorphness = 0;
5470 righthandmorphend = 1;
5471 targetrighthandmorphness = 1;
5474 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5475 lefthandmorphness = 0;
5476 lefthandmorphend = 1;
5477 targetlefthandmorphness = 1;
5480 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5483 targetheadmorphness = 1;
5487 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) {
5488 //close hands and yell
5489 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5490 righthandmorphness = 0;
5491 righthandmorphend = 1;
5492 targetrighthandmorphness = 1;
5495 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5496 lefthandmorphness = 0;
5497 lefthandmorphend = 1;
5498 targetlefthandmorphness = 1;
5501 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5504 targetheadmorphness = 1;
5511 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5512 (victim->aitype != searchtype) && (aitype != passivetype) &&
5513 (aitype != searchtype) && (victim->id < Person::players.size())) {
5514 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5518 if (!dead && animTarget != hurtidleanim)
5519 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5520 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5523 targetheadmorphness = 1;
5527 if (weaponactive != -1) {
5528 if (weapons[weaponids[weaponactive]].getType() != staff) {
5529 righthandmorphstart = 1;
5530 righthandmorphend = 1;
5532 if (weapons[weaponids[weaponactive]].getType() == staff) {
5533 righthandmorphstart = 2;
5534 righthandmorphend = 2;
5536 targetrighthandmorphness = 1;
5539 terrainnormal = terrain.getNormal(coords.x, coords.z);
5541 if (animation[animTarget].attack != reversal) {
5542 if (!isnormal(coords.x))
5550 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5551 facing = flatfacing;
5552 ReflectVector(&facing, terrainnormal);
5555 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5557 targettilt2 = -facing.y * 20;
5562 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5564 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5565 flatvelocity = velocity;
5567 flatvelspeed = findLength(&flatvelocity);
5568 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5569 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5574 if (targettilt > 25)
5576 if (targettilt < -25)
5580 if (targettilt2 > 45)
5582 if (targettilt2 < -45)
5584 if (abs(tilt2 - targettilt2) < multiplier * 400)
5585 tilt2 = targettilt2;
5586 else if (tilt2 > targettilt2) {
5587 tilt2 -= multiplier * 400;
5588 } else if (tilt2 < targettilt2) {
5589 tilt2 += multiplier * 400;
5591 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5598 if (!isnormal(targettilt) && targettilt) {
5601 if (!isnormal(targettilt2) && targettilt2) {
5606 if (animTarget == rabbittackleanim) {
5607 velocity += facing * multiplier * speed * 700 * scale;
5608 velspeed = findLength(&velocity);
5609 if (velspeed > speed * 65 * scale) {
5610 velocity /= velspeed;
5611 velspeed = speed * 65 * scale;
5612 velocity *= velspeed;
5614 velocity.y += gravity * multiplier * 20;
5615 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5616 velspeed = findLength(&velocity);
5617 velocity = flatfacing * velspeed;
5619 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5620 if (isRun() || animTarget == rabbitkickanim) {
5621 velocity += facing * multiplier * speed * 700 * scale;
5622 velspeed = findLength(&velocity);
5623 if (velspeed > speed * 45 * scale) {
5624 velocity /= velspeed;
5625 velspeed = speed * 45 * scale;
5626 velocity *= velspeed;
5628 velocity.y += gravity * multiplier * 20;
5629 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5630 velspeed = findLength(&velocity);
5631 if (velspeed < speed * 30 * scale)
5632 velspeed = speed * 30 * scale;
5633 velocity = flatfacing * velspeed;
5635 } else if (isRun()) {
5636 velocity += facing * multiplier * speed * 700 * scale;
5637 velspeed = findLength(&velocity);
5638 if (creature == rabbittype) {
5639 if (velspeed > speed * 55 * scale) {
5640 velocity /= velspeed;
5641 velspeed = speed * 55 * scale;
5642 velocity *= velspeed;
5645 if (creature == wolftype) {
5646 if (velspeed > speed * 75 * scale) {
5647 velocity /= velspeed;
5648 velspeed = speed * 75 * scale;
5649 velocity *= velspeed;
5652 velocity.y += gravity * multiplier * 20;
5653 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5654 velspeed = findLength(&velocity);
5655 velocity = flatfacing * velspeed;
5658 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5659 velocity += facing * multiplier * speed * 700 * scale;
5660 velspeed = findLength(&velocity);
5661 if (velspeed > speed * 45 * scale) {
5662 velocity /= velspeed;
5663 velspeed = speed * 45 * scale;
5664 velocity *= velspeed;
5666 velocity.y += gravity * multiplier * 20;
5667 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5668 velspeed = findLength(&velocity);
5669 velocity = flatfacing * velspeed;
5672 if (animTarget == sneakanim || animTarget == walkanim) {
5673 velocity += facing * multiplier * speed * 700 * scale;
5674 velspeed = findLength(&velocity);
5675 if (velspeed > speed * 12 * scale) {
5676 velocity /= velspeed;
5677 velspeed = speed * 12 * scale;
5678 velocity *= velspeed;
5680 velocity.y += gravity * multiplier * 20;
5681 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5682 velspeed = findLength(&velocity);
5683 velocity = flatfacing * velspeed;
5686 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5687 velocity += facing * multiplier * speed * 700 * scale;
5688 velspeed = findLength(&velocity);
5689 if (velspeed > speed * 2 * scale) {
5690 velocity /= velspeed;
5691 velspeed = speed * 2 * scale;
5692 velocity *= velspeed;
5694 velocity.y += gravity * multiplier * 20;
5695 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5696 velspeed = findLength(&velocity);
5697 velocity = flatfacing * velspeed;
5701 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5702 velocity -= facing * multiplier * speed * 700 * scale;
5703 velspeed = findLength(&velocity);
5704 if (velspeed > speed * 2 * scale) {
5705 velocity /= velspeed;
5706 velspeed = speed * 2 * scale;
5707 velocity *= velspeed;
5709 velocity.y += gravity * multiplier * 20;
5710 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5711 velspeed = findLength(&velocity);
5712 velocity = flatfacing * velspeed * -1;
5715 if (animTarget == fightsidestep) {
5716 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5717 velspeed = findLength(&velocity);
5718 if (velspeed > speed * 12 * scale) {
5719 velocity /= velspeed;
5720 velspeed = speed * 12 * scale;
5721 velocity *= velspeed;
5723 velocity.y += gravity * multiplier * 20;
5724 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5725 velspeed = findLength(&velocity);
5726 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5729 if (animTarget == staggerbackhighanim) {
5730 coords -= facing * multiplier * speed * 16 * scale;
5733 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5734 coords -= facing * multiplier * speed * 20 * scale;
5738 if (animTarget == backhandspringanim) {
5739 //coords-=facing*multiplier*50*scale;
5740 velocity += facing * multiplier * speed * 700 * scale * -1;
5741 velspeed = findLength(&velocity);
5742 if (velspeed > speed * 50 * scale) {
5743 velocity /= velspeed;
5744 velspeed = speed * 50 * scale;
5745 velocity *= velspeed;
5747 velocity.y += gravity * multiplier * 20;
5748 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5749 velspeed = findLength(&velocity);
5750 velocity = flatfacing * velspeed * -1;
5752 if (animTarget == dodgebackanim) {
5753 //coords-=facing*multiplier*50*scale;
5754 velocity += facing * multiplier * speed * 700 * scale * -1;
5755 velspeed = findLength(&velocity);
5756 if (velspeed > speed * 60 * scale) {
5757 velocity /= velspeed;
5758 velspeed = speed * 60 * scale;
5759 velocity *= velspeed;
5761 velocity.y += gravity * multiplier * 20;
5762 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5763 velspeed = findLength(&velocity);
5764 velocity = flatfacing * velspeed * -1;
5767 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5768 velspeed = findLength(&velocity);
5772 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5773 velocity.y += gravity * multiplier;
5776 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5777 coords += velocity * multiplier;
5779 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5780 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5783 if (animTarget == jumpupanim) {
5785 animTarget = getIdle();
5792 pause_sound(whooshsound);
5793 OPENAL_SetVolume(channels[whooshsound], 0);
5796 if (animTarget == jumpdownanim || isFlip()) {
5797 if (isFlip())jumppower = -4;
5798 animTarget = getLanding();
5799 emit_sound_at(landsound, coords, 128.);
5802 addEnvSound(coords);
5807 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5808 coords.y += gravity * multiplier * 2;
5809 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5810 coords.y = terrain.getHeight(coords.x, coords.z);
5815 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)) {
5816 velspeed = findLength(&velocity);
5818 if (velspeed < multiplier * 300 * scale) {
5821 velocity -= velocity / velspeed * multiplier * 300 * scale;
5822 if (velspeed > 5 && (isLanding() || isLandhard())) {
5823 skiddingdelay += multiplier;
5824 if (skiddelay <= 0) {
5825 FootLand(leftfoot, .5);
5826 FootLand(rightfoot, .5);
5834 velspeed = findLength(&velocity);
5836 if (velspeed < multiplier * 600 * scale) {
5839 velocity -= velocity / velspeed * multiplier * 600 * scale;
5841 if (velspeed > 5 && (isLanding() || isLandhard())) {
5842 skiddingdelay += multiplier;
5843 if (skiddelay <= 0) {
5844 FootLand(leftfoot, .5);
5845 FootLand(rightfoot, .5);
5852 if (skiddingdelay < 0)
5853 skiddingdelay += multiplier;
5854 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5856 if (!onterrain || environment == grassyenvironment) {
5857 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5859 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5863 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5864 terrainnormal = victim->coords - coords;
5865 Normalise(&terrainnormal);
5866 targetyaw = -asin(0 - terrainnormal.x);
5867 targetyaw *= 360 / 6.28;
5868 if (terrainnormal.z < 0)
5869 targetyaw = 180 - targetyaw;
5870 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5873 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5874 targetyaw = victim->targetyaw;
5876 if (animTarget == rabbittacklinganim) {
5877 coords = victim->coords;
5880 skeleton.oldfree = skeleton.free;
5884 midterrain.x = terrain.size * terrain.scale / 2;
5885 midterrain.z = terrain.size * terrain.scale / 2;
5886 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5888 tempposit = coords - midterrain;
5890 Normalise(&tempposit);
5891 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5892 coords.x = tempposit.x + midterrain.x;
5893 coords.z = tempposit.z + midterrain.z;
5899 * inverse kinematics helper function
5901 void IKHelper(Person *p, float interp)
5903 XYZ point, change, change2;
5904 float heightleft, heightright;
5906 // TODO: implement localToWorld and worldToLocal
5907 // but keep in mind it won't be the same math if player is ragdolled or something
5908 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5909 // then comb through code for places where to use it
5911 // point = localToWorld(jointPos(leftfoot))
5912 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5913 // adjust height of foot
5914 heightleft = terrain.getHeight(point.x, point.z) + .04;
5915 point.y = heightleft;
5916 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5917 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5918 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5919 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5920 // move ankle along with foot
5921 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5922 // average knee pos between old and new pos
5923 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5925 // do same as above for right leg
5926 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5927 heightright = terrain.getHeight(point.x, point.z) + .04;
5928 point.y = heightright;
5929 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5930 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5931 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5932 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5933 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5935 // fix up skeleton now that we've moved body parts?
5936 p->skeleton.DoConstraints(&p->coords, &p->scale);
5943 int Person::DrawSkeleton()
5945 int oldplayerdetail;
5946 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5947 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5957 glAlphaFunc(GL_GREATER, 0.0001);
5959 float terrainheight;
5963 if (!isnormal(tilt))
5965 if (!isnormal(tilt2))
5967 oldplayerdetail = playerdetail;
5969 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5972 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5975 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5980 if (playerdetail != oldplayerdetail) {
5982 normalsupdatedelay = 0;
5984 static float updatedelaychange;
5985 static float morphness;
5986 static float framemult;
5988 skeleton.FindForwards();
5989 if (howactive == typesittingwall) {
5990 skeleton.specialforward[1] = 0;
5991 skeleton.specialforward[1].z = 1;
5997 static int weaponattachmuscle;
5998 static int weaponrotatemuscle;
5999 static XYZ weaponpoint;
6000 static int start, endthing;
6001 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6002 if (!isSleeping() && !isSitting()) {
6003 // TODO: give these meaningful names
6004 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6005 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6006 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6007 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6009 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6011 if (creature == wolftype)
6015 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6016 IKHelper(this, target);
6017 if (creature == wolftype)
6018 IKHelper(this, target);
6021 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6022 IKHelper(this, 1 - target);
6023 if (creature == wolftype)
6024 IKHelper(this, 1 - target);
6028 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()))
6031 targetheadyaw = -targetyaw;
6032 targetheadpitch = 0;
6033 if (animation[animTarget].attack == 3)
6034 targetheadyaw += 180;
6036 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6037 skeleton.drawmodel.vertex[i] = 0;
6038 skeleton.drawmodel.vertex[i].y = 999;
6040 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6041 skeleton.drawmodellow.vertex[i] = 0;
6042 skeleton.drawmodellow.vertex[i].y = 999;
6044 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6045 skeleton.drawmodelclothes.vertex[i] = 0;
6046 skeleton.drawmodelclothes.vertex[i].y = 999;
6048 for (int i = 0; i < skeleton.num_muscles; i++) {
6049 // convenience renames
6050 const int p1 = skeleton.muscles[i].parent1->label;
6051 const int p2 = skeleton.muscles[i].parent2->label;
6053 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6058 if (p1 == righthand || p2 == righthand) {
6059 morphness = righthandmorphness;
6060 start = righthandmorphstart;
6061 endthing = righthandmorphend;
6063 if (p1 == lefthand || p2 == lefthand) {
6064 morphness = lefthandmorphness;
6065 start = lefthandmorphstart;
6066 endthing = lefthandmorphend;
6068 if (p1 == head || p2 == head) {
6069 morphness = headmorphness;
6070 start = headmorphstart;
6071 endthing = headmorphend;
6073 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6074 morphness = chestmorphness;
6075 start = chestmorphstart;
6076 endthing = chestmorphend;
6078 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6079 morphness = tailmorphness;
6080 start = tailmorphstart;
6081 endthing = tailmorphend;
6084 skeleton.FindRotationMuscle(i, animTarget);
6085 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6086 glMatrixMode(GL_MODELVIEW);
6090 glRotatef(tilt2, 1, 0, 0);
6092 glRotatef(tilt, 0, 0, 1);
6095 glTranslatef(mid.x, mid.y, mid.z);
6097 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6098 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6100 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6101 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6103 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6104 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6106 if (playerdetail || skeleton.free == 3) {
6107 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6108 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6109 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6110 glMatrixMode(GL_MODELVIEW);
6112 if (p1 == abdomen || p2 == abdomen)
6113 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6114 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6115 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6116 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6117 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6118 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6119 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6120 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6121 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6122 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6123 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6124 if (p1 == head || p2 == head)
6125 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6126 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6127 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6128 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6129 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6130 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6131 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6135 if (!playerdetail || skeleton.free == 3) {
6136 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6137 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6138 glMatrixMode(GL_MODELVIEW);
6140 if (p1 == abdomen || p2 == abdomen)
6141 glTranslatef(v0.x * proportionbody.x,
6142 v0.y * proportionbody.y,
6143 v0.z * proportionbody.z);
6144 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6145 glTranslatef(v0.x * proportionarms.x,
6146 v0.y * proportionarms.y,
6147 v0.z * proportionarms.z);
6148 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6149 glTranslatef(v0.x * proportionlegs.x,
6150 v0.y * proportionlegs.y,
6151 v0.z * proportionlegs.z);
6152 if (p1 == head || p2 == head)
6153 glTranslatef(v0.x * proportionhead.x,
6154 v0.y * proportionhead.y,
6155 v0.z * proportionhead.z);
6157 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6158 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6159 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6160 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6166 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6167 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6169 glMatrixMode(GL_MODELVIEW);
6173 glRotatef(tilt2, 1, 0, 0);
6175 glRotatef(tilt, 0, 0, 1);
6176 glTranslatef(mid.x, mid.y, mid.z);
6177 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6178 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6180 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6181 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6183 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6184 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6186 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6187 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6188 glMatrixMode(GL_MODELVIEW);
6190 if (p1 == abdomen || p2 == abdomen)
6191 glTranslatef(v0.x * proportionbody.x,
6192 v0.y * proportionbody.y,
6193 v0.z * proportionbody.z);
6194 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6195 glTranslatef(v0.x * proportionarms.x,
6196 v0.y * proportionarms.y,
6197 v0.z * proportionarms.z);
6198 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6199 glTranslatef(v0.x * proportionlegs.x,
6200 v0.y * proportionlegs.y,
6201 v0.z * proportionlegs.z);
6202 if (p1 == head || p2 == head)
6203 glTranslatef(v0.x * proportionhead.x,
6204 v0.y * proportionhead.y,
6205 v0.z * proportionhead.z);
6206 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6207 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6208 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6209 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6214 updatedelay = 1 + (float)(Random() % 100) / 1000;
6216 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6217 normalsupdatedelay = 1;
6218 if (playerdetail || skeleton.free == 3)
6219 skeleton.drawmodel.CalculateNormals(0);
6220 if (!playerdetail || skeleton.free == 3)
6221 skeleton.drawmodellow.CalculateNormals(0);
6222 if (skeleton.clothes)
6223 skeleton.drawmodelclothes.CalculateNormals(0);
6225 if (playerdetail || skeleton.free == 3)
6226 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6227 if (!playerdetail || skeleton.free == 3)
6228 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6229 if (skeleton.clothes) {
6230 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6235 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6236 if (updatedelaychange > -realmultiplier * 30)
6237 updatedelaychange = -realmultiplier * 30;
6238 if (updatedelaychange > -framemult * 4)
6239 updatedelaychange = -framemult * 4;
6240 if (skeleton.free == 1)
6241 updatedelaychange *= 6;
6243 updatedelaychange *= 8;
6244 updatedelay += updatedelaychange;
6246 glMatrixMode(GL_MODELVIEW);
6248 glTranslatef(coords.x, coords.y - .02, coords.z);
6249 if (!skeleton.free) {
6250 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6251 glRotatef(yaw, 0, 1, 0);
6255 glColor4f(.4, 1, .4, 1);
6256 glDisable(GL_LIGHTING);
6257 glDisable(GL_TEXTURE_2D);
6260 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6261 XYZ &v0 = skeleton.drawmodel.vertex[i];
6262 glVertex3f(v0.x, v0.y, v0.z);
6268 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6269 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6270 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6271 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6272 glVertex3f(v0.x, v0.y, v0.z);
6273 glVertex3f(v1.x, v1.y, v1.z);
6274 glVertex3f(v1.x, v1.y, v1.z);
6275 glVertex3f(v2.x, v2.y, v2.z);
6276 glVertex3f(v2.x, v2.y, v2.z);
6277 glVertex3f(v0.x, v0.y, v0.z);
6283 terrainlight = terrain.getLighting(coords.x, coords.z);
6284 distance = distsq(&viewer, &coords);
6285 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6289 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6290 if (terrainheight < 1)
6292 if (terrainheight > 1.7)
6293 terrainheight = 1.7;
6295 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6296 glDisable(GL_BLEND);
6297 glAlphaFunc(GL_GREATER, 0.0001);
6298 glEnable(GL_TEXTURE_2D);
6300 glDisable(GL_TEXTURE_2D);
6301 glColor4f(.7, .35, 0, .5);
6303 glEnable(GL_LIGHTING);
6306 if (tutoriallevel && id != 0) {
6307 glColor4f(.7, .7, .7, 0.6);
6309 glEnable(GL_LIGHTING);
6311 if (canattack && cananger)
6312 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6313 glDisable(GL_TEXTURE_2D);
6314 glColor4f(1, 0, 0, 0.8);
6316 glMatrixMode(GL_TEXTURE);
6318 glTranslatef(0, -smoketex, 0);
6319 glTranslatef(-smoketex, 0, 0);
6323 if ((tutoriallevel && id != 0))
6324 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6326 skeleton.drawmodel.draw();
6329 if (!playerdetail) {
6330 if ((tutoriallevel && id != 0))
6331 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6333 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6336 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6337 if (tutoriallevel && id != 0) {
6339 glMatrixMode(GL_MODELVIEW);
6340 glEnable(GL_TEXTURE_2D);
6341 glColor4f(.7, .7, .7, 0.6);
6343 glEnable(GL_LIGHTING);
6345 if (canattack && cananger)
6346 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6347 glDisable(GL_TEXTURE_2D);
6348 glColor4f(1, 0, 0, 0.8);
6350 glMatrixMode(GL_TEXTURE);
6352 glTranslatef(0, -smoketex * .6, 0);
6353 glTranslatef(smoketex * .6, 0, 0);
6356 if ((tutoriallevel && id != 0))
6357 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6359 skeleton.drawmodel.draw();
6362 if (!playerdetail) {
6363 if ((tutoriallevel && id != 0))
6364 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6366 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6371 if (tutoriallevel && id != 0) {
6373 glMatrixMode(GL_MODELVIEW);
6374 glEnable(GL_TEXTURE_2D);
6376 if (skeleton.clothes) {
6380 skeleton.drawmodelclothes.draw();
6382 skeleton.drawmodelclothes.drawimmediate();
6388 if (num_weapons > 0) {
6389 for (k = 0; k < num_weapons; k++) {
6391 if (weaponactive == k) {
6392 if (weapons[i].getType() != staff) {
6393 for (j = 0; j < skeleton.num_muscles; j++) {
6394 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6395 weaponattachmuscle = j;
6398 for (j = 0; j < skeleton.num_muscles; j++) {
6399 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) {
6400 weaponrotatemuscle = j;
6403 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6404 if (creature == wolftype)
6405 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6407 if (weapons[i].getType() == staff) {
6408 for (j = 0; j < skeleton.num_muscles; j++) {
6409 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6410 weaponattachmuscle = j;
6413 for (j = 0; j < skeleton.num_muscles; j++) {
6414 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) {
6415 weaponrotatemuscle = j;
6418 //weaponpoint=jointPos(rightwrist);
6419 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6420 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6421 XYZ tempnormthing, vec1, vec2;
6422 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6423 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6424 CrossProduct(&vec1, &vec2, &tempnormthing);
6425 Normalise(&tempnormthing);
6426 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6427 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6430 if (weaponactive != k && weaponstuck != k) {
6431 if (weapons[i].getType() == knife)
6432 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6433 if (weapons[i].getType() == sword)
6434 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6435 if (weapons[i].getType() == staff)
6436 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6437 for (j = 0; j < skeleton.num_muscles; j++) {
6438 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) {
6439 weaponrotatemuscle = j;
6443 if (weaponstuck == k) {
6444 if (weaponstuckwhere == 0)
6445 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6447 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6448 for (j = 0; j < skeleton.num_muscles; j++) {
6449 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) {
6450 weaponrotatemuscle = j;
6454 if (skeleton.free) {
6455 weapons[i].position = weaponpoint * scale + coords;
6456 weapons[i].bigrotation = 0;
6457 weapons[i].bigtilt = 0;
6458 weapons[i].bigtilt2 = 0;
6460 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;
6461 weapons[i].bigrotation = yaw;
6462 weapons[i].bigtilt = tilt;
6463 weapons[i].bigtilt2 = tilt2;
6465 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6466 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6467 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6468 if (weaponactive == k) {
6469 if (weapons[i].getType() == knife) {
6470 weapons[i].smallrotation = 180;
6471 weapons[i].smallrotation2 = 0;
6472 if (isCrouch() || wasCrouch()) {
6473 weapons[i].smallrotation2 = 20;
6475 if (animTarget == hurtidleanim) {
6476 weapons[i].smallrotation2 = 50;
6478 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6479 XYZ temppoint1, temppoint2;
6482 temppoint1 = jointPos(righthand);
6483 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6484 distance = findDistance(&temppoint1, &temppoint2);
6485 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6486 weapons[i].rotation2 *= 360 / 6.28;
6489 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6490 weapons[i].rotation1 *= 360 / 6.28;
6491 weapons[i].rotation3 = 0;
6492 weapons[i].smallrotation = -90;
6493 weapons[i].smallrotation2 = 0;
6494 if (temppoint1.x > temppoint2.x)
6495 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6497 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6498 XYZ temppoint1, temppoint2;
6501 temppoint1 = jointPos(righthand);
6502 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6503 distance = findDistance(&temppoint1, &temppoint2);
6504 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6505 weapons[i].rotation2 *= 360 / 6.28;
6508 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6509 weapons[i].rotation1 *= 360 / 6.28;
6510 weapons[i].rotation3 = 0;
6511 weapons[i].smallrotation = 90;
6512 weapons[i].smallrotation2 = 0;
6513 if (temppoint1.x > temppoint2.x)
6514 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6516 if (animTarget == knifethrowanim) {
6517 weapons[i].smallrotation = 90;
6518 //weapons[i].smallrotation2=-90;
6519 weapons[i].smallrotation2 = 0;
6520 weapons[i].rotation1 = 0;
6521 weapons[i].rotation2 = 0;
6522 weapons[i].rotation3 = 0;
6524 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6525 weapons[i].smallrotation = -90;
6526 weapons[i].rotation1 = 0;
6527 weapons[i].rotation2 = 0;
6528 weapons[i].rotation3 = 0;
6531 if (weapons[i].getType() == sword) {
6532 weapons[i].smallrotation = 0;
6533 weapons[i].smallrotation2 = 0;
6534 if (animTarget == knifethrowanim) {
6535 weapons[i].smallrotation = -90;
6536 weapons[i].smallrotation2 = 0;
6537 weapons[i].rotation1 = 0;
6538 weapons[i].rotation2 = 0;
6539 weapons[i].rotation3 = 0;
6541 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)) {
6542 XYZ temppoint1, temppoint2;
6545 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6546 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6547 distance = findDistance(&temppoint1, &temppoint2);
6548 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6549 weapons[i].rotation2 *= 360 / 6.28;
6552 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6553 weapons[i].rotation1 *= 360 / 6.28;
6554 weapons[i].rotation3 = 0;
6555 weapons[i].smallrotation = 90;
6556 weapons[i].smallrotation2 = 0;
6557 if (temppoint1.x > temppoint2.x)
6558 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6561 if (weapons[i].getType() == staff) {
6562 weapons[i].smallrotation = 100;
6563 weapons[i].smallrotation2 = 0;
6564 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6565 XYZ temppoint1, temppoint2;
6568 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6569 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6570 distance = findDistance(&temppoint1, &temppoint2);
6571 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6572 weapons[i].rotation2 *= 360 / 6.28;
6575 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6576 weapons[i].rotation1 *= 360 / 6.28;
6577 weapons[i].rotation3 = 0;
6578 weapons[i].smallrotation = 90;
6579 weapons[i].smallrotation2 = 0;
6580 if (temppoint1.x > temppoint2.x)
6581 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6585 if (weaponactive != k && weaponstuck != k) {
6586 if (weapons[i].getType() == knife) {
6587 weapons[i].smallrotation = -70;
6588 weapons[i].smallrotation2 = 10;
6590 if (weapons[i].getType() == sword) {
6591 weapons[i].smallrotation = -100;
6592 weapons[i].smallrotation2 = -8;
6594 if (weapons[i].getType() == staff) {
6595 weapons[i].smallrotation = -100;
6596 weapons[i].smallrotation2 = -8;
6599 if (weaponstuck == k) {
6600 if (weaponstuckwhere == 0)
6601 weapons[i].smallrotation = 180;
6603 weapons[i].smallrotation = 0;
6604 weapons[i].smallrotation2 = 10;
6613 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6615 if (animCurrent != animTarget)
6617 if (skeleton.free == 2)
6626 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6629 static float distance;
6630 static float olddistance;
6631 static int intersecting;
6632 static int firstintersecting;
6635 static XYZ start, end;
6636 static float slopethreshold = -.4;
6638 firstintersecting = -1;
6642 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6645 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6646 for (i = 0; i < 4; i++) {
6647 for (j = 0; j < model->TriangleNum; j++) {
6648 if (model->facenormals[j].y <= slopethreshold) {
6650 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)));
6651 if (distance < radius) {
6652 point = *p1 - model->facenormals[j] * distance;
6653 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]]))
6656 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6657 &model->vertex[model->Triangles[j].vertex[1]],
6660 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6661 &model->vertex[model->Triangles[j].vertex[2]],
6664 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6665 &model->vertex[model->Triangles[j].vertex[2]],
6668 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6672 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)) {
6673 p1->y = point.y + radius;
6674 if ((animTarget == jumpdownanim || isFlip())) {
6675 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6678 if (animTarget == jumpupanim) {
6680 animTarget = getIdle();
6687 pause_sound(whooshsound);
6688 OPENAL_SetVolume(channels[whooshsound], 0);
6691 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6694 animTarget = getLanding();
6695 emit_sound_at(landsound, coords, 128.);
6698 addEnvSound(coords);
6705 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6706 olddistance = distance;
6707 firstintersecting = j;
6712 for (j = 0; j < model->TriangleNum; j++) {
6713 if (model->facenormals[j].y > slopethreshold) {
6716 start.y -= radius / 4;
6717 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6718 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6719 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6720 distance = abs((model->facenormals[j].x * start.x)
6721 + (model->facenormals[j].y * start.y)
6722 + (model->facenormals[j].z * start.z)
6723 - ((model->facenormals[j].x * v0.x)
6724 + (model->facenormals[j].y * v0.y)
6725 + (model->facenormals[j].z * v0.z)));
6726 if (distance < radius * .5) {
6727 point = start - model->facenormals[j] * distance;
6728 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6731 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6733 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6735 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6737 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6738 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6740 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6741 if (findLengthfast(&start) < findLengthfast(&velocity))
6744 *p1 += model->facenormals[j] * (distance - radius * .5);
6747 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6748 olddistance = distance;
6749 firstintersecting = j;
6756 *p = DoRotation(*p, 0, *rotate, 0);
6759 *p1 = DoRotation(*p1, 0, *rotate, 0);
6761 return firstintersecting;
6764 void Person::takeWeapon(int weaponId)
6767 weapons[weaponId].owner = id;
6768 if (num_weapons > 0) {
6769 weaponids[num_weapons] = weaponids[0];
6772 weaponids[0] = weaponId;
6775 void Person::addClothes()
6777 if (numclothes > 0) {
6778 for (int i = 0; i < numclothes; i++) {
6785 bool Person::addClothes(const int& clothesId)
6788 const char* fileName = clothes[clothesId];
6790 GLubyte* array = &skeleton.skinText[0];
6794 bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture);
6799 float tintr = clothestintr[clothesId];
6800 float tintg = clothestintg[clothesId];
6801 float tintb = clothestintb[clothesId];
6803 if (tintr > 1) tintr = 1;
6804 if (tintg > 1) tintg = 1;
6805 if (tintb > 1) tintb = 1;
6807 if (tintr < 0) tintr = 0;
6808 if (tintg < 0) tintg = 0;
6809 if (tintb < 0) tintb = 0;
6811 int bytesPerPixel = texture.bpp / 8;
6815 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6816 if (bytesPerPixel == 3)
6818 else if ((i + 1) % 4 == 0)
6819 alphanum = texture.data[i];
6820 if ((i + 1) % 4 || bytesPerPixel == 3) {
6822 texture.data[i] *= tintr;
6824 texture.data[i] *= tintg;
6826 texture.data[i] *= tintb;
6827 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);