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),
314 * GameTick/doPlayerCollisions
316 void Person::CheckKick()
319 && (animTarget == rabbitkickanim
321 && victim != this->shared_from_this()
323 && animCurrent == rabbitkickanim)
324 && distsq(&coords, &victim->coords) < 1.2
325 && !victim->skeleton.free))
328 if (animation[victim->animTarget].height != lowheight) {
329 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
330 XYZ relative = velocity;
332 Normalise(&relative);
336 if (tutoriallevel != 1)
337 emit_sound_at(heavyimpactsound, victim->coords);
339 for (int i = 0; i < victim->skeleton.num_joints; i++) {
340 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
343 victim->DoDamage(100 * damagemult / victim->protectionhigh);
349 animTarget = backflipanim;
351 velocity = facing * -10;
355 resume_stream(whooshsound);
357 award_bonus(id, cannon);
358 } else if (victim->isCrouch()) {
359 animTarget = rabbitkickreversedanim;
360 animCurrent = rabbitkickreversedanim;
361 victim->animCurrent = rabbitkickreversalanim;
362 victim->animTarget = rabbitkickreversalanim;
368 victim->oldcoords = victim->coords;
369 coords = victim->coords;
370 victim->targetyaw = targetyaw;
371 victim->victim = this->shared_from_this();
378 * GameTick/doPlayerCollisions - spread fire between players
379 * GameTick/doDebugKeys - press f to ignite
380 * Person::DoStuff - spread fire from lit campfires and bushes
382 void Person::CatchFire()
384 XYZ flatfacing, flatvelocity;
386 for (int i = 0; i < 10; i++) {
387 howmany = abs(Random() % (skeleton.num_joints));
389 flatvelocity = skeleton.joints[howmany].velocity;
390 flatfacing = skeleton.joints[howmany].position * scale + coords;
392 flatvelocity = velocity;
393 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
395 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
400 emit_sound_at(firestartsound, coords);
402 emit_stream_at(stream_firesound, coords);
410 * idle animation for this creature (depending on status)
412 int Person::getIdle()
414 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
416 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
417 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
418 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
419 victim->id < Person::players.size())) {
420 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
421 if (creature == rabbittype)
422 return fightidleanim;
423 if (creature == wolftype)
426 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
427 if (weapons[weaponids[weaponactive]].getType() == knife)
428 return knifefightidleanim;
429 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
430 return swordfightidlebothanim;
431 if (weapons[weaponids[weaponactive]].getType() == sword)
432 return swordfightidleanim;
433 if (weapons[weaponids[weaponactive]].getType() == staff)
434 return swordfightidleanim;
436 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
437 return fightsidestep;
439 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
441 if (howactive == typesitting) return sitanim;
442 if (howactive == typesittingwall) return sitwallanim;
443 if (howactive == typesleeping) return sleepanim;
444 if (howactive == typedead1) return dead1anim;
445 if (howactive == typedead2) return dead2anim;
446 if (howactive == typedead3) return dead3anim;
447 if (howactive == typedead4) return dead4anim;
448 if (creature == rabbittype) return bounceidleanim;
449 if (creature == wolftype) return wolfidle;
454 * crouch animation for this creature
456 int Person::getCrouch()
458 if (creature == rabbittype)
460 if (creature == wolftype)
461 return wolfcrouchanim;
466 * running animation for this creature (can be upright or all fours)
470 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
472 if (creature == wolftype && (!superruntoggle))
475 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
476 return rabbitrunninganim;
477 if (creature == wolftype && (superruntoggle))
478 return wolfrunninganim;
484 int Person::getStop()
486 if (creature == rabbittype)
488 if (creature == wolftype)
495 int Person::getLanding()
497 if (creature == rabbittype)
499 if (creature == wolftype)
506 int Person::getLandhard()
508 if (creature == rabbittype)
510 if (creature == wolftype)
511 return wolflandhardanim;
518 * Person::DoAnimations
521 SolidHitBonus(int playerid)
523 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
524 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
526 award_bonus(playerid, solidhit);
530 * spawns blood effects
532 void Person::DoBlood(float howmuch, int which)
534 // FIXME: should abstract out inputs
535 static int bleedxint, bleedyint;
537 if (bloodtoggle && tutoriallevel != 1) {
538 if (bleeding <= 0 && spurt) {
540 for (int i = 0; i < 3; i++) {
541 // emit blood particles
544 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
545 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
546 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
547 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
550 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
551 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
552 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
553 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
556 if (Random() % 2 == 0) // 50% chance
557 for (int i = 0; i < 3; i++) {
558 if (Random() % 2 != 0) {
559 // emit teeth particles
562 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
563 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
566 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
567 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
571 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
573 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
575 Sprite::setLastSpriteSpecial(3); // sets it to teeth
580 // FIXME: manipulating attributes
581 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
584 if (creature == rabbittype)
585 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) {
586 bleedxint = abs(Random() % 512);
587 bleedyint = abs(Random() % 512);
589 if (creature == wolftype)
590 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) {
591 bleedxint = abs(Random() % 512);
592 bleedyint = abs(Random() % 512);
596 bleedy /= realtexdetail;
597 bleedx /= realtexdetail;
598 direction = abs(Random() % 2) * 2 - 1;
607 * spawns big blood effects and ???
608 * modifies character's skin texture
610 void Person::DoBloodBig(float howmuch, int which)
612 static int bleedxint, bleedyint, i, j;
614 if (howmuch && id == 0)
617 if (tutoriallevel != 1 || id == 0)
618 if (aitype != playercontrolled && howmuch > 0) {
622 if (creature == wolftype) {
623 int i = abs(Random() % 2);
625 whichsound = snarlsound;
627 whichsound = snarl2sound;
629 if (creature == rabbittype) {
630 int i = abs(Random() % 2);
632 whichsound = rabbitpainsound;
633 if (i == 1 && howmuch >= 2)
634 whichsound = rabbitpain1sound;
637 if (whichsound != -1) {
638 emit_sound_at(whichsound, coords);
643 if (id == 0 && howmuch > 0) {
647 if (bloodtoggle && decals && tutoriallevel != 1) {
648 if (bleeding <= 0 && spurt) {
650 for (int i = 0; i < 3; i++) {
651 // emit blood particles
652 // FIXME: copypaste from above
655 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
656 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
657 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
658 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
661 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
662 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
663 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
664 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
669 // weird texture manipulation code follows.
670 // looks like this is painting blood onto the character's skin texture
671 // FIXME: surely there's a better way
673 int offsetx = 0, offsety = 0;
675 offsety = Random() % 40;
676 offsetx = abs(Random() % 60);
678 if (which == 190 || which == 185) {
679 offsety = Random() % 40;
680 offsetx = abs(Random() % 100) - 20;
683 offsety = Random() % 10;
684 offsetx = Random() % 10;
687 offsety = Random() % 20;
688 offsetx = Random() % 20;
690 if (which == 220 || which == 215) {
700 if (creature == rabbittype)
701 for (i = 0; i < 512; i++) {
702 for (j = 0; j < 512; j++) {
703 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
704 if (i < startx) startx = i;
705 if (j < starty) starty = j;
706 if (i > endx) endx = i;
707 if (j > endy) endy = j;
711 if (creature == wolftype)
712 for (i = 0; i < 512; i++) {
713 for (j = 0; j < 512; j++) {
714 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
715 if (i < startx) startx = i;
716 if (j < starty) starty = j;
717 if (i > endx) endx = i;
718 if (j > endy) endy = j;
728 if (startx < 0) startx = 0;
729 if (starty < 0) starty = 0;
730 if (endx > 512 - 1) endx = 512 - 1;
731 if (endy > 512 - 1) endy = 512 - 1;
732 if (endx < startx) endx = startx;
733 if (endy < starty) endy = starty;
735 startx /= realtexdetail;
736 starty /= realtexdetail;
737 endx /= realtexdetail;
738 endy /= realtexdetail;
740 int texdetailint = realtexdetail;
742 if (creature == rabbittype)
743 for (i = startx; i < endx; i++) {
744 for (j = starty; j < endy; j++) {
745 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) {
746 color = Random() % 85 + 170;
747 where = i * skeleton.skinsize * 3 + j * 3;
748 if (skeleton.skinText[where + 0] > color / 2)
749 skeleton.skinText[where + 0] = color / 2;
750 skeleton.skinText[where + 1] = 0;
751 skeleton.skinText[where + 2] = 0;
755 if (creature == wolftype)
756 for (i = startx; i < endx; i++) {
757 for (j = starty; j < endy; j++) {
758 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) {
759 color = Random() % 85 + 170;
760 where = i * skeleton.skinsize * 3 + j * 3;
761 if (skeleton.skinText[where + 0] > color / 2)
762 skeleton.skinText[where + 0] = color / 2;
763 skeleton.skinText[where + 1] = 0;
764 skeleton.skinText[where + 2] = 0;
768 skeleton.drawmodel.textureptr.bind();
773 if (creature == rabbittype)
774 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) {
775 bleedxint = abs(Random() % 512);
776 bleedyint = abs(Random() % 512);
778 if (creature == wolftype)
779 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) {
780 bleedxint = abs(Random() % 512);
781 bleedyint = abs(Random() % 512);
783 bleedy = bleedxint + offsetx;
784 bleedx = bleedyint + offsety;
785 bleedy /= realtexdetail;
786 bleedx /= realtexdetail;
791 if (bleedx > skeleton.skinsize - 1)
792 bleedx = skeleton.skinsize - 1;
793 if (bleedy > skeleton.skinsize - 1)
794 bleedy = skeleton.skinsize - 1;
795 direction = abs(Random() % 2) * 2 - 1;
798 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
799 deathbleeding += bleeding;
800 bloodloss += bleeding * 3;
802 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
803 if (abs(Random() % 2) == 0) {
804 aitype = gethelptype;
807 aitype = attacktypecutoff;
815 * similar to DoBloodBig
817 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
821 static XYZ startpoint, endpoint, colpoint, movepoint;
822 static float rotationpoint;
824 static XYZ p1, p2, p3, p0;
827 float coordsx, coordsy;
830 if (bloodtoggle && decals && tutoriallevel != 1) {
833 where = DoRotation(where, 0, -yaw, 0);
841 // ray testing for a tri in the character model
842 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
843 if (whichtri != -1) {
844 // low level geometry math
846 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
847 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
848 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
850 bary.x = distsq(&p0, &p1);
851 bary.y = distsq(&p0, &p2);
852 bary.z = distsq(&p0, &p3);
854 total = bary.x + bary.y + bary.z;
863 total = bary.x + bary.y + bary.z;
869 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
870 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
871 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
872 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
873 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
874 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
875 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;
876 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;
878 if (bleeding <= 0 && spurt) {
880 for (int i = 0; i < 3; i++) {
881 // emit blood particles
882 // FIXME: more copypaste code
885 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
886 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
887 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
888 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
891 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
892 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
893 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
894 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
899 // texture manipulation follows
901 int offsetx = 0, offsety = 0;
902 offsetx = (1 + coordsy) * 512 - 291;
903 offsety = coordsx * 512 - 437;
910 if (creature == rabbittype)
911 for (i = 0; i < 512; i++) {
912 for (j = 0; j < 512; j++) {
913 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
914 if (i < startx) startx = i;
915 if (j < starty) starty = j;
916 if (i > endx) endx = i;
917 if (j > endy) endy = j;
921 if (creature == wolftype)
922 for (i = 0; i < 512; i++) {
923 for (j = 0; j < 512; j++) {
924 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
925 if (i < startx) startx = i;
926 if (j < starty) starty = j;
927 if (i > endx) endx = i;
928 if (j > endy) endy = j;
937 if (startx < 0) startx = 0;
938 if (starty < 0) starty = 0;
939 if (endx > 512 - 1) endx = 512 - 1;
940 if (endy > 512 - 1) endy = 512 - 1;
941 if (endx < startx) endx = startx;
942 if (endy < starty) endy = starty;
944 startx /= realtexdetail;
945 starty /= realtexdetail;
946 endx /= realtexdetail;
947 endy /= realtexdetail;
949 int texdetailint = realtexdetail;
951 if (creature == rabbittype)
952 for (i = startx; i < endx; i++) {
953 for (j = starty; j < endy; j++) {
954 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) {
955 color = Random() % 85 + 170;
956 where = i * skeleton.skinsize * 3 + j * 3;
957 if (skeleton.skinText[where + 0] > color / 2)
958 skeleton.skinText[where + 0] = color / 2;
959 skeleton.skinText[where + 1] = 0;
960 skeleton.skinText[where + 2] = 0;
961 } 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) {
962 color = Random() % 85 + 170;
963 where = i * skeleton.skinsize * 3 + j * 3;
964 if (skeleton.skinText[where + 0] > color / 2)
965 skeleton.skinText[where + 0] = color / 2;
966 skeleton.skinText[where + 1] = 0;
967 skeleton.skinText[where + 2] = 0;
971 if (creature == wolftype)
972 for (i = startx; i < endx; i++) {
973 for (j = starty; j < endy; j++) {
974 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) {
975 color = Random() % 85 + 170;
976 where = i * skeleton.skinsize * 3 + j * 3;
977 if (skeleton.skinText[where + 0] > color / 2)
978 skeleton.skinText[where + 0] = color / 2;
979 skeleton.skinText[where + 1] = 0;
980 skeleton.skinText[where + 2] = 0;
981 } 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) {
982 color = Random() % 85 + 170;
983 where = i * skeleton.skinsize * 3 + j * 3;
984 if (skeleton.skinText[where + 0] > color / 2)
985 skeleton.skinText[where + 0] = color / 2;
986 skeleton.skinText[where + 1] = 0;
987 skeleton.skinText[where + 2] = 0;
991 skeleton.drawmodel.textureptr.bind();
994 bleedy = (1 + coordsy) * 512;
995 bleedx = coordsx * 512;
996 bleedy /= realtexdetail;
997 bleedx /= realtexdetail;
1002 if (bleedx > skeleton.skinsize - 1)
1003 bleedx = skeleton.skinsize - 1;
1004 if (bleedy > skeleton.skinsize - 1)
1005 bleedy = skeleton.skinsize - 1;
1006 direction = abs(Random() % 2) * 2 - 1;
1011 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
1012 deathbleeding += bleeding;
1013 bloodloss += bleeding * 3;
1015 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
1016 if (abs(Random() % 2) == 0) {
1017 aitype = gethelptype;
1020 aitype = attacktypecutoff;
1031 * guessing this performs a reversal
1033 void Person::Reverse()
1035 if (!((victim->aitype == playercontrolled
1037 || staggerdelay <= 0)
1038 && victim->animTarget != jumpupanim
1039 && victim->animTarget != jumpdownanim
1040 && (tutoriallevel != 1 || cananger)
1044 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
1045 && (victim->id != 0 || difficulty >= 2)
1046 && (creature != wolftype || victim->creature == wolftype))
1049 if (animTarget == sweepanim) {
1050 animTarget = sweepreversedanim;
1051 animCurrent = sweepreversedanim;
1052 victim->animCurrent = sweepreversalanim;
1053 victim->animTarget = sweepreversalanim;
1055 if (animTarget == spinkickanim) {
1056 animTarget = spinkickreversedanim;
1057 animCurrent = spinkickreversedanim;
1058 victim->animCurrent = spinkickreversalanim;
1059 victim->animTarget = spinkickreversalanim;
1061 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
1062 if (animTarget == rabbittacklinganim) {
1065 victim->frameCurrent = 6;
1066 victim->frameTarget = 7;
1068 animTarget = upunchreversedanim;
1069 animCurrent = upunchreversedanim;
1070 victim->animCurrent = upunchreversalanim;
1071 victim->animTarget = upunchreversalanim;
1073 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1074 if (victim->weaponactive != -1) {
1075 victim->throwtogglekeydown = 1;
1076 XYZ tempVelocity = victim->velocity * .2;
1077 if (tempVelocity.x == 0)
1078 tempVelocity.x = .1;
1079 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1080 victim->num_weapons--;
1081 if (victim->num_weapons) {
1082 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1083 if (victim->weaponstuck == victim->num_weapons)
1084 victim->weaponstuck = 0;
1087 victim->weaponactive = -1;
1088 for (unsigned j = 0; j < Person::players.size(); j++) {
1089 Person::players[j]->wentforweapon = 0;
1093 animTarget = staffhitreversedanim;
1094 animCurrent = staffhitreversedanim;
1095 victim->animCurrent = staffhitreversalanim;
1096 victim->animTarget = staffhitreversalanim;
1098 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
1099 if (victim->weaponactive != -1) {
1100 victim->throwtogglekeydown = 1;
1101 XYZ tempVelocity = victim->velocity * .2;
1102 if (tempVelocity.x == 0)
1103 tempVelocity.x = .1;
1104 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1105 victim->num_weapons--;
1106 if (victim->num_weapons) {
1107 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1108 if (victim->weaponstuck == victim->num_weapons)
1109 victim->weaponstuck = 0;
1112 victim->weaponactive = -1;
1113 for (unsigned j = 0; j < Person::players.size(); j++) {
1114 Person::players[j]->wentforweapon = 0;
1117 animTarget = staffspinhitreversedanim;
1118 animCurrent = staffspinhitreversedanim;
1119 victim->animCurrent = staffspinhitreversalanim;
1120 victim->animTarget = staffspinhitreversalanim;
1122 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
1123 if (victim->weaponactive != -1) {
1124 victim->throwtogglekeydown = 1;
1125 XYZ tempVelocity = victim->velocity * .2;
1126 if (tempVelocity.x == 0)
1127 tempVelocity.x = .1;
1128 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1129 victim->num_weapons--;
1130 if (victim->num_weapons) {
1131 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1132 if (victim->weaponstuck == victim->num_weapons)
1133 victim->weaponstuck = 0;
1136 victim->weaponactive = -1;
1137 for (unsigned j = 0; j < Person::players.size(); j++) {
1138 Person::players[j]->wentforweapon = 0;
1141 animTarget = swordslashreversedanim;
1142 animCurrent = swordslashreversedanim;
1143 victim->animCurrent = swordslashreversalanim;
1144 victim->animTarget = swordslashreversalanim;
1146 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
1147 if (victim->weaponactive != -1) {
1148 victim->throwtogglekeydown = 1;
1149 XYZ tempVelocity = victim->velocity * .2;
1150 if (tempVelocity.x == 0)
1151 tempVelocity.x = .1;
1152 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
1153 victim->num_weapons--;
1154 if (victim->num_weapons) {
1155 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1156 if (victim->weaponstuck == victim->num_weapons)
1157 victim->weaponstuck = 0;
1160 victim->weaponactive = -1;
1161 for (unsigned j = 0; j < Person::players.size(); j++) {
1162 Person::players[j]->wentforweapon = 0;
1165 animTarget = knifeslashreversedanim;
1166 animCurrent = knifeslashreversedanim;
1167 victim->animCurrent = knifeslashreversalanim;
1168 victim->animTarget = knifeslashreversalanim;
1170 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
1171 victim->targettilt2 = targettilt2;
1172 victim->frameCurrent = frameCurrent;
1173 victim->frameTarget = frameTarget;
1174 victim->target = target;
1175 victim->velocity = 0;
1176 victim->oldcoords = victim->coords;
1177 victim->coords = coords;
1178 victim->targetyaw = targetyaw;
1179 victim->yaw = targetyaw;
1180 victim->victim = this->shared_from_this();
1182 if (animTarget == winduppunchanim) {
1183 animTarget = winduppunchblockedanim;
1184 victim->animTarget = blockhighleftanim;
1185 victim->frameTarget = 1;
1186 victim->target = .5;
1187 victim->victim = this->shared_from_this();
1188 victim->targetyaw = targetyaw + 180;
1190 if (animTarget == wolfslapanim) {
1191 animTarget = winduppunchblockedanim;
1192 victim->animTarget = blockhighleftanim;
1193 victim->frameTarget = 1;
1194 victim->target = .5;
1195 victim->victim = this->shared_from_this();
1196 victim->targetyaw = targetyaw + 180;
1198 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1199 animTarget = swordslashparriedanim;
1200 parriedrecently = .4;
1201 victim->parriedrecently = 0;
1202 victim->animTarget = swordslashparryanim;
1203 victim->frameTarget = 1;
1204 victim->target = .5;
1205 victim->victim = this->shared_from_this();
1206 victim->targetyaw = targetyaw + 180;
1208 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1209 if (victim->weaponactive != -1) {
1210 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1211 if (weapons[victim->weaponids[0]].getType() == staff)
1212 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1213 if (weapons[weaponids[0]].getType() == staff)
1214 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1215 emit_sound_at(swordstaffsound, victim->coords);
1217 emit_sound_at(metalhitsound, victim->coords);
1221 victim->Puff(righthand);
1223 victim->frameTarget = 0;
1224 victim->animTarget = staggerbackhighanim;
1225 victim->targetyaw = targetyaw + 180;
1227 aim = DoRotation(facing, 0, 90, 0) * 21;
1229 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1230 victim->num_weapons--;
1231 if (victim->num_weapons) {
1232 victim->weaponids[0] = victim->weaponids[num_weapons];
1233 if (victim->weaponstuck == victim->num_weapons)
1234 victim->weaponstuck = 0;
1236 victim->weaponactive = -1;
1237 for (unsigned i = 0; i < Person::players.size(); i++) {
1238 Person::players[i]->wentforweapon = 0;
1242 if (abs(Random() % 20) == 0) {
1243 if (weaponactive != -1) {
1244 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1245 if (weapons[victim->weaponids[0]].getType() == staff)
1246 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1247 if (weapons[weaponids[0]].getType() == staff)
1248 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1250 emit_sound_at(swordstaffsound, coords);
1252 emit_sound_at(metalhitsound, coords);
1260 animTarget = staggerbackhighanim;
1261 targetyaw = targetyaw + 180;
1263 aim = DoRotation(facing, 0, 90, 0) * 21;
1265 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1268 weaponids[0] = weaponids[num_weapons];
1269 if (weaponstuck == num_weapons)
1273 for (unsigned i = 0; i < Person::players.size(); i++) {
1274 Person::players[i]->wentforweapon = 0;
1281 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1282 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1283 victim->animTarget = dodgebackanim;
1284 victim->frameTarget = 0;
1288 rotatetarget = coords - victim->coords;
1289 Normalise(&rotatetarget);
1290 victim->targetyaw = -asin(0 - rotatetarget.x);
1291 victim->targetyaw *= 360 / 6.28;
1292 if (rotatetarget.z < 0)
1293 victim->targetyaw = 180 - victim->targetyaw;
1295 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1297 victim->lastattack3 = victim->lastattack2;
1298 victim->lastattack2 = victim->lastattack;
1299 victim->lastattack = victim->animTarget;
1301 victim->animTarget = sweepanim;
1302 victim->frameTarget = 0;
1306 rotatetarget = coords - victim->coords;
1307 Normalise(&rotatetarget);
1308 victim->targetyaw = -asin(0 - rotatetarget.x);
1309 victim->targetyaw *= 360 / 6.28;
1310 if (rotatetarget.z < 0)
1311 victim->targetyaw = 180 - victim->targetyaw;
1313 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1315 victim->lastattack3 = victim->lastattack2;
1316 victim->lastattack2 = victim->lastattack;
1317 victim->lastattack = victim->animTarget;
1322 victim->velocity = 0;
1324 if (aitype != playercontrolled)
1326 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1328 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1330 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1333 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1340 void Person::DoDamage(float howmuch)
1342 // subtract health (temporary?)
1343 if (tutoriallevel != 1)
1344 damage += howmuch / power;
1347 damagedealt += howmuch / power;
1349 damagetaken += howmuch / power;
1352 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1355 if (tutoriallevel != 1)
1356 permanentdamage += howmuch / 2 / power;
1357 if (tutoriallevel != 1)
1358 superpermanentdamage += howmuch / 4 / power;
1360 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1362 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1366 camerashake += howmuch / 100;
1367 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1368 blackout = damage / damagetolerance;
1373 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1374 aitype = attacktypecutoff;
1375 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1376 if (abs(Random() % 2) == 0) {
1377 aitype = gethelptype;
1380 aitype = attacktypecutoff;
1384 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1387 for (int i = 0; i < skeleton.num_joints; i++) {
1388 if (skeleton.free) {
1389 flatvelocity2 = skeleton.joints[i].velocity;
1390 flatfacing2 = skeleton.joints[i].position * scale + coords;
1392 flatvelocity2 = velocity;
1393 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1395 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1396 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1397 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1398 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1399 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1400 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1403 emit_sound_at(splattersound, coords);
1408 if (!dead && creature == wolftype) {
1409 award_bonus(0, Wolfbonus);
1416 if (tutoriallevel != 1 || id == 0)
1417 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1418 int whichsound = -1;
1420 if (creature == wolftype) {
1421 int i = abs(Random() % 2);
1423 whichsound = snarlsound;
1425 whichsound = snarl2sound;
1427 if (creature == rabbittype) {
1428 int i = abs(Random() % 2);
1430 whichsound = rabbitpainsound;
1431 if (i == 1 && damage > damagetolerance)
1432 whichsound = rabbitpain1sound;
1435 if (whichsound != -1) {
1436 emit_sound_at(whichsound, coords);
1437 addEnvSound(coords);
1444 * calculate/animate head facing direction?
1446 void Person::DoHead()
1448 static XYZ rotatearound;
1450 static float lookspeed = 500;
1452 if (!freeze && !winfreeze) {
1455 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1456 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1458 while (targetheadyaw > 180)targetheadyaw -= 360;
1459 while (targetheadyaw < -180)targetheadyaw += 360;
1461 if (targetheadyaw > 160)
1462 targetheadpitch = targetheadpitch * -1;
1463 if (targetheadyaw < -160)
1464 targetheadpitch = targetheadpitch * -1;
1465 if (targetheadyaw > 160)
1466 targetheadyaw = targetheadyaw - 180;
1467 if (targetheadyaw < -160)
1468 targetheadyaw = targetheadyaw + 180;
1470 if (targetheadpitch > 120)
1471 targetheadpitch = 120;
1472 if (targetheadpitch < -120)
1473 targetheadpitch = -120;
1474 if (targetheadyaw > 120)
1475 targetheadyaw = 120;
1476 if (targetheadyaw < -120)
1477 targetheadyaw = -120;
1480 targetheadpitch = 0;
1482 if (targetheadyaw > 80)
1484 if (targetheadyaw < -80)
1485 targetheadyaw = -80;
1486 if (targetheadpitch > 50)
1487 targetheadpitch = 50;
1488 if (targetheadpitch < -50)
1489 targetheadpitch = -50;
1492 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1493 headyaw = targetheadyaw;
1494 else if (headyaw > targetheadyaw) {
1495 headyaw -= multiplier * lookspeed;
1496 } else if (headyaw < targetheadyaw) {
1497 headyaw += multiplier * lookspeed;
1500 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1501 headpitch = targetheadpitch;
1502 else if (headpitch > targetheadpitch) {
1503 headpitch -= multiplier * lookspeed / 2;
1504 } else if (headpitch < targetheadpitch) {
1505 headpitch += multiplier * lookspeed / 2;
1508 rotatearound = jointPos(neck);
1509 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1513 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1514 facing = DoRotation(facing, headpitch * .4, 0, 0);
1515 facing = DoRotation(facing, 0, headyaw * .4, 0);
1518 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1519 facing = DoRotation(facing, headpitch * .8, 0, 0);
1520 facing = DoRotation(facing, 0, headyaw * .8, 0);
1523 if (animTarget == walkanim) {
1524 facing = DoRotation(facing, headpitch * .6, 0, 0);
1525 facing = DoRotation(facing, 0, headyaw * .6, 0);
1528 skeleton.specialforward[0] = facing;
1529 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1530 for (int i = 0; i < skeleton.num_muscles; i++) {
1531 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1532 skeleton.FindRotationMuscle(i, animTarget);
1539 * ragdolls character?
1541 void Person::RagDoll(bool checkcollision)
1546 if (!skeleton.free) {
1549 if (id == 0 && isFlip())
1556 facing = DoRotation(facing, 0, yaw, 0);
1558 skeleton.freetime = 0;
1560 skeleton.longdead = 0;
1563 skeleton.broken = 0;
1564 skeleton.spinny = 1;
1566 skeleton.freefall = 1;
1568 if (!isnormal(velocity.x)) velocity.x = 0;
1569 if (!isnormal(velocity.y)) velocity.y = 0;
1570 if (!isnormal(velocity.z)) velocity.z = 0;
1571 if (!isnormal(yaw)) yaw = 0;
1572 if (!isnormal(coords.x)) coords = 0;
1573 if (!isnormal(tilt)) tilt = 0;
1574 if (!isnormal(tilt2)) tilt2 = 0;
1576 for (int i = 0; i < skeleton.num_joints; i++) {
1577 skeleton.joints[i].delay = 0;
1578 skeleton.joints[i].locked = 0;
1579 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1580 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1581 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1582 skeleton.joints[i].position.y += .1;
1583 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1584 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1587 for (int i = 0; i < skeleton.num_joints; i++) {
1588 skeleton.joints[i].velocity = 0;
1589 skeleton.joints[i].velchange = 0;
1591 skeleton.DoConstraints(&coords, &scale);
1592 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1593 skeleton.DoConstraints(&coords, &scale);
1594 skeleton.DoConstraints(&coords, &scale);
1595 skeleton.DoConstraints(&coords, &scale);
1596 skeleton.DoConstraints(&coords, &scale);
1599 speed = animation[animTarget].speed[frameTarget] * 2;
1600 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1601 speed = animation[animCurrent].speed[frameCurrent] * 2;
1604 speed = transspeed * 2;
1608 for (int i = 0; i < skeleton.num_joints; i++) {
1609 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1610 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);
1612 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1613 change.x = (float)(Random() % 100) / 100;
1614 change.y = (float)(Random() % 100) / 100;
1615 change.z = (float)(Random() % 100) / 100;
1616 skeleton.joints[i].velocity += change;
1617 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1619 change.x = (float)(Random() % 100) / 100;
1620 change.y = (float)(Random() % 100) / 100;
1621 change.z = (float)(Random() % 100) / 100;
1622 skeleton.joints[i].velchange += change;
1623 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1626 if (checkcollision) {
1633 for (j = 0; j < skeleton.num_joints; j++) {
1634 average += skeleton.joints[j].position;
1638 coords += average * scale;
1639 for (j = 0; j < skeleton.num_joints; j++) {
1640 skeleton.joints[j].position -= average;
1643 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1644 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1645 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1646 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1647 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1650 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1651 coords.x = lowpoint.x;
1652 coords.z = lowpoint.z;
1661 for (int i = 0; i < skeleton.num_joints; i++) {
1662 velocity += skeleton.joints[i].velocity * scale;
1664 velocity /= skeleton.num_joints;
1667 if (Random() % 2 == 0) {
1668 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1669 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1670 weapons[weaponids[0]].velocity.x += .01;
1673 weaponids[0] = weaponids[num_weapons];
1674 if (weaponstuck == num_weapons)
1678 for (unsigned i = 0; i < Person::players.size(); i++) {
1679 Person::players[i]->wentforweapon = 0;
1684 animTarget = bounceidleanim;
1685 animCurrent = bounceidleanim;
1695 void Person::FootLand(int which, float opacity)
1697 static XYZ terrainlight;
1698 static XYZ footvel, footpoint;
1699 if (opacity >= 1 || skiddelay <= 0)
1703 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1705 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1706 //footpoint.y=coords.y;
1707 if (distsq(&footpoint, &viewer))
1708 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1709 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1710 footvel = velocity / 5;
1714 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1716 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1717 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1718 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1719 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1720 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1721 if (opacity >= 1 || detail == 2)
1723 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1724 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1725 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1726 footvel = velocity / 5;
1730 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1732 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1733 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1734 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1735 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1736 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1737 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1738 footvel = velocity / 5;
1742 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1744 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1745 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1746 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1747 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1748 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1749 if (opacity >= 1 || detail == 2)
1751 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1752 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1753 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1754 footvel = velocity / 5;
1758 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1760 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1761 //footpoint.y=coords.y;
1762 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1763 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1768 * make a puff effect at a body part (dust effect?)
1770 void Person::Puff(int whichlabel)
1772 static XYZ footvel, footpoint;
1775 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1776 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1780 * I think I added this in an attempt to clean up code
1782 void Person::setAnimation(int animation)
1784 animTarget = animation;
1793 void Person::DoAnimations()
1795 if (!skeleton.free) {
1796 static float oldtarget;
1798 if (isIdle() && animCurrent != getIdle())
1799 normalsupdatedelay = 0;
1801 if (animTarget == tempanim || animCurrent == tempanim) {
1802 animation[tempanim] = tempanimation;
1804 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1810 vel[0] = velocity.x;
1811 vel[1] = velocity.y;
1812 vel[2] = velocity.z;
1815 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1816 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1818 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1820 if (!crouchkeydown && velocity.y >= -15)
1823 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1828 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1830 if (normaldotproduct(targfacing, velocity) >= -.3)
1831 animTarget = flipanim;
1833 animTarget = backflipanim;
1834 crouchtogglekeydown = 1;
1842 if (animation[animTarget].attack != reversed)
1844 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1845 crouchtogglekeydown = 0;
1846 if (aitype == playercontrolled)
1849 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1852 crouchtogglekeydown = 1;
1856 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1858 normalsupdatedelay = 0;
1862 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1864 emit_sound_at(fireendsound, coords);
1865 pause_sound(stream_firesound);
1869 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1870 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1872 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1873 if (normaldotproduct(victim->facing, facing) > 0)
1874 victim->animTarget = rabbittackledbackanim;
1876 victim->animTarget = rabbittackledfrontanim;
1877 victim->frameTarget = 2;
1880 victim->targetyaw = yaw;
1881 if (victim->aitype == gethelptype)
1882 victim->DoDamage(victim->damagetolerance - victim->damage);
1883 //victim->DoDamage(30);
1884 if (creature == wolftype) {
1886 emit_sound_at(clawslicesound, victim->coords);
1888 victim->DoBloodBig(1 / victim->armorhead, 210);
1890 award_bonus(id, TackleBonus,
1891 victim->aitype == gethelptype ? 50 : 0);
1895 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1896 if (weapons[weaponids[0]].getType() == knife) {
1897 if (weaponactive == -1)
1899 else if (weaponactive == 0)
1902 if (weaponactive == -1) {
1903 emit_sound_at(knifesheathesound, coords);
1905 if (weaponactive != -1) {
1906 emit_sound_at(knifedrawsound, coords, 128);
1909 drawtogglekeydown = 1;
1912 if (tutoriallevel != 1 || id == 0)
1913 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1916 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1917 if (animation[animTarget].label[frameTarget] == 1)
1918 whichsound = footstepsound;
1920 whichsound = footstepsound2;
1921 if (animation[animTarget].label[frameTarget] == 1)
1923 if (animation[animTarget].label[frameTarget] == 2)
1925 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1931 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1932 if (animation[animTarget].label[frameTarget] == 1)
1933 whichsound = footstepsound3;
1935 whichsound = footstepsound4;
1939 if (animation[animTarget].label[frameTarget] == 1)
1940 whichsound = footstepsound3;
1942 whichsound = footstepsound4;
1944 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1945 if (animation[animTarget].attack != neutral) {
1946 unsigned r = abs(Random() % 3);
1948 whichsound = lowwhooshsound;
1950 whichsound = midwhooshsound;
1952 whichsound = highwhooshsound;
1954 if (animation[animTarget].attack == neutral)
1955 whichsound = movewhooshsound;
1956 } else if (animation[animTarget].label[frameTarget] == 4)
1957 whichsound = knifeswishsound;
1958 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1959 whichsound = landsound2;
1961 emit_sound_at(whichsound, coords, 256.);
1964 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1965 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) {
1966 addEnvSound(coords, 15);
1968 addEnvSound(coords, 6);
1972 if (animation[animTarget].label[frameTarget] == 3) {
1974 emit_sound_at(whichsound, coords, 128.);
1979 if (tutoriallevel != 1 || id == 0)
1980 if (speechdelay <= 0)
1981 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1982 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1983 int whichsound = -1;
1984 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1985 if (animation[animTarget].attack != neutral) {
1986 unsigned r = abs(Random() % 4);
1987 if (creature == rabbittype) {
1988 if (r == 0) whichsound = rabbitattacksound;
1989 if (r == 1) whichsound = rabbitattack2sound;
1990 if (r == 2) whichsound = rabbitattack3sound;
1991 if (r == 3) whichsound = rabbitattack4sound;
1993 if (creature == wolftype) {
1994 if (r == 0) whichsound = barksound;
1995 if (r == 1) whichsound = bark2sound;
1996 if (r == 2) whichsound = bark3sound;
1997 if (r == 3) whichsound = barkgrowlsound;
2003 if (whichsound != -1) {
2004 emit_sound_at(whichsound, coords);
2010 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
2016 currentoffset = targetoffset;
2017 frameTarget = frameCurrent;
2018 animCurrent = animTarget;
2021 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2022 for (unsigned i = 0; i < weapons.size(); i++) {
2023 if (weapons[i].owner == -1)
2024 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
2025 if (distsq(&coords, &weapons[i].position) >= 1) {
2026 if (weapons[i].getType() != staff) {
2027 emit_sound_at(knifedrawsound, coords, 128.);
2036 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
2037 for (unsigned i = 0; i < weapons.size(); i++) {
2038 bool willwork = true;
2039 if (weapons[i].owner != -1)
2040 if (Person::players[weapons[i].owner]->weaponstuck != -1)
2041 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
2042 if (Person::players[weapons[i].owner]->num_weapons > 1)
2044 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
2045 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
2046 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
2047 bool fleshstuck = false;
2048 if (weapons[i].owner != -1)
2049 if (victim->weaponstuck != -1) {
2050 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2055 emit_sound_at(fleshstabremovesound, coords, 128.);
2057 if (weapons[i].getType() != staff) {
2058 emit_sound_at(knifedrawsound, coords, 128.);
2061 if (weapons[i].owner != -1) {
2062 victim = Person::players[weapons[i].owner];
2063 if (victim->num_weapons == 1)
2064 victim->num_weapons = 0;
2066 victim->num_weapons = 1;
2068 //victim->weaponactive=-1;
2069 victim->skeleton.longdead = 0;
2070 victim->skeleton.free = 1;
2071 victim->skeleton.broken = 0;
2073 for (int j = 0; j < victim->skeleton.num_joints; j++) {
2074 victim->skeleton.joints[j].velchange = 0;
2075 victim->skeleton.joints[j].locked = 0;
2081 Normalise(&relative);
2082 XYZ footvel, footpoint;
2084 footpoint = weapons[i].position;
2085 if (victim->weaponstuck != -1) {
2086 if (victim->weaponids[victim->weaponstuck] == int(i)) {
2088 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2089 weapons[i].bloody = 2;
2090 weapons[i].blooddrip = 5;
2091 victim->weaponstuck = -1;
2094 if (victim->num_weapons > 0) {
2095 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
2096 victim->weaponstuck = 0;
2097 if (victim->weaponids[0] == int(i))
2098 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
2101 victim->jointVel(abdomen) += relative * 6;
2102 victim->jointVel(neck) += relative * 6;
2103 victim->jointVel(rightshoulder) += relative * 6;
2104 victim->jointVel(leftshoulder) += relative * 6;
2112 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
2113 if (weaponactive == -1)
2115 else if (weaponactive == 0) {
2117 if (num_weapons == 2) {
2119 buffer = weaponids[0];
2120 weaponids[0] = weaponids[1];
2121 weaponids[1] = buffer;
2124 if (weaponactive == -1) {
2125 emit_sound_at(knifesheathesound, coords, 128.);
2127 if (weaponactive != -1) {
2128 emit_sound_at(knifedrawsound, coords, 128.);
2133 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
2134 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
2135 Normalise(&rotatetarget);
2136 targetyaw = -asin(0 - rotatetarget.x);
2137 targetyaw *= 360 / 6.28;
2138 if (rotatetarget.z < 0)
2139 targetyaw = 180 - targetyaw;
2141 if (animTarget == walljumprightkickanim)
2143 if (animTarget == walljumpleftkickanim)
2149 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
2152 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2157 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2158 animTarget = rabbittackleanim;
2160 emit_sound_at(jumpsound, coords);
2168 targetloc = velocity;
2169 Normalise(&targetloc);
2170 targetloc += coords;
2171 for (unsigned i = 0; i < Person::players.size(); i++) {
2173 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2174 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2178 if (closestid != -1)
2179 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2181 victim = Person::players[closestid];
2182 coords = victim->coords;
2183 animCurrent = rabbittacklinganim;
2184 animTarget = rabbittacklinganim;
2188 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2189 rotatetarget = coords - victim->coords;
2190 Normalise(&rotatetarget);
2191 targetyaw = -asin(0 - rotatetarget.x);
2192 targetyaw *= 360 / 6.28;
2193 if (rotatetarget.z < 0)
2194 targetyaw = 180 - targetyaw;
2196 if (animTarget != rabbitrunninganim) {
2197 emit_sound_at(jumpsound, coords, 128.);
2203 float damagemult = 1 * power;
2204 if (creature == wolftype)
2205 damagemult = 2.5 * power;
2207 damagemult /= victim->damagetolerance / 200;
2209 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2210 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2211 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2215 if (Random() % 2 || creature == wolftype) {
2218 if (creature == wolftype)
2221 if (tutoriallevel != 1) {
2222 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2224 if (creature == wolftype) {
2225 emit_sound_at(clawslicesound, victim->coords, 128.);
2227 victim->DoBloodBig(2 / victim->armorhead, 175);
2231 relative = victim->coords - coords;
2233 Normalise(&relative);
2234 relative = DoRotation(relative, 0, -90, 0);
2235 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2236 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2238 victim->jointVel(head) += relative * damagemult * 200;
2241 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2247 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2248 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2252 if (Random() % 2 || creature == wolftype) {
2254 if (creature == wolftype)
2257 emit_sound_at(whooshhitsound, victim->coords);
2258 if (creature == wolftype) {
2259 emit_sound_at(clawslicesound, victim->coords, 128.);
2261 victim->DoBloodBig(2, 175);
2265 relative = victim->coords - coords;
2267 Normalise(&relative);
2269 Normalise(&relative);
2270 relative = DoRotation(relative, 0, 90, 0);
2271 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2272 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2274 victim->jointVel(head) += relative * damagemult * 100;
2277 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2281 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2282 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2288 if (tutoriallevel != 1) {
2289 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2291 if (creature == wolftype) {
2292 emit_sound_at(clawslicesound, victim->coords, 128.);
2294 victim->DoBloodBig(2 / victim->armorhead, 175);
2300 Normalise(&relative);
2301 relative = DoRotation(relative, 0, -90, 0);
2302 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2303 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2305 victim->jointVel(head) += relative * damagemult * 200;
2308 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2310 if (victim->damage > victim->damagetolerance)
2311 award_bonus(id, style);
2317 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2318 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2324 if (tutoriallevel != 1) {
2325 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2327 if (creature == wolftype) {
2328 emit_sound_at(clawslicesound, victim->coords, 128.);
2330 victim->DoBloodBig(2 / victim->armorhead, 175);
2336 Normalise(&relative);
2337 relative = DoRotation(relative, 0, 90, 0);
2338 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2339 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2341 victim->jointVel(head) += relative * damagemult * 200;
2344 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2346 if (victim->damage > victim->damagetolerance)
2347 award_bonus(id, style);
2353 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2354 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2362 emit_sound_at(whooshhitsound, victim->coords);
2365 relative = victim->coords - coords;
2367 Normalise(&relative);
2368 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2369 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2371 victim->jointVel(head) += relative * damagemult * 100;
2374 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2378 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2379 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2383 emit_sound_at(whooshhitsound, victim->coords, 128.);
2385 victim->skeleton.longdead = 0;
2386 victim->skeleton.free = 1;
2387 victim->skeleton.broken = 0;
2388 victim->skeleton.spinny = 1;
2390 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2391 victim->skeleton.joints[i].velchange = 0;
2392 victim->skeleton.joints[i].delay = 0;
2393 victim->skeleton.joints[i].locked = 0;
2394 //victim->skeleton.joints[i].velocity=0;
2400 Normalise(&relative);
2401 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2402 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2403 victim->skeleton.joints[i].position.y += relative.y * .3;
2404 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2405 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2407 victim->Puff(abdomen);
2408 victim->jointVel(abdomen).y = relative.y * 400;
2412 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2413 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2417 if (tutoriallevel != 1) {
2418 emit_sound_at(heavyimpactsound, coords, 128.);
2421 relative = victim->coords - coords;
2423 Normalise(&relative);
2424 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2425 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2427 victim->Puff(abdomen);
2428 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2432 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2433 victim->jointVel(abdomen) += relative * damagemult * 300;
2437 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2438 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2442 if (tutoriallevel != 1) {
2443 emit_sound_at(thudsound, coords);
2446 victim->skeleton.longdead = 0;
2447 victim->skeleton.free = 1;
2448 victim->skeleton.broken = 0;
2449 victim->skeleton.spinny = 1;
2451 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2452 victim->skeleton.joints[i].velchange = 0;
2453 //victim->skeleton.joints[i].delay=0;
2454 victim->skeleton.joints[i].locked = 0;
2457 relative = victim->coords - coords;
2458 Normalise(&relative);
2460 Normalise(&relative);
2461 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2462 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2467 victim->Puff(abdomen);
2468 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2469 victim->jointVel(abdomen) += relative * damagemult * 200;
2478 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2481 if (!victim->skeleton.free)
2485 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2486 emit_sound_at(knifesheathesound, coords, 128.);
2489 if (victim && hasvictim) {
2490 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2492 XYZ where, startpoint, endpoint, movepoint, colpoint;
2493 float rotationpoint;
2495 if (weapons[weaponids[weaponactive]].getType() == knife) {
2496 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2497 where -= victim->coords;
2498 if (!victim->skeleton.free)
2499 where = DoRotation(where, 0, -victim->yaw, 0);
2502 startpoint.y += 100;
2506 if (weapons[weaponids[weaponactive]].getType() == sword) {
2507 where = weapons[weaponids[weaponactive]].position;
2508 where -= victim->coords;
2509 if (!victim->skeleton.free)
2510 where = DoRotation(where, 0, -victim->yaw, 0);
2512 where = weapons[weaponids[weaponactive]].tippoint;
2513 where -= victim->coords;
2514 if (!victim->skeleton.free)
2515 where = DoRotation(where, 0, -victim->yaw, 0);
2518 if (weapons[weaponids[weaponactive]].getType() == staff) {
2519 where = weapons[weaponids[weaponactive]].position;
2520 where -= victim->coords;
2521 if (!victim->skeleton.free)
2522 where = DoRotation(where, 0, -victim->yaw, 0);
2524 where = weapons[weaponids[weaponactive]].tippoint;
2525 where -= victim->coords;
2526 if (!victim->skeleton.free)
2527 where = DoRotation(where, 0, -victim->yaw, 0);
2532 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2534 if (whichtri != -1) {
2535 if (victim->dead != 2) {
2536 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2538 award_bonus(id, FinishedBonus);
2541 weapons[weaponids[weaponactive]].bloody = 2;
2543 victim->skeleton.longdead = 0;
2544 victim->skeleton.free = 1;
2545 victim->skeleton.broken = 0;
2547 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2548 victim->skeleton.joints[i].velchange = 0;
2549 victim->skeleton.joints[i].locked = 0;
2550 //victim->skeleton.joints[i].velocity=0;
2552 emit_sound_at(fleshstabsound, coords, 128);
2555 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2556 weapons[weaponids[weaponactive]].blooddrip += 5;
2557 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2559 if (whichtri == -1) {
2561 emit_sound_at(knifesheathesound, coords, 128.);
2567 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2569 emit_sound_at(knifedrawsound, coords, 128);
2572 if (victim && hasvictim) {
2573 XYZ footvel, footpoint;
2575 emit_sound_at(fleshstabremovesound, coords, 128.);
2578 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2580 if (weapons[weaponids[weaponactive]].getType() == sword) {
2581 XYZ where, startpoint, endpoint, movepoint;
2582 float rotationpoint;
2585 where = weapons[weaponids[weaponactive]].position;
2586 where -= victim->coords;
2587 if (!victim->skeleton.free)
2588 where = DoRotation(where, 0, -victim->yaw, 0);
2590 where = weapons[weaponids[weaponactive]].tippoint;
2591 where -= victim->coords;
2592 if (!victim->skeleton.free)
2593 where = DoRotation(where, 0, -victim->yaw, 0);
2598 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2599 footpoint += victim->coords;
2601 if (whichtri == -1) {
2602 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2605 if (weapons[weaponids[weaponactive]].getType() == staff) {
2606 XYZ where, startpoint, endpoint, movepoint;
2607 float rotationpoint;
2610 where = weapons[weaponids[weaponactive]].position;
2611 where -= victim->coords;
2612 if (!victim->skeleton.free)
2613 where = DoRotation(where, 0, -victim->yaw, 0);
2615 where = weapons[weaponids[weaponactive]].tippoint;
2616 where -= victim->coords;
2617 if (!victim->skeleton.free)
2618 where = DoRotation(where, 0, -victim->yaw, 0);
2623 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2624 footpoint += victim->coords;
2626 if (whichtri == -1) {
2627 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2630 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2632 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2633 victim->skeleton.longdead = 0;
2634 victim->skeleton.free = 1;
2635 victim->skeleton.broken = 0;
2637 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2638 victim->skeleton.joints[i].velchange = 0;
2639 victim->skeleton.joints[i].locked = 0;
2640 //victim->skeleton.joints[i].velocity=0;
2646 Normalise(&relative);
2647 //victim->Puff(abdomen);
2649 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2651 if (victim->bloodloss < victim->damagetolerance) {
2652 victim->bloodloss += 1000;
2656 victim->jointVel(abdomen) += relative * damagemult * 20;
2660 if (!hasvictim && onterrain) {
2661 weapons[weaponids[weaponactive]].bloody = 0;
2662 weapons[weaponids[weaponactive]].blooddrip = 0;
2666 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2667 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2675 if (tutoriallevel != 1) {
2676 emit_sound_at(heavyimpactsound, victim->coords, 128);
2681 relative = victim->coords - coords;
2683 Normalise(&relative);
2684 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2685 victim->skeleton.joints[i].velocity = relative * 30;
2687 victim->jointVel(head) += relative * damagemult * 150;
2689 victim->frameTarget = 0;
2690 victim->animTarget = staggerbackhardanim;
2691 victim->targetyaw = targetyaw + 180;
2693 victim->stunned = 1;
2696 victim->Puff(abdomen);
2697 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2704 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2705 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2709 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2710 if (tutoriallevel != 1) {
2711 emit_sound_at(thudsound, victim->coords);
2713 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2714 if (tutoriallevel != 1) {
2715 emit_sound_at(whooshhitsound, victim->coords);
2718 if (tutoriallevel != 1) {
2719 emit_sound_at(heavyimpactsound, victim->coords);
2723 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2726 relative = victim->coords - coords;
2728 Normalise(&relative);
2730 Normalise(&relative);
2731 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2732 victim->skeleton.joints[i].velocity = relative * 5;
2734 victim->jointVel(abdomen) += relative * damagemult * 400;
2736 victim->frameTarget = 0;
2737 victim->animTarget = staggerbackhardanim;
2738 victim->targetyaw = targetyaw + 180;
2740 victim->stunned = 1;
2742 victim->Puff(abdomen);
2743 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2749 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2750 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2751 if (victim->id == 0)
2753 emit_sound_at(landsound2, victim->coords);
2759 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2760 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2761 if (victim->id == 0)
2764 if (weaponactive != -1) {
2765 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2766 if (weapons[victim->weaponids[0]].getType() == staff)
2767 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2768 if (weapons[weaponids[0]].getType() == staff)
2769 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2771 emit_sound_at(swordstaffsound, victim->coords);
2773 emit_sound_at(metalhitsound, victim->coords);
2781 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2782 if (weaponactive != -1) {
2785 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);
2787 weapons[weaponids[0]].thrown(aim * 50);
2790 weaponids[0] = weaponids[num_weapons];
2796 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2798 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2800 if (tutoriallevel != 1)
2801 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2803 award_bonus(id, Slicebonus);
2804 if (tutoriallevel != 1) {
2805 emit_sound_at(knifeslicesound, victim->coords);
2807 //victim->jointVel(abdomen)+=relative*damagemult*200;
2808 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2809 if (victim->id != 0 || difficulty == 2) {
2810 victim->frameTarget = 0;
2811 victim->animTarget = staggerbackhardanim;
2812 victim->targetyaw = targetyaw + 180;
2816 victim->lowreversaldelay = 0;
2817 victim->highreversaldelay = 0;
2818 if (aitype != playercontrolled)
2819 weaponmissdelay = .6;
2821 if (tutoriallevel != 1)
2822 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2823 weapons[weaponids[weaponactive]].bloody = 1;
2824 if (tutoriallevel != 1)
2825 weapons[weaponids[weaponactive]].blooddrip += 3;
2827 XYZ footvel, footpoint;
2829 if (skeleton.free) {
2830 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2832 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2834 if (tutoriallevel != 1) {
2836 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2837 footvel = DoRotation(facing, 0, 90, 0) * .8;
2839 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2840 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2841 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2842 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2844 if (tutoriallevel == 1) {
2845 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2847 victim->DoDamage(damagemult * 0);
2850 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2851 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2852 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2853 award_bonus(id, Slashbonus);
2855 if (tutoriallevel != 1) {
2856 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2857 victim->DoBloodBig(2 / victim->armorhigh, 190);
2859 victim->DoBloodBig(2 / victim->armorhigh, 185);
2860 victim->deathbleeding = 1;
2861 emit_sound_at(swordslicesound, victim->coords);
2863 //victim->jointVel(abdomen)+=relative*damagemult*200;
2864 if (tutoriallevel != 1) {
2865 victim->frameTarget = 0;
2866 victim->animTarget = staggerbackhardanim;
2867 victim->targetyaw = targetyaw + 180;
2871 if (tutoriallevel != 1) {
2872 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2873 weapons[weaponids[weaponactive]].bloody = 1;
2874 weapons[weaponids[weaponactive]].blooddrip += 3;
2876 float bloodlossamount;
2877 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2878 victim->bloodloss += bloodlossamount / victim->armorhigh;
2879 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2880 victim->DoDamage(damagemult * 0);
2882 XYZ footvel, footpoint;
2884 if (skeleton.free) {
2885 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2887 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2890 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2891 footvel = DoRotation(facing, 0, 90, 0) * .8;
2893 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2894 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2895 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2896 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2899 if (victim->weaponactive != -1) {
2900 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2901 if (weapons[victim->weaponids[0]].getType() == staff)
2902 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2903 if (weapons[weaponids[0]].getType() == staff)
2904 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2906 emit_sound_at(swordstaffsound, victim->coords);
2908 emit_sound_at(metalhitsound, victim->coords);
2914 victim->Puff(righthand);
2916 victim->frameTarget = 0;
2917 victim->animTarget = staggerbackhighanim;
2918 victim->targetyaw = targetyaw + 180;
2920 aim = DoRotation(facing, 0, 90, 0) * 21;
2922 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2923 victim->num_weapons--;
2924 if (victim->num_weapons) {
2925 victim->weaponids[0] = victim->weaponids[num_weapons];
2926 if (victim->weaponstuck == victim->num_weapons)
2927 victim->weaponstuck = 0;
2929 victim->weaponactive = -1;
2930 for (unsigned i = 0; i < Person::players.size(); i++) {
2931 Person::players[i]->wentforweapon = 0;
2938 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2939 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2940 if (tutoriallevel != 1) {
2941 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2945 if (Random() % 2 || creature == wolftype) {
2948 emit_sound_at(staffheadsound, victim->coords);
2952 relative = victim->coords - coords;
2954 Normalise(&relative);
2955 relative = DoRotation(relative, 0, 90, 0);
2957 Normalise(&relative);
2958 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2959 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2961 victim->jointVel(head) += relative * damagemult * 230;
2962 victim->jointVel(neck) += relative * damagemult * 230;
2965 if (tutoriallevel != 1) {
2966 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2968 award_bonus(id, solidhit, 30);
2973 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2974 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2975 if (tutoriallevel != 1) {
2976 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2980 if (Random() % 2 || creature == wolftype) {
2983 emit_sound_at(staffheadsound, victim->coords);
2987 relative = victim->coords - coords;
2989 Normalise(&relative);
2990 relative = DoRotation(relative, 0, -90, 0);
2991 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2992 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2994 victim->jointVel(head) += relative * damagemult * 220;
2995 victim->jointVel(neck) += relative * damagemult * 220;
2998 if (tutoriallevel != 1) {
2999 victim->DoDamage(damagemult * 350 / victim->protectionhead);
3001 award_bonus(id, solidhit, 60);
3006 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
3007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
3009 if (tutoriallevel != 1) {
3011 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
3014 if (Random() % 2 || creature == wolftype) {
3017 emit_sound_at(staffbodysound, victim->coords);
3019 victim->skeleton.longdead = 0;
3020 victim->skeleton.free = 1;
3021 victim->skeleton.broken = 0;
3023 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3024 victim->skeleton.joints[i].velchange = 0;
3025 victim->skeleton.joints[i].locked = 0;
3026 //victim->skeleton.joints[i].velocity=0;
3032 /*relative=victim->coords-coords;
3034 Normalise(&relative);
3035 relative=DoRotation(relative,0,90,0);*/
3037 Normalise(&relative);
3038 if (!victim->dead) {
3039 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3040 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
3043 victim->jointVel(abdomen) += relative * damagemult * 40;
3046 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3047 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
3050 //victim->jointVel(abdomen)+=relative*damagemult*20;
3052 victim->Puff(abdomen);
3053 if (tutoriallevel != 1) {
3054 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
3056 if (!victim->dead) {
3057 award_bonus(id, solidhit, 40);
3063 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
3064 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
3069 relative = victim->coords - coords;
3071 Normalise(&relative);
3075 if (animation[victim->animTarget].height == lowheight) {
3081 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3082 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3084 victim->jointVel(head) += relative * damagemult * 200;
3085 if (tutoriallevel != 1) {
3086 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3089 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3090 if (victim->howactive == typesleeping)
3091 victim->DoDamage(damagemult * 150 / victim->protectionhead);
3092 if (creature == wolftype) {
3093 emit_sound_at(clawslicesound, victim->coords, 128.);
3095 victim->DoBloodBig(2 / victim->armorhead, 175);
3098 if (victim->damage >= victim->damagetolerance)
3100 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3101 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3103 victim->jointVel(abdomen) += relative * damagemult * 200;
3104 victim->frameTarget = 0;
3105 victim->animTarget = staggerbackhighanim;
3106 victim->targetyaw = targetyaw + 180;
3108 if (tutoriallevel != 1) {
3109 emit_sound_at(landsound2, victim->coords, 128.);
3111 victim->Puff(abdomen);
3112 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3113 if (creature == wolftype) {
3114 emit_sound_at(clawslicesound, victim->coords, 128.);
3116 victim->DoBloodBig(2 / victim->armorhigh, 170);
3123 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
3124 if ((victim->animTarget != jumpupanim) &&
3125 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
3126 (victim != this->shared_from_this())) {
3130 if (tutoriallevel != 1) {
3131 emit_sound_at(landsound2, victim->coords, 128.);
3134 relative = victim->coords - coords;
3136 Normalise(&relative);
3138 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
3141 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3142 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
3144 relative = DoRotation(relative, 0, -90, 0);
3146 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3147 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)
3148 victim->skeleton.joints[i].velocity = relative * 80;
3150 victim->Puff(rightankle);
3151 victim->Puff(leftankle);
3152 victim->DoDamage(damagemult * 40 / victim->protectionlow);
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 relative = DoRotation(relative, 0, -90, 0);
3160 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3161 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)
3162 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3164 victim->jointVel(abdomen) += relative * damagemult * 200;
3165 victim->frameTarget = 0;
3166 victim->animTarget = staggerbackhighanim;
3167 victim->targetyaw = targetyaw + 180;
3169 if (tutoriallevel != 1) {
3170 emit_sound_at(landsound2, victim->coords, 128.);
3172 victim->Puff(abdomen);
3173 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3181 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3182 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3190 if (tutoriallevel != 1) {
3191 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3193 if (creature == wolftype) {
3194 emit_sound_at(clawslicesound, victim->coords, 128);
3196 victim->DoBloodBig(2 / victim->armorhigh, 170);
3200 relative = victim->coords - oldcoords;
3202 Normalise(&relative);
3203 //relative=DoRotation(relative,0,-90,0);
3204 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3205 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3207 victim->jointVel(abdomen) += relative * damagemult * 200;
3209 victim->Puff(abdomen);
3210 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3212 award_bonus(id, Reversal);
3215 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3216 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3217 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3218 takeWeapon(victim->weaponids[victim->weaponactive]);
3219 victim->num_weapons--;
3220 if (victim->num_weapons > 0) {
3221 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3223 victim->weaponactive = -1;
3228 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3236 emit_sound_at(whooshhitsound, victim->coords, 128.);
3239 relative = victim->coords - oldcoords;
3241 Normalise(&relative);
3242 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3243 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3245 victim->jointVel(abdomen) += relative * damagemult * 200;
3247 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3250 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3259 award_bonus(id, staffreversebonus);
3261 if (tutoriallevel != 1) {
3262 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3265 award_bonus(id, staffreversebonus); // Huh, again?
3268 relative = victim->coords - oldcoords;
3270 Normalise(&relative);
3271 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3272 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3274 victim->jointVel(abdomen) += relative * damagemult * 200;
3276 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3279 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3285 Normalise(&relative);
3287 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3288 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3290 victim->jointVel(lefthand) *= .1;
3291 victim->jointVel(leftwrist) *= .2;
3292 victim->jointVel(leftelbow) *= .5;
3293 victim->jointVel(leftshoulder) *= .7;
3294 victim->jointVel(righthand) *= .1;
3295 victim->jointVel(rightwrist) *= .2;
3296 victim->jointVel(rightelbow) *= .5;
3297 victim->jointVel(rightshoulder) *= .7;
3299 victim->Puff(abdomen);
3300 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3302 award_bonus(id, Reversal);
3306 if (weaponactive != -1 || creature == wolftype)
3308 if (creature == rabbittype && weaponactive != -1)
3309 if (weapons[weaponids[0]].getType() == staff)
3312 if (weaponactive != -1) {
3313 victim->DoBloodBig(2 / victim->armorhigh, 225);
3314 emit_sound_at(knifeslicesound, victim->coords);
3315 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3316 weapons[weaponids[weaponactive]].bloody = 1;
3317 weapons[weaponids[weaponactive]].blooddrip += 3;
3319 if (weaponactive == -1 && creature == wolftype) {
3320 emit_sound_at(clawslicesound, victim->coords, 128.);
3322 victim->DoBloodBig(2 / victim->armorhigh, 175);
3329 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3335 Normalise(&relative);
3337 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3338 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3340 victim->jointVel(lefthand) *= .1 - 1;
3341 victim->jointVel(leftwrist) *= .2 - 1;
3342 victim->jointVel(leftelbow) *= .5 - 1;
3343 victim->jointVel(leftshoulder) *= .7 - 1;
3344 victim->jointVel(righthand) *= .1 - 1;
3345 victim->jointVel(rightwrist) *= .2 - 1;
3346 victim->jointVel(rightelbow) *= .5 - 1;
3347 victim->jointVel(rightshoulder) *= .7 - 1;
3349 award_bonus(id, swordreversebonus);
3352 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3360 if (tutoriallevel != 1) {
3361 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3365 relative = victim->coords - oldcoords;
3367 Normalise(&relative);
3368 relative = DoRotation(relative, 0, -90, 0);
3369 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3370 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3372 victim->jointVel(abdomen) += relative * damagemult * 200;
3373 victim->Puff(abdomen);
3374 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3376 award_bonus(id, Reversal);
3379 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3382 victim->skeleton.spinny = 0;
3384 relative = facing * -1;
3386 Normalise(&relative);
3387 if (victim->id == 0)
3389 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3390 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3392 victim->damage = victim->damagetolerance;
3393 victim->permanentdamage = victim->damagetolerance - 1;
3396 if (weaponactive != -1 || creature == wolftype)
3398 if (creature == rabbittype && weaponactive != -1)
3399 if (weapons[weaponids[0]].getType() == staff)
3402 if (weaponactive != -1) {
3403 victim->DoBloodBig(200, 225);
3404 emit_sound_at(knifeslicesound, victim->coords);
3406 weapons[weaponids[weaponactive]].bloody = 2;
3407 weapons[weaponids[weaponactive]].blooddrip += 5;
3410 if (creature == wolftype && weaponactive == -1) {
3411 emit_sound_at(clawslicesound, victim->coords, 128.);
3413 victim->DoBloodBig(2, 175);
3416 award_bonus(id, spinecrusher);
3419 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3420 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3422 if (animTarget == knifefollowanim)
3423 victim->DoBloodBig(200, 210);
3424 if (animTarget == knifesneakattackanim) {
3425 XYZ footvel, footpoint;
3427 footpoint = weapons[weaponids[0]].tippoint;
3429 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3430 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3431 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3432 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3433 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3434 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3435 victim->DoBloodBig(200, 195);
3436 award_bonus(id, tracheotomy);
3438 if (animTarget == knifefollowanim) {
3439 award_bonus(id, Stabbonus);
3440 XYZ footvel, footpoint;
3442 footpoint = weapons[weaponids[0]].tippoint;
3444 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3445 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3446 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3447 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3448 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3449 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3452 victim->bloodloss += 10000;
3453 victim->velocity = 0;
3454 emit_sound_at(fleshstabsound, victim->coords);
3456 weapons[weaponids[weaponactive]].bloody = 2;
3457 weapons[weaponids[weaponactive]].blooddrip += 5;
3461 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3463 victim->velocity = 0;
3464 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3465 victim->skeleton.joints[i].velocity = 0;
3467 if (animTarget == knifefollowanim) {
3469 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3470 victim->skeleton.joints[i].velocity = 0;
3473 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3474 emit_sound_at(fleshstabremovesound, victim->coords);
3476 weapons[weaponids[weaponactive]].bloody = 2;
3477 weapons[weaponids[weaponactive]].blooddrip += 5;
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) * -1;
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);
3492 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3493 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3494 award_bonus(id, backstab);
3498 XYZ footvel, footpoint;
3500 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3502 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3503 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3504 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3505 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3506 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3507 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3508 victim->DoBloodBig(200, 180);
3509 victim->DoBloodBig(200, 215);
3510 victim->bloodloss += 10000;
3511 victim->velocity = 0;
3512 emit_sound_at(fleshstabsound, victim->coords);
3514 weapons[weaponids[weaponactive]].bloody = 2;
3515 weapons[weaponids[weaponactive]].blooddrip += 5;
3519 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3521 victim->velocity = 0;
3522 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3523 victim->skeleton.joints[i].velocity = 0;
3525 if (weaponactive != -1) {
3526 emit_sound_at(fleshstabremovesound, victim->coords);
3528 weapons[weaponids[weaponactive]].bloody = 2;
3529 weapons[weaponids[weaponactive]].blooddrip += 5;
3531 XYZ footvel, footpoint;
3533 footpoint = weapons[weaponids[0]].tippoint;
3535 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3536 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3537 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3538 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3539 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3540 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3544 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3552 if (weaponactive == -1) {
3553 if (tutoriallevel != 1) {
3554 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3559 if (weaponactive != -1 || creature == wolftype)
3561 if (creature == rabbittype && weaponactive != -1)
3562 if (weapons[weaponids[0]].getType() == staff)
3565 if (weaponactive != -1) {
3566 victim->DoBloodBig(2 / victim->armorhead, 225);
3567 emit_sound_at(knifeslicesound, victim->coords);
3568 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3569 weapons[weaponids[weaponactive]].bloody = 1;
3570 weapons[weaponids[weaponactive]].blooddrip += 3;
3572 if (weaponactive == -1 && creature == wolftype) {
3573 emit_sound_at(clawslicesound, victim->coords, 128.);
3575 victim->DoBloodBig(2 / victim->armorhead, 175);
3579 award_bonus(id, Reversal);
3584 relative = facing * -1;
3586 Normalise(&relative);
3587 relative = DoRotation(relative, 0, 90, 0);
3589 Normalise(&relative);
3590 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3591 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3593 victim->jointVel(head) += relative * damagemult * 200;
3594 if (victim->damage < victim->damagetolerance - 100)
3595 victim->velocity = relative * 200;
3596 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3597 victim->velocity = 0;
3600 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3604 relative = facing * -1;
3606 Normalise(&relative);
3607 relative = DoRotation(relative, 0, 90, 0);
3609 Normalise(&relative);
3610 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3611 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3613 victim->jointVel(head) += relative * damagemult * 200;
3616 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3617 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3618 award_bonus(id, reverseko);
3624 if (frameTarget > animation[animCurrent].numframes - 1) {
3627 animTarget = getIdle();
3631 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3632 animTarget = rollanim;
3634 emit_sound_at(movewhooshsound, coords, 128.);
3636 if (animCurrent == staggerbackhighanim) {
3637 animTarget = getIdle();
3639 if (animCurrent == staggerbackhardanim) {
3640 animTarget = getIdle();
3642 if (animCurrent == removeknifeanim) {
3643 animTarget = getIdle();
3645 if (animCurrent == crouchremoveknifeanim) {
3646 animTarget = getCrouch();
3648 if (animCurrent == backhandspringanim) {
3649 animTarget = getIdle();
3651 if (animCurrent == dodgebackanim) {
3652 animTarget = getIdle();
3654 if (animCurrent == drawleftanim) {
3655 animTarget = getIdle();
3657 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3658 animTarget = getIdle();
3659 if (animCurrent == crouchdrawrightanim) {
3660 animTarget = getCrouch();
3662 if (weaponactive == -1)
3664 else if (weaponactive == 0) {
3666 if (num_weapons == 2) {
3668 buffer = weaponids[0];
3669 weaponids[0] = weaponids[1];
3670 weaponids[1] = buffer;
3674 if (weaponactive == -1) {
3675 emit_sound_at(knifesheathesound, coords, 128.);
3677 if (weaponactive != -1) {
3678 emit_sound_at(knifedrawsound, coords, 128.);
3681 if (animCurrent == rollanim) {
3682 animTarget = getCrouch();
3687 if (animTarget == walljumprightkickanim) {
3690 if (animTarget == walljumpleftkickanim) {
3693 animTarget = jumpdownanim;
3695 if (animCurrent == climbanim) {
3696 animTarget = getCrouch();
3698 coords += facing * .1;
3699 if (!isnormal(coords.x))
3710 if (animTarget == rabbitkickreversalanim) {
3711 animTarget = getCrouch();
3714 if (animTarget == jumpreversalanim) {
3715 animTarget = getCrouch();
3718 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3719 if (attackkeydown && animTarget != walljumpfrontanim) {
3721 float closestdist = -1;
3723 if (Person::players.size() > 1)
3724 for (unsigned i = 0; i < Person::players.size(); i++) {
3725 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3726 distance = distsq(&Person::players[i]->coords, &coords);
3727 if (closestdist == -1 || distance < closestdist) {
3728 closestdist = distance;
3733 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3734 victim = Person::players[closest];
3735 animTarget = walljumprightkickanim;
3737 XYZ rotatetarget = victim->coords - coords;
3738 Normalise(&rotatetarget);
3739 yaw = -asin(0 - rotatetarget.x);
3741 if (rotatetarget.z < 0)
3743 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3744 velocity = (victim->coords - coords) * 4;
3749 if (animTarget == walljumpbackanim) {
3750 animTarget = backflipanim;
3752 velocity = facing * -8;
3755 resume_stream(whooshsound);
3757 if (animTarget == walljumprightanim) {
3758 animTarget = rightflipanim;
3762 velocity = DoRotation(facing, 0, 30, 0) * -8;
3765 if (animTarget == walljumpfrontanim) {
3766 animTarget = frontflipanim;
3770 velocity = facing * 8;
3774 resume_stream(whooshsound);
3776 if (animTarget == walljumpleftanim) {
3777 if (attackkeydown) {
3779 float closestdist = -1;
3781 if (Person::players.size() > 1)
3782 for (unsigned i = 0; i < Person::players.size(); i++) {
3783 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3784 distance = distsq(&Person::players[i]->coords, &coords);
3785 if (closestdist == -1 || distance < closestdist) {
3786 closestdist = distance;
3791 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3792 victim = Person::players[closest];
3793 animTarget = walljumpleftkickanim;
3795 XYZ rotatetarget = victim->coords - coords;
3796 Normalise(&rotatetarget);
3797 yaw = -asin(0 - rotatetarget.x);
3799 if (rotatetarget.z < 0)
3801 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3802 velocity = (victim->coords - coords) * 4;
3807 if (animTarget != walljumpleftkickanim) {
3808 animTarget = leftflipanim;
3812 velocity = DoRotation(facing, 0, -30, 0) * -8;
3816 resume_stream(whooshsound);
3818 if (animTarget == sneakattackanim) {
3819 animCurrent = getCrouch();
3820 animTarget = getCrouch();
3827 transspeed = 1000000;
3828 targetheadyaw += 180;
3829 coords -= facing * .7;
3831 coords.y = terrain.getHeight(coords.x, coords.z);
3835 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3836 animTarget = getIdle();
3839 coords.y = terrain.getHeight(coords.x, coords.z);
3843 if (animCurrent == knifefollowanim) {
3844 animTarget = getIdle();
3847 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3848 float ycoords = oldcoords.y;
3849 animTarget = getStop();
3854 transspeed = 1000000;
3855 targetheadyaw += 180;
3856 if (!isnormal(coords.x))
3858 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3859 oldcoords = coords + facing * .5;
3860 else if (animCurrent == sweepreversalanim)
3861 oldcoords = coords + facing * 1.1;
3862 else if (animCurrent == upunchreversalanim) {
3863 oldcoords = coords + facing * 1.5;
3866 targetheadyaw += 180;
3869 } else if (animCurrent == knifeslashreversalanim) {
3870 oldcoords = coords + facing * .5;
3873 targetheadyaw += 90;
3876 } else if (animCurrent == staffspinhitreversalanim) {
3879 targetheadyaw += 180;
3884 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3886 oldcoords.y = ycoords;
3887 currentoffset = coords - oldcoords;
3893 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3898 if (animation[animTarget].attack == reversed) {
3900 if (animTarget == sweepreversedanim)
3902 animTarget = backhandspringanim;
3904 emit_sound_at(landsound, coords, 128);
3906 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3907 animTarget = rollanim;
3910 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3911 coords.y = oldcoords.y;
3913 if (animCurrent == knifeslashreversedanim) {
3914 animTarget = rollanim;
3919 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3920 coords.y = oldcoords.y;
3924 animTarget = jumpdownanim;
3927 animTarget = getIdle();
3929 animTarget = getIdle();
3930 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3931 animTarget = getIdle();
3933 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3934 coords.y = oldcoords.y;
3935 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3936 targetoffset.y = coords.y;
3938 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3939 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3940 currentoffset.y -= (coords.y - targetoffset.y);
3941 coords.y = targetoffset.y;
3943 normalsupdatedelay = 0;
3945 if (animCurrent == upunchanim) {
3946 animTarget = getStop();
3947 normalsupdatedelay = 0;
3950 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3954 if (num_weapons > 0)
3955 if (weapons[0].getType() == staff)
3961 rabbitkickragdoll = 1;
3963 if (animCurrent == rabbitkickreversedanim) {
3969 skeleton.spinny = 0;
3970 SolidHitBonus(!id); // FIXME: tricky id
3974 animTarget = rollanim;
3977 pause_sound(whooshsound);
3981 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3985 skeleton.spinny = 0;
3987 if (animCurrent == jumpreversedanim) {
3993 skeleton.spinny = 0;
3994 SolidHitBonus(!id); // FIXME: tricky id
3998 animTarget = rollanim;
3999 coords += facing * 2;
4001 pause_sound(whooshsound);
4006 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) {
4007 animTarget = getupfromfrontanim;
4009 } else if (animation[animCurrent].attack == normalattack) {
4010 animTarget = getIdle();
4013 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
4014 animTarget = blockhighleftstrikeanim;
4016 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
4017 animTarget = getIdle();
4020 if (animCurrent == spinkickanim && victim->skeleton.free) {
4021 if (creature == rabbittype)
4022 animTarget = fightidleanim;
4027 if (isIdle() && !wasIdle())
4028 normalsupdatedelay = 0;
4030 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
4031 animTarget = jumpdownanim;
4034 if (!skeleton.free) {
4036 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
4037 if (!isRun() || !wasRun()) {
4038 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4039 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
4040 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4041 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
4043 if (isRun() && wasRun()) {
4045 tempspeed = velspeed;
4046 if (tempspeed < 10 * speedmult)
4047 tempspeed = 10 * speedmult;
4048 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
4050 } else if (transspeed)
4051 target += multiplier * transspeed * speed * 2;
4053 if (!isRun() || !wasRun()) {
4054 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
4055 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
4056 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
4057 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
4061 if (animCurrent != animTarget)
4062 target = (target + oldtarget) / 2;
4065 frameCurrent = frameTarget;
4069 rot = targetrot * target;
4070 yaw += rot - oldrot;
4076 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
4078 for (int i = 0; i < skeleton.num_joints; i++) {
4079 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
4082 skeleton.FindForwards();
4084 for (int i = 0; i < skeleton.num_muscles; i++) {
4085 if (skeleton.muscles[i].visible) {
4086 skeleton.FindRotationMuscle(i, animTarget);
4089 for (int i = 0; i < skeleton.num_muscles; i++) {
4090 if (skeleton.muscles[i].visible) {
4091 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4092 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4093 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4094 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4095 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4096 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4101 for (int i = 0; i < skeleton.num_joints; i++) {
4102 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
4105 skeleton.FindForwards();
4107 for (int i = 0; i < skeleton.num_muscles; i++) {
4108 if (skeleton.muscles[i].visible) {
4109 skeleton.FindRotationMuscle(i, animTarget);
4112 for (int i = 0; i < skeleton.num_muscles; i++) {
4113 if (skeleton.muscles[i].visible) {
4114 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
4115 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
4116 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
4117 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
4118 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
4119 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
4120 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
4121 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
4122 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
4123 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
4124 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
4125 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
4129 if (frameCurrent >= animation[animCurrent].numframes)
4130 frameCurrent = animation[animCurrent].numframes - 1;
4132 oldanimCurrent = animCurrent;
4133 oldanimTarget = animTarget;
4134 oldframeTarget = frameTarget;
4135 oldframeCurrent = frameCurrent;
4137 for (int i = 0; i < skeleton.num_joints; i++) {
4138 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
4139 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4141 offset = currentoffset * (1 - target) + targetoffset * target;
4142 for (int i = 0; i < skeleton.num_muscles; i++) {
4143 if (skeleton.muscles[i].visible) {
4144 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4145 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4146 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4151 if (isLanding() && landhard) {
4154 animTarget = getLandhard();
4167 void Person::DoStuff()
4169 static XYZ terrainnormal;
4170 static XYZ flatfacing;
4171 static XYZ flatvelocity;
4172 static float flatvelspeed;
4176 static int bloodsize;
4177 static int startx, starty, endx, endy;
4178 static GLubyte color;
4179 static XYZ bloodvel;
4181 onfiredelay -= multiplier;
4182 if (onfiredelay < 0 && onfire) {
4183 if (Random() % 2 == 0) {
4189 crouchkeydowntime += multiplier;
4191 crouchkeydowntime = 0;
4192 jumpkeydowntime += multiplier;
4193 if (!jumpkeydown && skeleton.free)
4194 jumpkeydowntime = 0;
4196 if (hostile || damage > 0 || bloodloss > 0)
4199 if (isIdle() || isRun())
4202 if (num_weapons == 1 && weaponactive != -1)
4206 blooddimamount -= multiplier * .3;
4207 speechdelay -= multiplier;
4208 texupdatedelay -= multiplier;
4209 interestdelay -= multiplier;
4210 flamedelay -= multiplier;
4211 parriedrecently -= multiplier;
4213 victim = this->shared_from_this();
4218 speed = 1.1 * speedmult;
4220 speed = 1.0 * speedmult;
4222 rabbitkickragdoll = 0;
4226 if (id != 0 && (creature == rabbittype || difficulty != 2))
4228 if (id != 0 && creature == wolftype && difficulty == 2) {
4230 if (aitype != passivetype) {
4232 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) {
4238 if (animTarget == wolfrunninganim && !superruntoggle) {
4239 animTarget = getRun();
4243 if (weaponactive == -1 && num_weapons > 0) {
4244 if (weapons[weaponids[0]].getType() == staff) {
4250 burnt += multiplier;
4254 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4256 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4262 vel[0] = velocity.x;
4263 vel[1] = velocity.y;
4264 vel[2] = velocity.z;
4267 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4268 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4272 while (flamedelay < 0 && onfire) {
4274 howmany = abs(Random() % (skeleton.num_joints));
4275 if (skeleton.free) {
4276 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4277 flatfacing = skeleton.joints[howmany].position * scale + coords;
4279 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4280 flatvelocity = (coords - oldcoords) / multiplier / 2;
4282 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4285 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4287 howmany = abs(Random() % (skeleton.num_joints));
4288 if (skeleton.free) {
4289 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4290 flatfacing = skeleton.joints[howmany].position * scale + coords;
4292 flatvelocity = (coords - oldcoords) / multiplier / 2;
4293 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4295 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4299 bleeding -= multiplier * .3;
4300 if (bloodtoggle == 2) {
4301 skeleton.drawmodel.textureptr.bind();
4302 if ((bleeding <= 0) && (detail != 2))
4307 if (neckspurtamount > 0) {
4308 neckspurtamount -= multiplier;
4309 neckspurtdelay -= multiplier * 3;
4310 neckspurtparticledelay -= multiplier * 3;
4311 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4314 if (skeleton.free) {
4315 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4316 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4317 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4319 bloodvel.z = 5 * neckspurtamount;
4320 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4321 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4322 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4324 neckspurtparticledelay = .05;
4326 if (neckspurtdelay < 0) {
4331 if (deathbleeding > 0 && dead != 2) {
4332 if (deathbleeding < 5)
4333 bleeddelay -= deathbleeding * multiplier / 4;
4335 bleeddelay -= 5 * multiplier / 4;
4336 if (bleeddelay < 0 && bloodtoggle) {
4341 if (skeleton.free) {
4342 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4343 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4345 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4346 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4350 bloodloss += deathbleeding * multiplier * 80;
4351 deathbleeding -= multiplier * 1.6;
4352 if (deathbleeding < 0)
4354 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4355 if (weaponactive != -1) {
4356 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4357 weapons[weaponids[0]].velocity.x += .01;
4360 weaponids[0] = weaponids[num_weapons];
4361 if (weaponstuck == num_weapons)
4365 for (unsigned i = 0; i < Person::players.size(); i++) {
4366 Person::players[i]->wentforweapon = 0;
4374 if (!dead && creature == wolftype) {
4375 award_bonus(0, Wolfbonus);
4378 if (animTarget == knifefollowedanim && !skeleton.free) {
4379 for (int i = 0; i < skeleton.num_joints; i++) {
4380 skeleton.joints[i].velocity = 0;
4381 skeleton.joints[i].velocity.y = -2;
4384 if (id != 0 && unconscioustime > .1) {
4392 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4393 texupdatedelay = .12;
4395 bloodsize = 5 - realtexdetail;
4399 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4400 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4401 endx = startx + bloodsize;
4402 endy = starty + bloodsize;
4412 if (endx > skeleton.skinsize - 1) {
4413 endx = skeleton.skinsize - 1;
4416 if (endy > skeleton.skinsize - 1) {
4417 endy = skeleton.skinsize - 1;
4425 for (i = startx; i < endx; i++) {
4426 for (j = starty; j < endy; j++) {
4427 if (Random() % 2 == 0) {
4428 color = Random() % 85 + 170;
4429 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4430 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4431 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4432 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4437 skeleton.drawmodel.textureptr.bind();
4441 if (skeleton.free) {
4442 bleedx += 4 * direction / realtexdetail;
4444 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4446 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4448 bleedy -= 4 / realtexdetail;
4450 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4452 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4456 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4457 righthandmorphness = targetrighthandmorphness;
4458 righthandmorphstart = righthandmorphend;
4459 } else if (righthandmorphness > targetrighthandmorphness) {
4460 righthandmorphness -= multiplier * 4;
4461 } else if (righthandmorphness < targetrighthandmorphness) {
4462 righthandmorphness += multiplier * 4;
4465 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4466 lefthandmorphness = targetlefthandmorphness;
4467 lefthandmorphstart = lefthandmorphend;
4468 } else if (lefthandmorphness > targetlefthandmorphness) {
4469 lefthandmorphness -= multiplier * 4;
4470 } else if (lefthandmorphness < targetlefthandmorphness) {
4471 lefthandmorphness += multiplier * 4;
4474 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4475 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4476 tailmorphness = targettailmorphness;
4477 tailmorphstart = tailmorphend;
4478 } else if (tailmorphness > targettailmorphness) {
4479 tailmorphness -= multiplier * 10;
4480 } else if (tailmorphness < targettailmorphness) {
4481 tailmorphness += multiplier * 10;
4485 if (creature == wolftype) {
4486 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4487 tailmorphness = targettailmorphness;
4488 tailmorphstart = tailmorphend;
4489 } else if (tailmorphness > targettailmorphness) {
4490 tailmorphness -= multiplier * 2;
4491 } else if (tailmorphness < targettailmorphness) {
4492 tailmorphness += multiplier * 2;
4496 if (headmorphend == 3 || headmorphstart == 3) {
4497 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4498 headmorphness = targetheadmorphness;
4499 headmorphstart = headmorphend;
4500 } else if (headmorphness > targetheadmorphness) {
4501 headmorphness -= multiplier * 7;
4502 } else if (headmorphness < targetheadmorphness) {
4503 headmorphness += multiplier * 7;
4505 } else if (headmorphend == 5 || headmorphstart == 5) {
4506 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4507 headmorphness = targetheadmorphness;
4508 headmorphstart = headmorphend;
4509 } else if (headmorphness > targetheadmorphness) {
4510 headmorphness -= multiplier * 10;
4511 } else if (headmorphness < targetheadmorphness) {
4512 headmorphness += multiplier * 10;
4515 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4516 headmorphness = targetheadmorphness;
4517 headmorphstart = headmorphend;
4518 } else if (headmorphness > targetheadmorphness) {
4519 headmorphness -= multiplier * 4;
4520 } else if (headmorphness < targetheadmorphness) {
4521 headmorphness += multiplier * 4;
4525 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4526 chestmorphness = targetchestmorphness;
4527 chestmorphstart = chestmorphend;
4528 } else if (chestmorphness > targetchestmorphness) {
4529 chestmorphness -= multiplier;
4530 } else if (chestmorphness < targetchestmorphness) {
4531 chestmorphness += multiplier;
4534 if (dead != 2 && howactive <= typesleeping) {
4535 if (chestmorphstart == 0 && chestmorphend == 0) {
4537 targetchestmorphness = 1;
4540 if (chestmorphstart != 0 && chestmorphend != 0) {
4542 targetchestmorphness = 1;
4544 if (environment == snowyenvironment) {
4547 if (skeleton.free) {
4548 footvel = skeleton.specialforward[0] * -1;
4549 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4551 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4552 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4554 if (animTarget == sleepanim)
4555 footvel = DoRotation(footvel, 0, 90, 0);
4556 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4560 if (!dead && howactive < typesleeping) {
4561 blinkdelay -= multiplier * 2;
4562 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4564 targetheadmorphness = 1;
4566 blinkdelay = (float)(abs(Random() % 40)) / 5;
4568 if (headmorphstart == 3 && headmorphend == 3) {
4570 targetheadmorphness = 1;
4575 twitchdelay -= multiplier * 1.5;
4576 if (animTarget != hurtidleanim) {
4577 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4579 targetheadmorphness = 1;
4581 twitchdelay = (float)(abs(Random() % 40)) / 5;
4583 if (headmorphstart == 5 && headmorphend == 5) {
4585 targetheadmorphness = 1;
4589 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4590 twitchdelay3 -= multiplier * 1;
4591 if (Random() % 2 == 0) {
4592 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4593 righthandmorphness = 0;
4594 targetrighthandmorphness = 1;
4595 righthandmorphend = 1;
4596 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4598 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4599 righthandmorphness = 0;
4600 targetrighthandmorphness = 1;
4601 righthandmorphend = 0;
4604 if (Random() % 2 == 0) {
4605 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4606 lefthandmorphness = 0;
4607 targetlefthandmorphness = 1;
4608 lefthandmorphend = 1;
4609 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4611 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4612 lefthandmorphness = 0;
4613 targetlefthandmorphness = 1;
4614 lefthandmorphend = 0;
4620 if (creature == rabbittype) {
4621 if (howactive < typesleeping)
4622 twitchdelay2 -= multiplier * 1.5;
4624 twitchdelay2 -= multiplier * 0.5;
4625 if (howactive <= typesleeping) {
4626 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4628 targettailmorphness = 1;
4630 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4632 if (tailmorphstart == 1 && tailmorphend == 1) {
4634 targettailmorphness = 1;
4637 if (tailmorphstart == 2 && tailmorphend == 2) {
4639 targettailmorphness = 1;
4646 if (creature == wolftype) {
4647 twitchdelay2 -= multiplier * 1.5;
4648 if (tailmorphend != 0)
4649 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4651 targettailmorphness = 1;
4655 if (tailmorphend != 5)
4656 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4658 targettailmorphness = 1;
4662 if (twitchdelay2 <= 0) {
4663 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4665 targettailmorphness = 1;
4668 if (tailmorphstart == 1 && tailmorphend == 1) {
4670 targettailmorphness = 1;
4673 if (tailmorphstart == 2 && tailmorphend == 2) {
4675 targettailmorphness = 1;
4678 if (tailmorphstart == 3 && tailmorphend == 3) {
4680 targettailmorphness = 1;
4683 if (tailmorphstart == 4 && tailmorphend == 4) {
4685 targettailmorphness = 1;
4692 unconscioustime = 0;
4694 if (dead == 1 || howactive == typesleeping) {
4695 unconscioustime += multiplier;
4696 //If unconscious, close eyes and mouth
4697 if (righthandmorphend != 0)
4698 righthandmorphness = 0;
4699 righthandmorphend = 0;
4700 targetrighthandmorphness = 1;
4702 if (lefthandmorphend != 0)
4703 lefthandmorphness = 0;
4704 lefthandmorphend = 0;
4705 targetlefthandmorphness = 1;
4707 if (headmorphend != 3 && headmorphend != 5)
4710 targetheadmorphness = 1;
4714 if (howactive > typesleeping) {
4717 if (bloodtoggle && !bled) {
4718 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4720 if (bloodtoggle && !bled)
4721 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4722 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4723 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4727 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4732 if (dead == 2 || howactive > typesleeping) {
4733 //If dead, open mouth and hands
4734 if (righthandmorphend != 0)
4735 righthandmorphness = 0;
4736 righthandmorphend = 0;
4737 targetrighthandmorphness = 1;
4739 if (lefthandmorphend != 0)
4740 lefthandmorphness = 0;
4741 lefthandmorphend = 0;
4742 targetlefthandmorphness = 1;
4744 if (headmorphend != 2)
4747 targetheadmorphness = 1;
4750 if (stunned > 0 && !dead && headmorphend != 2) {
4751 if (headmorphend != 4)
4754 targetheadmorphness = 1;
4757 if (damage > damagetolerance && !dead) {
4760 unconscioustime = 0;
4762 if (creature == wolftype) {
4763 award_bonus(0, Wolfbonus);
4768 if (weaponactive != -1) {
4769 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4770 weapons[weaponids[0]].velocity.x += .01;
4773 weaponids[0] = weaponids[num_weapons];
4774 if (weaponstuck == num_weapons)
4778 for (unsigned i = 0; i < Person::players.size(); i++) {
4779 Person::players[i]->wentforweapon = 0;
4785 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4794 damage -= multiplier * 13;
4796 permanentdamage -= multiplier * 4;
4797 if (isIdle() || isCrouch()) {
4799 permanentdamage -= multiplier * 4;
4803 if (permanentdamage < 0)
4804 permanentdamage = 0;
4805 if (superpermanentdamage < 0)
4806 superpermanentdamage = 0;
4807 if (permanentdamage < superpermanentdamage) {
4808 permanentdamage = superpermanentdamage;
4810 if (damage < permanentdamage) {
4811 damage = permanentdamage;
4813 if (dead == 1 && damage < damagetolerance) {
4817 for (int i = 0; i < skeleton.num_joints; i++) {
4818 skeleton.joints[i].velocity = 0;
4821 if (permanentdamage > damagetolerance && dead != 2) {
4824 if (weaponactive != -1) {
4825 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4826 weapons[weaponids[0]].velocity.x += .01;
4829 weaponids[0] = weaponids[num_weapons];
4830 if (weaponstuck == num_weapons)
4834 for (unsigned i = 0; i < Person::players.size(); i++) {
4835 Person::players[i]->wentforweapon = 0;
4841 if (!dead && creature == wolftype) {
4842 award_bonus(0, Wolfbonus);
4845 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4846 award_bonus(id, touchofdeath);
4847 if (id != 0 && unconscioustime > .1) {
4855 emit_sound_at(breaksound, coords);
4858 if (skeleton.free == 1) {
4860 pause_sound(whooshsound);
4863 //If knocked over, open hands and close mouth
4864 if (righthandmorphend != 0)
4865 righthandmorphness = 0;
4866 righthandmorphend = 0;
4867 targetrighthandmorphness = 1;
4869 if (lefthandmorphend != 0)
4870 lefthandmorphness = 0;
4871 lefthandmorphend = 0;
4872 targetlefthandmorphness = 1;
4874 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4875 if (headmorphend != 0)
4878 targetheadmorphness = 1;
4882 skeleton.DoGravity(&scale);
4884 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4885 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4886 award_bonus(id, deepimpact);
4887 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4891 for (j = 0; j < skeleton.num_joints; j++) {
4892 average += skeleton.joints[j].position;
4896 coords += average * scale;
4897 for (j = 0; j < skeleton.num_joints; j++) {
4898 skeleton.joints[j].position -= average;
4900 average /= multiplier;
4903 for (int i = 0; i < skeleton.num_joints; i++) {
4904 velocity += skeleton.joints[i].velocity * scale;
4906 velocity /= skeleton.num_joints;
4908 if (!isnormal(velocity.x) && velocity.x) {
4912 if (findLength(&average) < 10 && dead && skeleton.free) {
4913 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4914 if (skeleton.longdead > 2000) {
4915 if (skeleton.longdead > 6000) {
4917 pause_sound(whooshsound);
4922 if (dead == 2 && bloodloss < damagetolerance) {
4924 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4926 if (bloodtoggle && !bled) {
4927 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4929 if (bloodtoggle && !bled)
4930 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4931 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4932 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4933 float size = .2 * 1.2;
4936 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4940 if (dead == 2 && bloodloss >= damagetolerance) {
4942 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4945 if (bloodtoggle && !bled) {
4946 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4948 if (bloodtoggle && !bled)
4949 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4950 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4951 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4955 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4962 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4963 bool canrecover = 1;
4964 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4965 startpoint = coords;
4968 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4970 if (velocity.y < -30)
4972 for (i = 0; i < objects.numobjects; i++) {
4973 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4974 colviewer = startpoint;
4975 coltarget = endpoint;
4976 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4985 terrainnormal = jointPos(groin) - jointPos(abdomen);
4986 if (joint(groin).locked && joint(abdomen).locked) {
4987 terrainnormal = jointPos(groin) - jointPos(abdomen);
4988 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4990 if (joint(abdomen).locked && joint(neck).locked) {
4991 terrainnormal = jointPos(abdomen) - jointPos(neck);
4992 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4994 if (joint(groin).locked && joint(neck).locked) {
4995 terrainnormal = jointPos(groin) - jointPos(neck);
4996 middle = (jointPos(groin) + jointPos(neck)) / 2;
4998 Normalise(&terrainnormal);
5000 targetyaw = -asin(0 - terrainnormal.x);
5001 targetyaw *= 360 / 6.28;
5002 if (terrainnormal.z < 0)
5003 targetyaw = 180 - targetyaw;
5007 animTarget = flipanim;
5008 crouchtogglekeydown = 1;
5013 animCurrent = tempanim;
5017 for (int i = 0; i < skeleton.num_joints; i++) {
5018 tempanimation.position[i][0] = skeleton.joints[i].position;
5019 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5024 if (findLength(&average) < 10 && !dead && skeleton.free) {
5025 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
5026 if (skeleton.longdead > (damage + 500) * 1.5) {
5028 pause_sound(whooshsound);
5034 terrainnormal = jointPos(groin) - jointPos(abdomen);
5035 if (joint(groin).locked && joint(abdomen).locked) {
5036 terrainnormal = jointPos(groin) - jointPos(abdomen);
5037 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
5039 if (joint(abdomen).locked && joint(neck).locked) {
5040 terrainnormal = jointPos(abdomen) - jointPos(neck);
5041 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
5043 if (joint(groin).locked && joint(neck).locked) {
5044 terrainnormal = jointPos(groin) - jointPos(neck);
5045 middle = (jointPos(groin) + jointPos(neck)) / 2;
5047 Normalise(&terrainnormal);
5049 targetyaw = -asin(0 - terrainnormal.x);
5050 targetyaw *= 360 / 6.28;
5051 if (terrainnormal.z < 0)
5052 targetyaw = 180 - targetyaw;
5055 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
5058 if (skeleton.forward.y < 0) {
5059 animTarget = getupfrombackanim;
5063 if (skeleton.forward.y > -.3) {
5064 animTarget = getupfromfrontanim;
5072 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
5073 animTarget = rollanim;
5074 targetyaw = lookyaw;
5091 if ( !leftkeydown && !rightkeydown)
5098 if (abs(targettilt2) > 50)
5100 animCurrent = tempanim;
5103 tilt2 = targettilt2;
5105 if (middle.y > 0 && animTarget != rollanim)
5106 targetoffset.y = middle.y + 1;
5108 for (int i = 0; i < skeleton.num_joints; i++) {
5109 tempanimation.position[i][0] = skeleton.joints[i].position;
5110 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
5117 if (num_weapons > 0)
5118 if (weapons[0].getType() == staff)
5120 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
5121 if (velocity.y > -30) {
5123 tempvelocity = velocity;
5124 Normalise(&tempvelocity);
5125 targetyaw = -asin(0 - tempvelocity.x);
5126 targetyaw *= 360 / 6.28;
5128 targetyaw = 180 - targetyaw;
5132 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5133 animTarget = rollanim;
5136 animTarget = backhandspringanim;
5142 emit_sound_at(movewhooshsound, coords, 128.);
5144 animCurrent = animTarget;
5145 frameCurrent = frameTarget - 1;
5157 if (skeleton.freefall == 0)
5162 if (aitype != passivetype || skeleton.free == 1)
5163 if (findLengthfast(&velocity) > .1)
5164 for (i = 0; i < objects.numobjects; i++) {
5165 if (objects.type[i] == firetype)
5166 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) {
5168 if (!objects.onfire[i]) {
5169 emit_sound_at(firestartsound, objects.position[i]);
5171 objects.onfire[i] = 1;
5174 if (objects.onfire[i]) {
5179 if (objects.type[i] == bushtype)
5180 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) {
5182 if (!objects.onfire[i]) {
5183 emit_sound_at(firestartsound, objects.position[i]);
5185 objects.onfire[i] = 1;
5189 if (objects.onfire[i]) {
5193 if (objects.messedwith[i] <= 0) {
5197 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5200 addEnvSound(coords, 4 * findLength(&velocity));
5204 if (environment == grassyenvironment)
5205 howmany = findLength(&velocity) * 4;
5206 if (environment == snowyenvironment)
5207 howmany = findLength(&velocity) * 2;
5209 if (environment != desertenvironment)
5210 for (j = 0; j < howmany; j++) {
5211 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5212 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5213 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5216 pos.x += float(abs(Random() % 100) - 50) / 200;
5217 pos.y += float(abs(Random() % 100) - 50) / 200;
5218 pos.z += float(abs(Random() % 100) - 50) / 200;
5219 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);
5220 Sprite::setLastSpriteSpecial(1);
5222 howmany = findLength(&velocity) * 4;
5224 if (environment == snowyenvironment)
5225 for (j = 0; j < howmany; j++) {
5226 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5227 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5228 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5231 pos.x += float(abs(Random() % 100) - 50) / 200;
5232 pos.y += float(abs(Random() % 100) - 50) / 200;
5233 pos.z += float(abs(Random() % 100) - 50) / 200;
5234 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5235 Sprite::setLastSpriteSpecial(2);
5238 objects.rotx[i] += velocity.x * multiplier * 6;
5239 objects.roty[i] += velocity.z * multiplier * 6;
5240 objects.messedwith[i] = .5;
5243 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5244 if (objects.pitch[i] == 0)
5247 tempcoord = coords - objects.position[i];
5248 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5249 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5250 tempcoord += objects.position[i];
5252 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]) {
5253 if (objects.messedwith[i] <= 0) {
5257 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5260 addEnvSound(coords, 4 * findLength(&velocity));
5264 if (environment == grassyenvironment)
5265 howmany = findLength(&velocity) * 4;
5266 if (environment == snowyenvironment)
5267 howmany = findLength(&velocity) * 2;
5269 if (environment != desertenvironment)
5270 for (j = 0; j < howmany; j++) {
5271 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5272 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5273 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5275 pos += velocity * .1;
5277 pos.x += float(abs(Random() % 100) - 50) / 150;
5278 pos.y += float(abs(Random() % 100) - 50) / 150;
5279 pos.z += float(abs(Random() % 100) - 50) / 150;
5280 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);
5281 Sprite::setLastSpriteSpecial(1);
5283 howmany = findLength(&velocity) * 4;
5285 if (environment == snowyenvironment)
5286 for (j = 0; j < howmany; j++) {
5287 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5288 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5289 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5291 pos += velocity * .1;
5293 pos.x += float(abs(Random() % 100) - 50) / 150;
5294 pos.y += float(abs(Random() % 100) - 50) / 150;
5295 pos.z += float(abs(Random() % 100) - 50) / 150;
5296 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5297 Sprite::setLastSpriteSpecial(2);
5300 objects.messedwith[i] = .5;
5305 if (!skeleton.free) {
5308 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5311 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5313 if (tutoriallevel == 1 && id != 0)
5315 if (play && aitype != playercontrolled) {
5316 int whichsound = -1;
5317 i = abs(Random() % 4);
5318 if (speechdelay <= 0) {
5319 if (creature == rabbittype) {
5321 whichsound = rabbitchitter;
5323 whichsound = rabbitchitter2;
5325 if (creature == wolftype) {
5327 whichsound = growlsound;
5329 whichsound = growl2sound;
5334 if (whichsound != -1) {
5335 emit_sound_at(whichsound, coords);
5339 if (animTarget == staggerbackhighanim)
5341 if (animTarget == staggerbackhardanim)
5343 staggerdelay -= multiplier;
5344 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5346 if (velocity.y < -30 && animTarget == jumpdownanim)
5348 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5349 animTarget = getIdle();
5353 weaponmissdelay -= multiplier;
5354 highreversaldelay -= multiplier;
5355 lowreversaldelay -= multiplier;
5356 lastcollide -= multiplier;
5357 skiddelay -= multiplier;
5358 if (!isnormal(velocity.x) && velocity.x) {
5361 if (!isnormal(targettilt) && targettilt) {
5364 if (!isnormal(targettilt2) && targettilt2) {
5367 if (!isnormal(targetyaw) && targetyaw) {
5371 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5372 //open hands and close mouth
5373 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5374 righthandmorphness = 0;
5375 righthandmorphend = 0;
5376 targetrighthandmorphness = 1;
5379 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5380 lefthandmorphness = 0;
5381 lefthandmorphend = 0;
5382 targetlefthandmorphness = 1;
5385 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5388 targetheadmorphness = 1;
5392 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) {
5393 //open hands and mouth
5394 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5395 righthandmorphness = 0;
5396 righthandmorphend = 0;
5397 targetrighthandmorphness = 1;
5400 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5401 lefthandmorphness = 0;
5402 lefthandmorphend = 0;
5403 targetlefthandmorphness = 1;
5406 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5409 targetheadmorphness = 1;
5413 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5414 //close hands and mouth
5415 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5416 righthandmorphness = 0;
5417 righthandmorphend = 1;
5418 targetrighthandmorphness = 1;
5421 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5422 lefthandmorphness = 0;
5423 lefthandmorphend = 1;
5424 targetlefthandmorphness = 1;
5427 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5430 targetheadmorphness = 1;
5434 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) {
5435 //close hands and yell
5436 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5437 righthandmorphness = 0;
5438 righthandmorphend = 1;
5439 targetrighthandmorphness = 1;
5442 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5443 lefthandmorphness = 0;
5444 lefthandmorphend = 1;
5445 targetlefthandmorphness = 1;
5448 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5451 targetheadmorphness = 1;
5458 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5459 (victim->aitype != searchtype) && (aitype != passivetype) &&
5460 (aitype != searchtype) && (victim->id < Person::players.size())) {
5461 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5465 if (!dead && animTarget != hurtidleanim)
5466 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5467 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5470 targetheadmorphness = 1;
5474 if (weaponactive != -1) {
5475 if (weapons[weaponids[weaponactive]].getType() != staff) {
5476 righthandmorphstart = 1;
5477 righthandmorphend = 1;
5479 if (weapons[weaponids[weaponactive]].getType() == staff) {
5480 righthandmorphstart = 2;
5481 righthandmorphend = 2;
5483 targetrighthandmorphness = 1;
5486 terrainnormal = terrain.getNormal(coords.x, coords.z);
5488 if (animation[animTarget].attack != reversal) {
5489 if (!isnormal(coords.x))
5497 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5498 facing = flatfacing;
5499 ReflectVector(&facing, terrainnormal);
5502 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5504 targettilt2 = -facing.y * 20;
5509 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5511 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5512 flatvelocity = velocity;
5514 flatvelspeed = findLength(&flatvelocity);
5515 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5516 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5521 if (targettilt > 25)
5523 if (targettilt < -25)
5527 if (targettilt2 > 45)
5529 if (targettilt2 < -45)
5531 if (abs(tilt2 - targettilt2) < multiplier * 400)
5532 tilt2 = targettilt2;
5533 else if (tilt2 > targettilt2) {
5534 tilt2 -= multiplier * 400;
5535 } else if (tilt2 < targettilt2) {
5536 tilt2 += multiplier * 400;
5538 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5545 if (!isnormal(targettilt) && targettilt) {
5548 if (!isnormal(targettilt2) && targettilt2) {
5553 if (animTarget == rabbittackleanim) {
5554 velocity += facing * multiplier * speed * 700 * scale;
5555 velspeed = findLength(&velocity);
5556 if (velspeed > speed * 65 * scale) {
5557 velocity /= velspeed;
5558 velspeed = speed * 65 * scale;
5559 velocity *= velspeed;
5561 velocity.y += gravity * multiplier * 20;
5562 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5563 velspeed = findLength(&velocity);
5564 velocity = flatfacing * velspeed;
5566 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5567 if (isRun() || animTarget == rabbitkickanim) {
5568 velocity += facing * multiplier * speed * 700 * scale;
5569 velspeed = findLength(&velocity);
5570 if (velspeed > speed * 45 * scale) {
5571 velocity /= velspeed;
5572 velspeed = speed * 45 * scale;
5573 velocity *= velspeed;
5575 velocity.y += gravity * multiplier * 20;
5576 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5577 velspeed = findLength(&velocity);
5578 if (velspeed < speed * 30 * scale)
5579 velspeed = speed * 30 * scale;
5580 velocity = flatfacing * velspeed;
5582 } else if (isRun()) {
5583 velocity += facing * multiplier * speed * 700 * scale;
5584 velspeed = findLength(&velocity);
5585 if (creature == rabbittype) {
5586 if (velspeed > speed * 55 * scale) {
5587 velocity /= velspeed;
5588 velspeed = speed * 55 * scale;
5589 velocity *= velspeed;
5592 if (creature == wolftype) {
5593 if (velspeed > speed * 75 * scale) {
5594 velocity /= velspeed;
5595 velspeed = speed * 75 * scale;
5596 velocity *= velspeed;
5599 velocity.y += gravity * multiplier * 20;
5600 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5601 velspeed = findLength(&velocity);
5602 velocity = flatfacing * velspeed;
5605 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5606 velocity += facing * multiplier * speed * 700 * scale;
5607 velspeed = findLength(&velocity);
5608 if (velspeed > speed * 45 * scale) {
5609 velocity /= velspeed;
5610 velspeed = speed * 45 * scale;
5611 velocity *= velspeed;
5613 velocity.y += gravity * multiplier * 20;
5614 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5615 velspeed = findLength(&velocity);
5616 velocity = flatfacing * velspeed;
5619 if (animTarget == sneakanim || animTarget == walkanim) {
5620 velocity += facing * multiplier * speed * 700 * scale;
5621 velspeed = findLength(&velocity);
5622 if (velspeed > speed * 12 * scale) {
5623 velocity /= velspeed;
5624 velspeed = speed * 12 * scale;
5625 velocity *= velspeed;
5627 velocity.y += gravity * multiplier * 20;
5628 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5629 velspeed = findLength(&velocity);
5630 velocity = flatfacing * velspeed;
5633 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5634 velocity += facing * multiplier * speed * 700 * scale;
5635 velspeed = findLength(&velocity);
5636 if (velspeed > speed * 2 * scale) {
5637 velocity /= velspeed;
5638 velspeed = speed * 2 * scale;
5639 velocity *= velspeed;
5641 velocity.y += gravity * multiplier * 20;
5642 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5643 velspeed = findLength(&velocity);
5644 velocity = flatfacing * velspeed;
5648 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5649 velocity -= facing * multiplier * speed * 700 * scale;
5650 velspeed = findLength(&velocity);
5651 if (velspeed > speed * 2 * scale) {
5652 velocity /= velspeed;
5653 velspeed = speed * 2 * scale;
5654 velocity *= velspeed;
5656 velocity.y += gravity * multiplier * 20;
5657 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5658 velspeed = findLength(&velocity);
5659 velocity = flatfacing * velspeed * -1;
5662 if (animTarget == fightsidestep) {
5663 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5664 velspeed = findLength(&velocity);
5665 if (velspeed > speed * 12 * scale) {
5666 velocity /= velspeed;
5667 velspeed = speed * 12 * scale;
5668 velocity *= velspeed;
5670 velocity.y += gravity * multiplier * 20;
5671 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5672 velspeed = findLength(&velocity);
5673 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5676 if (animTarget == staggerbackhighanim) {
5677 coords -= facing * multiplier * speed * 16 * scale;
5680 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5681 coords -= facing * multiplier * speed * 20 * scale;
5685 if (animTarget == backhandspringanim) {
5686 //coords-=facing*multiplier*50*scale;
5687 velocity += facing * multiplier * speed * 700 * scale * -1;
5688 velspeed = findLength(&velocity);
5689 if (velspeed > speed * 50 * scale) {
5690 velocity /= velspeed;
5691 velspeed = speed * 50 * scale;
5692 velocity *= velspeed;
5694 velocity.y += gravity * multiplier * 20;
5695 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5696 velspeed = findLength(&velocity);
5697 velocity = flatfacing * velspeed * -1;
5699 if (animTarget == dodgebackanim) {
5700 //coords-=facing*multiplier*50*scale;
5701 velocity += facing * multiplier * speed * 700 * scale * -1;
5702 velspeed = findLength(&velocity);
5703 if (velspeed > speed * 60 * scale) {
5704 velocity /= velspeed;
5705 velspeed = speed * 60 * scale;
5706 velocity *= velspeed;
5708 velocity.y += gravity * multiplier * 20;
5709 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5710 velspeed = findLength(&velocity);
5711 velocity = flatfacing * velspeed * -1;
5714 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5715 velspeed = findLength(&velocity);
5719 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5720 velocity.y += gravity * multiplier;
5723 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5724 coords += velocity * multiplier;
5726 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5727 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5730 if (animTarget == jumpupanim) {
5732 animTarget = getIdle();
5739 pause_sound(whooshsound);
5740 OPENAL_SetVolume(channels[whooshsound], 0);
5743 if (animTarget == jumpdownanim || isFlip()) {
5744 if (isFlip())jumppower = -4;
5745 animTarget = getLanding();
5746 emit_sound_at(landsound, coords, 128.);
5749 addEnvSound(coords);
5754 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5755 coords.y += gravity * multiplier * 2;
5756 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5757 coords.y = terrain.getHeight(coords.x, coords.z);
5762 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)) {
5763 velspeed = findLength(&velocity);
5765 if (velspeed < multiplier * 300 * scale) {
5768 velocity -= velocity / velspeed * multiplier * 300 * scale;
5769 if (velspeed > 5 && (isLanding() || isLandhard())) {
5770 skiddingdelay += multiplier;
5771 if (skiddelay <= 0) {
5781 velspeed = findLength(&velocity);
5783 if (velspeed < multiplier * 600 * scale) {
5786 velocity -= velocity / velspeed * multiplier * 600 * scale;
5788 if (velspeed > 5 && (isLanding() || isLandhard())) {
5789 skiddingdelay += multiplier;
5790 if (skiddelay <= 0) {
5799 if (skiddingdelay < 0)
5800 skiddingdelay += multiplier;
5801 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5803 if (!onterrain || environment == grassyenvironment) {
5804 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5806 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5810 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5811 terrainnormal = victim->coords - coords;
5812 Normalise(&terrainnormal);
5813 targetyaw = -asin(0 - terrainnormal.x);
5814 targetyaw *= 360 / 6.28;
5815 if (terrainnormal.z < 0)
5816 targetyaw = 180 - targetyaw;
5817 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5820 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5821 targetyaw = victim->targetyaw;
5823 if (animTarget == rabbittacklinganim) {
5824 coords = victim->coords;
5827 skeleton.oldfree = skeleton.free;
5831 midterrain.x = terrain.size * terrain.scale / 2;
5832 midterrain.z = terrain.size * terrain.scale / 2;
5833 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5835 tempposit = coords - midterrain;
5837 Normalise(&tempposit);
5838 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5839 coords.x = tempposit.x + midterrain.x;
5840 coords.z = tempposit.z + midterrain.z;
5846 * inverse kinematics helper function
5848 void IKHelper(Person *p, float interp)
5850 XYZ point, change, change2;
5851 float heightleft, heightright;
5853 // TODO: implement localToWorld and worldToLocal
5854 // but keep in mind it won't be the same math if player is ragdolled or something
5855 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5856 // then comb through code for places where to use it
5858 // point = localToWorld(jointPos(leftfoot))
5859 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5860 // adjust height of foot
5861 heightleft = terrain.getHeight(point.x, point.z) + .04;
5862 point.y = heightleft;
5863 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5864 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5865 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5866 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5867 // move ankle along with foot
5868 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5869 // average knee pos between old and new pos
5870 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5872 // do same as above for right leg
5873 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5874 heightright = terrain.getHeight(point.x, point.z) + .04;
5875 point.y = heightright;
5876 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5877 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5878 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5879 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5880 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5882 // fix up skeleton now that we've moved body parts?
5883 p->skeleton.DoConstraints(&p->coords, &p->scale);
5890 int Person::DrawSkeleton()
5892 int oldplayerdetail;
5893 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5894 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5904 glAlphaFunc(GL_GREATER, 0.0001);
5906 float terrainheight;
5910 if (!isnormal(tilt))
5912 if (!isnormal(tilt2))
5914 oldplayerdetail = playerdetail;
5916 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5919 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5922 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5927 if (playerdetail != oldplayerdetail) {
5929 normalsupdatedelay = 0;
5931 static float updatedelaychange;
5932 static float morphness;
5933 static float framemult;
5935 skeleton.FindForwards();
5936 if (howactive == typesittingwall) {
5937 skeleton.specialforward[1] = 0;
5938 skeleton.specialforward[1].z = 1;
5944 static int weaponattachmuscle;
5945 static int weaponrotatemuscle;
5946 static XYZ weaponpoint;
5947 static int start, endthing;
5948 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5949 if (!isSleeping() && !isSitting()) {
5950 // TODO: give these meaningful names
5951 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5952 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5953 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5954 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5956 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5958 if (creature == wolftype)
5962 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5963 IKHelper(this, target);
5964 if (creature == wolftype)
5965 IKHelper(this, target);
5968 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5969 IKHelper(this, 1 - target);
5970 if (creature == wolftype)
5971 IKHelper(this, 1 - target);
5975 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()))
5978 targetheadyaw = -targetyaw;
5979 targetheadpitch = 0;
5980 if (animation[animTarget].attack == 3)
5981 targetheadyaw += 180;
5983 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5984 skeleton.drawmodel.vertex[i] = 0;
5985 skeleton.drawmodel.vertex[i].y = 999;
5987 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5988 skeleton.drawmodellow.vertex[i] = 0;
5989 skeleton.drawmodellow.vertex[i].y = 999;
5991 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5992 skeleton.drawmodelclothes.vertex[i] = 0;
5993 skeleton.drawmodelclothes.vertex[i].y = 999;
5995 for (int i = 0; i < skeleton.num_muscles; i++) {
5996 // convenience renames
5997 const int p1 = skeleton.muscles[i].parent1->label;
5998 const int p2 = skeleton.muscles[i].parent2->label;
6000 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
6005 if (p1 == righthand || p2 == righthand) {
6006 morphness = righthandmorphness;
6007 start = righthandmorphstart;
6008 endthing = righthandmorphend;
6010 if (p1 == lefthand || p2 == lefthand) {
6011 morphness = lefthandmorphness;
6012 start = lefthandmorphstart;
6013 endthing = lefthandmorphend;
6015 if (p1 == head || p2 == head) {
6016 morphness = headmorphness;
6017 start = headmorphstart;
6018 endthing = headmorphend;
6020 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
6021 morphness = chestmorphness;
6022 start = chestmorphstart;
6023 endthing = chestmorphend;
6025 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
6026 morphness = tailmorphness;
6027 start = tailmorphstart;
6028 endthing = tailmorphend;
6031 skeleton.FindRotationMuscle(i, animTarget);
6032 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6033 glMatrixMode(GL_MODELVIEW);
6037 glRotatef(tilt2, 1, 0, 0);
6039 glRotatef(tilt, 0, 0, 1);
6042 glTranslatef(mid.x, mid.y, mid.z);
6044 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6045 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6047 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6048 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6050 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6051 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6053 if (playerdetail || skeleton.free == 3) {
6054 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
6055 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
6056 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
6057 glMatrixMode(GL_MODELVIEW);
6059 if (p1 == abdomen || p2 == abdomen)
6060 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
6061 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
6062 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
6063 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6064 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
6065 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
6066 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
6067 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6068 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
6069 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
6070 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
6071 if (p1 == head || p2 == head)
6072 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
6073 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
6074 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
6075 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6076 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
6077 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
6078 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
6082 if (!playerdetail || skeleton.free == 3) {
6083 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
6084 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
6085 glMatrixMode(GL_MODELVIEW);
6087 if (p1 == abdomen || p2 == abdomen)
6088 glTranslatef(v0.x * proportionbody.x,
6089 v0.y * proportionbody.y,
6090 v0.z * proportionbody.z);
6091 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6092 glTranslatef(v0.x * proportionarms.x,
6093 v0.y * proportionarms.y,
6094 v0.z * proportionarms.z);
6095 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6096 glTranslatef(v0.x * proportionlegs.x,
6097 v0.y * proportionlegs.y,
6098 v0.z * proportionlegs.z);
6099 if (p1 == head || p2 == head)
6100 glTranslatef(v0.x * proportionhead.x,
6101 v0.y * proportionhead.y,
6102 v0.z * proportionhead.z);
6104 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6105 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
6106 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
6107 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
6113 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
6114 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
6116 glMatrixMode(GL_MODELVIEW);
6120 glRotatef(tilt2, 1, 0, 0);
6122 glRotatef(tilt, 0, 0, 1);
6123 glTranslatef(mid.x, mid.y, mid.z);
6124 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6125 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6127 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6128 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6130 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6131 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6133 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6134 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6135 glMatrixMode(GL_MODELVIEW);
6137 if (p1 == abdomen || p2 == abdomen)
6138 glTranslatef(v0.x * proportionbody.x,
6139 v0.y * proportionbody.y,
6140 v0.z * proportionbody.z);
6141 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6142 glTranslatef(v0.x * proportionarms.x,
6143 v0.y * proportionarms.y,
6144 v0.z * proportionarms.z);
6145 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6146 glTranslatef(v0.x * proportionlegs.x,
6147 v0.y * proportionlegs.y,
6148 v0.z * proportionlegs.z);
6149 if (p1 == head || p2 == head)
6150 glTranslatef(v0.x * proportionhead.x,
6151 v0.y * proportionhead.y,
6152 v0.z * proportionhead.z);
6153 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6154 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6155 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6156 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6161 updatedelay = 1 + (float)(Random() % 100) / 1000;
6163 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6164 normalsupdatedelay = 1;
6165 if (playerdetail || skeleton.free == 3)
6166 skeleton.drawmodel.CalculateNormals(0);
6167 if (!playerdetail || skeleton.free == 3)
6168 skeleton.drawmodellow.CalculateNormals(0);
6169 if (skeleton.clothes)
6170 skeleton.drawmodelclothes.CalculateNormals(0);
6172 if (playerdetail || skeleton.free == 3)
6173 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6174 if (!playerdetail || skeleton.free == 3)
6175 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6176 if (skeleton.clothes) {
6177 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6182 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6183 if (updatedelaychange > -realmultiplier * 30)
6184 updatedelaychange = -realmultiplier * 30;
6185 if (updatedelaychange > -framemult * 4)
6186 updatedelaychange = -framemult * 4;
6187 if (skeleton.free == 1)
6188 updatedelaychange *= 6;
6190 updatedelaychange *= 8;
6191 updatedelay += updatedelaychange;
6193 glMatrixMode(GL_MODELVIEW);
6195 glTranslatef(coords.x, coords.y - .02, coords.z);
6196 if (!skeleton.free) {
6197 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6198 glRotatef(yaw, 0, 1, 0);
6202 glColor4f(.4, 1, .4, 1);
6203 glDisable(GL_LIGHTING);
6204 glDisable(GL_TEXTURE_2D);
6207 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6208 XYZ &v0 = skeleton.drawmodel.vertex[i];
6209 glVertex3f(v0.x, v0.y, v0.z);
6215 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6216 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6217 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6218 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6219 glVertex3f(v0.x, v0.y, v0.z);
6220 glVertex3f(v1.x, v1.y, v1.z);
6221 glVertex3f(v1.x, v1.y, v1.z);
6222 glVertex3f(v2.x, v2.y, v2.z);
6223 glVertex3f(v2.x, v2.y, v2.z);
6224 glVertex3f(v0.x, v0.y, v0.z);
6230 terrainlight = terrain.getLighting(coords.x, coords.z);
6231 distance = distsq(&viewer, &coords);
6232 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6236 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6237 if (terrainheight < 1)
6239 if (terrainheight > 1.7)
6240 terrainheight = 1.7;
6243 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6244 glDisable(GL_BLEND);
6245 glAlphaFunc(GL_GREATER, 0.0001);
6246 glEnable(GL_TEXTURE_2D);
6248 glDisable(GL_TEXTURE_2D);
6249 glColor4f(.7, .35, 0, .5);
6251 glEnable(GL_LIGHTING);
6254 if (tutoriallevel && id != 0) {
6255 glColor4f(.7, .7, .7, 0.6);
6257 glEnable(GL_LIGHTING);
6259 if (canattack && cananger)
6260 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6261 glDisable(GL_TEXTURE_2D);
6262 glColor4f(1, 0, 0, 0.8);
6264 glMatrixMode(GL_TEXTURE);
6266 glTranslatef(0, -smoketex, 0);
6267 glTranslatef(-smoketex, 0, 0);
6271 if ((tutoriallevel && id != 0))
6272 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6274 skeleton.drawmodel.draw();
6277 if (!playerdetail) {
6278 if ((tutoriallevel && id != 0))
6279 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6281 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6284 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6285 if (tutoriallevel && id != 0) {
6287 glMatrixMode(GL_MODELVIEW);
6288 glEnable(GL_TEXTURE_2D);
6289 glColor4f(.7, .7, .7, 0.6);
6291 glEnable(GL_LIGHTING);
6293 if (canattack && cananger)
6294 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6295 glDisable(GL_TEXTURE_2D);
6296 glColor4f(1, 0, 0, 0.8);
6298 glMatrixMode(GL_TEXTURE);
6300 glTranslatef(0, -smoketex * .6, 0);
6301 glTranslatef(smoketex * .6, 0, 0);
6304 if ((tutoriallevel && id != 0))
6305 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6307 skeleton.drawmodel.draw();
6310 if (!playerdetail) {
6311 if ((tutoriallevel && id != 0))
6312 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6314 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6319 if (tutoriallevel && id != 0) {
6321 glMatrixMode(GL_MODELVIEW);
6322 glEnable(GL_TEXTURE_2D);
6324 if (skeleton.clothes) {
6328 skeleton.drawmodelclothes.draw();
6330 skeleton.drawmodelclothes.drawimmediate();
6336 if (num_weapons > 0) {
6337 for (k = 0; k < num_weapons; k++) {
6339 if (weaponactive == k) {
6340 if (weapons[i].getType() != staff) {
6341 for (j = 0; j < skeleton.num_muscles; j++) {
6342 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6343 weaponattachmuscle = j;
6346 for (j = 0; j < skeleton.num_muscles; j++) {
6347 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) {
6348 weaponrotatemuscle = j;
6351 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6352 if (creature == wolftype)
6353 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6355 if (weapons[i].getType() == staff) {
6356 for (j = 0; j < skeleton.num_muscles; j++) {
6357 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6358 weaponattachmuscle = j;
6361 for (j = 0; j < skeleton.num_muscles; j++) {
6362 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) {
6363 weaponrotatemuscle = j;
6366 //weaponpoint=jointPos(rightwrist);
6367 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6368 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6369 XYZ tempnormthing, vec1, vec2;
6370 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6371 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6372 CrossProduct(&vec1, &vec2, &tempnormthing);
6373 Normalise(&tempnormthing);
6374 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6375 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6378 if (weaponactive != k && weaponstuck != k) {
6379 if (weapons[i].getType() == knife)
6380 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6381 if (weapons[i].getType() == sword)
6382 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6383 if (weapons[i].getType() == staff)
6384 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6385 for (j = 0; j < skeleton.num_muscles; j++) {
6386 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) {
6387 weaponrotatemuscle = j;
6391 if (weaponstuck == k) {
6392 if (weaponstuckwhere == 0)
6393 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6395 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6396 for (j = 0; j < skeleton.num_muscles; j++) {
6397 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) {
6398 weaponrotatemuscle = j;
6402 if (skeleton.free) {
6403 weapons[i].position = weaponpoint * scale + coords;
6404 weapons[i].bigrotation = 0;
6405 weapons[i].bigtilt = 0;
6406 weapons[i].bigtilt2 = 0;
6408 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;
6409 weapons[i].bigrotation = yaw;
6410 weapons[i].bigtilt = tilt;
6411 weapons[i].bigtilt2 = tilt2;
6413 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6414 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6415 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6416 if (weaponactive == k) {
6417 if (weapons[i].getType() == knife) {
6418 weapons[i].smallrotation = 180;
6419 weapons[i].smallrotation2 = 0;
6420 if (isCrouch() || wasCrouch()) {
6421 weapons[i].smallrotation2 = 20;
6423 if (animTarget == hurtidleanim) {
6424 weapons[i].smallrotation2 = 50;
6426 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6427 XYZ temppoint1, temppoint2;
6430 temppoint1 = jointPos(righthand);
6431 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6432 distance = findDistance(&temppoint1, &temppoint2);
6433 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6434 weapons[i].rotation2 *= 360 / 6.28;
6437 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6438 weapons[i].rotation1 *= 360 / 6.28;
6439 weapons[i].rotation3 = 0;
6440 weapons[i].smallrotation = -90;
6441 weapons[i].smallrotation2 = 0;
6442 if (temppoint1.x > temppoint2.x)
6443 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6445 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6446 XYZ temppoint1, temppoint2;
6449 temppoint1 = jointPos(righthand);
6450 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6451 distance = findDistance(&temppoint1, &temppoint2);
6452 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6453 weapons[i].rotation2 *= 360 / 6.28;
6456 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6457 weapons[i].rotation1 *= 360 / 6.28;
6458 weapons[i].rotation3 = 0;
6459 weapons[i].smallrotation = 90;
6460 weapons[i].smallrotation2 = 0;
6461 if (temppoint1.x > temppoint2.x)
6462 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6464 if (animTarget == knifethrowanim) {
6465 weapons[i].smallrotation = 90;
6466 //weapons[i].smallrotation2=-90;
6467 weapons[i].smallrotation2 = 0;
6468 weapons[i].rotation1 = 0;
6469 weapons[i].rotation2 = 0;
6470 weapons[i].rotation3 = 0;
6472 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6473 weapons[i].smallrotation = -90;
6474 weapons[i].rotation1 = 0;
6475 weapons[i].rotation2 = 0;
6476 weapons[i].rotation3 = 0;
6479 if (weapons[i].getType() == sword) {
6480 weapons[i].smallrotation = 0;
6481 weapons[i].smallrotation2 = 0;
6482 if (animTarget == knifethrowanim) {
6483 weapons[i].smallrotation = -90;
6484 weapons[i].smallrotation2 = 0;
6485 weapons[i].rotation1 = 0;
6486 weapons[i].rotation2 = 0;
6487 weapons[i].rotation3 = 0;
6489 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)) {
6490 XYZ temppoint1, temppoint2;
6493 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6494 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6495 distance = findDistance(&temppoint1, &temppoint2);
6496 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6497 weapons[i].rotation2 *= 360 / 6.28;
6500 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6501 weapons[i].rotation1 *= 360 / 6.28;
6502 weapons[i].rotation3 = 0;
6503 weapons[i].smallrotation = 90;
6504 weapons[i].smallrotation2 = 0;
6505 if (temppoint1.x > temppoint2.x)
6506 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6509 if (weapons[i].getType() == staff) {
6510 weapons[i].smallrotation = 100;
6511 weapons[i].smallrotation2 = 0;
6512 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6513 XYZ temppoint1, temppoint2;
6516 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6517 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6518 distance = findDistance(&temppoint1, &temppoint2);
6519 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6520 weapons[i].rotation2 *= 360 / 6.28;
6523 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6524 weapons[i].rotation1 *= 360 / 6.28;
6525 weapons[i].rotation3 = 0;
6526 weapons[i].smallrotation = 90;
6527 weapons[i].smallrotation2 = 0;
6528 if (temppoint1.x > temppoint2.x)
6529 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6533 if (weaponactive != k && weaponstuck != k) {
6534 if (weapons[i].getType() == knife) {
6535 weapons[i].smallrotation = -70;
6536 weapons[i].smallrotation2 = 10;
6538 if (weapons[i].getType() == sword) {
6539 weapons[i].smallrotation = -100;
6540 weapons[i].smallrotation2 = -8;
6542 if (weapons[i].getType() == staff) {
6543 weapons[i].smallrotation = -100;
6544 weapons[i].smallrotation2 = -8;
6547 if (weaponstuck == k) {
6548 if (weaponstuckwhere == 0)
6549 weapons[i].smallrotation = 180;
6551 weapons[i].smallrotation = 0;
6552 weapons[i].smallrotation2 = 10;
6561 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6563 if (animCurrent != animTarget)
6565 if (skeleton.free == 2)
6574 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6577 static float distance;
6578 static float olddistance;
6579 static int intersecting;
6580 static int firstintersecting;
6583 static XYZ start, end;
6584 static float slopethreshold = -.4;
6586 firstintersecting = -1;
6590 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6593 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6594 for (i = 0; i < 4; i++) {
6595 for (j = 0; j < model->TriangleNum; j++) {
6596 if (model->facenormals[j].y <= slopethreshold) {
6598 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)));
6599 if (distance < radius) {
6600 point = *p1 - model->facenormals[j] * distance;
6601 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]]))
6604 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6605 &model->vertex[model->Triangles[j].vertex[1]],
6608 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6609 &model->vertex[model->Triangles[j].vertex[2]],
6612 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6613 &model->vertex[model->Triangles[j].vertex[2]],
6616 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6620 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)) {
6621 p1->y = point.y + radius;
6622 if ((animTarget == jumpdownanim || isFlip())) {
6623 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6626 if (animTarget == jumpupanim) {
6628 animTarget = getIdle();
6635 pause_sound(whooshsound);
6636 OPENAL_SetVolume(channels[whooshsound], 0);
6639 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6642 animTarget = getLanding();
6643 emit_sound_at(landsound, coords, 128.);
6646 addEnvSound(coords);
6653 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6654 olddistance = distance;
6655 firstintersecting = j;
6660 for (j = 0; j < model->TriangleNum; j++) {
6661 if (model->facenormals[j].y > slopethreshold) {
6664 start.y -= radius / 4;
6665 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6666 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6667 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6668 distance = abs((model->facenormals[j].x * start.x)
6669 + (model->facenormals[j].y * start.y)
6670 + (model->facenormals[j].z * start.z)
6671 - ((model->facenormals[j].x * v0.x)
6672 + (model->facenormals[j].y * v0.y)
6673 + (model->facenormals[j].z * v0.z)));
6674 if (distance < radius * .5) {
6675 point = start - model->facenormals[j] * distance;
6676 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6679 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6681 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6683 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6685 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6686 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6688 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6689 if (findLengthfast(&start) < findLengthfast(&velocity))
6692 *p1 += model->facenormals[j] * (distance - radius * .5);
6695 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6696 olddistance = distance;
6697 firstintersecting = j;
6704 *p = DoRotation(*p, 0, *rotate, 0);
6707 *p1 = DoRotation(*p1, 0, *rotate, 0);
6709 return firstintersecting;
6712 void Person::takeWeapon(int weaponId)
6715 weapons[weaponId].owner = id;
6716 if (num_weapons > 0) {
6717 weaponids[num_weapons] = weaponids[0];
6720 weaponids[0] = weaponId;
6723 void Person::addClothes()
6725 if (numclothes > 0) {
6726 for (int i = 0; i < numclothes; i++) {
6733 bool Person::addClothes(const int& clothesId)
6736 const char* fileName = clothes[clothesId];
6738 GLubyte* array = &skeleton.skinText[0];
6742 bool opened = load_image(fileName, texture);
6747 float tintr = clothestintr[clothesId];
6748 float tintg = clothestintg[clothesId];
6749 float tintb = clothestintb[clothesId];
6751 if (tintr > 1) tintr = 1;
6752 if (tintg > 1) tintg = 1;
6753 if (tintb > 1) tintb = 1;
6755 if (tintr < 0) tintr = 0;
6756 if (tintg < 0) tintg = 0;
6757 if (tintb < 0) tintb = 0;
6759 int bytesPerPixel = texture.bpp / 8;
6763 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6764 if (bytesPerPixel == 3)
6766 else if ((i + 1) % 4 == 0)
6767 alphanum = texture.data[i];
6768 if ((i + 1) % 4 || bytesPerPixel == 3) {
6770 texture.data[i] *= tintr;
6772 texture.data[i] *= tintg;
6774 texture.data[i] *= tintb;
6775 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);