2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 extern float multiplier;
30 extern Terrain terrain;
32 extern int environment;
34 extern FRUSTUM frustum;
36 extern float realmultiplier;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern bool showpoints;
57 extern bool immediate;
58 extern int tutoriallevel;
59 extern float smoketex;
60 extern int tutorialstage;
61 extern bool reversaltrain;
62 extern bool canattack;
64 extern float damagedealt;
66 extern float hostiletime;
68 extern int indialogue;
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),
297 neckspurtparticledelay(0),
301 rabbitkickragdoll(false),
311 /* Read a person in tfile. Throws an error if it’s not valid */
312 Person::Person(FILE *tfile, int mapvers, unsigned i) : Person()
315 funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons);
317 funpackf(tfile, "Bi", &howactive);
319 howactive = typeactive;
322 funpackf(tfile, "Bf", &scale);
327 funpackf(tfile, "Bb", &immobile);
332 funpackf(tfile, "Bf", &yaw);
337 if (num_weapons < 0 || num_weapons > 5) {
338 throw InvalidPersonException();
340 if (num_weapons > 0 && num_weapons < 5) {
341 for (int j = 0; j < num_weapons; j++) {
342 weaponids[j] = weapons.size();
344 funpackf(tfile, "Bi", &type);
345 weapons.push_back(Weapon(type, id));
348 funpackf(tfile, "Bi", &numwaypoints);
349 for (int j = 0; j < numwaypoints; j++) {
350 funpackf(tfile, "Bf", &waypoints[j].x);
351 funpackf(tfile, "Bf", &waypoints[j].y);
352 funpackf(tfile, "Bf", &waypoints[j].z);
354 funpackf(tfile, "Bi", &waypointtype[j]);
356 waypointtype[j] = wpkeepwalking;
360 funpackf(tfile, "Bi", &waypoint);
361 if (waypoint > (numwaypoints - 1)) {
365 funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow);
366 funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow);
367 funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow);
368 funpackf(tfile, "Bf Bf", &power, &speedmult);
370 float headprop, legprop, armprop, bodyprop;
373 funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
381 if (creature == wolftype) {
382 proportionhead = 1.1 * headprop;
383 proportionbody = 1.1 * bodyprop;
384 proportionarms = 1.1 * armprop;
385 proportionlegs = 1.1 * legprop;
386 } else if (creature == rabbittype) {
387 proportionhead = 1.2 * headprop;
388 proportionbody = 1.05 * bodyprop;
389 proportionarms = 1.00 * armprop;
390 proportionlegs = 1.1 * legprop;
391 proportionlegs.y = 1.05 * legprop;
394 funpackf(tfile, "Bi", &numclothes);
395 for (int k = 0; k < numclothes; k++) {
397 funpackf(tfile, "Bi", &templength);
398 for (int l = 0; l < templength; l++)
399 funpackf(tfile, "Bb", &clothes[k][l]);
400 clothes[k][templength] = '\0';
401 funpackf(tfile, "Bf Bf Bf", &clothestintr[k], &clothestintg[k], &clothestintb[k]);
408 * GameTick/doPlayerCollisions
410 void Person::CheckKick()
413 && (animTarget == rabbitkickanim
415 && victim != this->shared_from_this()
417 && animCurrent == rabbitkickanim)
418 && distsq(&coords, &victim->coords) < 1.2
419 && !victim->skeleton.free))
422 if (animation[victim->animTarget].height != lowheight) {
423 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
424 XYZ relative = velocity;
426 Normalise(&relative);
430 if (tutoriallevel != 1)
431 emit_sound_at(heavyimpactsound, victim->coords);
433 for (int i = 0; i < victim->skeleton.num_joints; i++) {
434 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
437 victim->DoDamage(100 * damagemult / victim->protectionhigh);
443 animTarget = backflipanim;
445 velocity = facing * -10;
449 resume_stream(whooshsound);
451 award_bonus(id, cannon);
452 } else if (victim->isCrouch()) {
453 animTarget = rabbitkickreversedanim;
454 animCurrent = rabbitkickreversedanim;
455 victim->animCurrent = rabbitkickreversalanim;
456 victim->animTarget = rabbitkickreversalanim;
462 victim->oldcoords = victim->coords;
463 coords = victim->coords;
464 victim->targetyaw = targetyaw;
465 victim->victim = this->shared_from_this();
472 * GameTick/doPlayerCollisions - spread fire between players
473 * GameTick/doDebugKeys - press f to ignite
474 * Person::DoStuff - spread fire from lit campfires and bushes
476 void Person::CatchFire()
478 XYZ flatfacing, flatvelocity;
480 for (int i = 0; i < 10; i++) {
481 howmany = abs(Random() % (skeleton.num_joints));
483 flatvelocity = skeleton.joints[howmany].velocity;
484 flatfacing = skeleton.joints[howmany].position * scale + coords;
486 flatvelocity = velocity;
487 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
489 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
494 emit_sound_at(firestartsound, coords);
496 emit_stream_at(stream_firesound, coords);
504 * idle animation for this creature (depending on status)
506 int Person::getIdle()
508 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
510 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
511 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
512 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
513 victim->id < Person::players.size())) {
514 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
515 if (creature == rabbittype)
516 return fightidleanim;
517 if (creature == wolftype)
520 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
521 if (weapons[weaponids[weaponactive]].getType() == knife)
522 return knifefightidleanim;
523 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
524 return swordfightidlebothanim;
525 if (weapons[weaponids[weaponactive]].getType() == sword)
526 return swordfightidleanim;
527 if (weapons[weaponids[weaponactive]].getType() == staff)
528 return swordfightidleanim;
530 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
531 return fightsidestep;
533 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
535 if (howactive == typesitting) return sitanim;
536 if (howactive == typesittingwall) return sitwallanim;
537 if (howactive == typesleeping) return sleepanim;
538 if (howactive == typedead1) return dead1anim;
539 if (howactive == typedead2) return dead2anim;
540 if (howactive == typedead3) return dead3anim;
541 if (howactive == typedead4) return dead4anim;
542 if (creature == rabbittype) return bounceidleanim;
543 if (creature == wolftype) return wolfidle;
548 * crouch animation for this creature
550 int Person::getCrouch()
552 if (creature == rabbittype)
554 if (creature == wolftype)
555 return wolfcrouchanim;
560 * running animation for this creature (can be upright or all fours)
564 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
566 if (creature == wolftype && (!superruntoggle))
569 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
570 return rabbitrunninganim;
571 if (creature == wolftype && (superruntoggle))
572 return wolfrunninganim;
578 int Person::getStop()
580 if (creature == rabbittype)
582 if (creature == wolftype)
589 int Person::getLanding()
591 if (creature == rabbittype)
593 if (creature == wolftype)
600 int Person::getLandhard()
602 if (creature == rabbittype)
604 if (creature == wolftype)
605 return wolflandhardanim;
612 * Person::DoAnimations
615 SolidHitBonus(int playerid)
617 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
618 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
620 award_bonus(playerid, solidhit);
624 * spawns blood effects
626 void Person::DoBlood(float howmuch, int which)
628 // FIXME: should abstract out inputs
629 static int bleedxint, bleedyint;
631 if (bloodtoggle && tutoriallevel != 1) {
632 if (bleeding <= 0 && spurt) {
634 for (int i = 0; i < 3; i++) {
635 // emit blood particles
638 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
639 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
640 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
641 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
644 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
645 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
646 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
647 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
650 if (Random() % 2 == 0) // 50% chance
651 for (int i = 0; i < 3; i++) {
652 if (Random() % 2 != 0) {
653 // emit teeth particles
656 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
657 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
660 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
661 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
665 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
667 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
669 Sprite::setLastSpriteSpecial(3); // sets it to teeth
674 // FIXME: manipulating attributes
675 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
678 if (creature == rabbittype)
679 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) {
680 bleedxint = abs(Random() % 512);
681 bleedyint = abs(Random() % 512);
683 if (creature == wolftype)
684 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) {
685 bleedxint = abs(Random() % 512);
686 bleedyint = abs(Random() % 512);
690 bleedy /= realtexdetail;
691 bleedx /= realtexdetail;
692 direction = abs(Random() % 2) * 2 - 1;
701 * spawns big blood effects and ???
702 * modifies character's skin texture
704 void Person::DoBloodBig(float howmuch, int which)
706 static int bleedxint, bleedyint, i, j;
708 if (howmuch && id == 0)
711 if (tutoriallevel != 1 || id == 0)
712 if (aitype != playercontrolled && howmuch > 0) {
716 if (creature == wolftype) {
717 int i = abs(Random() % 2);
719 whichsound = snarlsound;
721 whichsound = snarl2sound;
723 if (creature == rabbittype) {
724 int i = abs(Random() % 2);
726 whichsound = rabbitpainsound;
727 if (i == 1 && howmuch >= 2)
728 whichsound = rabbitpain1sound;
731 if (whichsound != -1) {
732 emit_sound_at(whichsound, coords);
737 if (id == 0 && howmuch > 0) {
741 if (bloodtoggle && decals && tutoriallevel != 1) {
742 if (bleeding <= 0 && spurt) {
744 for (int i = 0; i < 3; i++) {
745 // emit blood particles
746 // FIXME: copypaste from above
749 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
750 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
751 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
752 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
755 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
756 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
757 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
758 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
763 // weird texture manipulation code follows.
764 // looks like this is painting blood onto the character's skin texture
765 // FIXME: surely there's a better way
767 int offsetx = 0, offsety = 0;
769 offsety = Random() % 40;
770 offsetx = abs(Random() % 60);
772 if (which == 190 || which == 185) {
773 offsety = Random() % 40;
774 offsetx = abs(Random() % 100) - 20;
777 offsety = Random() % 10;
778 offsetx = Random() % 10;
781 offsety = Random() % 20;
782 offsetx = Random() % 20;
784 if (which == 220 || which == 215) {
794 if (creature == rabbittype)
795 for (i = 0; i < 512; i++) {
796 for (j = 0; j < 512; j++) {
797 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
798 if (i < startx) startx = i;
799 if (j < starty) starty = j;
800 if (i > endx) endx = i;
801 if (j > endy) endy = j;
805 if (creature == wolftype)
806 for (i = 0; i < 512; i++) {
807 for (j = 0; j < 512; j++) {
808 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
809 if (i < startx) startx = i;
810 if (j < starty) starty = j;
811 if (i > endx) endx = i;
812 if (j > endy) endy = j;
822 if (startx < 0) startx = 0;
823 if (starty < 0) starty = 0;
824 if (endx > 512 - 1) endx = 512 - 1;
825 if (endy > 512 - 1) endy = 512 - 1;
826 if (endx < startx) endx = startx;
827 if (endy < starty) endy = starty;
829 startx /= realtexdetail;
830 starty /= realtexdetail;
831 endx /= realtexdetail;
832 endy /= realtexdetail;
834 int texdetailint = realtexdetail;
836 if (creature == rabbittype)
837 for (i = startx; i < endx; i++) {
838 for (j = starty; j < endy; j++) {
839 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) {
840 color = Random() % 85 + 170;
841 where = i * skeleton.skinsize * 3 + j * 3;
842 if (skeleton.skinText[where + 0] > color / 2)
843 skeleton.skinText[where + 0] = color / 2;
844 skeleton.skinText[where + 1] = 0;
845 skeleton.skinText[where + 2] = 0;
849 if (creature == wolftype)
850 for (i = startx; i < endx; i++) {
851 for (j = starty; j < endy; j++) {
852 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) {
853 color = Random() % 85 + 170;
854 where = i * skeleton.skinsize * 3 + j * 3;
855 if (skeleton.skinText[where + 0] > color / 2)
856 skeleton.skinText[where + 0] = color / 2;
857 skeleton.skinText[where + 1] = 0;
858 skeleton.skinText[where + 2] = 0;
862 skeleton.drawmodel.textureptr.bind();
867 if (creature == rabbittype)
868 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) {
869 bleedxint = abs(Random() % 512);
870 bleedyint = abs(Random() % 512);
872 if (creature == wolftype)
873 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) {
874 bleedxint = abs(Random() % 512);
875 bleedyint = abs(Random() % 512);
877 bleedy = bleedxint + offsetx;
878 bleedx = bleedyint + offsety;
879 bleedy /= realtexdetail;
880 bleedx /= realtexdetail;
885 if (bleedx > skeleton.skinsize - 1)
886 bleedx = skeleton.skinsize - 1;
887 if (bleedy > skeleton.skinsize - 1)
888 bleedy = skeleton.skinsize - 1;
889 direction = abs(Random() % 2) * 2 - 1;
892 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
893 deathbleeding += bleeding;
894 bloodloss += bleeding * 3;
896 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
897 if (abs(Random() % 2) == 0) {
898 aitype = gethelptype;
901 aitype = attacktypecutoff;
909 * similar to DoBloodBig
911 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
915 static XYZ startpoint, endpoint, colpoint, movepoint;
916 static float rotationpoint;
918 static XYZ p1, p2, p3, p0;
921 float coordsx, coordsy;
924 if (bloodtoggle && decals && tutoriallevel != 1) {
927 where = DoRotation(where, 0, -yaw, 0);
935 // ray testing for a tri in the character model
936 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
937 if (whichtri != -1) {
938 // low level geometry math
940 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
941 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
942 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
944 bary.x = distsq(&p0, &p1);
945 bary.y = distsq(&p0, &p2);
946 bary.z = distsq(&p0, &p3);
948 total = bary.x + bary.y + bary.z;
957 total = bary.x + bary.y + bary.z;
963 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
964 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
965 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
966 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
967 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
968 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
969 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;
970 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;
972 if (bleeding <= 0 && spurt) {
974 for (int i = 0; i < 3; i++) {
975 // emit blood particles
976 // FIXME: more copypaste code
979 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
980 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
981 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
982 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
985 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
986 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
987 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
988 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
993 // texture manipulation follows
995 int offsetx = 0, offsety = 0;
996 offsetx = (1 + coordsy) * 512 - 291;
997 offsety = coordsx * 512 - 437;
1004 if (creature == rabbittype)
1005 for (i = 0; i < 512; i++) {
1006 for (j = 0; j < 512; j++) {
1007 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1008 if (i < startx) startx = i;
1009 if (j < starty) starty = j;
1010 if (i > endx) endx = i;
1011 if (j > endy) endy = j;
1015 if (creature == wolftype)
1016 for (i = 0; i < 512; i++) {
1017 for (j = 0; j < 512; j++) {
1018 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
1019 if (i < startx) startx = i;
1020 if (j < starty) starty = j;
1021 if (i > endx) endx = i;
1022 if (j > endy) endy = j;
1031 if (startx < 0) startx = 0;
1032 if (starty < 0) starty = 0;
1033 if (endx > 512 - 1) endx = 512 - 1;
1034 if (endy > 512 - 1) endy = 512 - 1;
1035 if (endx < startx) endx = startx;
1036 if (endy < starty) endy = starty;
1038 startx /= realtexdetail;
1039 starty /= realtexdetail;
1040 endx /= realtexdetail;
1041 endy /= realtexdetail;
1043 int texdetailint = realtexdetail;
1045 if (creature == rabbittype)
1046 for (i = startx; i < endx; i++) {
1047 for (j = starty; j < endy; j++) {
1048 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) {
1049 color = Random() % 85 + 170;
1050 where = i * skeleton.skinsize * 3 + j * 3;
1051 if (skeleton.skinText[where + 0] > color / 2)
1052 skeleton.skinText[where + 0] = color / 2;
1053 skeleton.skinText[where + 1] = 0;
1054 skeleton.skinText[where + 2] = 0;
1055 } 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) {
1056 color = Random() % 85 + 170;
1057 where = i * skeleton.skinsize * 3 + j * 3;
1058 if (skeleton.skinText[where + 0] > color / 2)
1059 skeleton.skinText[where + 0] = color / 2;
1060 skeleton.skinText[where + 1] = 0;
1061 skeleton.skinText[where + 2] = 0;
1065 if (creature == wolftype)
1066 for (i = startx; i < endx; i++) {
1067 for (j = starty; j < endy; j++) {
1068 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) {
1069 color = Random() % 85 + 170;
1070 where = i * skeleton.skinsize * 3 + j * 3;
1071 if (skeleton.skinText[where + 0] > color / 2)
1072 skeleton.skinText[where + 0] = color / 2;
1073 skeleton.skinText[where + 1] = 0;
1074 skeleton.skinText[where + 2] = 0;
1075 } 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) {
1076 color = Random() % 85 + 170;
1077 where = i * skeleton.skinsize * 3 + j * 3;
1078 if (skeleton.skinText[where + 0] > color / 2)
1079 skeleton.skinText[where + 0] = color / 2;
1080 skeleton.skinText[where + 1] = 0;
1081 skeleton.skinText[where + 2] = 0;
1085 skeleton.drawmodel.textureptr.bind();
1088 bleedy = (1 + coordsy) * 512;
1089 bleedx = coordsx * 512;
1090 bleedy /= realtexdetail;
1091 bleedx /= realtexdetail;
1096 if (bleedx > skeleton.skinsize - 1)
1097 bleedx = skeleton.skinsize - 1;
1098 if (bleedy > skeleton.skinsize - 1)
1099 bleedy = skeleton.skinsize - 1;
1100 direction = abs(Random() % 2) * 2 - 1;
1105 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1106 deathbleeding += bleeding;
1107 bloodloss += bleeding * 3;
1109 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1110 if (abs(Random() % 2) == 0) {
1111 aitype = gethelptype;
1114 aitype = attacktypecutoff;
1125 * guessing this performs a reversal
1127 void Person::Reverse()
1129 if (!((victim->aitype == playercontrolled
1131 || staggerdelay <= 0)
1132 && victim->animTarget != jumpupanim
1133 && victim->animTarget != jumpdownanim
1134 && (tutoriallevel != 1 || cananger)
1138 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1139 && (victim->id != 0 || difficulty >= 2)
1140 && (creature != wolftype || victim->creature == wolftype))
1143 if (animTarget == sweepanim) {
1144 animTarget = sweepreversedanim;
1145 animCurrent = sweepreversedanim;
1146 victim->animCurrent = sweepreversalanim;
1147 victim->animTarget = sweepreversalanim;
1149 if (animTarget == spinkickanim) {
1150 animTarget = spinkickreversedanim;
1151 animCurrent = spinkickreversedanim;
1152 victim->animCurrent = spinkickreversalanim;
1153 victim->animTarget = spinkickreversalanim;
1155 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1156 if (animTarget == rabbittacklinganim) {
1159 victim->frameCurrent = 6;
1160 victim->frameTarget = 7;
1162 animTarget = upunchreversedanim;
1163 animCurrent = upunchreversedanim;
1164 victim->animCurrent = upunchreversalanim;
1165 victim->animTarget = upunchreversalanim;
1167 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1168 if (victim->weaponactive != -1) {
1169 victim->throwtogglekeydown = 1;
1170 XYZ tempVelocity = victim->velocity * .2;
1171 if (tempVelocity.x == 0)
1172 tempVelocity.x = .1;
1173 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1174 victim->num_weapons--;
1175 if (victim->num_weapons) {
1176 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1177 if (victim->weaponstuck == victim->num_weapons)
1178 victim->weaponstuck = 0;
1181 victim->weaponactive = -1;
1182 for (unsigned j = 0; j < Person::players.size(); j++) {
1183 Person::players[j]->wentforweapon = 0;
1187 animTarget = staffhitreversedanim;
1188 animCurrent = staffhitreversedanim;
1189 victim->animCurrent = staffhitreversalanim;
1190 victim->animTarget = staffhitreversalanim;
1192 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1193 if (victim->weaponactive != -1) {
1194 victim->throwtogglekeydown = 1;
1195 XYZ tempVelocity = victim->velocity * .2;
1196 if (tempVelocity.x == 0)
1197 tempVelocity.x = .1;
1198 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1199 victim->num_weapons--;
1200 if (victim->num_weapons) {
1201 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1202 if (victim->weaponstuck == victim->num_weapons)
1203 victim->weaponstuck = 0;
1206 victim->weaponactive = -1;
1207 for (unsigned j = 0; j < Person::players.size(); j++) {
1208 Person::players[j]->wentforweapon = 0;
1211 animTarget = staffspinhitreversedanim;
1212 animCurrent = staffspinhitreversedanim;
1213 victim->animCurrent = staffspinhitreversalanim;
1214 victim->animTarget = staffspinhitreversalanim;
1216 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1217 if (victim->weaponactive != -1) {
1218 victim->throwtogglekeydown = 1;
1219 XYZ tempVelocity = victim->velocity * .2;
1220 if (tempVelocity.x == 0)
1221 tempVelocity.x = .1;
1222 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1223 victim->num_weapons--;
1224 if (victim->num_weapons) {
1225 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1226 if (victim->weaponstuck == victim->num_weapons)
1227 victim->weaponstuck = 0;
1230 victim->weaponactive = -1;
1231 for (unsigned j = 0; j < Person::players.size(); j++) {
1232 Person::players[j]->wentforweapon = 0;
1235 animTarget = swordslashreversedanim;
1236 animCurrent = swordslashreversedanim;
1237 victim->animCurrent = swordslashreversalanim;
1238 victim->animTarget = swordslashreversalanim;
1240 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1241 if (victim->weaponactive != -1) {
1242 victim->throwtogglekeydown = 1;
1243 XYZ tempVelocity = victim->velocity * .2;
1244 if (tempVelocity.x == 0)
1245 tempVelocity.x = .1;
1246 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1247 victim->num_weapons--;
1248 if (victim->num_weapons) {
1249 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1250 if (victim->weaponstuck == victim->num_weapons)
1251 victim->weaponstuck = 0;
1254 victim->weaponactive = -1;
1255 for (unsigned j = 0; j < Person::players.size(); j++) {
1256 Person::players[j]->wentforweapon = 0;
1259 animTarget = knifeslashreversedanim;
1260 animCurrent = knifeslashreversedanim;
1261 victim->animCurrent = knifeslashreversalanim;
1262 victim->animTarget = knifeslashreversalanim;
1264 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1265 victim->targettilt2 = targettilt2;
1266 victim->frameCurrent = frameCurrent;
1267 victim->frameTarget = frameTarget;
1268 victim->target = target;
1269 victim->velocity = 0;
1270 victim->oldcoords = victim->coords;
1271 victim->coords = coords;
1272 victim->targetyaw = targetyaw;
1273 victim->yaw = targetyaw;
1274 victim->victim = this->shared_from_this();
1276 if (animTarget == winduppunchanim) {
1277 animTarget = winduppunchblockedanim;
1278 victim->animTarget = blockhighleftanim;
1279 victim->frameTarget = 1;
1280 victim->target = .5;
1281 victim->victim = this->shared_from_this();
1282 victim->targetyaw = targetyaw + 180;
1284 if (animTarget == wolfslapanim) {
1285 animTarget = winduppunchblockedanim;
1286 victim->animTarget = blockhighleftanim;
1287 victim->frameTarget = 1;
1288 victim->target = .5;
1289 victim->victim = this->shared_from_this();
1290 victim->targetyaw = targetyaw + 180;
1292 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1293 animTarget = swordslashparriedanim;
1294 parriedrecently = .4;
1295 victim->parriedrecently = 0;
1296 victim->animTarget = swordslashparryanim;
1297 victim->frameTarget = 1;
1298 victim->target = .5;
1299 victim->victim = this->shared_from_this();
1300 victim->targetyaw = targetyaw + 180;
1302 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1303 if (victim->weaponactive != -1) {
1304 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1305 if (weapons[victim->weaponids[0]].getType() == staff)
1306 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1307 if (weapons[weaponids[0]].getType() == staff)
1308 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1309 emit_sound_at(swordstaffsound, victim->coords);
1311 emit_sound_at(metalhitsound, victim->coords);
1315 victim->Puff(righthand);
1317 victim->frameTarget = 0;
1318 victim->animTarget = staggerbackhighanim;
1319 victim->targetyaw = targetyaw + 180;
1321 aim = DoRotation(facing, 0, 90, 0) * 21;
1323 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1324 victim->num_weapons--;
1325 if (victim->num_weapons) {
1326 victim->weaponids[0] = victim->weaponids[num_weapons];
1327 if (victim->weaponstuck == victim->num_weapons)
1328 victim->weaponstuck = 0;
1330 victim->weaponactive = -1;
1331 for (unsigned i = 0; i < Person::players.size(); i++) {
1332 Person::players[i]->wentforweapon = 0;
1336 if (abs(Random() % 20) == 0) {
1337 if (weaponactive != -1) {
1338 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1339 if (weapons[victim->weaponids[0]].getType() == staff)
1340 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1341 if (weapons[weaponids[0]].getType() == staff)
1342 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1344 emit_sound_at(swordstaffsound, coords);
1346 emit_sound_at(metalhitsound, coords);
1354 animTarget = staggerbackhighanim;
1355 targetyaw = targetyaw + 180;
1357 aim = DoRotation(facing, 0, 90, 0) * 21;
1359 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1362 weaponids[0] = weaponids[num_weapons];
1363 if (weaponstuck == num_weapons)
1367 for (unsigned i = 0; i < Person::players.size(); i++) {
1368 Person::players[i]->wentforweapon = 0;
1375 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1376 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1377 victim->animTarget = dodgebackanim;
1378 victim->frameTarget = 0;
1382 rotatetarget = coords - victim->coords;
1383 Normalise(&rotatetarget);
1384 victim->targetyaw = -asin(0 - rotatetarget.x);
1385 victim->targetyaw *= 360 / 6.28;
1386 if (rotatetarget.z < 0)
1387 victim->targetyaw = 180 - victim->targetyaw;
1389 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1391 victim->lastattack3 = victim->lastattack2;
1392 victim->lastattack2 = victim->lastattack;
1393 victim->lastattack = victim->animTarget;
1395 victim->animTarget = sweepanim;
1396 victim->frameTarget = 0;
1400 rotatetarget = coords - victim->coords;
1401 Normalise(&rotatetarget);
1402 victim->targetyaw = -asin(0 - rotatetarget.x);
1403 victim->targetyaw *= 360 / 6.28;
1404 if (rotatetarget.z < 0)
1405 victim->targetyaw = 180 - victim->targetyaw;
1407 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1409 victim->lastattack3 = victim->lastattack2;
1410 victim->lastattack2 = victim->lastattack;
1411 victim->lastattack = victim->animTarget;
1416 victim->velocity = 0;
1418 if (aitype != playercontrolled)
1420 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1422 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1424 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1427 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1434 void Person::DoDamage(float howmuch)
1436 // subtract health (temporary?)
1437 if (tutoriallevel != 1)
1438 damage += howmuch / power;
1441 damagedealt += howmuch / power;
1443 damagetaken += howmuch / power;
1446 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1449 if (tutoriallevel != 1)
1450 permanentdamage += howmuch / 2 / power;
1451 if (tutoriallevel != 1)
1452 superpermanentdamage += howmuch / 4 / power;
1454 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1456 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1460 camerashake += howmuch / 100;
1461 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1462 blackout = damage / damagetolerance;
1467 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1468 aitype = attacktypecutoff;
1469 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1470 if (abs(Random() % 2) == 0) {
1471 aitype = gethelptype;
1474 aitype = attacktypecutoff;
1478 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1481 for (int i = 0; i < skeleton.num_joints; i++) {
1482 if (skeleton.free) {
1483 flatvelocity2 = skeleton.joints[i].velocity;
1484 flatfacing2 = skeleton.joints[i].position * scale + coords;
1486 flatvelocity2 = velocity;
1487 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1489 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1490 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1491 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1492 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1493 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1494 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1497 emit_sound_at(splattersound, coords);
1502 if (!dead && creature == wolftype) {
1503 award_bonus(0, Wolfbonus);
1510 if (tutoriallevel != 1 || id == 0)
1511 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1512 int whichsound = -1;
1514 if (creature == wolftype) {
1515 int i = abs(Random() % 2);
1517 whichsound = snarlsound;
1519 whichsound = snarl2sound;
1521 if (creature == rabbittype) {
1522 int i = abs(Random() % 2);
1524 whichsound = rabbitpainsound;
1525 if (i == 1 && damage > damagetolerance)
1526 whichsound = rabbitpain1sound;
1529 if (whichsound != -1) {
1530 emit_sound_at(whichsound, coords);
1531 addEnvSound(coords);
1538 * calculate/animate head facing direction?
1540 void Person::DoHead()
1542 static XYZ rotatearound;
1544 static float lookspeed = 500;
1546 if (!freeze && !winfreeze) {
1549 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1550 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1552 while (targetheadyaw > 180)targetheadyaw -= 360;
1553 while (targetheadyaw < -180)targetheadyaw += 360;
1555 if (targetheadyaw > 160)
1556 targetheadpitch = targetheadpitch * -1;
1557 if (targetheadyaw < -160)
1558 targetheadpitch = targetheadpitch * -1;
1559 if (targetheadyaw > 160)
1560 targetheadyaw = targetheadyaw - 180;
1561 if (targetheadyaw < -160)
1562 targetheadyaw = targetheadyaw + 180;
1564 if (targetheadpitch > 120)
1565 targetheadpitch = 120;
1566 if (targetheadpitch < -120)
1567 targetheadpitch = -120;
1568 if (targetheadyaw > 120)
1569 targetheadyaw = 120;
1570 if (targetheadyaw < -120)
1571 targetheadyaw = -120;
1574 targetheadpitch = 0;
1576 if (targetheadyaw > 80)
1578 if (targetheadyaw < -80)
1579 targetheadyaw = -80;
1580 if (targetheadpitch > 50)
1581 targetheadpitch = 50;
1582 if (targetheadpitch < -50)
1583 targetheadpitch = -50;
1586 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1587 headyaw = targetheadyaw;
1588 else if (headyaw > targetheadyaw) {
1589 headyaw -= multiplier * lookspeed;
1590 } else if (headyaw < targetheadyaw) {
1591 headyaw += multiplier * lookspeed;
1594 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1595 headpitch = targetheadpitch;
1596 else if (headpitch > targetheadpitch) {
1597 headpitch -= multiplier * lookspeed / 2;
1598 } else if (headpitch < targetheadpitch) {
1599 headpitch += multiplier * lookspeed / 2;
1602 rotatearound = jointPos(neck);
1603 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1607 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1608 facing = DoRotation(facing, headpitch * .4, 0, 0);
1609 facing = DoRotation(facing, 0, headyaw * .4, 0);
1612 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1613 facing = DoRotation(facing, headpitch * .8, 0, 0);
1614 facing = DoRotation(facing, 0, headyaw * .8, 0);
1617 if (animTarget == walkanim) {
1618 facing = DoRotation(facing, headpitch * .6, 0, 0);
1619 facing = DoRotation(facing, 0, headyaw * .6, 0);
1622 skeleton.specialforward[0] = facing;
1623 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1624 for (int i = 0; i < skeleton.num_muscles; i++) {
1625 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1626 skeleton.FindRotationMuscle(i, animTarget);
1633 * ragdolls character?
1635 void Person::RagDoll(bool checkcollision)
1640 if (!skeleton.free) {
1643 if (id == 0 && isFlip())
1650 facing = DoRotation(facing, 0, yaw, 0);
1652 skeleton.freetime = 0;
1654 skeleton.longdead = 0;
1657 skeleton.broken = 0;
1658 skeleton.spinny = 1;
1660 skeleton.freefall = 1;
1662 if (!isnormal(velocity.x)) velocity.x = 0;
1663 if (!isnormal(velocity.y)) velocity.y = 0;
1664 if (!isnormal(velocity.z)) velocity.z = 0;
1665 if (!isnormal(yaw)) yaw = 0;
1666 if (!isnormal(coords.x)) coords = 0;
1667 if (!isnormal(tilt)) tilt = 0;
1668 if (!isnormal(tilt2)) tilt2 = 0;
1670 for (int i = 0; i < skeleton.num_joints; i++) {
1671 skeleton.joints[i].delay = 0;
1672 skeleton.joints[i].locked = 0;
1673 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1674 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1675 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1676 skeleton.joints[i].position.y += .1;
1677 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1678 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1681 for (int i = 0; i < skeleton.num_joints; i++) {
1682 skeleton.joints[i].velocity = 0;
1683 skeleton.joints[i].velchange = 0;
1685 skeleton.DoConstraints(&coords, &scale);
1686 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1687 skeleton.DoConstraints(&coords, &scale);
1688 skeleton.DoConstraints(&coords, &scale);
1689 skeleton.DoConstraints(&coords, &scale);
1690 skeleton.DoConstraints(&coords, &scale);
1693 speed = animation[animTarget].speed[frameTarget] * 2;
1694 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1695 speed = animation[animCurrent].speed[frameCurrent] * 2;
1698 speed = transspeed * 2;
1702 for (int i = 0; i < skeleton.num_joints; i++) {
1703 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1704 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);
1706 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1707 change.x = (float)(Random() % 100) / 100;
1708 change.y = (float)(Random() % 100) / 100;
1709 change.z = (float)(Random() % 100) / 100;
1710 skeleton.joints[i].velocity += change;
1711 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1713 change.x = (float)(Random() % 100) / 100;
1714 change.y = (float)(Random() % 100) / 100;
1715 change.z = (float)(Random() % 100) / 100;
1716 skeleton.joints[i].velchange += change;
1717 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1720 if (checkcollision) {
1727 for (j = 0; j < skeleton.num_joints; j++) {
1728 average += skeleton.joints[j].position;
1732 coords += average * scale;
1733 for (j = 0; j < skeleton.num_joints; j++) {
1734 skeleton.joints[j].position -= average;
1737 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1738 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1739 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1740 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1741 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1744 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1745 coords.x = lowpoint.x;
1746 coords.z = lowpoint.z;
1755 for (int i = 0; i < skeleton.num_joints; i++) {
1756 velocity += skeleton.joints[i].velocity * scale;
1758 velocity /= skeleton.num_joints;
1761 if (Random() % 2 == 0) {
1762 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1763 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1764 weapons[weaponids[0]].velocity.x += .01;
1767 weaponids[0] = weaponids[num_weapons];
1768 if (weaponstuck == num_weapons)
1772 for (unsigned i = 0; i < Person::players.size(); i++) {
1773 Person::players[i]->wentforweapon = 0;
1778 animTarget = bounceidleanim;
1779 animCurrent = bounceidleanim;
1789 void Person::FootLand(bodyparts whichfoot, float opacity)
1791 if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) {
1792 cerr << "FootLand called on wrong bodypart" << endl;
1795 static XYZ terrainlight;
1796 static XYZ footvel, footpoint;
1797 if (opacity >= 1 || skiddelay <= 0) {
1800 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1801 if (distsq(&footpoint, &viewer))
1802 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1803 } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1804 footvel = velocity / 5;
1807 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1808 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1809 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1810 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1811 if (environment == snowyenvironment) {
1812 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1814 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1816 } else if (environment == grassyenvironment) {
1817 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1818 } else if (environment == desertenvironment) {
1819 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1821 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1825 } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) {
1826 footvel = velocity / 5;
1829 footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords;
1830 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) {
1831 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1838 * make a puff effect at a body part (dust effect?)
1840 void Person::Puff(int whichlabel)
1842 static XYZ footvel, footpoint;
1845 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1846 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1850 * I think I added this in an attempt to clean up code
1852 void Person::setAnimation(int animation)
1854 animTarget = animation;
1863 void Person::DoAnimations()
1865 if (!skeleton.free) {
1866 static float oldtarget;
1868 if (isIdle() && animCurrent != getIdle())
1869 normalsupdatedelay = 0;
1871 if (animTarget == tempanim || animCurrent == tempanim) {
1872 animation[tempanim] = tempanimation;
1874 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1880 vel[0] = velocity.x;
1881 vel[1] = velocity.y;
1882 vel[2] = velocity.z;
1885 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1886 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1888 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1890 if (!crouchkeydown && velocity.y >= -15)
1893 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1898 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1900 if (normaldotproduct(targfacing, velocity) >= -.3)
1901 animTarget = flipanim;
1903 animTarget = backflipanim;
1904 crouchtogglekeydown = 1;
1912 if (animation[animTarget].attack != reversed)
1914 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1915 crouchtogglekeydown = 0;
1916 if (aitype == playercontrolled)
1919 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1922 crouchtogglekeydown = 1;
1926 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1928 normalsupdatedelay = 0;
1932 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1934 emit_sound_at(fireendsound, coords);
1935 pause_sound(stream_firesound);
1939 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1940 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1942 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1943 if (normaldotproduct(victim->facing, facing) > 0)
1944 victim->animTarget = rabbittackledbackanim;
1946 victim->animTarget = rabbittackledfrontanim;
1947 victim->frameTarget = 2;
1950 victim->targetyaw = yaw;
1951 if (victim->aitype == gethelptype)
1952 victim->DoDamage(victim->damagetolerance - victim->damage);
1953 //victim->DoDamage(30);
1954 if (creature == wolftype) {
1956 emit_sound_at(clawslicesound, victim->coords);
1958 victim->DoBloodBig(1 / victim->armorhead, 210);
1960 award_bonus(id, TackleBonus,
1961 victim->aitype == gethelptype ? 50 : 0);
1965 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1966 if (weapons[weaponids[0]].getType() == knife) {
1967 if (weaponactive == -1)
1969 else if (weaponactive == 0)
1972 if (weaponactive == -1) {
1973 emit_sound_at(knifesheathesound, coords);
1975 if (weaponactive != -1) {
1976 emit_sound_at(knifedrawsound, coords, 128);
1979 drawtogglekeydown = 1;
1982 if (tutoriallevel != 1 || id == 0)
1983 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1986 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1987 if (animation[animTarget].label[frameTarget] == 1)
1988 whichsound = footstepsound;
1990 whichsound = footstepsound2;
1991 if (animation[animTarget].label[frameTarget] == 1)
1992 FootLand(leftfoot, 1);
1993 if (animation[animTarget].label[frameTarget] == 2)
1994 FootLand(rightfoot, 1);
1995 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1996 FootLand(rightfoot, 1);
1997 FootLand(leftfoot, 1);
2001 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
2002 if (animation[animTarget].label[frameTarget] == 1)
2003 whichsound = footstepsound3;
2005 whichsound = footstepsound4;
2009 if (animation[animTarget].label[frameTarget] == 1)
2010 whichsound = footstepsound3;
2012 whichsound = footstepsound4;
2014 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
2015 if (animation[animTarget].attack != neutral) {
2016 unsigned r = abs(Random() % 3);
2018 whichsound = lowwhooshsound;
2020 whichsound = midwhooshsound;
2022 whichsound = highwhooshsound;
2024 if (animation[animTarget].attack == neutral)
2025 whichsound = movewhooshsound;
2026 } else if (animation[animTarget].label[frameTarget] == 4)
2027 whichsound = knifeswishsound;
2028 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
2029 whichsound = landsound2;
2031 emit_sound_at(whichsound, coords, 256.);
2034 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
2035 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
2036 addEnvSound(coords, 15);
2038 addEnvSound(coords, 6);
2042 if (animation[animTarget].label[frameTarget] == 3) {
2044 emit_sound_at(whichsound, coords, 128.);
2049 if (tutoriallevel != 1 || id == 0)
2050 if (speechdelay <= 0)
2051 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
2052 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
2053 int whichsound = -1;
2054 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
2055 if (animation[animTarget].attack != neutral) {
2056 unsigned r = abs(Random() % 4);
2057 if (creature == rabbittype) {
2058 if (r == 0) whichsound = rabbitattacksound;
2059 if (r == 1) whichsound = rabbitattack2sound;
2060 if (r == 2) whichsound = rabbitattack3sound;
2061 if (r == 3) whichsound = rabbitattack4sound;
2063 if (creature == wolftype) {
2064 if (r == 0) whichsound = barksound;
2065 if (r == 1) whichsound = bark2sound;
2066 if (r == 2) whichsound = bark3sound;
2067 if (r == 3) whichsound = barkgrowlsound;
2073 if (whichsound != -1) {
2074 emit_sound_at(whichsound, coords);
2080 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2081 FootLand(leftfoot, 1);
2082 FootLand(rightfoot, 1);
2086 currentoffset = targetoffset;
2087 frameTarget = frameCurrent;
2088 animCurrent = animTarget;
2091 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2092 for (unsigned i = 0; i < weapons.size(); i++) {
2093 if (weapons[i].owner == -1)
2094 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2095 if (distsq(&coords, &weapons[i].position) >= 1) {
2096 if (weapons[i].getType() != staff) {
2097 emit_sound_at(knifedrawsound, coords, 128.);
2106 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2107 for (unsigned i = 0; i < weapons.size(); i++) {
2108 bool willwork = true;
2109 if (weapons[i].owner != -1)
2110 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2111 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2112 if (Person::players[weapons[i].owner]->num_weapons > 1)
2114 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2115 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2116 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2117 bool fleshstuck = false;
2118 if (weapons[i].owner != -1)
2119 if (victim->weaponstuck != -1) {
2120 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2125 emit_sound_at(fleshstabremovesound, coords, 128.);
2127 if (weapons[i].getType() != staff) {
2128 emit_sound_at(knifedrawsound, coords, 128.);
2131 if (weapons[i].owner != -1) {
2132 victim = Person::players[weapons[i].owner];
2133 if (victim->num_weapons == 1)
2134 victim->num_weapons = 0;
2136 victim->num_weapons = 1;
2138 //victim->weaponactive=-1;
2139 victim->skeleton.longdead = 0;
2140 victim->skeleton.free = 1;
2141 victim->skeleton.broken = 0;
2143 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2144 victim->skeleton.joints[j].velchange = 0;
2145 victim->skeleton.joints[j].locked = 0;
2151 Normalise(&relative);
2152 XYZ footvel, footpoint;
2154 footpoint = weapons[i].position;
2155 if (victim->weaponstuck != -1) {
2156 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2158 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2159 weapons[i].bloody = 2;
2160 weapons[i].blooddrip = 5;
2161 victim->weaponstuck = -1;
2164 if (victim->num_weapons > 0) {
2165 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2166 victim->weaponstuck = 0;
2167 if (victim->weaponids[0] == int(i))
2168 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2171 victim->jointVel(abdomen) += relative * 6;
2172 victim->jointVel(neck) += relative * 6;
2173 victim->jointVel(rightshoulder) += relative * 6;
2174 victim->jointVel(leftshoulder) += relative * 6;
2182 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2183 if (weaponactive == -1)
2185 else if (weaponactive == 0) {
2187 if (num_weapons == 2) {
2189 buffer = weaponids[0];
2190 weaponids[0] = weaponids[1];
2191 weaponids[1] = buffer;
2194 if (weaponactive == -1) {
2195 emit_sound_at(knifesheathesound, coords, 128.);
2197 if (weaponactive != -1) {
2198 emit_sound_at(knifedrawsound, coords, 128.);
2203 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2204 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2205 Normalise(&rotatetarget);
2206 targetyaw = -asin(0 - rotatetarget.x);
2207 targetyaw *= 360 / 6.28;
2208 if (rotatetarget.z < 0)
2209 targetyaw = 180 - targetyaw;
2211 if (animTarget == walljumprightkickanim)
2213 if (animTarget == walljumpleftkickanim)
2219 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2222 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2227 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2228 animTarget = rabbittackleanim;
2230 emit_sound_at(jumpsound, coords);
2238 targetloc = velocity;
2239 Normalise(&targetloc);
2240 targetloc += coords;
2241 for (unsigned i = 0; i < Person::players.size(); i++) {
2243 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2244 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2248 if (closestid != -1)
2249 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2251 victim = Person::players[closestid];
2252 coords = victim->coords;
2253 animCurrent = rabbittacklinganim;
2254 animTarget = rabbittacklinganim;
2258 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2259 rotatetarget = coords - victim->coords;
2260 Normalise(&rotatetarget);
2261 targetyaw = -asin(0 - rotatetarget.x);
2262 targetyaw *= 360 / 6.28;
2263 if (rotatetarget.z < 0)
2264 targetyaw = 180 - targetyaw;
2266 if (animTarget != rabbitrunninganim) {
2267 emit_sound_at(jumpsound, coords, 128.);
2273 float damagemult = 1 * power;
2274 if (creature == wolftype)
2275 damagemult = 2.5 * power;
2277 damagemult /= victim->damagetolerance / 200;
2279 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2280 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2281 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2285 if (Random() % 2 || creature == wolftype) {
2288 if (creature == wolftype)
2291 if (tutoriallevel != 1) {
2292 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2294 if (creature == wolftype) {
2295 emit_sound_at(clawslicesound, victim->coords, 128.);
2297 victim->DoBloodBig(2 / victim->armorhead, 175);
2301 relative = victim->coords - coords;
2303 Normalise(&relative);
2304 relative = DoRotation(relative, 0, -90, 0);
2305 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2306 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2308 victim->jointVel(head) += relative * damagemult * 200;
2310 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2316 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2317 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2321 if (Random() % 2 || creature == wolftype) {
2323 if (creature == wolftype)
2326 emit_sound_at(whooshhitsound, victim->coords);
2327 if (creature == wolftype) {
2328 emit_sound_at(clawslicesound, victim->coords, 128.);
2330 victim->DoBloodBig(2, 175);
2334 relative = victim->coords - coords;
2336 Normalise(&relative);
2338 Normalise(&relative);
2339 relative = DoRotation(relative, 0, 90, 0);
2340 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2341 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2343 victim->jointVel(head) += relative * damagemult * 100;
2345 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2349 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2350 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2356 if (tutoriallevel != 1) {
2357 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2359 if (creature == wolftype) {
2360 emit_sound_at(clawslicesound, victim->coords, 128.);
2362 victim->DoBloodBig(2 / victim->armorhead, 175);
2368 Normalise(&relative);
2369 relative = DoRotation(relative, 0, -90, 0);
2370 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2371 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2373 victim->jointVel(head) += relative * damagemult * 200;
2375 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2377 if (victim->damage > victim->damagetolerance)
2378 award_bonus(id, style);
2384 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2385 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2391 if (tutoriallevel != 1) {
2392 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2394 if (creature == wolftype) {
2395 emit_sound_at(clawslicesound, victim->coords, 128.);
2397 victim->DoBloodBig(2 / victim->armorhead, 175);
2403 Normalise(&relative);
2404 relative = DoRotation(relative, 0, 90, 0);
2405 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2406 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2408 victim->jointVel(head) += relative * damagemult * 200;
2410 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2412 if (victim->damage > victim->damagetolerance)
2413 award_bonus(id, style);
2419 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2420 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2428 emit_sound_at(whooshhitsound, victim->coords);
2431 relative = victim->coords - coords;
2433 Normalise(&relative);
2434 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2435 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2437 victim->jointVel(head) += relative * damagemult * 100;
2439 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2443 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2444 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2448 emit_sound_at(whooshhitsound, victim->coords, 128.);
2450 victim->skeleton.longdead = 0;
2451 victim->skeleton.free = 1;
2452 victim->skeleton.broken = 0;
2453 victim->skeleton.spinny = 1;
2455 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2456 victim->skeleton.joints[i].velchange = 0;
2457 victim->skeleton.joints[i].delay = 0;
2458 victim->skeleton.joints[i].locked = 0;
2459 //victim->skeleton.joints[i].velocity=0;
2465 Normalise(&relative);
2466 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2467 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2468 victim->skeleton.joints[i].position.y += relative.y * .3;
2469 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2470 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2472 victim->Puff(abdomen);
2473 victim->jointVel(abdomen).y = relative.y * 400;
2477 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2478 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2482 if (tutoriallevel != 1) {
2483 emit_sound_at(heavyimpactsound, coords, 128.);
2486 relative = victim->coords - coords;
2488 Normalise(&relative);
2489 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2490 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2492 victim->Puff(abdomen);
2493 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2497 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2498 victim->jointVel(abdomen) += relative * damagemult * 300;
2502 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2503 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2507 if (tutoriallevel != 1) {
2508 emit_sound_at(thudsound, coords);
2511 victim->skeleton.longdead = 0;
2512 victim->skeleton.free = 1;
2513 victim->skeleton.broken = 0;
2514 victim->skeleton.spinny = 1;
2516 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2517 victim->skeleton.joints[i].velchange = 0;
2518 //victim->skeleton.joints[i].delay=0;
2519 victim->skeleton.joints[i].locked = 0;
2522 relative = victim->coords - coords;
2523 Normalise(&relative);
2525 Normalise(&relative);
2526 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2527 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2532 victim->Puff(abdomen);
2533 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2534 victim->jointVel(abdomen) += relative * damagemult * 200;
2543 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2546 if (!victim->skeleton.free)
2550 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2551 emit_sound_at(knifesheathesound, coords, 128.);
2554 if (victim && hasvictim) {
2555 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2557 XYZ where, startpoint, endpoint, movepoint, colpoint;
2558 float rotationpoint;
2560 if (weapons[weaponids[weaponactive]].getType() == knife) {
2561 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2562 where -= victim->coords;
2563 if (!victim->skeleton.free)
2564 where = DoRotation(where, 0, -victim->yaw, 0);
2567 startpoint.y += 100;
2571 if (weapons[weaponids[weaponactive]].getType() == sword) {
2572 where = weapons[weaponids[weaponactive]].position;
2573 where -= victim->coords;
2574 if (!victim->skeleton.free)
2575 where = DoRotation(where, 0, -victim->yaw, 0);
2577 where = weapons[weaponids[weaponactive]].tippoint;
2578 where -= victim->coords;
2579 if (!victim->skeleton.free)
2580 where = DoRotation(where, 0, -victim->yaw, 0);
2583 if (weapons[weaponids[weaponactive]].getType() == staff) {
2584 where = weapons[weaponids[weaponactive]].position;
2585 where -= victim->coords;
2586 if (!victim->skeleton.free)
2587 where = DoRotation(where, 0, -victim->yaw, 0);
2589 where = weapons[weaponids[weaponactive]].tippoint;
2590 where -= victim->coords;
2591 if (!victim->skeleton.free)
2592 where = DoRotation(where, 0, -victim->yaw, 0);
2597 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2599 if (whichtri != -1) {
2600 if (victim->dead != 2) {
2601 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2603 award_bonus(id, FinishedBonus);
2606 weapons[weaponids[weaponactive]].bloody = 2;
2608 victim->skeleton.longdead = 0;
2609 victim->skeleton.free = 1;
2610 victim->skeleton.broken = 0;
2612 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2613 victim->skeleton.joints[i].velchange = 0;
2614 victim->skeleton.joints[i].locked = 0;
2615 //victim->skeleton.joints[i].velocity=0;
2617 emit_sound_at(fleshstabsound, coords, 128);
2620 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2621 weapons[weaponids[weaponactive]].blooddrip += 5;
2622 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2624 if (whichtri == -1) {
2626 emit_sound_at(knifesheathesound, coords, 128.);
2632 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2634 emit_sound_at(knifedrawsound, coords, 128);
2637 if (victim && hasvictim) {
2638 XYZ footvel, footpoint;
2640 emit_sound_at(fleshstabremovesound, coords, 128.);
2643 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2645 if (weapons[weaponids[weaponactive]].getType() == sword) {
2646 XYZ where, startpoint, endpoint, movepoint;
2647 float rotationpoint;
2650 where = weapons[weaponids[weaponactive]].position;
2651 where -= victim->coords;
2652 if (!victim->skeleton.free)
2653 where = DoRotation(where, 0, -victim->yaw, 0);
2655 where = weapons[weaponids[weaponactive]].tippoint;
2656 where -= victim->coords;
2657 if (!victim->skeleton.free)
2658 where = DoRotation(where, 0, -victim->yaw, 0);
2663 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2664 footpoint += victim->coords;
2666 if (whichtri == -1) {
2667 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2670 if (weapons[weaponids[weaponactive]].getType() == staff) {
2671 XYZ where, startpoint, endpoint, movepoint;
2672 float rotationpoint;
2675 where = weapons[weaponids[weaponactive]].position;
2676 where -= victim->coords;
2677 if (!victim->skeleton.free)
2678 where = DoRotation(where, 0, -victim->yaw, 0);
2680 where = weapons[weaponids[weaponactive]].tippoint;
2681 where -= victim->coords;
2682 if (!victim->skeleton.free)
2683 where = DoRotation(where, 0, -victim->yaw, 0);
2688 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2689 footpoint += victim->coords;
2691 if (whichtri == -1) {
2692 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2695 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2697 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2698 victim->skeleton.longdead = 0;
2699 victim->skeleton.free = 1;
2700 victim->skeleton.broken = 0;
2702 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2703 victim->skeleton.joints[i].velchange = 0;
2704 victim->skeleton.joints[i].locked = 0;
2705 //victim->skeleton.joints[i].velocity=0;
2711 Normalise(&relative);
2712 //victim->Puff(abdomen);
2714 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2716 if (victim->bloodloss < victim->damagetolerance) {
2717 victim->bloodloss += 1000;
2721 victim->jointVel(abdomen) += relative * damagemult * 20;
2725 if (!hasvictim && onterrain) {
2726 weapons[weaponids[weaponactive]].bloody = 0;
2727 weapons[weaponids[weaponactive]].blooddrip = 0;
2731 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2732 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2740 if (tutoriallevel != 1) {
2741 emit_sound_at(heavyimpactsound, victim->coords, 128);
2746 relative = victim->coords - coords;
2748 Normalise(&relative);
2749 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2750 victim->skeleton.joints[i].velocity = relative * 30;
2752 victim->jointVel(head) += relative * damagemult * 150;
2754 victim->frameTarget = 0;
2755 victim->animTarget = staggerbackhardanim;
2756 victim->targetyaw = targetyaw + 180;
2758 victim->stunned = 1;
2761 victim->Puff(abdomen);
2762 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2769 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2770 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2774 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2775 if (tutoriallevel != 1) {
2776 emit_sound_at(thudsound, victim->coords);
2778 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2779 if (tutoriallevel != 1) {
2780 emit_sound_at(whooshhitsound, victim->coords);
2783 if (tutoriallevel != 1) {
2784 emit_sound_at(heavyimpactsound, victim->coords);
2788 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2791 relative = victim->coords - coords;
2793 Normalise(&relative);
2795 Normalise(&relative);
2796 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2797 victim->skeleton.joints[i].velocity = relative * 5;
2799 victim->jointVel(abdomen) += relative * damagemult * 400;
2801 victim->frameTarget = 0;
2802 victim->animTarget = staggerbackhardanim;
2803 victim->targetyaw = targetyaw + 180;
2805 victim->stunned = 1;
2807 victim->Puff(abdomen);
2808 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2814 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2815 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2816 if (victim->id == 0)
2818 emit_sound_at(landsound2, victim->coords);
2824 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2825 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2826 if (victim->id == 0)
2829 if (weaponactive != -1) {
2830 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2831 if (weapons[victim->weaponids[0]].getType() == staff)
2832 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2833 if (weapons[weaponids[0]].getType() == staff)
2834 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2836 emit_sound_at(swordstaffsound, victim->coords);
2838 emit_sound_at(metalhitsound, victim->coords);
2846 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2847 if (weaponactive != -1) {
2850 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);
2852 weapons[weaponids[0]].thrown(aim * 50);
2855 weaponids[0] = weaponids[num_weapons];
2861 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2863 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2865 if (tutoriallevel != 1)
2866 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2868 award_bonus(id, Slicebonus);
2869 if (tutoriallevel != 1) {
2870 emit_sound_at(knifeslicesound, victim->coords);
2872 //victim->jointVel(abdomen)+=relative*damagemult*200;
2873 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2874 if (victim->id != 0 || difficulty == 2) {
2875 victim->frameTarget = 0;
2876 victim->animTarget = staggerbackhardanim;
2877 victim->targetyaw = targetyaw + 180;
2881 victim->lowreversaldelay = 0;
2882 victim->highreversaldelay = 0;
2883 if (aitype != playercontrolled)
2884 weaponmissdelay = .6;
2886 if (tutoriallevel != 1)
2887 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2888 weapons[weaponids[weaponactive]].bloody = 1;
2889 if (tutoriallevel != 1)
2890 weapons[weaponids[weaponactive]].blooddrip += 3;
2892 XYZ footvel, footpoint;
2894 if (skeleton.free) {
2895 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2897 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2899 if (tutoriallevel != 1) {
2901 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2902 footvel = DoRotation(facing, 0, 90, 0) * .8;
2904 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2905 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2906 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2907 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2909 if (tutoriallevel == 1) {
2910 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2912 victim->DoDamage(damagemult * 0);
2915 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2916 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2917 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2918 award_bonus(id, Slashbonus);
2920 if (tutoriallevel != 1) {
2921 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2922 victim->DoBloodBig(2 / victim->armorhigh, 190);
2924 victim->DoBloodBig(2 / victim->armorhigh, 185);
2925 victim->deathbleeding = 1;
2926 emit_sound_at(swordslicesound, victim->coords);
2928 //victim->jointVel(abdomen)+=relative*damagemult*200;
2929 if (tutoriallevel != 1) {
2930 victim->frameTarget = 0;
2931 victim->animTarget = staggerbackhardanim;
2932 victim->targetyaw = targetyaw + 180;
2936 if (tutoriallevel != 1) {
2937 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2938 weapons[weaponids[weaponactive]].bloody = 1;
2939 weapons[weaponids[weaponactive]].blooddrip += 3;
2941 float bloodlossamount;
2942 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2943 victim->bloodloss += bloodlossamount / victim->armorhigh;
2944 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2945 victim->DoDamage(damagemult * 0);
2947 XYZ footvel, footpoint;
2949 if (skeleton.free) {
2950 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2952 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2955 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2956 footvel = DoRotation(facing, 0, 90, 0) * .8;
2958 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2959 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2960 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2961 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2964 if (victim->weaponactive != -1) {
2965 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2966 if (weapons[victim->weaponids[0]].getType() == staff)
2967 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2968 if (weapons[weaponids[0]].getType() == staff)
2969 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2971 emit_sound_at(swordstaffsound, victim->coords);
2973 emit_sound_at(metalhitsound, victim->coords);
2979 victim->Puff(righthand);
2981 victim->frameTarget = 0;
2982 victim->animTarget = staggerbackhighanim;
2983 victim->targetyaw = targetyaw + 180;
2985 aim = DoRotation(facing, 0, 90, 0) * 21;
2987 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2988 victim->num_weapons--;
2989 if (victim->num_weapons) {
2990 victim->weaponids[0] = victim->weaponids[num_weapons];
2991 if (victim->weaponstuck == victim->num_weapons)
2992 victim->weaponstuck = 0;
2994 victim->weaponactive = -1;
2995 for (unsigned i = 0; i < Person::players.size(); i++) {
2996 Person::players[i]->wentforweapon = 0;
3003 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3004 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3005 if (tutoriallevel != 1) {
3006 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
3010 if (Random() % 2 || creature == wolftype) {
3013 emit_sound_at(staffheadsound, victim->coords);
3017 relative = victim->coords - coords;
3019 Normalise(&relative);
3020 relative = DoRotation(relative, 0, 90, 0);
3022 Normalise(&relative);
3023 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3024 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
3026 victim->jointVel(head) += relative * damagemult * 230;
3027 victim->jointVel(neck) += relative * damagemult * 230;
3029 if (tutoriallevel != 1) {
3030 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
3032 award_bonus(id, solidhit, 30);
3037 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
3038 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
3039 if (tutoriallevel != 1) {
3040 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
3044 if (Random() % 2 || creature == wolftype) {
3047 emit_sound_at(staffheadsound, victim->coords);
3051 relative = victim->coords - coords;
3053 Normalise(&relative);
3054 relative = DoRotation(relative, 0, -90, 0);
3055 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3056 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3058 victim->jointVel(head) += relative * damagemult * 220;
3059 victim->jointVel(neck) += relative * damagemult * 220;
3061 if (tutoriallevel != 1) {
3062 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3064 award_bonus(id, solidhit, 60);
3069 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3070 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3072 if (tutoriallevel != 1) {
3074 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3077 if (Random() % 2 || creature == wolftype) {
3080 emit_sound_at(staffbodysound, victim->coords);
3082 victim->skeleton.longdead = 0;
3083 victim->skeleton.free = 1;
3084 victim->skeleton.broken = 0;
3086 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3087 victim->skeleton.joints[i].velchange = 0;
3088 victim->skeleton.joints[i].locked = 0;
3089 //victim->skeleton.joints[i].velocity=0;
3096 Normalise(&relative);
3097 if (!victim->dead) {
3098 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3099 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3101 victim->jointVel(abdomen) += relative * damagemult * 40;
3104 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3105 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3108 victim->Puff(abdomen);
3109 if (tutoriallevel != 1) {
3110 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3112 if (!victim->dead) {
3113 award_bonus(id, solidhit, 40);
3119 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3120 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3125 relative = victim->coords - coords;
3127 Normalise(&relative);
3131 if (animation[victim->animTarget].height == lowheight) {
3137 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3138 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3140 victim->jointVel(head) += relative * damagemult * 200;
3141 if (tutoriallevel != 1) {
3142 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3145 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3146 if (victim->howactive == typesleeping)
3147 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3148 if (creature == wolftype) {
3149 emit_sound_at(clawslicesound, victim->coords, 128.);
3151 victim->DoBloodBig(2 / victim->armorhead, 175);
3154 if (victim->damage >= victim->damagetolerance)
3156 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3157 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3159 victim->jointVel(abdomen) += relative * damagemult * 200;
3160 victim->frameTarget = 0;
3161 victim->animTarget = staggerbackhighanim;
3162 victim->targetyaw = targetyaw + 180;
3164 if (tutoriallevel != 1) {
3165 emit_sound_at(landsound2, victim->coords, 128.);
3167 victim->Puff(abdomen);
3168 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3169 if (creature == wolftype) {
3170 emit_sound_at(clawslicesound, victim->coords, 128.);
3172 victim->DoBloodBig(2 / victim->armorhigh, 170);
3179 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3180 if ((victim->animTarget != jumpupanim) &&
3181 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3182 (victim != this->shared_from_this())) {
3186 if (tutoriallevel != 1) {
3187 emit_sound_at(landsound2, victim->coords, 128.);
3190 relative = victim->coords - coords;
3192 Normalise(&relative);
3194 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3197 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3198 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3200 relative = DoRotation(relative, 0, -90, 0);
3202 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3203 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)
3204 victim->skeleton.joints[i].velocity = relative * 80;
3206 victim->Puff(rightankle);
3207 victim->Puff(leftankle);
3208 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3210 if (victim->damage >= victim->damagetolerance)
3212 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3213 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3215 relative = DoRotation(relative, 0, -90, 0);
3216 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3217 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)
3218 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3220 victim->jointVel(abdomen) += relative * damagemult * 200;
3221 victim->frameTarget = 0;
3222 victim->animTarget = staggerbackhighanim;
3223 victim->targetyaw = targetyaw + 180;
3225 if (tutoriallevel != 1) {
3226 emit_sound_at(landsound2, victim->coords, 128.);
3228 victim->Puff(abdomen);
3229 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3237 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3238 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3246 if (tutoriallevel != 1) {
3247 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3249 if (creature == wolftype) {
3250 emit_sound_at(clawslicesound, victim->coords, 128);
3252 victim->DoBloodBig(2 / victim->armorhigh, 170);
3256 relative = victim->coords - oldcoords;
3258 Normalise(&relative);
3259 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3260 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3262 victim->jointVel(abdomen) += relative * damagemult * 200;
3263 victim->Puff(abdomen);
3264 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3266 award_bonus(id, Reversal);
3269 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3270 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3271 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3272 takeWeapon(victim->weaponids[victim->weaponactive]);
3273 victim->num_weapons--;
3274 if (victim->num_weapons > 0) {
3275 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3277 victim->weaponactive = -1;
3282 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3290 emit_sound_at(whooshhitsound, victim->coords, 128.);
3293 relative = victim->coords - oldcoords;
3295 Normalise(&relative);
3296 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3297 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3299 victim->jointVel(abdomen) += relative * damagemult * 200;
3301 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3304 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3313 award_bonus(id, staffreversebonus);
3315 if (tutoriallevel != 1) {
3316 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3319 award_bonus(id, staffreversebonus); // Huh, again?
3322 relative = victim->coords - oldcoords;
3324 Normalise(&relative);
3325 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3326 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3328 victim->jointVel(abdomen) += relative * damagemult * 200;
3330 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3333 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3339 Normalise(&relative);
3341 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3342 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3344 victim->jointVel(lefthand) *= .1;
3345 victim->jointVel(leftwrist) *= .2;
3346 victim->jointVel(leftelbow) *= .5;
3347 victim->jointVel(leftshoulder) *= .7;
3348 victim->jointVel(righthand) *= .1;
3349 victim->jointVel(rightwrist) *= .2;
3350 victim->jointVel(rightelbow) *= .5;
3351 victim->jointVel(rightshoulder) *= .7;
3353 victim->Puff(abdomen);
3354 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3356 award_bonus(id, Reversal);
3360 if (weaponactive != -1 || creature == wolftype)
3362 if (creature == rabbittype && weaponactive != -1)
3363 if (weapons[weaponids[0]].getType() == staff)
3366 if (weaponactive != -1) {
3367 victim->DoBloodBig(2 / victim->armorhigh, 225);
3368 emit_sound_at(knifeslicesound, victim->coords);
3369 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3370 weapons[weaponids[weaponactive]].bloody = 1;
3371 weapons[weaponids[weaponactive]].blooddrip += 3;
3373 if (weaponactive == -1 && creature == wolftype) {
3374 emit_sound_at(clawslicesound, victim->coords, 128.);
3376 victim->DoBloodBig(2 / victim->armorhigh, 175);
3383 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3389 Normalise(&relative);
3391 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3392 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3394 victim->jointVel(lefthand) *= .1 - 1;
3395 victim->jointVel(leftwrist) *= .2 - 1;
3396 victim->jointVel(leftelbow) *= .5 - 1;
3397 victim->jointVel(leftshoulder) *= .7 - 1;
3398 victim->jointVel(righthand) *= .1 - 1;
3399 victim->jointVel(rightwrist) *= .2 - 1;
3400 victim->jointVel(rightelbow) *= .5 - 1;
3401 victim->jointVel(rightshoulder) *= .7 - 1;
3403 award_bonus(id, swordreversebonus);
3406 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3414 if (tutoriallevel != 1) {
3415 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3419 relative = victim->coords - oldcoords;
3421 Normalise(&relative);
3422 relative = DoRotation(relative, 0, -90, 0);
3423 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3424 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3426 victim->jointVel(abdomen) += relative * damagemult * 200;
3427 victim->Puff(abdomen);
3428 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3430 award_bonus(id, Reversal);
3433 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3436 victim->skeleton.spinny = 0;
3438 relative = facing * -1;
3440 Normalise(&relative);
3441 if (victim->id == 0)
3443 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3444 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3446 victim->damage = victim->damagetolerance;
3447 victim->permanentdamage = victim->damagetolerance - 1;
3450 if (weaponactive != -1 || creature == wolftype)
3452 if (creature == rabbittype && weaponactive != -1)
3453 if (weapons[weaponids[0]].getType() == staff)
3456 if (weaponactive != -1) {
3457 victim->DoBloodBig(200, 225);
3458 emit_sound_at(knifeslicesound, victim->coords);
3460 weapons[weaponids[weaponactive]].bloody = 2;
3461 weapons[weaponids[weaponactive]].blooddrip += 5;
3464 if (creature == wolftype && weaponactive == -1) {
3465 emit_sound_at(clawslicesound, victim->coords, 128.);
3467 victim->DoBloodBig(2, 175);
3470 award_bonus(id, spinecrusher);
3473 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3474 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3476 if (animTarget == knifefollowanim)
3477 victim->DoBloodBig(200, 210);
3478 if (animTarget == knifesneakattackanim) {
3479 XYZ footvel, footpoint;
3481 footpoint = weapons[weaponids[0]].tippoint;
3483 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3484 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3485 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3486 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3487 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3488 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3489 victim->DoBloodBig(200, 195);
3490 award_bonus(id, tracheotomy);
3492 if (animTarget == knifefollowanim) {
3493 award_bonus(id, Stabbonus);
3494 XYZ footvel, footpoint;
3496 footpoint = weapons[weaponids[0]].tippoint;
3498 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3499 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3500 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3501 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3502 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3503 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3506 victim->bloodloss += 10000;
3507 victim->velocity = 0;
3508 emit_sound_at(fleshstabsound, victim->coords);
3510 weapons[weaponids[weaponactive]].bloody = 2;
3511 weapons[weaponids[weaponactive]].blooddrip += 5;
3515 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3517 victim->velocity = 0;
3518 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3519 victim->skeleton.joints[i].velocity = 0;
3521 if (animTarget == knifefollowanim) {
3523 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3524 victim->skeleton.joints[i].velocity = 0;
3527 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3528 emit_sound_at(fleshstabremovesound, victim->coords);
3530 weapons[weaponids[weaponactive]].bloody = 2;
3531 weapons[weaponids[weaponactive]].blooddrip += 5;
3533 XYZ footvel, footpoint;
3535 footpoint = weapons[weaponids[0]].tippoint;
3537 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3538 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3539 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3540 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3541 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3542 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3546 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3547 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3548 award_bonus(id, backstab);
3552 XYZ footvel, footpoint;
3554 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3556 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3557 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3558 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3559 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3560 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3561 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3562 victim->DoBloodBig(200, 180);
3563 victim->DoBloodBig(200, 215);
3564 victim->bloodloss += 10000;
3565 victim->velocity = 0;
3566 emit_sound_at(fleshstabsound, victim->coords);
3568 weapons[weaponids[weaponactive]].bloody = 2;
3569 weapons[weaponids[weaponactive]].blooddrip += 5;
3573 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3575 victim->velocity = 0;
3576 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3577 victim->skeleton.joints[i].velocity = 0;
3579 if (weaponactive != -1) {
3580 emit_sound_at(fleshstabremovesound, victim->coords);
3582 weapons[weaponids[weaponactive]].bloody = 2;
3583 weapons[weaponids[weaponactive]].blooddrip += 5;
3585 XYZ footvel, footpoint;
3587 footpoint = weapons[weaponids[0]].tippoint;
3589 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3590 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3591 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3592 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3593 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3594 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3598 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3606 if (weaponactive == -1) {
3607 if (tutoriallevel != 1) {
3608 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3613 if (weaponactive != -1 || creature == wolftype)
3615 if (creature == rabbittype && weaponactive != -1)
3616 if (weapons[weaponids[0]].getType() == staff)
3619 if (weaponactive != -1) {
3620 victim->DoBloodBig(2 / victim->armorhead, 225);
3621 emit_sound_at(knifeslicesound, victim->coords);
3622 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3623 weapons[weaponids[weaponactive]].bloody = 1;
3624 weapons[weaponids[weaponactive]].blooddrip += 3;
3626 if (weaponactive == -1 && creature == wolftype) {
3627 emit_sound_at(clawslicesound, victim->coords, 128.);
3629 victim->DoBloodBig(2 / victim->armorhead, 175);
3633 award_bonus(id, Reversal);
3638 relative = facing * -1;
3640 Normalise(&relative);
3641 relative = DoRotation(relative, 0, 90, 0);
3643 Normalise(&relative);
3644 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3645 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3647 victim->jointVel(head) += relative * damagemult * 200;
3648 if (victim->damage < victim->damagetolerance - 100)
3649 victim->velocity = relative * 200;
3650 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3651 victim->velocity = 0;
3654 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3658 relative = facing * -1;
3660 Normalise(&relative);
3661 relative = DoRotation(relative, 0, 90, 0);
3663 Normalise(&relative);
3664 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3665 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3667 victim->jointVel(head) += relative * damagemult * 200;
3670 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3671 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3672 award_bonus(id, reverseko);
3678 if (frameTarget > animation[animCurrent].numframes - 1) {
3681 animTarget = getIdle();
3682 FootLand(leftfoot, 1);
3683 FootLand(rightfoot, 1);
3685 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3686 animTarget = rollanim;
3688 emit_sound_at(movewhooshsound, coords, 128.);
3690 if (animCurrent == staggerbackhighanim) {
3691 animTarget = getIdle();
3693 if (animCurrent == staggerbackhardanim) {
3694 animTarget = getIdle();
3696 if (animCurrent == removeknifeanim) {
3697 animTarget = getIdle();
3699 if (animCurrent == crouchremoveknifeanim) {
3700 animTarget = getCrouch();
3702 if (animCurrent == backhandspringanim) {
3703 animTarget = getIdle();
3705 if (animCurrent == dodgebackanim) {
3706 animTarget = getIdle();
3708 if (animCurrent == drawleftanim) {
3709 animTarget = getIdle();
3711 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3712 animTarget = getIdle();
3713 if (animCurrent == crouchdrawrightanim) {
3714 animTarget = getCrouch();
3716 if (weaponactive == -1)
3718 else if (weaponactive == 0) {
3720 if (num_weapons == 2) {
3722 buffer = weaponids[0];
3723 weaponids[0] = weaponids[1];
3724 weaponids[1] = buffer;
3728 if (weaponactive == -1) {
3729 emit_sound_at(knifesheathesound, coords, 128.);
3731 if (weaponactive != -1) {
3732 emit_sound_at(knifedrawsound, coords, 128.);
3735 if (animCurrent == rollanim) {
3736 animTarget = getCrouch();
3737 FootLand(leftfoot, 1);
3738 FootLand(rightfoot, 1);
3741 if (animTarget == walljumprightkickanim) {
3744 if (animTarget == walljumpleftkickanim) {
3747 animTarget = jumpdownanim;
3749 if (animCurrent == climbanim) {
3750 animTarget = getCrouch();
3752 coords += facing * .1;
3753 if (!isnormal(coords.x))
3764 if (animTarget == rabbitkickreversalanim) {
3765 animTarget = getCrouch();
3768 if (animTarget == jumpreversalanim) {
3769 animTarget = getCrouch();
3772 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3773 if (attackkeydown && animTarget != walljumpfrontanim) {
3775 float closestdist = -1;
3777 if (Person::players.size() > 1)
3778 for (unsigned i = 0; i < Person::players.size(); i++) {
3779 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3780 distance = distsq(&Person::players[i]->coords, &coords);
3781 if (closestdist == -1 || distance < closestdist) {
3782 closestdist = distance;
3787 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3788 victim = Person::players[closest];
3789 animTarget = walljumprightkickanim;
3791 XYZ rotatetarget = victim->coords - coords;
3792 Normalise(&rotatetarget);
3793 yaw = -asin(0 - rotatetarget.x);
3795 if (rotatetarget.z < 0)
3797 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3798 velocity = (victim->coords - coords) * 4;
3803 if (animTarget == walljumpbackanim) {
3804 animTarget = backflipanim;
3806 velocity = facing * -8;
3809 resume_stream(whooshsound);
3811 if (animTarget == walljumprightanim) {
3812 animTarget = rightflipanim;
3816 velocity = DoRotation(facing, 0, 30, 0) * -8;
3819 if (animTarget == walljumpfrontanim) {
3820 animTarget = frontflipanim;
3824 velocity = facing * 8;
3828 resume_stream(whooshsound);
3830 if (animTarget == walljumpleftanim) {
3831 if (attackkeydown) {
3833 float closestdist = -1;
3835 if (Person::players.size() > 1)
3836 for (unsigned i = 0; i < Person::players.size(); i++) {
3837 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3838 distance = distsq(&Person::players[i]->coords, &coords);
3839 if (closestdist == -1 || distance < closestdist) {
3840 closestdist = distance;
3845 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3846 victim = Person::players[closest];
3847 animTarget = walljumpleftkickanim;
3849 XYZ rotatetarget = victim->coords - coords;
3850 Normalise(&rotatetarget);
3851 yaw = -asin(0 - rotatetarget.x);
3853 if (rotatetarget.z < 0)
3855 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3856 velocity = (victim->coords - coords) * 4;
3861 if (animTarget != walljumpleftkickanim) {
3862 animTarget = leftflipanim;
3866 velocity = DoRotation(facing, 0, -30, 0) * -8;
3870 resume_stream(whooshsound);
3872 if (animTarget == sneakattackanim) {
3873 animCurrent = getCrouch();
3874 animTarget = getCrouch();
3881 transspeed = 1000000;
3882 targetheadyaw += 180;
3883 coords -= facing * .7;
3885 coords.y = terrain.getHeight(coords.x, coords.z);
3889 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3890 animTarget = getIdle();
3893 coords.y = terrain.getHeight(coords.x, coords.z);
3897 if (animCurrent == knifefollowanim) {
3898 animTarget = getIdle();
3901 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3902 float ycoords = oldcoords.y;
3903 animTarget = getStop();
3908 transspeed = 1000000;
3909 targetheadyaw += 180;
3910 if (!isnormal(coords.x))
3912 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3913 oldcoords = coords + facing * .5;
3914 else if (animCurrent == sweepreversalanim)
3915 oldcoords = coords + facing * 1.1;
3916 else if (animCurrent == upunchreversalanim) {
3917 oldcoords = coords + facing * 1.5;
3920 targetheadyaw += 180;
3923 } else if (animCurrent == knifeslashreversalanim) {
3924 oldcoords = coords + facing * .5;
3927 targetheadyaw += 90;
3930 } else if (animCurrent == staffspinhitreversalanim) {
3933 targetheadyaw += 180;
3938 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3940 oldcoords.y = ycoords;
3941 currentoffset = coords - oldcoords;
3947 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3952 if (animation[animTarget].attack == reversed) {
3954 if (animTarget == sweepreversedanim)
3956 animTarget = backhandspringanim;
3958 emit_sound_at(landsound, coords, 128);
3960 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3961 animTarget = rollanim;
3964 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3965 coords.y = oldcoords.y;
3967 if (animCurrent == knifeslashreversedanim) {
3968 animTarget = rollanim;
3973 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3974 coords.y = oldcoords.y;
3978 animTarget = jumpdownanim;
3981 animTarget = getIdle();
3983 animTarget = getIdle();
3984 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3985 animTarget = getIdle();
3987 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3988 coords.y = oldcoords.y;
3989 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3990 targetoffset.y = coords.y;
3992 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3993 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3994 currentoffset.y -= (coords.y - targetoffset.y);
3995 coords.y = targetoffset.y;
3997 normalsupdatedelay = 0;
3999 if (animCurrent == upunchanim) {
4000 animTarget = getStop();
4001 normalsupdatedelay = 0;
4004 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
4008 if (num_weapons > 0)
4009 if (weapons[0].getType() == staff)
4015 rabbitkickragdoll = 1;
4017 if (animCurrent == rabbitkickreversedanim) {
4023 skeleton.spinny = 0;
4024 SolidHitBonus(!id); // FIXME: tricky id
4028 animTarget = rollanim;
4031 pause_sound(whooshsound);
4035 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
4039 skeleton.spinny = 0;
4041 if (animCurrent == jumpreversedanim) {
4047 skeleton.spinny = 0;
4048 SolidHitBonus(!id); // FIXME: tricky id
4052 animTarget = rollanim;
4053 coords += facing * 2;
4055 pause_sound(whooshsound);
4060 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) {
4061 animTarget = getupfromfrontanim;
4063 } else if (animation[animCurrent].attack == normalattack) {
4064 animTarget = getIdle();
4067 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4068 animTarget = blockhighleftstrikeanim;
4070 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4071 animTarget = getIdle();
4074 if (animCurrent == spinkickanim && victim->skeleton.free) {
4075 if (creature == rabbittype)
4076 animTarget = fightidleanim;
4081 if (isIdle() && !wasIdle())
4082 normalsupdatedelay = 0;
4084 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4085 animTarget = jumpdownanim;
4088 if (!skeleton.free) {
4090 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4091 if (!isRun() || !wasRun()) {
4092 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4093 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4094 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4095 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4097 if (isRun() && wasRun()) {
4099 tempspeed = velspeed;
4100 if (tempspeed < 10 * speedmult)
4101 tempspeed = 10 * speedmult;
4102 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4104 } else if (transspeed)
4105 target += multiplier * transspeed * speed * 2;
4107 if (!isRun() || !wasRun()) {
4108 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4109 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4110 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4111 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4115 if (animCurrent != animTarget)
4116 target = (target + oldtarget) / 2;
4119 frameCurrent = frameTarget;
4123 rot = targetrot * target;
4124 yaw += rot - oldrot;
4130 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4132 for (int i = 0; i < skeleton.num_joints; i++) {
4133 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4136 skeleton.FindForwards();
4138 for (int i = 0; i < skeleton.num_muscles; i++) {
4139 if (skeleton.muscles[i].visible) {
4140 skeleton.FindRotationMuscle(i, animTarget);
4143 for (int i = 0; i < skeleton.num_muscles; i++) {
4144 if (skeleton.muscles[i].visible) {
4145 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4146 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4147 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4148 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4149 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4150 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4155 for (int i = 0; i < skeleton.num_joints; i++) {
4156 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4159 skeleton.FindForwards();
4161 for (int i = 0; i < skeleton.num_muscles; i++) {
4162 if (skeleton.muscles[i].visible) {
4163 skeleton.FindRotationMuscle(i, animTarget);
4166 for (int i = 0; i < skeleton.num_muscles; i++) {
4167 if (skeleton.muscles[i].visible) {
4168 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4169 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4170 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4171 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4172 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4173 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4174 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4175 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4176 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4177 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4178 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4179 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4183 if (frameCurrent >= animation[animCurrent].numframes)
4184 frameCurrent = animation[animCurrent].numframes - 1;
4186 oldanimCurrent = animCurrent;
4187 oldanimTarget = animTarget;
4188 oldframeTarget = frameTarget;
4189 oldframeCurrent = frameCurrent;
4191 for (int i = 0; i < skeleton.num_joints; i++) {
4192 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4193 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4195 offset = currentoffset * (1 - target) + targetoffset * target;
4196 for (int i = 0; i < skeleton.num_muscles; i++) {
4197 if (skeleton.muscles[i].visible) {
4198 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4199 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4200 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4205 if (isLanding() && landhard) {
4208 animTarget = getLandhard();
4221 void Person::DoStuff()
4223 static XYZ terrainnormal;
4224 static XYZ flatfacing;
4225 static XYZ flatvelocity;
4226 static float flatvelspeed;
4230 static int bloodsize;
4231 static int startx, starty, endx, endy;
4232 static GLubyte color;
4233 static XYZ bloodvel;
4235 onfiredelay -= multiplier;
4236 if (onfiredelay < 0 && onfire) {
4237 if (Random() % 2 == 0) {
4243 crouchkeydowntime += multiplier;
4245 crouchkeydowntime = 0;
4246 jumpkeydowntime += multiplier;
4247 if (!jumpkeydown && skeleton.free)
4248 jumpkeydowntime = 0;
4250 if (hostile || damage > 0 || bloodloss > 0)
4253 if (isIdle() || isRun())
4256 if (num_weapons == 1 && weaponactive != -1)
4260 blooddimamount -= multiplier * .3;
4261 speechdelay -= multiplier;
4262 texupdatedelay -= multiplier;
4263 interestdelay -= multiplier;
4264 flamedelay -= multiplier;
4265 parriedrecently -= multiplier;
4267 victim = this->shared_from_this();
4272 speed = 1.1 * speedmult;
4274 speed = 1.0 * speedmult;
4276 rabbitkickragdoll = 0;
4280 if (id != 0 && (creature == rabbittype || difficulty != 2))
4282 if (id != 0 && creature == wolftype && difficulty == 2) {
4284 if (aitype != passivetype) {
4286 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) {
4292 if (animTarget == wolfrunninganim && !superruntoggle) {
4293 animTarget = getRun();
4297 if (weaponactive == -1 && num_weapons > 0) {
4298 if (weapons[weaponids[0]].getType() == staff) {
4304 burnt += multiplier;
4308 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4310 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4316 vel[0] = velocity.x;
4317 vel[1] = velocity.y;
4318 vel[2] = velocity.z;
4321 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4322 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4326 while (flamedelay < 0 && onfire) {
4328 howmany = abs(Random() % (skeleton.num_joints));
4329 if (skeleton.free) {
4330 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4331 flatfacing = skeleton.joints[howmany].position * scale + coords;
4333 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4334 flatvelocity = (coords - oldcoords) / multiplier / 2;
4336 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4339 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4341 howmany = abs(Random() % (skeleton.num_joints));
4342 if (skeleton.free) {
4343 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4344 flatfacing = skeleton.joints[howmany].position * scale + coords;
4346 flatvelocity = (coords - oldcoords) / multiplier / 2;
4347 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4349 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4353 bleeding -= multiplier * .3;
4354 if (bloodtoggle == 2) {
4355 skeleton.drawmodel.textureptr.bind();
4356 if ((bleeding <= 0) && (detail != 2))
4361 if (neckspurtamount > 0) {
4362 neckspurtamount -= multiplier;
4363 neckspurtdelay -= multiplier * 3;
4364 neckspurtparticledelay -= multiplier * 3;
4365 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4368 if (skeleton.free) {
4369 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4370 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4371 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4373 bloodvel.z = 5 * neckspurtamount;
4374 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4375 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4376 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4378 neckspurtparticledelay = .05;
4380 if (neckspurtdelay < 0) {
4385 if (deathbleeding > 0 && dead != 2) {
4386 if (deathbleeding < 5)
4387 bleeddelay -= deathbleeding * multiplier / 4;
4389 bleeddelay -= 5 * multiplier / 4;
4390 if (bleeddelay < 0 && bloodtoggle) {
4395 if (skeleton.free) {
4396 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4397 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4399 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4400 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4404 bloodloss += deathbleeding * multiplier * 80;
4405 deathbleeding -= multiplier * 1.6;
4406 if (deathbleeding < 0)
4408 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4409 if (weaponactive != -1) {
4410 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4411 weapons[weaponids[0]].velocity.x += .01;
4414 weaponids[0] = weaponids[num_weapons];
4415 if (weaponstuck == num_weapons)
4419 for (unsigned i = 0; i < Person::players.size(); i++) {
4420 Person::players[i]->wentforweapon = 0;
4428 if (!dead && creature == wolftype) {
4429 award_bonus(0, Wolfbonus);
4432 if (animTarget == knifefollowedanim && !skeleton.free) {
4433 for (int i = 0; i < skeleton.num_joints; i++) {
4434 skeleton.joints[i].velocity = 0;
4435 skeleton.joints[i].velocity.y = -2;
4438 if (id != 0 && unconscioustime > .1) {
4446 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4447 texupdatedelay = .12;
4449 bloodsize = 5 - realtexdetail;
4453 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4454 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4455 endx = startx + bloodsize;
4456 endy = starty + bloodsize;
4466 if (endx > skeleton.skinsize - 1) {
4467 endx = skeleton.skinsize - 1;
4470 if (endy > skeleton.skinsize - 1) {
4471 endy = skeleton.skinsize - 1;
4479 for (i = startx; i < endx; i++) {
4480 for (j = starty; j < endy; j++) {
4481 if (Random() % 2 == 0) {
4482 color = Random() % 85 + 170;
4483 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4484 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4485 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4486 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4491 skeleton.drawmodel.textureptr.bind();
4495 if (skeleton.free) {
4496 bleedx += 4 * direction / realtexdetail;
4498 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4500 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4502 bleedy -= 4 / realtexdetail;
4504 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4506 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4510 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4511 righthandmorphness = targetrighthandmorphness;
4512 righthandmorphstart = righthandmorphend;
4513 } else if (righthandmorphness > targetrighthandmorphness) {
4514 righthandmorphness -= multiplier * 4;
4515 } else if (righthandmorphness < targetrighthandmorphness) {
4516 righthandmorphness += multiplier * 4;
4519 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4520 lefthandmorphness = targetlefthandmorphness;
4521 lefthandmorphstart = lefthandmorphend;
4522 } else if (lefthandmorphness > targetlefthandmorphness) {
4523 lefthandmorphness -= multiplier * 4;
4524 } else if (lefthandmorphness < targetlefthandmorphness) {
4525 lefthandmorphness += multiplier * 4;
4528 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4529 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4530 tailmorphness = targettailmorphness;
4531 tailmorphstart = tailmorphend;
4532 } else if (tailmorphness > targettailmorphness) {
4533 tailmorphness -= multiplier * 10;
4534 } else if (tailmorphness < targettailmorphness) {
4535 tailmorphness += multiplier * 10;
4539 if (creature == wolftype) {
4540 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4541 tailmorphness = targettailmorphness;
4542 tailmorphstart = tailmorphend;
4543 } else if (tailmorphness > targettailmorphness) {
4544 tailmorphness -= multiplier * 2;
4545 } else if (tailmorphness < targettailmorphness) {
4546 tailmorphness += multiplier * 2;
4550 if (headmorphend == 3 || headmorphstart == 3) {
4551 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4552 headmorphness = targetheadmorphness;
4553 headmorphstart = headmorphend;
4554 } else if (headmorphness > targetheadmorphness) {
4555 headmorphness -= multiplier * 7;
4556 } else if (headmorphness < targetheadmorphness) {
4557 headmorphness += multiplier * 7;
4559 } else if (headmorphend == 5 || headmorphstart == 5) {
4560 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4561 headmorphness = targetheadmorphness;
4562 headmorphstart = headmorphend;
4563 } else if (headmorphness > targetheadmorphness) {
4564 headmorphness -= multiplier * 10;
4565 } else if (headmorphness < targetheadmorphness) {
4566 headmorphness += multiplier * 10;
4569 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4570 headmorphness = targetheadmorphness;
4571 headmorphstart = headmorphend;
4572 } else if (headmorphness > targetheadmorphness) {
4573 headmorphness -= multiplier * 4;
4574 } else if (headmorphness < targetheadmorphness) {
4575 headmorphness += multiplier * 4;
4579 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4580 chestmorphness = targetchestmorphness;
4581 chestmorphstart = chestmorphend;
4582 } else if (chestmorphness > targetchestmorphness) {
4583 chestmorphness -= multiplier;
4584 } else if (chestmorphness < targetchestmorphness) {
4585 chestmorphness += multiplier;
4588 if (dead != 2 && howactive <= typesleeping) {
4589 if (chestmorphstart == 0 && chestmorphend == 0) {
4591 targetchestmorphness = 1;
4594 if (chestmorphstart != 0 && chestmorphend != 0) {
4596 targetchestmorphness = 1;
4598 if (environment == snowyenvironment) {
4601 if (skeleton.free) {
4602 footvel = skeleton.specialforward[0] * -1;
4603 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4605 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4606 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4608 if (animTarget == sleepanim)
4609 footvel = DoRotation(footvel, 0, 90, 0);
4610 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4614 if (!dead && howactive < typesleeping) {
4615 blinkdelay -= multiplier * 2;
4616 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4618 targetheadmorphness = 1;
4620 blinkdelay = (float)(abs(Random() % 40)) / 5;
4622 if (headmorphstart == 3 && headmorphend == 3) {
4624 targetheadmorphness = 1;
4629 twitchdelay -= multiplier * 1.5;
4630 if (animTarget != hurtidleanim) {
4631 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4633 targetheadmorphness = 1;
4635 twitchdelay = (float)(abs(Random() % 40)) / 5;
4637 if (headmorphstart == 5 && headmorphend == 5) {
4639 targetheadmorphness = 1;
4643 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4644 twitchdelay3 -= multiplier * 1;
4645 if (Random() % 2 == 0) {
4646 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4647 righthandmorphness = 0;
4648 targetrighthandmorphness = 1;
4649 righthandmorphend = 1;
4650 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4652 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4653 righthandmorphness = 0;
4654 targetrighthandmorphness = 1;
4655 righthandmorphend = 0;
4658 if (Random() % 2 == 0) {
4659 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4660 lefthandmorphness = 0;
4661 targetlefthandmorphness = 1;
4662 lefthandmorphend = 1;
4663 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4665 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4666 lefthandmorphness = 0;
4667 targetlefthandmorphness = 1;
4668 lefthandmorphend = 0;
4674 if (creature == rabbittype) {
4675 if (howactive < typesleeping)
4676 twitchdelay2 -= multiplier * 1.5;
4678 twitchdelay2 -= multiplier * 0.5;
4679 if (howactive <= typesleeping) {
4680 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4682 targettailmorphness = 1;
4684 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4686 if (tailmorphstart == 1 && tailmorphend == 1) {
4688 targettailmorphness = 1;
4691 if (tailmorphstart == 2 && tailmorphend == 2) {
4693 targettailmorphness = 1;
4700 if (creature == wolftype) {
4701 twitchdelay2 -= multiplier * 1.5;
4702 if (tailmorphend != 0)
4703 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4705 targettailmorphness = 1;
4709 if (tailmorphend != 5)
4710 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4712 targettailmorphness = 1;
4716 if (twitchdelay2 <= 0) {
4717 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4719 targettailmorphness = 1;
4722 if (tailmorphstart == 1 && tailmorphend == 1) {
4724 targettailmorphness = 1;
4727 if (tailmorphstart == 2 && tailmorphend == 2) {
4729 targettailmorphness = 1;
4732 if (tailmorphstart == 3 && tailmorphend == 3) {
4734 targettailmorphness = 1;
4737 if (tailmorphstart == 4 && tailmorphend == 4) {
4739 targettailmorphness = 1;
4746 unconscioustime = 0;
4748 if (dead == 1 || howactive == typesleeping) {
4749 unconscioustime += multiplier;
4750 //If unconscious, close eyes and mouth
4751 if (righthandmorphend != 0)
4752 righthandmorphness = 0;
4753 righthandmorphend = 0;
4754 targetrighthandmorphness = 1;
4756 if (lefthandmorphend != 0)
4757 lefthandmorphness = 0;
4758 lefthandmorphend = 0;
4759 targetlefthandmorphness = 1;
4761 if (headmorphend != 3 && headmorphend != 5)
4764 targetheadmorphness = 1;
4768 if (howactive > typesleeping) {
4771 if (bloodtoggle && !bled) {
4772 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4774 if (bloodtoggle && !bled)
4775 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4776 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4777 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4781 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4786 if (dead == 2 || howactive > typesleeping) {
4787 //If dead, open mouth and hands
4788 if (righthandmorphend != 0)
4789 righthandmorphness = 0;
4790 righthandmorphend = 0;
4791 targetrighthandmorphness = 1;
4793 if (lefthandmorphend != 0)
4794 lefthandmorphness = 0;
4795 lefthandmorphend = 0;
4796 targetlefthandmorphness = 1;
4798 if (headmorphend != 2)
4801 targetheadmorphness = 1;
4804 if (stunned > 0 && !dead && headmorphend != 2) {
4805 if (headmorphend != 4)
4808 targetheadmorphness = 1;
4811 if (damage > damagetolerance && !dead) {
4814 unconscioustime = 0;
4816 if (creature == wolftype) {
4817 award_bonus(0, Wolfbonus);
4822 if (weaponactive != -1) {
4823 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4824 weapons[weaponids[0]].velocity.x += .01;
4827 weaponids[0] = weaponids[num_weapons];
4828 if (weaponstuck == num_weapons)
4832 for (unsigned i = 0; i < Person::players.size(); i++) {
4833 Person::players[i]->wentforweapon = 0;
4839 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4848 damage -= multiplier * 13;
4850 permanentdamage -= multiplier * 4;
4851 if (isIdle() || isCrouch()) {
4853 permanentdamage -= multiplier * 4;
4857 if (permanentdamage < 0)
4858 permanentdamage = 0;
4859 if (superpermanentdamage < 0)
4860 superpermanentdamage = 0;
4861 if (permanentdamage < superpermanentdamage) {
4862 permanentdamage = superpermanentdamage;
4864 if (damage < permanentdamage) {
4865 damage = permanentdamage;
4867 if (dead == 1 && damage < damagetolerance) {
4871 for (int i = 0; i < skeleton.num_joints; i++) {
4872 skeleton.joints[i].velocity = 0;
4875 if (permanentdamage > damagetolerance && dead != 2) {
4878 if (weaponactive != -1) {
4879 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4880 weapons[weaponids[0]].velocity.x += .01;
4883 weaponids[0] = weaponids[num_weapons];
4884 if (weaponstuck == num_weapons)
4888 for (unsigned i = 0; i < Person::players.size(); i++) {
4889 Person::players[i]->wentforweapon = 0;
4895 if (!dead && creature == wolftype) {
4896 award_bonus(0, Wolfbonus);
4899 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4900 award_bonus(id, touchofdeath);
4901 if (id != 0 && unconscioustime > .1) {
4909 emit_sound_at(breaksound, coords);
4912 if (skeleton.free == 1) {
4914 pause_sound(whooshsound);
4917 //If knocked over, open hands and close mouth
4918 if (righthandmorphend != 0)
4919 righthandmorphness = 0;
4920 righthandmorphend = 0;
4921 targetrighthandmorphness = 1;
4923 if (lefthandmorphend != 0)
4924 lefthandmorphness = 0;
4925 lefthandmorphend = 0;
4926 targetlefthandmorphness = 1;
4928 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4929 if (headmorphend != 0)
4932 targetheadmorphness = 1;
4936 skeleton.DoGravity(&scale);
4938 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4939 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4940 award_bonus(id, deepimpact);
4941 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4945 for (j = 0; j < skeleton.num_joints; j++) {
4946 average += skeleton.joints[j].position;
4950 coords += average * scale;
4951 for (j = 0; j < skeleton.num_joints; j++) {
4952 skeleton.joints[j].position -= average;
4954 average /= multiplier;
4957 for (int i = 0; i < skeleton.num_joints; i++) {
4958 velocity += skeleton.joints[i].velocity * scale;
4960 velocity /= skeleton.num_joints;
4962 if (!isnormal(velocity.x) && velocity.x) {
4966 if (findLength(&average) < 10 && dead && skeleton.free) {
4967 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4968 if (skeleton.longdead > 2000) {
4969 if (skeleton.longdead > 6000) {
4971 pause_sound(whooshsound);
4976 if (dead == 2 && bloodloss < damagetolerance) {
4978 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4980 if (bloodtoggle && !bled) {
4981 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4983 if (bloodtoggle && !bled)
4984 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4985 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4986 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4987 float size = .2 * 1.2;
4990 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4994 if (dead == 2 && bloodloss >= damagetolerance) {
4996 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4999 if (bloodtoggle && !bled) {
5000 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
5002 if (bloodtoggle && !bled)
5003 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
5004 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
5005 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
5009 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
5016 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
5017 bool canrecover = 1;
5018 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
5019 startpoint = coords;
5022 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
5024 if (velocity.y < -30)
5026 for (i = 0; i < objects.numobjects; i++) {
5027 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
5028 colviewer = startpoint;
5029 coltarget = endpoint;
5030 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
5039 terrainnormal = jointPos(groin) - jointPos(abdomen);
5040 if (joint(groin).locked && joint(abdomen).locked) {
5041 terrainnormal = jointPos(groin) - jointPos(abdomen);
5042 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5044 if (joint(abdomen).locked && joint(neck).locked) {
5045 terrainnormal = jointPos(abdomen) - jointPos(neck);
5046 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5048 if (joint(groin).locked && joint(neck).locked) {
5049 terrainnormal = jointPos(groin) - jointPos(neck);
5050 middle = (jointPos(groin) + jointPos(neck)) / 2;
5052 Normalise(&terrainnormal);
5054 targetyaw = -asin(0 - terrainnormal.x);
5055 targetyaw *= 360 / 6.28;
5056 if (terrainnormal.z < 0)
5057 targetyaw = 180 - targetyaw;
5061 animTarget = flipanim;
5062 crouchtogglekeydown = 1;
5067 animCurrent = tempanim;
5071 for (int i = 0; i < skeleton.num_joints; i++) {
5072 tempanimation.position[i][0] = skeleton.joints[i].position;
5073 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5078 if (findLength(&average) < 10 && !dead && skeleton.free) {
5079 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5080 if (skeleton.longdead > (damage + 500) * 1.5) {
5082 pause_sound(whooshsound);
5088 terrainnormal = jointPos(groin) - jointPos(abdomen);
5089 if (joint(groin).locked && joint(abdomen).locked) {
5090 terrainnormal = jointPos(groin) - jointPos(abdomen);
5091 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5093 if (joint(abdomen).locked && joint(neck).locked) {
5094 terrainnormal = jointPos(abdomen) - jointPos(neck);
5095 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5097 if (joint(groin).locked && joint(neck).locked) {
5098 terrainnormal = jointPos(groin) - jointPos(neck);
5099 middle = (jointPos(groin) + jointPos(neck)) / 2;
5101 Normalise(&terrainnormal);
5103 targetyaw = -asin(0 - terrainnormal.x);
5104 targetyaw *= 360 / 6.28;
5105 if (terrainnormal.z < 0)
5106 targetyaw = 180 - targetyaw;
5109 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5112 if (skeleton.forward.y < 0) {
5113 animTarget = getupfrombackanim;
5117 if (skeleton.forward.y > -.3) {
5118 animTarget = getupfromfrontanim;
5126 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5127 animTarget = rollanim;
5128 targetyaw = lookyaw;
5145 if ( !leftkeydown && !rightkeydown)
5152 if (abs(targettilt2) > 50)
5154 animCurrent = tempanim;
5157 tilt2 = targettilt2;
5159 if (middle.y > 0 && animTarget != rollanim)
5160 targetoffset.y = middle.y + 1;
5162 for (int i = 0; i < skeleton.num_joints; i++) {
5163 tempanimation.position[i][0] = skeleton.joints[i].position;
5164 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5171 if (num_weapons > 0)
5172 if (weapons[0].getType() == staff)
5174 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5175 if (velocity.y > -30) {
5177 tempvelocity = velocity;
5178 Normalise(&tempvelocity);
5179 targetyaw = -asin(0 - tempvelocity.x);
5180 targetyaw *= 360 / 6.28;
5182 targetyaw = 180 - targetyaw;
5186 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5187 animTarget = rollanim;
5190 animTarget = backhandspringanim;
5196 emit_sound_at(movewhooshsound, coords, 128.);
5198 animCurrent = animTarget;
5199 frameCurrent = frameTarget - 1;
5211 if (skeleton.freefall == 0)
5216 if (aitype != passivetype || skeleton.free == 1)
5217 if (findLengthfast(&velocity) > .1)
5218 for (i = 0; i < objects.numobjects; i++) {
5219 if (objects.type[i] == firetype)
5220 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) {
5222 if (!objects.onfire[i]) {
5223 emit_sound_at(firestartsound, objects.position[i]);
5225 objects.onfire[i] = 1;
5228 if (objects.onfire[i]) {
5233 if (objects.type[i] == bushtype)
5234 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) {
5236 if (!objects.onfire[i]) {
5237 emit_sound_at(firestartsound, objects.position[i]);
5239 objects.onfire[i] = 1;
5243 if (objects.onfire[i]) {
5247 if (objects.messedwith[i] <= 0) {
5251 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5254 addEnvSound(coords, 4 * findLength(&velocity));
5258 if (environment == grassyenvironment)
5259 howmany = findLength(&velocity) * 4;
5260 if (environment == snowyenvironment)
5261 howmany = findLength(&velocity) * 2;
5263 if (environment != desertenvironment)
5264 for (j = 0; j < howmany; j++) {
5265 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5266 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5267 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5270 pos.x += float(abs(Random() % 100) - 50) / 200;
5271 pos.y += float(abs(Random() % 100) - 50) / 200;
5272 pos.z += float(abs(Random() % 100) - 50) / 200;
5273 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);
5274 Sprite::setLastSpriteSpecial(1);
5276 howmany = findLength(&velocity) * 4;
5278 if (environment == snowyenvironment)
5279 for (j = 0; j < howmany; j++) {
5280 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5281 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5282 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5285 pos.x += float(abs(Random() % 100) - 50) / 200;
5286 pos.y += float(abs(Random() % 100) - 50) / 200;
5287 pos.z += float(abs(Random() % 100) - 50) / 200;
5288 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5289 Sprite::setLastSpriteSpecial(2);
5292 objects.rotx[i] += velocity.x * multiplier * 6;
5293 objects.roty[i] += velocity.z * multiplier * 6;
5294 objects.messedwith[i] = .5;
5297 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5298 if (objects.pitch[i] == 0)
5301 tempcoord = coords - objects.position[i];
5302 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5303 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5304 tempcoord += objects.position[i];
5306 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]) {
5307 if (objects.messedwith[i] <= 0) {
5311 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5314 addEnvSound(coords, 4 * findLength(&velocity));
5318 if (environment == grassyenvironment)
5319 howmany = findLength(&velocity) * 4;
5320 if (environment == snowyenvironment)
5321 howmany = findLength(&velocity) * 2;
5323 if (environment != desertenvironment)
5324 for (j = 0; j < howmany; j++) {
5325 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5326 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5327 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5329 pos += velocity * .1;
5331 pos.x += float(abs(Random() % 100) - 50) / 150;
5332 pos.y += float(abs(Random() % 100) - 50) / 150;
5333 pos.z += float(abs(Random() % 100) - 50) / 150;
5334 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);
5335 Sprite::setLastSpriteSpecial(1);
5337 howmany = findLength(&velocity) * 4;
5339 if (environment == snowyenvironment)
5340 for (j = 0; j < howmany; j++) {
5341 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5342 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5343 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5345 pos += velocity * .1;
5347 pos.x += float(abs(Random() % 100) - 50) / 150;
5348 pos.y += float(abs(Random() % 100) - 50) / 150;
5349 pos.z += float(abs(Random() % 100) - 50) / 150;
5350 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5351 Sprite::setLastSpriteSpecial(2);
5354 objects.messedwith[i] = .5;
5359 if (!skeleton.free) {
5362 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5365 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5367 if (tutoriallevel == 1 && id != 0)
5369 if (play && aitype != playercontrolled) {
5370 int whichsound = -1;
5371 i = abs(Random() % 4);
5372 if (speechdelay <= 0) {
5373 if (creature == rabbittype) {
5375 whichsound = rabbitchitter;
5377 whichsound = rabbitchitter2;
5379 if (creature == wolftype) {
5381 whichsound = growlsound;
5383 whichsound = growl2sound;
5388 if (whichsound != -1) {
5389 emit_sound_at(whichsound, coords);
5393 if (animTarget == staggerbackhighanim)
5395 if (animTarget == staggerbackhardanim)
5397 staggerdelay -= multiplier;
5398 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5400 if (velocity.y < -30 && animTarget == jumpdownanim)
5402 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5403 animTarget = getIdle();
5407 weaponmissdelay -= multiplier;
5408 highreversaldelay -= multiplier;
5409 lowreversaldelay -= multiplier;
5410 lastcollide -= multiplier;
5411 skiddelay -= multiplier;
5412 if (!isnormal(velocity.x) && velocity.x) {
5415 if (!isnormal(targettilt) && targettilt) {
5418 if (!isnormal(targettilt2) && targettilt2) {
5421 if (!isnormal(targetyaw) && targetyaw) {
5425 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5426 //open hands and close mouth
5427 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5428 righthandmorphness = 0;
5429 righthandmorphend = 0;
5430 targetrighthandmorphness = 1;
5433 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5434 lefthandmorphness = 0;
5435 lefthandmorphend = 0;
5436 targetlefthandmorphness = 1;
5439 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5442 targetheadmorphness = 1;
5446 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) {
5447 //open hands and mouth
5448 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5449 righthandmorphness = 0;
5450 righthandmorphend = 0;
5451 targetrighthandmorphness = 1;
5454 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5455 lefthandmorphness = 0;
5456 lefthandmorphend = 0;
5457 targetlefthandmorphness = 1;
5460 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5463 targetheadmorphness = 1;
5467 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5468 //close hands and mouth
5469 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5470 righthandmorphness = 0;
5471 righthandmorphend = 1;
5472 targetrighthandmorphness = 1;
5475 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5476 lefthandmorphness = 0;
5477 lefthandmorphend = 1;
5478 targetlefthandmorphness = 1;
5481 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5484 targetheadmorphness = 1;
5488 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) {
5489 //close hands and yell
5490 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5491 righthandmorphness = 0;
5492 righthandmorphend = 1;
5493 targetrighthandmorphness = 1;
5496 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5497 lefthandmorphness = 0;
5498 lefthandmorphend = 1;
5499 targetlefthandmorphness = 1;
5502 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5505 targetheadmorphness = 1;
5512 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5513 (victim->aitype != searchtype) && (aitype != passivetype) &&
5514 (aitype != searchtype) && (victim->id < Person::players.size())) {
5515 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5519 if (!dead && animTarget != hurtidleanim)
5520 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5521 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5524 targetheadmorphness = 1;
5528 if (weaponactive != -1) {
5529 if (weapons[weaponids[weaponactive]].getType() != staff) {
5530 righthandmorphstart = 1;
5531 righthandmorphend = 1;
5533 if (weapons[weaponids[weaponactive]].getType() == staff) {
5534 righthandmorphstart = 2;
5535 righthandmorphend = 2;
5537 targetrighthandmorphness = 1;
5540 terrainnormal = terrain.getNormal(coords.x, coords.z);
5542 if (animation[animTarget].attack != reversal) {
5543 if (!isnormal(coords.x))
5551 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5552 facing = flatfacing;
5553 ReflectVector(&facing, terrainnormal);
5556 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5558 targettilt2 = -facing.y * 20;
5563 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5565 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5566 flatvelocity = velocity;
5568 flatvelspeed = findLength(&flatvelocity);
5569 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5570 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5575 if (targettilt > 25)
5577 if (targettilt < -25)
5581 if (targettilt2 > 45)
5583 if (targettilt2 < -45)
5585 if (abs(tilt2 - targettilt2) < multiplier * 400)
5586 tilt2 = targettilt2;
5587 else if (tilt2 > targettilt2) {
5588 tilt2 -= multiplier * 400;
5589 } else if (tilt2 < targettilt2) {
5590 tilt2 += multiplier * 400;
5592 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5599 if (!isnormal(targettilt) && targettilt) {
5602 if (!isnormal(targettilt2) && targettilt2) {
5607 if (animTarget == rabbittackleanim) {
5608 velocity += facing * multiplier * speed * 700 * scale;
5609 velspeed = findLength(&velocity);
5610 if (velspeed > speed * 65 * scale) {
5611 velocity /= velspeed;
5612 velspeed = speed * 65 * scale;
5613 velocity *= velspeed;
5615 velocity.y += gravity * multiplier * 20;
5616 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5617 velspeed = findLength(&velocity);
5618 velocity = flatfacing * velspeed;
5620 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5621 if (isRun() || animTarget == rabbitkickanim) {
5622 velocity += facing * multiplier * speed * 700 * scale;
5623 velspeed = findLength(&velocity);
5624 if (velspeed > speed * 45 * scale) {
5625 velocity /= velspeed;
5626 velspeed = speed * 45 * scale;
5627 velocity *= velspeed;
5629 velocity.y += gravity * multiplier * 20;
5630 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5631 velspeed = findLength(&velocity);
5632 if (velspeed < speed * 30 * scale)
5633 velspeed = speed * 30 * scale;
5634 velocity = flatfacing * velspeed;
5636 } else if (isRun()) {
5637 velocity += facing * multiplier * speed * 700 * scale;
5638 velspeed = findLength(&velocity);
5639 if (creature == rabbittype) {
5640 if (velspeed > speed * 55 * scale) {
5641 velocity /= velspeed;
5642 velspeed = speed * 55 * scale;
5643 velocity *= velspeed;
5646 if (creature == wolftype) {
5647 if (velspeed > speed * 75 * scale) {
5648 velocity /= velspeed;
5649 velspeed = speed * 75 * scale;
5650 velocity *= velspeed;
5653 velocity.y += gravity * multiplier * 20;
5654 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5655 velspeed = findLength(&velocity);
5656 velocity = flatfacing * velspeed;
5659 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5660 velocity += facing * multiplier * speed * 700 * scale;
5661 velspeed = findLength(&velocity);
5662 if (velspeed > speed * 45 * scale) {
5663 velocity /= velspeed;
5664 velspeed = speed * 45 * scale;
5665 velocity *= velspeed;
5667 velocity.y += gravity * multiplier * 20;
5668 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5669 velspeed = findLength(&velocity);
5670 velocity = flatfacing * velspeed;
5673 if (animTarget == sneakanim || animTarget == walkanim) {
5674 velocity += facing * multiplier * speed * 700 * scale;
5675 velspeed = findLength(&velocity);
5676 if (velspeed > speed * 12 * scale) {
5677 velocity /= velspeed;
5678 velspeed = speed * 12 * scale;
5679 velocity *= velspeed;
5681 velocity.y += gravity * multiplier * 20;
5682 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5683 velspeed = findLength(&velocity);
5684 velocity = flatfacing * velspeed;
5687 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5688 velocity += facing * multiplier * speed * 700 * scale;
5689 velspeed = findLength(&velocity);
5690 if (velspeed > speed * 2 * scale) {
5691 velocity /= velspeed;
5692 velspeed = speed * 2 * scale;
5693 velocity *= velspeed;
5695 velocity.y += gravity * multiplier * 20;
5696 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5697 velspeed = findLength(&velocity);
5698 velocity = flatfacing * velspeed;
5702 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5703 velocity -= facing * multiplier * speed * 700 * scale;
5704 velspeed = findLength(&velocity);
5705 if (velspeed > speed * 2 * scale) {
5706 velocity /= velspeed;
5707 velspeed = speed * 2 * scale;
5708 velocity *= velspeed;
5710 velocity.y += gravity * multiplier * 20;
5711 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5712 velspeed = findLength(&velocity);
5713 velocity = flatfacing * velspeed * -1;
5716 if (animTarget == fightsidestep) {
5717 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5718 velspeed = findLength(&velocity);
5719 if (velspeed > speed * 12 * scale) {
5720 velocity /= velspeed;
5721 velspeed = speed * 12 * scale;
5722 velocity *= velspeed;
5724 velocity.y += gravity * multiplier * 20;
5725 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5726 velspeed = findLength(&velocity);
5727 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5730 if (animTarget == staggerbackhighanim) {
5731 coords -= facing * multiplier * speed * 16 * scale;
5734 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5735 coords -= facing * multiplier * speed * 20 * scale;
5739 if (animTarget == backhandspringanim) {
5740 //coords-=facing*multiplier*50*scale;
5741 velocity += facing * multiplier * speed * 700 * scale * -1;
5742 velspeed = findLength(&velocity);
5743 if (velspeed > speed * 50 * scale) {
5744 velocity /= velspeed;
5745 velspeed = speed * 50 * scale;
5746 velocity *= velspeed;
5748 velocity.y += gravity * multiplier * 20;
5749 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5750 velspeed = findLength(&velocity);
5751 velocity = flatfacing * velspeed * -1;
5753 if (animTarget == dodgebackanim) {
5754 //coords-=facing*multiplier*50*scale;
5755 velocity += facing * multiplier * speed * 700 * scale * -1;
5756 velspeed = findLength(&velocity);
5757 if (velspeed > speed * 60 * scale) {
5758 velocity /= velspeed;
5759 velspeed = speed * 60 * scale;
5760 velocity *= velspeed;
5762 velocity.y += gravity * multiplier * 20;
5763 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5764 velspeed = findLength(&velocity);
5765 velocity = flatfacing * velspeed * -1;
5768 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5769 velspeed = findLength(&velocity);
5773 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5774 velocity.y += gravity * multiplier;
5777 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5778 coords += velocity * multiplier;
5780 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5781 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5784 if (animTarget == jumpupanim) {
5786 animTarget = getIdle();
5793 pause_sound(whooshsound);
5794 OPENAL_SetVolume(channels[whooshsound], 0);
5797 if (animTarget == jumpdownanim || isFlip()) {
5798 if (isFlip())jumppower = -4;
5799 animTarget = getLanding();
5800 emit_sound_at(landsound, coords, 128.);
5803 addEnvSound(coords);
5808 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5809 coords.y += gravity * multiplier * 2;
5810 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5811 coords.y = terrain.getHeight(coords.x, coords.z);
5816 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)) {
5817 velspeed = findLength(&velocity);
5819 if (velspeed < multiplier * 300 * scale) {
5822 velocity -= velocity / velspeed * multiplier * 300 * scale;
5823 if (velspeed > 5 && (isLanding() || isLandhard())) {
5824 skiddingdelay += multiplier;
5825 if (skiddelay <= 0) {
5826 FootLand(leftfoot, .5);
5827 FootLand(rightfoot, .5);
5835 velspeed = findLength(&velocity);
5837 if (velspeed < multiplier * 600 * scale) {
5840 velocity -= velocity / velspeed * multiplier * 600 * scale;
5842 if (velspeed > 5 && (isLanding() || isLandhard())) {
5843 skiddingdelay += multiplier;
5844 if (skiddelay <= 0) {
5845 FootLand(leftfoot, .5);
5846 FootLand(rightfoot, .5);
5853 if (skiddingdelay < 0)
5854 skiddingdelay += multiplier;
5855 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5857 if (!onterrain || environment == grassyenvironment) {
5858 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5860 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5864 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5865 terrainnormal = victim->coords - coords;
5866 Normalise(&terrainnormal);
5867 targetyaw = -asin(0 - terrainnormal.x);
5868 targetyaw *= 360 / 6.28;
5869 if (terrainnormal.z < 0)
5870 targetyaw = 180 - targetyaw;
5871 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5874 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5875 targetyaw = victim->targetyaw;
5877 if (animTarget == rabbittacklinganim) {
5878 coords = victim->coords;
5881 skeleton.oldfree = skeleton.free;
5885 midterrain.x = terrain.size * terrain.scale / 2;
5886 midterrain.z = terrain.size * terrain.scale / 2;
5887 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5889 tempposit = coords - midterrain;
5891 Normalise(&tempposit);
5892 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5893 coords.x = tempposit.x + midterrain.x;
5894 coords.z = tempposit.z + midterrain.z;
5900 * inverse kinematics helper function
5902 void IKHelper(Person *p, float interp)
5904 XYZ point, change, change2;
5905 float heightleft, heightright;
5907 // TODO: implement localToWorld and worldToLocal
5908 // but keep in mind it won't be the same math if player is ragdolled or something
5909 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5910 // then comb through code for places where to use it
5912 // point = localToWorld(jointPos(leftfoot))
5913 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5914 // adjust height of foot
5915 heightleft = terrain.getHeight(point.x, point.z) + .04;
5916 point.y = heightleft;
5917 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5918 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5919 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5920 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5921 // move ankle along with foot
5922 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5923 // average knee pos between old and new pos
5924 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5926 // do same as above for right leg
5927 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5928 heightright = terrain.getHeight(point.x, point.z) + .04;
5929 point.y = heightright;
5930 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5931 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5932 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5933 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5934 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5936 // fix up skeleton now that we've moved body parts?
5937 p->skeleton.DoConstraints(&p->coords, &p->scale);
5944 int Person::DrawSkeleton()
5946 int oldplayerdetail;
5947 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5948 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5958 glAlphaFunc(GL_GREATER, 0.0001);
5960 float terrainheight;
5964 if (!isnormal(tilt))
5966 if (!isnormal(tilt2))
5968 oldplayerdetail = playerdetail;
5970 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5973 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5976 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5981 if (playerdetail != oldplayerdetail) {
5983 normalsupdatedelay = 0;
5985 static float updatedelaychange;
5986 static float morphness;
5987 static float framemult;
5989 skeleton.FindForwards();
5990 if (howactive == typesittingwall) {
5991 skeleton.specialforward[1] = 0;
5992 skeleton.specialforward[1].z = 1;
5998 static int weaponattachmuscle;
5999 static int weaponrotatemuscle;
6000 static XYZ weaponpoint;
6001 static int start, endthing;
6002 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
6003 if (!isSleeping() && !isSitting()) {
6004 // TODO: give these meaningful names
6005 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
6006 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
6007 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
6008 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
6010 if (onterrain && (cond1 && cond2) && !skeleton.free) {
6012 if (creature == wolftype)
6016 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
6017 IKHelper(this, target);
6018 if (creature == wolftype)
6019 IKHelper(this, target);
6022 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
6023 IKHelper(this, 1 - target);
6024 if (creature == wolftype)
6025 IKHelper(this, 1 - target);
6029 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()))
6032 targetheadyaw = -targetyaw;
6033 targetheadpitch = 0;
6034 if (animation[animTarget].attack == 3)
6035 targetheadyaw += 180;
6037 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6038 skeleton.drawmodel.vertex[i] = 0;
6039 skeleton.drawmodel.vertex[i].y = 999;
6041 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
6042 skeleton.drawmodellow.vertex[i] = 0;
6043 skeleton.drawmodellow.vertex[i].y = 999;
6045 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
6046 skeleton.drawmodelclothes.vertex[i] = 0;
6047 skeleton.drawmodelclothes.vertex[i].y = 999;
6049 for (int i = 0; i < skeleton.num_muscles; i++) {
6050 // convenience renames
6051 const int p1 = skeleton.muscles[i].parent1->label;
6052 const int p2 = skeleton.muscles[i].parent2->label;
6054 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6059 if (p1 == righthand || p2 == righthand) {
6060 morphness = righthandmorphness;
6061 start = righthandmorphstart;
6062 endthing = righthandmorphend;
6064 if (p1 == lefthand || p2 == lefthand) {
6065 morphness = lefthandmorphness;
6066 start = lefthandmorphstart;
6067 endthing = lefthandmorphend;
6069 if (p1 == head || p2 == head) {
6070 morphness = headmorphness;
6071 start = headmorphstart;
6072 endthing = headmorphend;
6074 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6075 morphness = chestmorphness;
6076 start = chestmorphstart;
6077 endthing = chestmorphend;
6079 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6080 morphness = tailmorphness;
6081 start = tailmorphstart;
6082 endthing = tailmorphend;
6085 skeleton.FindRotationMuscle(i, animTarget);
6086 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6087 glMatrixMode(GL_MODELVIEW);
6091 glRotatef(tilt2, 1, 0, 0);
6093 glRotatef(tilt, 0, 0, 1);
6096 glTranslatef(mid.x, mid.y, mid.z);
6098 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6099 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6101 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6102 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6104 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6105 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6107 if (playerdetail || skeleton.free == 3) {
6108 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6109 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6110 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6111 glMatrixMode(GL_MODELVIEW);
6113 if (p1 == abdomen || p2 == abdomen)
6114 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6115 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6116 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6117 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6118 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6119 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6120 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6121 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6122 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6123 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6124 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6125 if (p1 == head || p2 == head)
6126 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6127 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6128 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6129 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6130 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6131 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6132 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6136 if (!playerdetail || skeleton.free == 3) {
6137 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6138 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6139 glMatrixMode(GL_MODELVIEW);
6141 if (p1 == abdomen || p2 == abdomen)
6142 glTranslatef(v0.x * proportionbody.x,
6143 v0.y * proportionbody.y,
6144 v0.z * proportionbody.z);
6145 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6146 glTranslatef(v0.x * proportionarms.x,
6147 v0.y * proportionarms.y,
6148 v0.z * proportionarms.z);
6149 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6150 glTranslatef(v0.x * proportionlegs.x,
6151 v0.y * proportionlegs.y,
6152 v0.z * proportionlegs.z);
6153 if (p1 == head || p2 == head)
6154 glTranslatef(v0.x * proportionhead.x,
6155 v0.y * proportionhead.y,
6156 v0.z * proportionhead.z);
6158 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6159 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6160 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6161 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6167 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6168 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6170 glMatrixMode(GL_MODELVIEW);
6174 glRotatef(tilt2, 1, 0, 0);
6176 glRotatef(tilt, 0, 0, 1);
6177 glTranslatef(mid.x, mid.y, mid.z);
6178 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6179 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6181 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6182 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6184 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6185 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6187 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6188 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6189 glMatrixMode(GL_MODELVIEW);
6191 if (p1 == abdomen || p2 == abdomen)
6192 glTranslatef(v0.x * proportionbody.x,
6193 v0.y * proportionbody.y,
6194 v0.z * proportionbody.z);
6195 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6196 glTranslatef(v0.x * proportionarms.x,
6197 v0.y * proportionarms.y,
6198 v0.z * proportionarms.z);
6199 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6200 glTranslatef(v0.x * proportionlegs.x,
6201 v0.y * proportionlegs.y,
6202 v0.z * proportionlegs.z);
6203 if (p1 == head || p2 == head)
6204 glTranslatef(v0.x * proportionhead.x,
6205 v0.y * proportionhead.y,
6206 v0.z * proportionhead.z);
6207 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6208 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6209 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6210 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6215 updatedelay = 1 + (float)(Random() % 100) / 1000;
6217 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6218 normalsupdatedelay = 1;
6219 if (playerdetail || skeleton.free == 3)
6220 skeleton.drawmodel.CalculateNormals(0);
6221 if (!playerdetail || skeleton.free == 3)
6222 skeleton.drawmodellow.CalculateNormals(0);
6223 if (skeleton.clothes)
6224 skeleton.drawmodelclothes.CalculateNormals(0);
6226 if (playerdetail || skeleton.free == 3)
6227 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6228 if (!playerdetail || skeleton.free == 3)
6229 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6230 if (skeleton.clothes) {
6231 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6236 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6237 if (updatedelaychange > -realmultiplier * 30)
6238 updatedelaychange = -realmultiplier * 30;
6239 if (updatedelaychange > -framemult * 4)
6240 updatedelaychange = -framemult * 4;
6241 if (skeleton.free == 1)
6242 updatedelaychange *= 6;
6244 updatedelaychange *= 8;
6245 updatedelay += updatedelaychange;
6247 glMatrixMode(GL_MODELVIEW);
6249 glTranslatef(coords.x, coords.y - .02, coords.z);
6250 if (!skeleton.free) {
6251 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6252 glRotatef(yaw, 0, 1, 0);
6256 glColor4f(.4, 1, .4, 1);
6257 glDisable(GL_LIGHTING);
6258 glDisable(GL_TEXTURE_2D);
6261 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6262 XYZ &v0 = skeleton.drawmodel.vertex[i];
6263 glVertex3f(v0.x, v0.y, v0.z);
6269 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6270 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6271 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6272 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6273 glVertex3f(v0.x, v0.y, v0.z);
6274 glVertex3f(v1.x, v1.y, v1.z);
6275 glVertex3f(v1.x, v1.y, v1.z);
6276 glVertex3f(v2.x, v2.y, v2.z);
6277 glVertex3f(v2.x, v2.y, v2.z);
6278 glVertex3f(v0.x, v0.y, v0.z);
6284 terrainlight = terrain.getLighting(coords.x, coords.z);
6285 distance = distsq(&viewer, &coords);
6286 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6290 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6291 if (terrainheight < 1)
6293 if (terrainheight > 1.7)
6294 terrainheight = 1.7;
6296 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6297 glDisable(GL_BLEND);
6298 glAlphaFunc(GL_GREATER, 0.0001);
6299 glEnable(GL_TEXTURE_2D);
6301 glDisable(GL_TEXTURE_2D);
6302 glColor4f(.7, .35, 0, .5);
6304 glEnable(GL_LIGHTING);
6307 if (tutoriallevel && id != 0) {
6308 glColor4f(.7, .7, .7, 0.6);
6310 glEnable(GL_LIGHTING);
6312 if (canattack && cananger)
6313 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6314 glDisable(GL_TEXTURE_2D);
6315 glColor4f(1, 0, 0, 0.8);
6317 glMatrixMode(GL_TEXTURE);
6319 glTranslatef(0, -smoketex, 0);
6320 glTranslatef(-smoketex, 0, 0);
6324 if ((tutoriallevel && id != 0))
6325 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6327 skeleton.drawmodel.draw();
6330 if (!playerdetail) {
6331 if ((tutoriallevel && id != 0))
6332 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6334 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6337 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6338 if (tutoriallevel && id != 0) {
6340 glMatrixMode(GL_MODELVIEW);
6341 glEnable(GL_TEXTURE_2D);
6342 glColor4f(.7, .7, .7, 0.6);
6344 glEnable(GL_LIGHTING);
6346 if (canattack && cananger)
6347 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6348 glDisable(GL_TEXTURE_2D);
6349 glColor4f(1, 0, 0, 0.8);
6351 glMatrixMode(GL_TEXTURE);
6353 glTranslatef(0, -smoketex * .6, 0);
6354 glTranslatef(smoketex * .6, 0, 0);
6357 if ((tutoriallevel && id != 0))
6358 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6360 skeleton.drawmodel.draw();
6363 if (!playerdetail) {
6364 if ((tutoriallevel && id != 0))
6365 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6367 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6372 if (tutoriallevel && id != 0) {
6374 glMatrixMode(GL_MODELVIEW);
6375 glEnable(GL_TEXTURE_2D);
6377 if (skeleton.clothes) {
6381 skeleton.drawmodelclothes.draw();
6383 skeleton.drawmodelclothes.drawimmediate();
6389 if (num_weapons > 0) {
6390 for (k = 0; k < num_weapons; k++) {
6392 if (weaponactive == k) {
6393 if (weapons[i].getType() != staff) {
6394 for (j = 0; j < skeleton.num_muscles; j++) {
6395 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6396 weaponattachmuscle = j;
6399 for (j = 0; j < skeleton.num_muscles; j++) {
6400 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) {
6401 weaponrotatemuscle = j;
6404 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6405 if (creature == wolftype)
6406 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6408 if (weapons[i].getType() == staff) {
6409 for (j = 0; j < skeleton.num_muscles; j++) {
6410 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6411 weaponattachmuscle = j;
6414 for (j = 0; j < skeleton.num_muscles; j++) {
6415 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) {
6416 weaponrotatemuscle = j;
6419 //weaponpoint=jointPos(rightwrist);
6420 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6421 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6422 XYZ tempnormthing, vec1, vec2;
6423 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6424 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6425 CrossProduct(&vec1, &vec2, &tempnormthing);
6426 Normalise(&tempnormthing);
6427 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6428 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6431 if (weaponactive != k && weaponstuck != k) {
6432 if (weapons[i].getType() == knife)
6433 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6434 if (weapons[i].getType() == sword)
6435 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6436 if (weapons[i].getType() == staff)
6437 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6438 for (j = 0; j < skeleton.num_muscles; j++) {
6439 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) {
6440 weaponrotatemuscle = j;
6444 if (weaponstuck == k) {
6445 if (weaponstuckwhere == 0)
6446 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6448 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6449 for (j = 0; j < skeleton.num_muscles; j++) {
6450 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) {
6451 weaponrotatemuscle = j;
6455 if (skeleton.free) {
6456 weapons[i].position = weaponpoint * scale + coords;
6457 weapons[i].bigrotation = 0;
6458 weapons[i].bigtilt = 0;
6459 weapons[i].bigtilt2 = 0;
6461 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;
6462 weapons[i].bigrotation = yaw;
6463 weapons[i].bigtilt = tilt;
6464 weapons[i].bigtilt2 = tilt2;
6466 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6467 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6468 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6469 if (weaponactive == k) {
6470 if (weapons[i].getType() == knife) {
6471 weapons[i].smallrotation = 180;
6472 weapons[i].smallrotation2 = 0;
6473 if (isCrouch() || wasCrouch()) {
6474 weapons[i].smallrotation2 = 20;
6476 if (animTarget == hurtidleanim) {
6477 weapons[i].smallrotation2 = 50;
6479 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6480 XYZ temppoint1, temppoint2;
6483 temppoint1 = jointPos(righthand);
6484 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6485 distance = findDistance(&temppoint1, &temppoint2);
6486 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6487 weapons[i].rotation2 *= 360 / 6.28;
6490 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6491 weapons[i].rotation1 *= 360 / 6.28;
6492 weapons[i].rotation3 = 0;
6493 weapons[i].smallrotation = -90;
6494 weapons[i].smallrotation2 = 0;
6495 if (temppoint1.x > temppoint2.x)
6496 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6498 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6499 XYZ temppoint1, temppoint2;
6502 temppoint1 = jointPos(righthand);
6503 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6504 distance = findDistance(&temppoint1, &temppoint2);
6505 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6506 weapons[i].rotation2 *= 360 / 6.28;
6509 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6510 weapons[i].rotation1 *= 360 / 6.28;
6511 weapons[i].rotation3 = 0;
6512 weapons[i].smallrotation = 90;
6513 weapons[i].smallrotation2 = 0;
6514 if (temppoint1.x > temppoint2.x)
6515 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6517 if (animTarget == knifethrowanim) {
6518 weapons[i].smallrotation = 90;
6519 //weapons[i].smallrotation2=-90;
6520 weapons[i].smallrotation2 = 0;
6521 weapons[i].rotation1 = 0;
6522 weapons[i].rotation2 = 0;
6523 weapons[i].rotation3 = 0;
6525 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6526 weapons[i].smallrotation = -90;
6527 weapons[i].rotation1 = 0;
6528 weapons[i].rotation2 = 0;
6529 weapons[i].rotation3 = 0;
6532 if (weapons[i].getType() == sword) {
6533 weapons[i].smallrotation = 0;
6534 weapons[i].smallrotation2 = 0;
6535 if (animTarget == knifethrowanim) {
6536 weapons[i].smallrotation = -90;
6537 weapons[i].smallrotation2 = 0;
6538 weapons[i].rotation1 = 0;
6539 weapons[i].rotation2 = 0;
6540 weapons[i].rotation3 = 0;
6542 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)) {
6543 XYZ temppoint1, temppoint2;
6546 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6547 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6548 distance = findDistance(&temppoint1, &temppoint2);
6549 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6550 weapons[i].rotation2 *= 360 / 6.28;
6553 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6554 weapons[i].rotation1 *= 360 / 6.28;
6555 weapons[i].rotation3 = 0;
6556 weapons[i].smallrotation = 90;
6557 weapons[i].smallrotation2 = 0;
6558 if (temppoint1.x > temppoint2.x)
6559 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6562 if (weapons[i].getType() == staff) {
6563 weapons[i].smallrotation = 100;
6564 weapons[i].smallrotation2 = 0;
6565 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6566 XYZ temppoint1, temppoint2;
6569 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6570 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6571 distance = findDistance(&temppoint1, &temppoint2);
6572 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6573 weapons[i].rotation2 *= 360 / 6.28;
6576 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6577 weapons[i].rotation1 *= 360 / 6.28;
6578 weapons[i].rotation3 = 0;
6579 weapons[i].smallrotation = 90;
6580 weapons[i].smallrotation2 = 0;
6581 if (temppoint1.x > temppoint2.x)
6582 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6586 if (weaponactive != k && weaponstuck != k) {
6587 if (weapons[i].getType() == knife) {
6588 weapons[i].smallrotation = -70;
6589 weapons[i].smallrotation2 = 10;
6591 if (weapons[i].getType() == sword) {
6592 weapons[i].smallrotation = -100;
6593 weapons[i].smallrotation2 = -8;
6595 if (weapons[i].getType() == staff) {
6596 weapons[i].smallrotation = -100;
6597 weapons[i].smallrotation2 = -8;
6600 if (weaponstuck == k) {
6601 if (weaponstuckwhere == 0)
6602 weapons[i].smallrotation = 180;
6604 weapons[i].smallrotation = 0;
6605 weapons[i].smallrotation2 = 10;
6614 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6616 if (animCurrent != animTarget)
6618 if (skeleton.free == 2)
6627 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6630 static float distance;
6631 static float olddistance;
6632 static int intersecting;
6633 static int firstintersecting;
6636 static XYZ start, end;
6637 static float slopethreshold = -.4;
6639 firstintersecting = -1;
6643 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6646 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6647 for (i = 0; i < 4; i++) {
6648 for (j = 0; j < model->TriangleNum; j++) {
6649 if (model->facenormals[j].y <= slopethreshold) {
6651 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)));
6652 if (distance < radius) {
6653 point = *p1 - model->facenormals[j] * distance;
6654 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]]))
6657 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6658 &model->vertex[model->Triangles[j].vertex[1]],
6661 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6662 &model->vertex[model->Triangles[j].vertex[2]],
6665 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6666 &model->vertex[model->Triangles[j].vertex[2]],
6669 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6673 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)) {
6674 p1->y = point.y + radius;
6675 if ((animTarget == jumpdownanim || isFlip())) {
6676 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6679 if (animTarget == jumpupanim) {
6681 animTarget = getIdle();
6688 pause_sound(whooshsound);
6689 OPENAL_SetVolume(channels[whooshsound], 0);
6692 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6695 animTarget = getLanding();
6696 emit_sound_at(landsound, coords, 128.);
6699 addEnvSound(coords);
6706 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6707 olddistance = distance;
6708 firstintersecting = j;
6713 for (j = 0; j < model->TriangleNum; j++) {
6714 if (model->facenormals[j].y > slopethreshold) {
6717 start.y -= radius / 4;
6718 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6719 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6720 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6721 distance = abs((model->facenormals[j].x * start.x)
6722 + (model->facenormals[j].y * start.y)
6723 + (model->facenormals[j].z * start.z)
6724 - ((model->facenormals[j].x * v0.x)
6725 + (model->facenormals[j].y * v0.y)
6726 + (model->facenormals[j].z * v0.z)));
6727 if (distance < radius * .5) {
6728 point = start - model->facenormals[j] * distance;
6729 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6732 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6734 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6736 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6738 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6739 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6741 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6742 if (findLengthfast(&start) < findLengthfast(&velocity))
6745 *p1 += model->facenormals[j] * (distance - radius * .5);
6748 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6749 olddistance = distance;
6750 firstintersecting = j;
6757 *p = DoRotation(*p, 0, *rotate, 0);
6760 *p1 = DoRotation(*p1, 0, *rotate, 0);
6762 return firstintersecting;
6765 void Person::takeWeapon(int weaponId)
6768 weapons[weaponId].owner = id;
6769 if (num_weapons > 0) {
6770 weaponids[num_weapons] = weaponids[0];
6773 weaponids[0] = weaponId;
6776 void Person::addClothes()
6778 if (numclothes > 0) {
6779 for (int i = 0; i < numclothes; i++) {
6786 bool Person::addClothes(const int& clothesId)
6789 const char* fileName = clothes[clothesId];
6791 GLubyte* array = &skeleton.skinText[0];
6795 bool opened = load_image(fileName, texture);
6800 float tintr = clothestintr[clothesId];
6801 float tintg = clothestintg[clothesId];
6802 float tintb = clothestintb[clothesId];
6804 if (tintr > 1) tintr = 1;
6805 if (tintg > 1) tintg = 1;
6806 if (tintb > 1) tintb = 1;
6808 if (tintr < 0) tintr = 0;
6809 if (tintg < 0) tintg = 0;
6810 if (tintb < 0) tintb = 0;
6812 int bytesPerPixel = texture.bpp / 8;
6816 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6817 if (bytesPerPixel == 3)
6819 else if ((i + 1) % 4 == 0)
6820 alphanum = texture.data[i];
6821 if ((i + 1) % 4 || bytesPerPixel == 3) {
6823 texture.data[i] *= tintr;
6825 texture.data[i] *= tintg;
6827 texture.data[i] *= tintb;
6828 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);