2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
21 /**> HEADER FILES <**/
23 #include "openal_wrapper.h"
24 #include "Animation.h"
29 extern float multiplier;
30 extern Terrain terrain;
32 extern int environment;
34 extern FRUSTUM frustum;
36 extern float realmultiplier;
38 extern float slomodelay;
39 extern bool cellophane;
40 extern float texdetail;
41 extern float realtexdetail;
42 extern GLubyte bloodText[512 * 512 * 3];
43 extern GLubyte wolfbloodText[512 * 512 * 3];
44 extern int bloodtoggle;
45 extern Objects objects;
46 extern bool autoslomo;
47 extern float camerashake;
49 extern float viewdistance;
50 extern float blackout;
51 extern int difficulty;
53 extern float fadestart;
55 extern bool winfreeze;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern bool showpoints;
59 extern bool immediate;
61 extern bool tilt2weird;
62 extern bool tiltweird;
64 extern bool proportionweird;
65 extern bool vertexweird[6];
66 extern XYZ envsound[30];
67 extern float envsoundvol[30];
68 extern float envsoundlife[30];
69 extern int numenvsounds;
70 extern int tutoriallevel;
71 extern float smoketex;
72 extern int tutorialstage;
73 extern bool reversaltrain;
74 extern bool canattack;
76 extern float damagedealt;
78 extern float hostiletime;
80 extern int indialogue;
82 extern bool gamestarted;
84 std::vector<std::shared_ptr<Person>> Person::players(1, std::shared_ptr<Person>(new Person()));
89 * GameTick/doPlayerCollisions
91 void Person::CheckKick()
94 && (animTarget == rabbitkickanim
96 && victim != this->shared_from_this()
98 && animCurrent == rabbitkickanim)
99 && distsq(&coords, &victim->coords) < 1.2
100 && !victim->skeleton.free))
103 if (animation[victim->animTarget].height != lowheight) {
104 float damagemult = (creature == wolftype ? 2.5 : 1.) * power * power;
105 XYZ relative = velocity;
107 Normalise(&relative);
111 if (tutoriallevel != 1)
112 emit_sound_at(heavyimpactsound, victim->coords);
114 for (int i = 0; i < victim->skeleton.num_joints; i++) {
115 victim->skeleton.joints[i].velocity += relative * 120 * damagemult;
118 victim->DoDamage(100 * damagemult / victim->protectionhigh);
124 animTarget = backflipanim;
126 velocity = facing * -10;
130 resume_stream(whooshsound);
132 award_bonus(id, cannon);
133 } else if (victim->isCrouch()) {
134 animTarget = rabbitkickreversedanim;
135 animCurrent = rabbitkickreversedanim;
136 victim->animCurrent = rabbitkickreversalanim;
137 victim->animTarget = rabbitkickreversalanim;
143 victim->oldcoords = victim->coords;
144 coords = victim->coords;
145 victim->targetyaw = targetyaw;
146 victim->victim = this->shared_from_this();
153 * GameTick/doPlayerCollisions - spread fire between players
154 * GameTick/doDebugKeys - press f to ignite
155 * Person::DoStuff - spread fire from lit campfires and bushes
157 void Person::CatchFire()
159 XYZ flatfacing, flatvelocity;
161 for (int i = 0; i < 10; i++) {
162 howmany = abs(Random() % (skeleton.num_joints));
164 flatvelocity = velocity;
166 flatvelocity = skeleton.joints[howmany].velocity;
168 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
170 flatfacing = skeleton.joints[howmany].position * scale + coords;
171 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
176 emit_sound_at(firestartsound, coords);
178 emit_stream_at(stream_firesound, coords);
186 * idle animation for this creature (depending on status)
188 int Person::getIdle()
190 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
192 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
193 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
194 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
195 victim->id < Person::players.size())) {
196 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
197 if (creature == rabbittype)
198 return fightidleanim;
199 if (creature == wolftype)
202 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
203 if (weapons[weaponids[weaponactive]].getType() == knife)
204 return knifefightidleanim;
205 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
206 return swordfightidlebothanim;
207 if (weapons[weaponids[weaponactive]].getType() == sword)
208 return swordfightidleanim;
209 if (weapons[weaponids[weaponactive]].getType() == staff)
210 return swordfightidleanim;
212 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
213 return fightsidestep;
215 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
217 if (howactive == typesitting) return sitanim;
218 if (howactive == typesittingwall) return sitwallanim;
219 if (howactive == typesleeping) return sleepanim;
220 if (howactive == typedead1) return dead1anim;
221 if (howactive == typedead2) return dead2anim;
222 if (howactive == typedead3) return dead3anim;
223 if (howactive == typedead4) return dead4anim;
224 if (creature == rabbittype) return bounceidleanim;
225 if (creature == wolftype) return wolfidle;
230 * crouch animation for this creature
232 int Person::getCrouch()
234 if (creature == rabbittype)
236 if (creature == wolftype)
237 return wolfcrouchanim;
242 * running animation for this creature (can be upright or all fours)
246 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
248 if (creature == wolftype && (!superruntoggle))
251 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
252 return rabbitrunninganim;
253 if (creature == wolftype && (superruntoggle))
254 return wolfrunninganim;
260 int Person::getStop()
262 if (creature == rabbittype)
264 if (creature == wolftype)
271 int Person::getLanding()
273 if (creature == rabbittype)
275 if (creature == wolftype)
282 int Person::getLandhard()
284 if (creature == rabbittype)
286 if (creature == wolftype)
287 return wolflandhardanim;
294 * Person::DoAnimations
297 SolidHitBonus(int playerid)
299 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
300 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
302 award_bonus(playerid, solidhit);
306 * spawns blood effects
308 void Person::DoBlood(float howmuch, int which)
310 // FIXME: should abstract out inputs
311 static int bleedxint, bleedyint;
313 if (bloodtoggle && tutoriallevel != 1) {
314 if (bleeding <= 0 && spurt) {
316 for (int i = 0; i < 3; i++) {
317 // emit blood particles
319 if (!skeleton.free) {
321 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
324 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
327 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
329 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
331 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
332 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
334 if (!skeleton.free) {
335 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
336 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
339 if (Random() % 2 == 0) // 50% chance
340 for (int i = 0; i < 3; i++) {
341 if (Random() % 2 != 0) {
342 // emit teeth particles
345 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
346 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
349 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
350 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
354 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
356 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
358 Sprite::setLastSpriteSpecial(3); // sets it to teeth
363 // FIXME: manipulating attributes
364 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
367 if (creature == rabbittype)
368 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) {
369 bleedxint = abs(Random() % 512);
370 bleedyint = abs(Random() % 512);
372 if (creature == wolftype)
373 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) {
374 bleedxint = abs(Random() % 512);
375 bleedyint = abs(Random() % 512);
379 bleedy /= realtexdetail;
380 bleedx /= realtexdetail;
381 direction = abs(Random() % 2) * 2 - 1;
390 * spawns big blood effects and ???
391 * modifies character's skin texture
393 void Person::DoBloodBig(float howmuch, int which)
395 static int bleedxint, bleedyint, i, j;
397 if (howmuch && id == 0)
400 if (tutoriallevel != 1 || id == 0)
401 if (aitype != playercontrolled && howmuch > 0) {
405 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
406 if (creature == wolftype) {
407 int i = abs(Random() % 2);
409 whichsound = snarlsound;
411 whichsound = snarl2sound;
412 envsound[numenvsounds] = coords;
413 envsoundvol[numenvsounds] = 16;
414 envsoundlife[numenvsounds] = .4;
417 if (creature == rabbittype) {
418 int i = abs(Random() % 2);
420 whichsound = rabbitpainsound;
421 if (i == 1 && howmuch >= 2)
422 whichsound = rabbitpain1sound;
423 envsound[numenvsounds] = coords;
424 envsoundvol[numenvsounds] = 16;
425 envsoundlife[numenvsounds] = .4;
429 if (whichsound != -1)
430 emit_sound_at(whichsound, coords);
433 if (id == 0 && howmuch > 0) {
434 // FIXME: manipulating attributes
442 if (bloodtoggle && decals && tutoriallevel != 1) {
443 if (bleeding <= 0 && spurt) {
445 for (int i = 0; i < 3; i++) {
446 // emit blood particles
447 // FIXME: copypaste from above
449 if (!skeleton.free) {
451 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
454 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
457 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
459 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
461 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
462 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
464 if (!skeleton.free) {
465 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
466 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
471 // weird texture manipulation code follows.
472 // looks like this is painting blood onto the character's skin texture
473 // FIXME: surely there's a better way
475 int offsetx = 0, offsety = 0;
477 offsety = Random() % 40;
478 offsetx = abs(Random() % 60);
480 if (which == 190 || which == 185) {
481 offsety = Random() % 40;
482 offsetx = abs(Random() % 100) - 20;
485 offsety = Random() % 10;
486 offsetx = Random() % 10;
489 offsety = Random() % 20;
490 offsetx = Random() % 20;
492 if (which == 220 || which == 215) {
502 if (creature == rabbittype)
503 for (i = 0; i < 512; i++) {
504 for (j = 0; j < 512; j++) {
505 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
506 if (i < startx) startx = i;
507 if (j < starty) starty = j;
508 if (i > endx) endx = i;
509 if (j > endy) endy = j;
513 if (creature == wolftype)
514 for (i = 0; i < 512; i++) {
515 for (j = 0; j < 512; j++) {
516 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
517 if (i < startx) startx = i;
518 if (j < starty) starty = j;
519 if (i > endx) endx = i;
520 if (j > endy) endy = j;
530 if (startx < 0) startx = 0;
531 if (starty < 0) starty = 0;
532 if (endx > 512 - 1) endx = 512 - 1;
533 if (endy > 512 - 1) endy = 512 - 1;
534 if (endx < startx) endx = startx;
535 if (endy < starty) endy = starty;
537 startx /= realtexdetail;
538 starty /= realtexdetail;
539 endx /= realtexdetail;
540 endy /= realtexdetail;
542 int texdetailint = realtexdetail;
544 if (creature == rabbittype)
545 for (i = startx; i < endx; i++) {
546 for (j = starty; j < endy; j++) {
547 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) {
548 color = Random() % 85 + 170;
549 where = i * skeleton.skinsize * 3 + j * 3;
550 if (skeleton.skinText[where + 0] > color / 2)
551 skeleton.skinText[where + 0] = color / 2;
552 skeleton.skinText[where + 1] = 0;
553 skeleton.skinText[where + 2] = 0;
557 if (creature == wolftype)
558 for (i = startx; i < endx; i++) {
559 for (j = starty; j < endy; j++) {
560 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) {
561 color = Random() % 85 + 170;
562 where = i * skeleton.skinsize * 3 + j * 3;
563 if (skeleton.skinText[where + 0] > color / 2)
564 skeleton.skinText[where + 0] = color / 2;
565 skeleton.skinText[where + 1] = 0;
566 skeleton.skinText[where + 2] = 0;
570 skeleton.drawmodel.textureptr.bind();
575 if (creature == rabbittype)
576 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) {
577 bleedxint = abs(Random() % 512);
578 bleedyint = abs(Random() % 512);
580 if (creature == wolftype)
581 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) {
582 bleedxint = abs(Random() % 512);
583 bleedyint = abs(Random() % 512);
585 bleedy = bleedxint + offsetx;
586 bleedx = bleedyint + offsety;
587 bleedy /= realtexdetail;
588 bleedx /= realtexdetail;
593 if (bleedx > skeleton.skinsize - 1)
594 bleedx = skeleton.skinsize - 1;
595 if (bleedy > skeleton.skinsize - 1)
596 bleedy = skeleton.skinsize - 1;
597 direction = abs(Random() % 2) * 2 - 1;
600 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
601 deathbleeding += bleeding;
602 bloodloss += bleeding * 3;
604 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
605 if (abs(Random() % 2) == 0) {
606 aitype = gethelptype;
609 aitype = attacktypecutoff;
617 * similar to DoBloodBig
619 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
623 static XYZ startpoint, endpoint, colpoint, movepoint;
624 static float rotationpoint;
626 static XYZ p1, p2, p3, p0;
630 float coordsx, coordsy;
633 if (bloodtoggle && decals && tutoriallevel != 1) {
636 where = DoRotation(where, 0, -yaw, 0);
644 // ray testing for a tri in the character model
645 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
646 if (whichtri != -1) {
647 // low level geometry math
649 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
650 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
651 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
653 CrossProduct(p2-p1,p3-p1,&N);
654 CrossProduct(p0-p1,p3-p1,&temp);
655 s = dotproduct(&temp,&N)/findLength(&N);
656 CrossProduct(p2-p1,p1-p0,&temp);
657 t = dotproduct(&temp,&N)/findLength(&N);
660 bary.x = distsq(&p0, &p1);
661 bary.y = distsq(&p0, &p2);
662 bary.z = distsq(&p0, &p3);
664 total = bary.x + bary.y + bary.z;
673 total = bary.x + bary.y + bary.z;
679 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
680 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
681 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
682 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
683 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
684 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
685 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;
686 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;
688 //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
689 //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
691 if (bleeding <= 0 && spurt) {
693 for (int i = 0; i < 3; i++) {
694 // emit blood particles
695 // FIXME: more copypaste code
697 if (!skeleton.free) {
699 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
702 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
705 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
707 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
709 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
710 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
712 if (!skeleton.free) {
713 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
714 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
719 // texture manipulation follows
721 int offsetx = 0, offsety = 0;
722 offsetx = (1 + coordsy) * 512 - 291;
723 offsety = coordsx * 512 - 437;
730 if (creature == rabbittype)
731 for (i = 0; i < 512; i++) {
732 for (j = 0; j < 512; j++) {
733 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
734 if (i < startx) startx = i;
735 if (j < starty) starty = j;
736 if (i > endx) endx = i;
737 if (j > endy) endy = j;
741 if (creature == wolftype)
742 for (i = 0; i < 512; i++) {
743 for (j = 0; j < 512; j++) {
744 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
745 if (i < startx) startx = i;
746 if (j < starty) starty = j;
747 if (i > endx) endx = i;
748 if (j > endy) endy = j;
757 if (startx < 0) startx = 0;
758 if (starty < 0) starty = 0;
759 if (endx > 512 - 1) endx = 512 - 1;
760 if (endy > 512 - 1) endy = 512 - 1;
761 if (endx < startx) endx = startx;
762 if (endy < starty) endy = starty;
764 startx /= realtexdetail;
765 starty /= realtexdetail;
766 endx /= realtexdetail;
767 endy /= realtexdetail;
769 int texdetailint = realtexdetail;
771 if (creature == rabbittype)
772 for (i = startx; i < endx; i++) {
773 for (j = starty; j < endy; j++) {
774 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) {
775 color = Random() % 85 + 170;
776 where = i * skeleton.skinsize * 3 + j * 3;
777 if (skeleton.skinText[where + 0] > color / 2)
778 skeleton.skinText[where + 0] = color / 2;
779 skeleton.skinText[where + 1] = 0;
780 skeleton.skinText[where + 2] = 0;
781 } 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) {
782 color = Random() % 85 + 170;
783 where = i * skeleton.skinsize * 3 + j * 3;
784 if (skeleton.skinText[where + 0] > color / 2)
785 skeleton.skinText[where + 0] = color / 2;
786 skeleton.skinText[where + 1] = 0;
787 skeleton.skinText[where + 2] = 0;
791 if (creature == wolftype)
792 for (i = startx; i < endx; i++) {
793 for (j = starty; j < endy; j++) {
794 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) {
795 color = Random() % 85 + 170;
796 where = i * skeleton.skinsize * 3 + j * 3;
797 if (skeleton.skinText[where + 0] > color / 2)
798 skeleton.skinText[where + 0] = color / 2;
799 skeleton.skinText[where + 1] = 0;
800 skeleton.skinText[where + 2] = 0;
801 } 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) {
802 color = Random() % 85 + 170;
803 where = i * skeleton.skinsize * 3 + j * 3;
804 if (skeleton.skinText[where + 0] > color / 2)
805 skeleton.skinText[where + 0] = color / 2;
806 skeleton.skinText[where + 1] = 0;
807 skeleton.skinText[where + 2] = 0;
811 skeleton.drawmodel.textureptr.bind();
814 bleedy = (1 + coordsy) * 512;
815 bleedx = coordsx * 512;
816 bleedy /= realtexdetail;
817 bleedx /= realtexdetail;
822 if (bleedx > skeleton.skinsize - 1)
823 bleedx = skeleton.skinsize - 1;
824 if (bleedy > skeleton.skinsize - 1)
825 bleedy = skeleton.skinsize - 1;
826 direction = abs(Random() % 2) * 2 - 1;
831 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
832 deathbleeding += bleeding;
833 bloodloss += bleeding * 3;
835 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
836 if (abs(Random() % 2) == 0) {
837 aitype = gethelptype;
840 aitype = attacktypecutoff;
851 * guessing this performs a reversal
853 void Person::Reverse()
855 if (!((victim->aitype == playercontrolled
857 || staggerdelay <= 0)
858 && victim->animTarget != jumpupanim
859 && victim->animTarget != jumpdownanim
860 && (tutoriallevel != 1 || cananger)
864 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
865 && (victim->id != 0 || difficulty >= 2)
866 && (creature != wolftype || victim->creature == wolftype))
869 if (animTarget == sweepanim) {
870 animTarget = sweepreversedanim;
871 animCurrent = sweepreversedanim;
872 victim->animCurrent = sweepreversalanim;
873 victim->animTarget = sweepreversalanim;
875 if (animTarget == spinkickanim) {
876 animTarget = spinkickreversedanim;
877 animCurrent = spinkickreversedanim;
878 victim->animCurrent = spinkickreversalanim;
879 victim->animTarget = spinkickreversalanim;
881 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
882 if (animTarget == rabbittacklinganim) {
885 victim->frameCurrent = 6;
886 victim->frameTarget = 7;
888 animTarget = upunchreversedanim;
889 animCurrent = upunchreversedanim;
890 victim->animCurrent = upunchreversalanim;
891 victim->animTarget = upunchreversalanim;
893 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
894 if (victim->weaponactive != -1) {
895 victim->throwtogglekeydown = 1;
896 XYZ tempVelocity = victim->velocity * .2;
897 if (tempVelocity.x == 0)
899 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
900 victim->num_weapons--;
901 if (victim->num_weapons) {
902 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
903 if (victim->weaponstuck == victim->num_weapons)
904 victim->weaponstuck = 0;
907 victim->weaponactive = -1;
908 for (unsigned j = 0; j < Person::players.size(); j++) {
909 Person::players[j]->wentforweapon = 0;
913 animTarget = staffhitreversedanim;
914 animCurrent = staffhitreversedanim;
915 victim->animCurrent = staffhitreversalanim;
916 victim->animTarget = staffhitreversalanim;
918 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
919 if (victim->weaponactive != -1) {
920 victim->throwtogglekeydown = 1;
921 XYZ tempVelocity = victim->velocity * .2;
922 if (tempVelocity.x == 0)
924 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
925 victim->num_weapons--;
926 if (victim->num_weapons) {
927 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
928 if (victim->weaponstuck == victim->num_weapons)
929 victim->weaponstuck = 0;
932 victim->weaponactive = -1;
933 for (unsigned j = 0; j < Person::players.size(); j++) {
934 Person::players[j]->wentforweapon = 0;
937 animTarget = staffspinhitreversedanim;
938 animCurrent = staffspinhitreversedanim;
939 victim->animCurrent = staffspinhitreversalanim;
940 victim->animTarget = staffspinhitreversalanim;
942 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
943 if (victim->weaponactive != -1) {
944 victim->throwtogglekeydown = 1;
945 XYZ tempVelocity = victim->velocity * .2;
946 if (tempVelocity.x == 0)
948 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
949 victim->num_weapons--;
950 if (victim->num_weapons) {
951 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
952 if (victim->weaponstuck == victim->num_weapons)
953 victim->weaponstuck = 0;
956 victim->weaponactive = -1;
957 for (unsigned j = 0; j < Person::players.size(); j++) {
958 Person::players[j]->wentforweapon = 0;
961 animTarget = swordslashreversedanim;
962 animCurrent = swordslashreversedanim;
963 victim->animCurrent = swordslashreversalanim;
964 victim->animTarget = swordslashreversalanim;
966 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
967 if (victim->weaponactive != -1) {
968 victim->throwtogglekeydown = 1;
969 XYZ tempVelocity = victim->velocity * .2;
970 if (tempVelocity.x == 0)
972 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
973 victim->num_weapons--;
974 if (victim->num_weapons) {
975 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
976 if (victim->weaponstuck == victim->num_weapons)
977 victim->weaponstuck = 0;
980 victim->weaponactive = -1;
981 for (unsigned j = 0; j < Person::players.size(); j++) {
982 Person::players[j]->wentforweapon = 0;
985 animTarget = knifeslashreversedanim;
986 animCurrent = knifeslashreversedanim;
987 victim->animCurrent = knifeslashreversalanim;
988 victim->animTarget = knifeslashreversalanim;
990 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
991 victim->targettilt2 = targettilt2;
992 victim->frameCurrent = frameCurrent;
993 victim->frameTarget = frameTarget;
994 victim->target = target;
995 victim->velocity = 0;
996 victim->oldcoords = victim->coords;
997 victim->coords = coords;
998 victim->targetyaw = targetyaw;
999 victim->yaw = targetyaw;
1000 victim->victim = this->shared_from_this();
1002 if (animTarget == winduppunchanim) {
1003 animTarget = winduppunchblockedanim;
1004 victim->animTarget = blockhighleftanim;
1005 victim->frameTarget = 1;
1006 victim->target = .5;
1007 victim->victim = this->shared_from_this();
1008 victim->targetyaw = targetyaw + 180;
1010 if (animTarget == wolfslapanim) {
1011 animTarget = winduppunchblockedanim;
1012 victim->animTarget = blockhighleftanim;
1013 victim->frameTarget = 1;
1014 victim->target = .5;
1015 victim->victim = this->shared_from_this();
1016 victim->targetyaw = targetyaw + 180;
1018 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
1019 animTarget = swordslashparriedanim;
1020 parriedrecently = .4;
1021 victim->parriedrecently = 0;
1022 victim->animTarget = swordslashparryanim;
1023 victim->frameTarget = 1;
1024 victim->target = .5;
1025 victim->victim = this->shared_from_this();
1026 victim->targetyaw = targetyaw + 180;
1028 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
1029 if (victim->weaponactive != -1) {
1030 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1031 if (weapons[victim->weaponids[0]].getType() == staff)
1032 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1033 if (weapons[weaponids[0]].getType() == staff)
1034 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1035 emit_sound_at(swordstaffsound, victim->coords);
1037 emit_sound_at(metalhitsound, victim->coords);
1041 victim->Puff(righthand);
1043 victim->frameTarget = 0;
1044 victim->animTarget = staggerbackhighanim;
1045 victim->targetyaw = targetyaw + 180;
1047 aim = DoRotation(facing, 0, 90, 0) * 21;
1049 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1050 victim->num_weapons--;
1051 if (victim->num_weapons) {
1052 victim->weaponids[0] = victim->weaponids[num_weapons];
1053 if (victim->weaponstuck == victim->num_weapons)
1054 victim->weaponstuck = 0;
1056 victim->weaponactive = -1;
1057 for (unsigned i = 0; i < Person::players.size(); i++) {
1058 Person::players[i]->wentforweapon = 0;
1062 if (abs(Random() % 20) == 0) {
1063 if (weaponactive != -1) {
1064 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1065 if (weapons[victim->weaponids[0]].getType() == staff)
1066 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1067 if (weapons[weaponids[0]].getType() == staff)
1068 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1070 emit_sound_at(swordstaffsound, coords);
1072 emit_sound_at(metalhitsound, coords);
1080 animTarget = staggerbackhighanim;
1081 targetyaw = targetyaw + 180;
1083 aim = DoRotation(facing, 0, 90, 0) * 21;
1085 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1088 weaponids[0] = weaponids[num_weapons];
1089 if (weaponstuck == num_weapons)
1093 for (unsigned i = 0; i < Person::players.size(); i++) {
1094 Person::players[i]->wentforweapon = 0;
1101 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1102 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1103 victim->animTarget = dodgebackanim;
1104 victim->frameTarget = 0;
1108 rotatetarget = coords - victim->coords;
1109 Normalise(&rotatetarget);
1110 victim->targetyaw = -asin(0 - rotatetarget.x);
1111 victim->targetyaw *= 360 / 6.28;
1112 if (rotatetarget.z < 0)
1113 victim->targetyaw = 180 - victim->targetyaw;
1115 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1117 victim->lastattack3 = victim->lastattack2;
1118 victim->lastattack2 = victim->lastattack;
1119 victim->lastattack = victim->animTarget;
1121 victim->animTarget = sweepanim;
1122 victim->frameTarget = 0;
1126 rotatetarget = coords - victim->coords;
1127 Normalise(&rotatetarget);
1128 victim->targetyaw = -asin(0 - rotatetarget.x);
1129 victim->targetyaw *= 360 / 6.28;
1130 if (rotatetarget.z < 0)
1131 victim->targetyaw = 180 - victim->targetyaw;
1133 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1135 victim->lastattack3 = victim->lastattack2;
1136 victim->lastattack2 = victim->lastattack;
1137 victim->lastattack = victim->animTarget;
1142 victim->velocity = 0;
1144 if (aitype != playercontrolled)
1146 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1148 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1150 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1153 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1160 void Person::DoDamage(float howmuch)
1162 // subtract health (temporary?)
1163 if (tutoriallevel != 1)
1164 damage += howmuch / power;
1167 damagedealt += howmuch / power;
1169 damagetaken += howmuch / power;
1172 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1175 if (tutoriallevel != 1)
1176 permanentdamage += howmuch / 2 / power;
1177 if (tutoriallevel != 1)
1178 superpermanentdamage += howmuch / 4 / power;
1180 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1182 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1186 camerashake += howmuch / 100;
1187 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1188 blackout = damage / damagetolerance;
1193 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1194 aitype = attacktypecutoff;
1195 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1196 if (abs(Random() % 2) == 0) {
1197 aitype = gethelptype;
1200 aitype = attacktypecutoff;
1204 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1207 for (int i = 0; i < skeleton.num_joints; i++) {
1209 flatvelocity2 = velocity;
1211 flatvelocity2 = skeleton.joints[i].velocity;
1213 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1215 flatfacing2 = skeleton.joints[i].position * scale + coords;
1216 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1217 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1218 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1219 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1220 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1221 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1224 emit_sound_at(splattersound, coords);
1229 if (!dead && creature == wolftype) {
1230 award_bonus(0, Wolfbonus);
1237 if (tutoriallevel != 1 || id == 0)
1238 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1239 int whichsound = -1;
1241 if (creature == wolftype) {
1242 int i = abs(Random() % 2);
1244 whichsound = snarlsound;
1246 whichsound = snarl2sound;
1247 envsound[numenvsounds] = coords;
1248 envsoundvol[numenvsounds] = 16;
1249 envsoundlife[numenvsounds] = .4;
1252 if (creature == rabbittype) {
1253 int i = abs(Random() % 2);
1255 whichsound = rabbitpainsound;
1256 if (i == 1 && damage > damagetolerance)
1257 whichsound = rabbitpain1sound;
1258 envsound[numenvsounds] = coords;
1259 envsoundvol[numenvsounds] = 16;
1260 envsoundlife[numenvsounds] = .4;
1264 if (whichsound != -1) {
1265 emit_sound_at(whichsound, coords);
1272 * calculate/animate head facing direction?
1274 void Person::DoHead()
1276 static XYZ rotatearound;
1278 static float lookspeed = 500;
1280 if (!freeze && !winfreeze) {
1283 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1284 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1286 while (targetheadyaw > 180)targetheadyaw -= 360;
1287 while (targetheadyaw < -180)targetheadyaw += 360;
1289 if (targetheadyaw > 160)
1290 targetheadpitch = targetheadpitch * -1;
1291 if (targetheadyaw < -160)
1292 targetheadpitch = targetheadpitch * -1;
1293 if (targetheadyaw > 160)
1294 targetheadyaw = targetheadyaw - 180;
1295 if (targetheadyaw < -160)
1296 targetheadyaw = targetheadyaw + 180;
1298 if (targetheadpitch > 120)
1299 targetheadpitch = 120;
1300 if (targetheadpitch < -120)
1301 targetheadpitch = -120;
1302 if (targetheadyaw > 120)
1303 targetheadyaw = 120;
1304 if (targetheadyaw < -120)
1305 targetheadyaw = -120;
1308 targetheadpitch = 0;
1310 if (targetheadyaw > 80)
1312 if (targetheadyaw < -80)
1313 targetheadyaw = -80;
1314 if (targetheadpitch > 50)
1315 targetheadpitch = 50;
1316 if (targetheadpitch < -50)
1317 targetheadpitch = -50;
1320 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1321 headyaw = targetheadyaw;
1322 else if (headyaw > targetheadyaw) {
1323 headyaw -= multiplier * lookspeed;
1324 } else if (headyaw < targetheadyaw) {
1325 headyaw += multiplier * lookspeed;
1328 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1329 headpitch = targetheadpitch;
1330 else if (headpitch > targetheadpitch) {
1331 headpitch -= multiplier * lookspeed / 2;
1332 } else if (headpitch < targetheadpitch) {
1333 headpitch += multiplier * lookspeed / 2;
1336 rotatearound = jointPos(neck);
1337 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1341 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1342 facing = DoRotation(facing, headpitch * .4, 0, 0);
1343 facing = DoRotation(facing, 0, headyaw * .4, 0);
1346 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1347 facing = DoRotation(facing, headpitch * .8, 0, 0);
1348 facing = DoRotation(facing, 0, headyaw * .8, 0);
1351 if (animTarget == walkanim) {
1352 facing = DoRotation(facing, headpitch * .6, 0, 0);
1353 facing = DoRotation(facing, 0, headyaw * .6, 0);
1356 skeleton.specialforward[0] = facing;
1357 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1358 for (int i = 0; i < skeleton.num_muscles; i++) {
1359 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1360 skeleton.FindRotationMuscle(i, animTarget);
1367 * ragdolls character?
1369 void Person::RagDoll(bool checkcollision)
1374 if (!skeleton.free) {
1377 if (id == 0 && isFlip())
1384 facing = DoRotation(facing, 0, yaw, 0);
1386 skeleton.freetime = 0;
1388 skeleton.longdead = 0;
1391 skeleton.broken = 0;
1392 skeleton.spinny = 1;
1394 skeleton.freefall = 1;
1396 if (!isnormal(velocity.x)) velocity.x = 0;
1397 if (!isnormal(velocity.y)) velocity.y = 0;
1398 if (!isnormal(velocity.z)) velocity.z = 0;
1399 if (!isnormal(yaw)) yaw = 0;
1400 if (!isnormal(coords.x)) coords = 0;
1401 if (!isnormal(tilt)) tilt = 0;
1402 if (!isnormal(tilt2)) tilt2 = 0;
1404 for (int i = 0; i < skeleton.num_joints; i++) {
1405 skeleton.joints[i].delay = 0;
1406 skeleton.joints[i].locked = 0;
1407 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1408 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1409 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1410 skeleton.joints[i].position.y += .1;
1411 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1412 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1415 for (int i = 0; i < skeleton.num_joints; i++) {
1416 skeleton.joints[i].velocity = 0;
1417 skeleton.joints[i].velchange = 0;
1419 skeleton.DoConstraints(&coords, &scale);
1420 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1421 skeleton.DoConstraints(&coords, &scale);
1422 skeleton.DoConstraints(&coords, &scale);
1423 skeleton.DoConstraints(&coords, &scale);
1424 skeleton.DoConstraints(&coords, &scale);
1427 speed = animation[animTarget].speed[frameTarget] * 2;
1428 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1429 speed = animation[animCurrent].speed[frameCurrent] * 2;
1432 speed = transspeed * 2;
1436 for (int i = 0; i < skeleton.num_joints; i++) {
1437 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1438 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);
1440 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1441 change.x = (float)(Random() % 100) / 100;
1442 change.y = (float)(Random() % 100) / 100;
1443 change.z = (float)(Random() % 100) / 100;
1444 skeleton.joints[i].velocity += change;
1445 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1447 change.x = (float)(Random() % 100) / 100;
1448 change.y = (float)(Random() % 100) / 100;
1449 change.z = (float)(Random() % 100) / 100;
1450 skeleton.joints[i].velchange += change;
1451 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1454 if (checkcollision) {
1461 for (j = 0; j < skeleton.num_joints; j++) {
1462 average += skeleton.joints[j].position;
1466 coords += average * scale;
1467 for (j = 0; j < skeleton.num_joints; j++) {
1468 skeleton.joints[j].position -= average;
1471 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1472 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1473 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1474 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1475 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1478 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1479 coords.x = lowpoint.x;
1480 coords.z = lowpoint.z;
1489 for (int i = 0; i < skeleton.num_joints; i++) {
1490 velocity += skeleton.joints[i].velocity * scale;
1492 velocity /= skeleton.num_joints;
1495 if (Random() % 2 == 0) {
1496 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1497 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1498 weapons[weaponids[0]].velocity.x += .01;
1501 weaponids[0] = weaponids[num_weapons];
1502 if (weaponstuck == num_weapons)
1506 for (unsigned i = 0; i < Person::players.size(); i++) {
1507 Person::players[i]->wentforweapon = 0;
1512 animTarget = bounceidleanim;
1513 animCurrent = bounceidleanim;
1523 void Person::FootLand(int which, float opacity)
1525 static XYZ terrainlight;
1526 static XYZ footvel, footpoint;
1527 if (opacity >= 1 || skiddelay <= 0)
1531 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1533 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1534 //footpoint.y=coords.y;
1535 if (distsq(&footpoint, &viewer))
1536 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1537 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1538 footvel = velocity / 5;
1542 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1544 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1545 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1546 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1547 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1548 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1549 if (opacity >= 1 || detail == 2)
1551 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1552 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1553 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1554 footvel = velocity / 5;
1558 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1560 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1561 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1562 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1563 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1564 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1565 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1566 footvel = velocity / 5;
1570 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1572 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1573 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1574 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1575 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1576 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1577 if (opacity >= 1 || detail == 2)
1579 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1580 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1581 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1582 footvel = velocity / 5;
1586 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1588 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1589 //footpoint.y=coords.y;
1590 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1591 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1596 * make a puff effect at a body part (dust effect?)
1598 void Person::Puff(int whichlabel)
1600 static XYZ footvel, footpoint;
1603 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1604 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1608 * I think I added this in an attempt to clean up code
1610 void Person::setAnimation(int animation)
1612 animTarget = animation;
1621 void Person::DoAnimations()
1623 if (!skeleton.free) {
1624 static float oldtarget;
1626 if (isIdle() && animCurrent != getIdle())
1627 normalsupdatedelay = 0;
1629 if (animTarget == tempanim || animCurrent == tempanim) {
1630 animation[tempanim] = tempanimation;
1632 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1638 vel[0] = velocity.x;
1639 vel[1] = velocity.y;
1640 vel[2] = velocity.z;
1643 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1644 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1646 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1648 if (!crouchkeydown && velocity.y >= -15)
1651 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1656 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1658 if (normaldotproduct(targfacing, velocity) >= -.3)
1659 animTarget = flipanim;
1661 animTarget = backflipanim;
1662 crouchtogglekeydown = 1;
1670 if (animation[animTarget].attack != reversed)
1672 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1673 crouchtogglekeydown = 0;
1674 if (aitype == playercontrolled)
1677 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1680 crouchtogglekeydown = 1;
1684 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1686 normalsupdatedelay = 0;
1690 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1692 emit_sound_at(fireendsound, coords);
1693 pause_sound(stream_firesound);
1697 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1698 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1700 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1701 if (normaldotproduct(victim->facing, facing) > 0)
1702 victim->animTarget = rabbittackledbackanim;
1704 victim->animTarget = rabbittackledfrontanim;
1705 victim->frameTarget = 2;
1708 victim->targetyaw = yaw;
1709 if (victim->aitype == gethelptype)
1710 victim->DoDamage(victim->damagetolerance - victim->damage);
1711 //victim->DoDamage(30);
1712 if (creature == wolftype) {
1714 emit_sound_at(clawslicesound, victim->coords);
1716 victim->DoBloodBig(1 / victim->armorhead, 210);
1718 award_bonus(id, TackleBonus,
1719 victim->aitype == gethelptype ? 50 : 0);
1723 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1724 if (weapons[weaponids[0]].getType() == knife) {
1725 if (weaponactive == -1)
1727 else if (weaponactive == 0)
1730 if (weaponactive == -1) {
1731 emit_sound_at(knifesheathesound, coords);
1733 if (weaponactive != -1) {
1734 emit_sound_at(knifedrawsound, coords, 128);
1737 drawtogglekeydown = 1;
1740 if (tutoriallevel != 1 || id == 0)
1741 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1744 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1745 if (animation[animTarget].label[frameTarget] == 1)
1746 whichsound = footstepsound;
1748 whichsound = footstepsound2;
1749 if (animation[animTarget].label[frameTarget] == 1)
1751 if (animation[animTarget].label[frameTarget] == 2)
1753 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1759 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1760 if (animation[animTarget].label[frameTarget] == 1)
1761 whichsound = footstepsound3;
1763 whichsound = footstepsound4;
1767 if (animation[animTarget].label[frameTarget] == 1)
1768 whichsound = footstepsound3;
1770 whichsound = footstepsound4;
1772 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1773 if (animation[animTarget].attack != neutral) {
1774 unsigned r = abs(Random() % 3);
1776 whichsound = lowwhooshsound;
1778 whichsound = midwhooshsound;
1780 whichsound = highwhooshsound;
1782 if (animation[animTarget].attack == neutral)
1783 whichsound = movewhooshsound;
1784 } else if (animation[animTarget].label[frameTarget] == 4)
1785 whichsound = knifeswishsound;
1786 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1787 whichsound = landsound2;
1789 emit_sound_at(whichsound, coords, 256.);
1792 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1793 envsound[numenvsounds] = coords;
1794 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1795 envsoundvol[numenvsounds] = 15;
1797 envsoundvol[numenvsounds] = 6;
1798 envsoundlife[numenvsounds] = .4;
1802 if (animation[animTarget].label[frameTarget] == 3) {
1804 emit_sound_at(whichsound, coords, 128.);
1809 if (tutoriallevel != 1 || id == 0)
1810 if (speechdelay <= 0)
1811 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1812 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1813 int whichsound = -1;
1814 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1815 if (animation[animTarget].attack != neutral) {
1816 unsigned r = abs(Random() % 4);
1817 if (creature == rabbittype) {
1818 if (r == 0) whichsound = rabbitattacksound;
1819 if (r == 1) whichsound = rabbitattack2sound;
1820 if (r == 2) whichsound = rabbitattack3sound;
1821 if (r == 3) whichsound = rabbitattack4sound;
1823 if (creature == wolftype) {
1824 if (r == 0) whichsound = barksound;
1825 if (r == 1) whichsound = bark2sound;
1826 if (r == 2) whichsound = bark3sound;
1827 if (r == 3) whichsound = barkgrowlsound;
1833 if (whichsound != -1) {
1834 emit_sound_at(whichsound, coords);
1840 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1846 currentoffset = targetoffset;
1847 frameTarget = frameCurrent;
1848 animCurrent = animTarget;
1851 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1852 for (unsigned i = 0; i < weapons.size(); i++) {
1853 if (weapons[i].owner == -1)
1854 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1855 if (distsq(&coords, &weapons[i].position) >= 1) {
1856 if (weapons[i].getType() != staff) {
1857 emit_sound_at(knifedrawsound, coords, 128.);
1861 weapons[i].owner = id;
1862 if (num_weapons > 0) {
1863 weaponids[num_weapons] = weaponids[0];
1872 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1873 for (unsigned i = 0; i < weapons.size(); i++) {
1874 bool willwork = true;
1875 if (weapons[i].owner != -1)
1876 if (Person::players[weapons[i].owner]->weaponstuck != -1)
1877 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
1878 if (Person::players[weapons[i].owner]->num_weapons > 1)
1880 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
1881 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1882 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1883 bool fleshstuck = false;
1884 if (weapons[i].owner != -1)
1885 if (victim->weaponstuck != -1) {
1886 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1891 emit_sound_at(fleshstabremovesound, coords, 128.);
1893 if (weapons[i].getType() != staff) {
1894 emit_sound_at(knifedrawsound, coords, 128.);
1898 if (weapons[i].owner != -1) {
1900 victim = Person::players[weapons[i].owner];
1901 if (victim->num_weapons == 1)
1902 victim->num_weapons = 0;
1904 victim->num_weapons = 1;
1906 //victim->weaponactive=-1;
1907 victim->skeleton.longdead = 0;
1908 victim->skeleton.free = 1;
1909 victim->skeleton.broken = 0;
1911 for (int j = 0; j < victim->skeleton.num_joints; j++) {
1912 victim->skeleton.joints[j].velchange = 0;
1913 victim->skeleton.joints[j].locked = 0;
1919 Normalise(&relative);
1920 XYZ footvel, footpoint;
1922 footpoint = weapons[i].position;
1923 if (victim->weaponstuck != -1) {
1924 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1926 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
1927 weapons[i].bloody = 2;
1928 weapons[i].blooddrip = 5;
1929 victim->weaponstuck = -1;
1932 if (victim->num_weapons > 0) {
1933 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
1934 victim->weaponstuck = 0;
1935 if (victim->weaponids[0] == int(i))
1936 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1939 victim->jointVel(abdomen) += relative * 6;
1940 victim->jointVel(neck) += relative * 6;
1941 victim->jointVel(rightshoulder) += relative * 6;
1942 victim->jointVel(leftshoulder) += relative * 6;
1944 weapons[i].owner = id;
1945 if (num_weapons > 0) {
1946 weaponids[num_weapons] = weaponids[0];
1955 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
1956 if (weaponactive == -1)
1958 else if (weaponactive == 0) {
1960 if (num_weapons == 2) {
1962 buffer = weaponids[0];
1963 weaponids[0] = weaponids[1];
1964 weaponids[1] = buffer;
1967 if (weaponactive == -1) {
1968 emit_sound_at(knifesheathesound, coords, 128.);
1970 if (weaponactive != -1) {
1971 emit_sound_at(knifedrawsound, coords, 128.);
1976 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
1977 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
1978 Normalise(&rotatetarget);
1979 targetyaw = -asin(0 - rotatetarget.x);
1980 targetyaw *= 360 / 6.28;
1981 if (rotatetarget.z < 0)
1982 targetyaw = 180 - targetyaw;
1984 if (animTarget == walljumprightkickanim)
1986 if (animTarget == walljumpleftkickanim)
1992 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
1995 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
2000 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
2001 animTarget = rabbittackleanim;
2003 emit_sound_at(jumpsound, coords);
2011 targetloc = velocity;
2012 Normalise(&targetloc);
2013 targetloc += coords;
2014 for (unsigned i = 0; i < Person::players.size(); i++) {
2016 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
2017 closestdist = distsq(&targetloc, &Person::players[i]->coords);
2021 if (closestid != -1)
2022 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
2024 victim = Person::players[closestid];
2025 coords = victim->coords;
2026 animCurrent = rabbittacklinganim;
2027 animTarget = rabbittacklinganim;
2031 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
2032 rotatetarget = coords - victim->coords;
2033 Normalise(&rotatetarget);
2034 targetyaw = -asin(0 - rotatetarget.x);
2035 targetyaw *= 360 / 6.28;
2036 if (rotatetarget.z < 0)
2037 targetyaw = 180 - targetyaw;
2039 if (animTarget != rabbitrunninganim) {
2040 emit_sound_at(jumpsound, coords, 128.);
2046 float damagemult = 1 * power;
2047 if (creature == wolftype)
2048 damagemult = 2.5 * power;
2050 damagemult /= victim->damagetolerance / 200;
2052 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2053 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2054 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2058 if (Random() % 2 || creature == wolftype) {
2061 if (creature == wolftype)
2064 if (tutoriallevel != 1) {
2065 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2067 if (creature == wolftype) {
2068 emit_sound_at(clawslicesound, victim->coords, 128.);
2070 victim->DoBloodBig(2 / victim->armorhead, 175);
2074 relative = victim->coords - coords;
2076 Normalise(&relative);
2077 relative = DoRotation(relative, 0, -90, 0);
2078 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2079 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2081 victim->jointVel(head) += relative * damagemult * 200;
2084 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2090 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2091 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2095 if (Random() % 2 || creature == wolftype) {
2097 if (creature == wolftype)
2100 emit_sound_at(whooshhitsound, victim->coords);
2101 if (creature == wolftype) {
2102 emit_sound_at(clawslicesound, victim->coords, 128.);
2104 victim->DoBloodBig(2, 175);
2108 relative = victim->coords - coords;
2110 Normalise(&relative);
2112 Normalise(&relative);
2113 relative = DoRotation(relative, 0, 90, 0);
2114 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2115 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2117 victim->jointVel(head) += relative * damagemult * 100;
2120 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2124 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2125 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2131 if (tutoriallevel != 1) {
2132 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2134 if (creature == wolftype) {
2135 emit_sound_at(clawslicesound, victim->coords, 128.);
2137 victim->DoBloodBig(2 / victim->armorhead, 175);
2143 Normalise(&relative);
2144 relative = DoRotation(relative, 0, -90, 0);
2145 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2146 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2148 victim->jointVel(head) += relative * damagemult * 200;
2151 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2153 if (victim->damage > victim->damagetolerance)
2154 award_bonus(id, style);
2160 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2161 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2167 if (tutoriallevel != 1) {
2168 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2170 if (creature == wolftype) {
2171 emit_sound_at(clawslicesound, victim->coords, 128.);
2173 victim->DoBloodBig(2 / victim->armorhead, 175);
2179 Normalise(&relative);
2180 relative = DoRotation(relative, 0, 90, 0);
2181 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2182 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2184 victim->jointVel(head) += relative * damagemult * 200;
2187 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2189 if (victim->damage > victim->damagetolerance)
2190 award_bonus(id, style);
2196 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2197 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2205 emit_sound_at(whooshhitsound, victim->coords);
2208 relative = victim->coords - coords;
2210 Normalise(&relative);
2211 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2212 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2214 victim->jointVel(head) += relative * damagemult * 100;
2217 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2221 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2222 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2226 emit_sound_at(whooshhitsound, victim->coords, 128.);
2228 victim->skeleton.longdead = 0;
2229 victim->skeleton.free = 1;
2230 victim->skeleton.broken = 0;
2231 victim->skeleton.spinny = 1;
2233 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2234 victim->skeleton.joints[i].velchange = 0;
2235 victim->skeleton.joints[i].delay = 0;
2236 victim->skeleton.joints[i].locked = 0;
2237 //victim->skeleton.joints[i].velocity=0;
2243 Normalise(&relative);
2244 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2245 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2246 victim->skeleton.joints[i].position.y += relative.y * .3;
2247 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2248 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2250 victim->Puff(abdomen);
2251 victim->jointVel(abdomen).y = relative.y * 400;
2255 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2256 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2260 if (tutoriallevel != 1) {
2261 emit_sound_at(heavyimpactsound, coords, 128.);
2264 relative = victim->coords - coords;
2266 Normalise(&relative);
2267 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2268 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2270 victim->Puff(abdomen);
2271 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2275 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2276 victim->jointVel(abdomen) += relative * damagemult * 300;
2280 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2281 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2285 if (tutoriallevel != 1) {
2286 emit_sound_at(thudsound, coords);
2289 victim->skeleton.longdead = 0;
2290 victim->skeleton.free = 1;
2291 victim->skeleton.broken = 0;
2292 victim->skeleton.spinny = 1;
2294 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2295 victim->skeleton.joints[i].velchange = 0;
2296 //victim->skeleton.joints[i].delay=0;
2297 victim->skeleton.joints[i].locked = 0;
2300 relative = victim->coords - coords;
2301 Normalise(&relative);
2303 Normalise(&relative);
2304 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2305 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2310 victim->Puff(abdomen);
2311 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2312 victim->jointVel(abdomen) += relative * damagemult * 200;
2321 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2324 if (!victim->skeleton.free)
2328 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2329 emit_sound_at(knifesheathesound, coords, 128.);
2332 if (victim && hasvictim) {
2333 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2335 XYZ where, startpoint, endpoint, movepoint, colpoint;
2336 float rotationpoint;
2338 if (weapons[weaponids[weaponactive]].getType() == knife) {
2339 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2340 where -= victim->coords;
2341 if (!victim->skeleton.free)
2342 where = DoRotation(where, 0, -victim->yaw, 0);
2345 startpoint.y += 100;
2349 if (weapons[weaponids[weaponactive]].getType() == sword) {
2350 where = weapons[weaponids[weaponactive]].position;
2351 where -= victim->coords;
2352 if (!victim->skeleton.free)
2353 where = DoRotation(where, 0, -victim->yaw, 0);
2355 where = weapons[weaponids[weaponactive]].tippoint;
2356 where -= victim->coords;
2357 if (!victim->skeleton.free)
2358 where = DoRotation(where, 0, -victim->yaw, 0);
2361 if (weapons[weaponids[weaponactive]].getType() == staff) {
2362 where = weapons[weaponids[weaponactive]].position;
2363 where -= victim->coords;
2364 if (!victim->skeleton.free)
2365 where = DoRotation(where, 0, -victim->yaw, 0);
2367 where = weapons[weaponids[weaponactive]].tippoint;
2368 where -= victim->coords;
2369 if (!victim->skeleton.free)
2370 where = DoRotation(where, 0, -victim->yaw, 0);
2375 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2377 if (whichtri != -1) {
2378 if (victim->dead != 2) {
2379 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2381 award_bonus(id, FinishedBonus);
2384 weapons[weaponids[weaponactive]].bloody = 2;
2386 victim->skeleton.longdead = 0;
2387 victim->skeleton.free = 1;
2388 victim->skeleton.broken = 0;
2390 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2391 victim->skeleton.joints[i].velchange = 0;
2392 victim->skeleton.joints[i].locked = 0;
2393 //victim->skeleton.joints[i].velocity=0;
2395 emit_sound_at(fleshstabsound, coords, 128);
2398 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2399 weapons[weaponids[weaponactive]].blooddrip += 5;
2400 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2402 if (whichtri == -1) {
2404 emit_sound_at(knifesheathesound, coords, 128.);
2410 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2412 emit_sound_at(knifedrawsound, coords, 128);
2415 if (victim && hasvictim) {
2416 XYZ footvel, footpoint;
2418 emit_sound_at(fleshstabremovesound, coords, 128.);
2421 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2423 if (weapons[weaponids[weaponactive]].getType() == sword) {
2424 XYZ where, startpoint, endpoint, movepoint;
2425 float rotationpoint;
2428 where = weapons[weaponids[weaponactive]].position;
2429 where -= victim->coords;
2430 if (!victim->skeleton.free)
2431 where = DoRotation(where, 0, -victim->yaw, 0);
2433 where = weapons[weaponids[weaponactive]].tippoint;
2434 where -= victim->coords;
2435 if (!victim->skeleton.free)
2436 where = DoRotation(where, 0, -victim->yaw, 0);
2441 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2442 footpoint += victim->coords;
2444 if (whichtri == -1) {
2445 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2448 if (weapons[weaponids[weaponactive]].getType() == staff) {
2449 XYZ where, startpoint, endpoint, movepoint;
2450 float rotationpoint;
2453 where = weapons[weaponids[weaponactive]].position;
2454 where -= victim->coords;
2455 if (!victim->skeleton.free)
2456 where = DoRotation(where, 0, -victim->yaw, 0);
2458 where = weapons[weaponids[weaponactive]].tippoint;
2459 where -= victim->coords;
2460 if (!victim->skeleton.free)
2461 where = DoRotation(where, 0, -victim->yaw, 0);
2466 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2467 footpoint += victim->coords;
2469 if (whichtri == -1) {
2470 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2473 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2475 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2476 victim->skeleton.longdead = 0;
2477 victim->skeleton.free = 1;
2478 victim->skeleton.broken = 0;
2480 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2481 victim->skeleton.joints[i].velchange = 0;
2482 victim->skeleton.joints[i].locked = 0;
2483 //victim->skeleton.joints[i].velocity=0;
2489 Normalise(&relative);
2490 //victim->Puff(abdomen);
2492 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2494 if (victim->bloodloss < victim->damagetolerance) {
2495 victim->bloodloss += 1000;
2499 victim->jointVel(abdomen) += relative * damagemult * 20;
2503 if (!hasvictim && onterrain) {
2504 weapons[weaponids[weaponactive]].bloody = 0;
2505 weapons[weaponids[weaponactive]].blooddrip = 0;
2509 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2510 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2518 if (tutoriallevel != 1) {
2519 emit_sound_at(heavyimpactsound, victim->coords, 128);
2524 relative = victim->coords - coords;
2526 Normalise(&relative);
2527 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2528 victim->skeleton.joints[i].velocity = relative * 30;
2530 victim->jointVel(head) += relative * damagemult * 150;
2532 victim->frameTarget = 0;
2533 victim->animTarget = staggerbackhardanim;
2534 victim->targetyaw = targetyaw + 180;
2536 victim->stunned = 1;
2539 victim->Puff(abdomen);
2540 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2547 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2548 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2552 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2553 if (tutoriallevel != 1) {
2554 emit_sound_at(thudsound, victim->coords);
2556 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2557 if (tutoriallevel != 1) {
2558 emit_sound_at(whooshhitsound, victim->coords);
2561 if (tutoriallevel != 1) {
2562 emit_sound_at(heavyimpactsound, victim->coords);
2566 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2569 relative = victim->coords - coords;
2571 Normalise(&relative);
2573 Normalise(&relative);
2574 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2575 victim->skeleton.joints[i].velocity = relative * 5;
2577 victim->jointVel(abdomen) += relative * damagemult * 400;
2579 victim->frameTarget = 0;
2580 victim->animTarget = staggerbackhardanim;
2581 victim->targetyaw = targetyaw + 180;
2583 victim->stunned = 1;
2585 victim->Puff(abdomen);
2586 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2592 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2593 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2594 if (victim->id == 0)
2596 emit_sound_at(landsound2, victim->coords);
2602 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2603 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2604 if (victim->id == 0)
2607 if (weaponactive != -1) {
2608 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2609 if (weapons[victim->weaponids[0]].getType() == staff)
2610 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2611 if (weapons[weaponids[0]].getType() == staff)
2612 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2614 emit_sound_at(swordstaffsound, victim->coords);
2616 emit_sound_at(metalhitsound, victim->coords);
2624 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2625 if (weaponactive != -1) {
2628 weapons[weaponids[0]].owner = -1;
2629 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);
2631 weapons[weaponids[0]].velocity = aim * 50;
2632 weapons[weaponids[0]].tipvelocity = aim * 50;
2633 weapons[weaponids[0]].missed = 0;
2634 weapons[weaponids[0]].hitsomething = 0;
2635 weapons[weaponids[0]].freetime = 0;
2636 weapons[weaponids[0]].firstfree = 1;
2637 weapons[weaponids[0]].physics = 0;
2640 weaponids[0] = weaponids[num_weapons];
2646 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2648 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2650 if (tutoriallevel != 1)
2651 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2653 award_bonus(id, Slicebonus);
2654 if (tutoriallevel != 1) {
2655 emit_sound_at(knifeslicesound, victim->coords);
2657 //victim->jointVel(abdomen)+=relative*damagemult*200;
2658 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2659 if (victim->id != 0 || difficulty == 2) {
2660 victim->frameTarget = 0;
2661 victim->animTarget = staggerbackhardanim;
2662 victim->targetyaw = targetyaw + 180;
2666 victim->lowreversaldelay = 0;
2667 victim->highreversaldelay = 0;
2668 if (aitype != playercontrolled)
2669 weaponmissdelay = .6;
2671 if (tutoriallevel != 1)
2672 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2673 weapons[weaponids[weaponactive]].bloody = 1;
2674 if (tutoriallevel != 1)
2675 weapons[weaponids[weaponactive]].blooddrip += 3;
2677 XYZ footvel, footpoint;
2679 if (skeleton.free) {
2680 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2682 if (!skeleton.free) {
2683 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2685 if (tutoriallevel != 1) {
2687 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2688 footvel = DoRotation(facing, 0, 90, 0) * .8;
2690 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2691 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2692 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2693 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2695 if (tutoriallevel == 1) {
2696 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2698 victim->DoDamage(damagemult * 0);
2701 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2702 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2703 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2704 award_bonus(id, Slashbonus);
2706 if (tutoriallevel != 1) {
2707 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2708 victim->DoBloodBig(2 / victim->armorhigh, 190);
2710 victim->DoBloodBig(2 / victim->armorhigh, 185);
2711 victim->deathbleeding = 1;
2712 emit_sound_at(swordslicesound, victim->coords);
2714 //victim->jointVel(abdomen)+=relative*damagemult*200;
2715 if (tutoriallevel != 1) {
2716 victim->frameTarget = 0;
2717 victim->animTarget = staggerbackhardanim;
2718 victim->targetyaw = targetyaw + 180;
2722 if (tutoriallevel != 1) {
2723 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2724 weapons[weaponids[weaponactive]].bloody = 1;
2725 weapons[weaponids[weaponactive]].blooddrip += 3;
2727 float bloodlossamount;
2728 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2729 victim->bloodloss += bloodlossamount / victim->armorhigh;
2730 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2731 victim->DoDamage(damagemult * 0);
2733 XYZ footvel, footpoint;
2735 if (skeleton.free) {
2736 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2738 if (!skeleton.free) {
2739 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2742 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2743 footvel = DoRotation(facing, 0, 90, 0) * .8;
2745 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2746 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2747 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2748 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2751 if (victim->weaponactive != -1) {
2752 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2753 if (weapons[victim->weaponids[0]].getType() == staff)
2754 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2755 if (weapons[weaponids[0]].getType() == staff)
2756 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2758 emit_sound_at(swordstaffsound, victim->coords);
2760 emit_sound_at(metalhitsound, victim->coords);
2766 victim->Puff(righthand);
2768 victim->frameTarget = 0;
2769 victim->animTarget = staggerbackhighanim;
2770 victim->targetyaw = targetyaw + 180;
2772 aim = DoRotation(facing, 0, 90, 0) * 21;
2774 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2775 victim->num_weapons--;
2776 if (victim->num_weapons) {
2777 victim->weaponids[0] = victim->weaponids[num_weapons];
2778 if (victim->weaponstuck == victim->num_weapons)
2779 victim->weaponstuck = 0;
2781 victim->weaponactive = -1;
2782 for (unsigned i = 0; i < Person::players.size(); i++) {
2783 Person::players[i]->wentforweapon = 0;
2790 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2791 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2792 if (tutoriallevel != 1) {
2793 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2797 if (Random() % 2 || creature == wolftype) {
2800 emit_sound_at(staffheadsound, victim->coords);
2804 relative = victim->coords - coords;
2806 Normalise(&relative);
2807 relative = DoRotation(relative, 0, 90, 0);
2809 Normalise(&relative);
2810 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2811 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2813 victim->jointVel(head) += relative * damagemult * 230;
2814 victim->jointVel(neck) += relative * damagemult * 230;
2817 if (tutoriallevel != 1) {
2818 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2820 award_bonus(id, solidhit, 30);
2825 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2826 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2827 if (tutoriallevel != 1) {
2828 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2832 if (Random() % 2 || creature == wolftype) {
2835 emit_sound_at(staffheadsound, victim->coords);
2839 relative = victim->coords - coords;
2841 Normalise(&relative);
2842 relative = DoRotation(relative, 0, -90, 0);
2843 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2844 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2846 victim->jointVel(head) += relative * damagemult * 220;
2847 victim->jointVel(neck) += relative * damagemult * 220;
2850 if (tutoriallevel != 1) {
2851 victim->DoDamage(damagemult * 350 / victim->protectionhead);
2853 award_bonus(id, solidhit, 60);
2858 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2859 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2861 if (tutoriallevel != 1) {
2863 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2866 if (Random() % 2 || creature == wolftype) {
2869 emit_sound_at(staffbodysound, victim->coords);
2871 victim->skeleton.longdead = 0;
2872 victim->skeleton.free = 1;
2873 victim->skeleton.broken = 0;
2875 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2876 victim->skeleton.joints[i].velchange = 0;
2877 victim->skeleton.joints[i].locked = 0;
2878 //victim->skeleton.joints[i].velocity=0;
2884 /*relative=victim->coords-coords;
2886 Normalise(&relative);
2887 relative=DoRotation(relative,0,90,0);*/
2889 Normalise(&relative);
2890 if (!victim->dead) {
2891 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2892 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2895 victim->jointVel(abdomen) += relative * damagemult * 40;
2898 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2899 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2902 //victim->jointVel(abdomen)+=relative*damagemult*20;
2904 victim->Puff(abdomen);
2905 if (tutoriallevel != 1) {
2906 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2908 if (!victim->dead) {
2909 award_bonus(id, solidhit, 40);
2915 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
2916 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
2921 relative = victim->coords - coords;
2923 Normalise(&relative);
2927 if (animation[victim->animTarget].height == lowheight) {
2933 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2934 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2936 victim->jointVel(head) += relative * damagemult * 200;
2937 if (tutoriallevel != 1) {
2938 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2941 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2942 if (victim->howactive == typesleeping)
2943 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2944 if (creature == wolftype) {
2945 emit_sound_at(clawslicesound, victim->coords, 128.);
2947 victim->DoBloodBig(2 / victim->armorhead, 175);
2950 if (victim->damage >= victim->damagetolerance)
2952 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2953 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
2955 victim->jointVel(abdomen) += relative * damagemult * 200;
2956 victim->frameTarget = 0;
2957 victim->animTarget = staggerbackhighanim;
2958 victim->targetyaw = targetyaw + 180;
2960 if (tutoriallevel != 1) {
2961 emit_sound_at(landsound2, victim->coords, 128.);
2963 victim->Puff(abdomen);
2964 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
2965 if (creature == wolftype) {
2966 emit_sound_at(clawslicesound, victim->coords, 128.);
2968 victim->DoBloodBig(2 / victim->armorhigh, 170);
2975 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
2976 if ((victim->animTarget != jumpupanim) &&
2977 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
2978 (victim != this->shared_from_this())) {
2982 if (tutoriallevel != 1) {
2983 emit_sound_at(landsound2, victim->coords, 128.);
2986 relative = victim->coords - coords;
2988 Normalise(&relative);
2990 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
2993 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2994 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
2996 relative = DoRotation(relative, 0, -90, 0);
2998 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2999 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)
3000 victim->skeleton.joints[i].velocity = relative * 80;
3002 victim->Puff(rightankle);
3003 victim->Puff(leftankle);
3004 victim->DoDamage(damagemult * 40 / victim->protectionlow);
3006 if (victim->damage >= victim->damagetolerance)
3008 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3009 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
3011 relative = DoRotation(relative, 0, -90, 0);
3012 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3013 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)
3014 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
3016 victim->jointVel(abdomen) += relative * damagemult * 200;
3017 victim->frameTarget = 0;
3018 victim->animTarget = staggerbackhighanim;
3019 victim->targetyaw = targetyaw + 180;
3021 if (tutoriallevel != 1) {
3022 emit_sound_at(landsound2, victim->coords, 128.);
3024 victim->Puff(abdomen);
3025 victim->DoDamage(damagemult * 30 / victim->protectionlow);
3033 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
3034 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3042 if (tutoriallevel != 1) {
3043 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3045 if (creature == wolftype) {
3046 emit_sound_at(clawslicesound, victim->coords, 128);
3048 victim->DoBloodBig(2 / victim->armorhigh, 170);
3052 relative = victim->coords - oldcoords;
3054 Normalise(&relative);
3055 //relative=DoRotation(relative,0,-90,0);
3056 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3057 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3059 victim->jointVel(abdomen) += relative * damagemult * 200;
3061 victim->Puff(abdomen);
3062 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3064 award_bonus(id, Reversal);
3067 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3068 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3069 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3070 weapons[victim->weaponids[victim->weaponactive]].owner = id;
3072 if (num_weapons > 0) {
3073 weaponids[num_weapons] = weaponids[victim->weaponactive];
3076 weaponids[0] = victim->weaponids[victim->weaponactive];
3077 victim->num_weapons--;
3078 if (victim->num_weapons > 0) {
3079 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3081 victim->weaponactive = -1;
3086 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3094 emit_sound_at(whooshhitsound, victim->coords, 128.);
3097 relative = victim->coords - oldcoords;
3099 Normalise(&relative);
3100 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3101 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3103 victim->jointVel(abdomen) += relative * damagemult * 200;
3105 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3108 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3117 award_bonus(id, staffreversebonus);
3119 if (tutoriallevel != 1) {
3120 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3123 award_bonus(id, staffreversebonus); // Huh, again?
3126 relative = victim->coords - oldcoords;
3128 Normalise(&relative);
3129 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3130 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3132 victim->jointVel(abdomen) += relative * damagemult * 200;
3134 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3137 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3143 Normalise(&relative);
3145 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3146 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3148 victim->jointVel(lefthand) *= .1;
3149 victim->jointVel(leftwrist) *= .2;
3150 victim->jointVel(leftelbow) *= .5;
3151 victim->jointVel(leftshoulder) *= .7;
3152 victim->jointVel(righthand) *= .1;
3153 victim->jointVel(rightwrist) *= .2;
3154 victim->jointVel(rightelbow) *= .5;
3155 victim->jointVel(rightshoulder) *= .7;
3157 victim->Puff(abdomen);
3158 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3160 award_bonus(id, Reversal);
3164 if (weaponactive != -1 || creature == wolftype)
3166 if (creature == rabbittype && weaponactive != -1)
3167 if (weapons[weaponids[0]].getType() == staff)
3170 if (weaponactive != -1) {
3171 victim->DoBloodBig(2 / victim->armorhigh, 225);
3172 emit_sound_at(knifeslicesound, victim->coords);
3173 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3174 weapons[weaponids[weaponactive]].bloody = 1;
3175 weapons[weaponids[weaponactive]].blooddrip += 3;
3177 if (weaponactive == -1 && creature == wolftype) {
3179 emit_sound_at(clawslicesound, victim->coords, 128.);
3181 victim->DoBloodBig(2 / victim->armorhigh, 175);
3188 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3194 Normalise(&relative);
3196 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3197 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3199 victim->jointVel(lefthand) *= .1 - 1;
3200 victim->jointVel(leftwrist) *= .2 - 1;
3201 victim->jointVel(leftelbow) *= .5 - 1;
3202 victim->jointVel(leftshoulder) *= .7 - 1;
3203 victim->jointVel(righthand) *= .1 - 1;
3204 victim->jointVel(rightwrist) *= .2 - 1;
3205 victim->jointVel(rightelbow) *= .5 - 1;
3206 victim->jointVel(rightshoulder) *= .7 - 1;
3208 award_bonus(id, swordreversebonus);
3211 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3219 if (tutoriallevel != 1) {
3220 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3224 relative = victim->coords - oldcoords;
3226 Normalise(&relative);
3227 relative = DoRotation(relative, 0, -90, 0);
3228 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3229 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3231 victim->jointVel(abdomen) += relative * damagemult * 200;
3232 victim->Puff(abdomen);
3233 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3235 award_bonus(id, Reversal);
3238 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3241 victim->skeleton.spinny = 0;
3243 relative = facing * -1;
3245 Normalise(&relative);
3246 if (victim->id == 0)
3248 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3249 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3251 victim->damage = victim->damagetolerance;
3252 victim->permanentdamage = victim->damagetolerance - 1;
3255 if (weaponactive != -1 || creature == wolftype)
3257 if (creature == rabbittype && weaponactive != -1)
3258 if (weapons[weaponids[0]].getType() == staff)
3261 if (weaponactive != -1) {
3262 victim->DoBloodBig(200, 225);
3263 emit_sound_at(knifeslicesound, victim->coords);
3265 weapons[weaponids[weaponactive]].bloody = 2;
3266 weapons[weaponids[weaponactive]].blooddrip += 5;
3269 if (creature == wolftype && weaponactive == -1) {
3270 emit_sound_at(clawslicesound, victim->coords, 128.);
3272 victim->DoBloodBig(2, 175);
3275 award_bonus(id, spinecrusher);
3278 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3279 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3281 if (animTarget == knifefollowanim)
3282 victim->DoBloodBig(200, 210);
3283 if (animTarget == knifesneakattackanim) {
3284 XYZ footvel, footpoint;
3286 footpoint = weapons[weaponids[0]].tippoint;
3288 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3289 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3290 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3291 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3292 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3293 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3294 victim->DoBloodBig(200, 195);
3295 award_bonus(id, tracheotomy);
3297 if (animTarget == knifefollowanim) {
3298 award_bonus(id, Stabbonus);
3299 XYZ footvel, footpoint;
3301 footpoint = weapons[weaponids[0]].tippoint;
3303 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3304 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3305 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3306 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3307 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3308 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3311 victim->bloodloss += 10000;
3312 victim->velocity = 0;
3313 emit_sound_at(fleshstabsound, victim->coords);
3315 weapons[weaponids[weaponactive]].bloody = 2;
3316 weapons[weaponids[weaponactive]].blooddrip += 5;
3320 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3322 victim->velocity = 0;
3323 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3324 victim->skeleton.joints[i].velocity = 0;
3326 if (animTarget == knifefollowanim) {
3328 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3329 victim->skeleton.joints[i].velocity = 0;
3332 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3333 emit_sound_at(fleshstabremovesound, victim->coords);
3335 weapons[weaponids[weaponactive]].bloody = 2;
3336 weapons[weaponids[weaponactive]].blooddrip += 5;
3338 XYZ footvel, footpoint;
3340 footpoint = weapons[weaponids[0]].tippoint;
3342 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3343 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3344 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3345 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3346 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3347 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3351 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3352 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3353 award_bonus(id, backstab);
3357 XYZ footvel, footpoint;
3359 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3361 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3362 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3363 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3364 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3365 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3366 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3367 victim->DoBloodBig(200, 180);
3368 victim->DoBloodBig(200, 215);
3369 victim->bloodloss += 10000;
3370 victim->velocity = 0;
3371 emit_sound_at(fleshstabsound, victim->coords);
3373 weapons[weaponids[weaponactive]].bloody = 2;
3374 weapons[weaponids[weaponactive]].blooddrip += 5;
3378 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3380 victim->velocity = 0;
3381 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3382 victim->skeleton.joints[i].velocity = 0;
3384 if (weaponactive != -1) {
3385 emit_sound_at(fleshstabremovesound, victim->coords);
3387 weapons[weaponids[weaponactive]].bloody = 2;
3388 weapons[weaponids[weaponactive]].blooddrip += 5;
3390 XYZ footvel, footpoint;
3392 footpoint = weapons[weaponids[0]].tippoint;
3394 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3395 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3396 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3397 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3398 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3399 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3403 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3411 if (weaponactive == -1) {
3412 if (tutoriallevel != 1) {
3413 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3418 if (weaponactive != -1 || creature == wolftype)
3420 if (creature == rabbittype && weaponactive != -1)
3421 if (weapons[weaponids[0]].getType() == staff)
3424 if (weaponactive != -1) {
3425 victim->DoBloodBig(2 / victim->armorhead, 225);
3426 emit_sound_at(knifeslicesound, victim->coords);
3427 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3428 weapons[weaponids[weaponactive]].bloody = 1;
3429 weapons[weaponids[weaponactive]].blooddrip += 3;
3431 if (weaponactive == -1 && creature == wolftype) {
3432 emit_sound_at(clawslicesound, victim->coords, 128.);
3434 victim->DoBloodBig(2 / victim->armorhead, 175);
3438 award_bonus(id, Reversal);
3443 relative = facing * -1;
3445 Normalise(&relative);
3446 relative = DoRotation(relative, 0, 90, 0);
3448 Normalise(&relative);
3449 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3450 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3452 victim->jointVel(head) += relative * damagemult * 200;
3453 if (victim->damage < victim->damagetolerance - 100)
3454 victim->velocity = relative * 200;
3455 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3456 victim->velocity = 0;
3459 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3463 relative = facing * -1;
3465 Normalise(&relative);
3466 relative = DoRotation(relative, 0, 90, 0);
3468 Normalise(&relative);
3469 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3470 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3472 victim->jointVel(head) += relative * damagemult * 200;
3475 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3476 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3477 award_bonus(id, reverseko);
3483 if (frameTarget > animation[animCurrent].numframes - 1) {
3486 animTarget = getIdle();
3490 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3491 animTarget = rollanim;
3493 emit_sound_at(movewhooshsound, coords, 128.);
3495 if (animCurrent == staggerbackhighanim) {
3496 animTarget = getIdle();
3498 if (animCurrent == staggerbackhardanim) {
3499 animTarget = getIdle();
3501 if (animCurrent == removeknifeanim) {
3502 animTarget = getIdle();
3504 if (animCurrent == crouchremoveknifeanim) {
3505 animTarget = getCrouch();
3507 if (animCurrent == backhandspringanim) {
3508 animTarget = getIdle();
3510 if (animCurrent == dodgebackanim) {
3511 animTarget = getIdle();
3513 if (animCurrent == drawleftanim) {
3514 animTarget = getIdle();
3516 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3517 animTarget = getIdle();
3518 if (animCurrent == crouchdrawrightanim) {
3519 animTarget = getCrouch();
3521 if (weaponactive == -1)
3523 else if (weaponactive == 0) {
3525 if (num_weapons == 2) {
3527 buffer = weaponids[0];
3528 weaponids[0] = weaponids[1];
3529 weaponids[1] = buffer;
3533 if (weaponactive == -1) {
3534 emit_sound_at(knifesheathesound, coords, 128.);
3536 if (weaponactive != -1) {
3537 emit_sound_at(knifedrawsound, coords, 128.);
3540 if (animCurrent == rollanim) {
3541 animTarget = getCrouch();
3546 if (animTarget == walljumprightkickanim) {
3549 if (animTarget == walljumpleftkickanim) {
3552 animTarget = jumpdownanim;
3554 if (animCurrent == climbanim) {
3555 animTarget = getCrouch();
3557 coords += facing * .1;
3558 if (!isnormal(coords.x))
3569 if (animTarget == rabbitkickreversalanim) {
3570 animTarget = getCrouch();
3573 if (animTarget == jumpreversalanim) {
3574 animTarget = getCrouch();
3577 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3578 if (attackkeydown && animTarget != walljumpfrontanim) {
3580 float closestdist = -1;
3582 if (Person::players.size() > 1)
3583 for (unsigned i = 0; i < Person::players.size(); i++) {
3584 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3585 distance = distsq(&Person::players[i]->coords, &coords);
3586 if (closestdist == -1 || distance < closestdist) {
3587 closestdist = distance;
3592 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3593 victim = Person::players[closest];
3594 animTarget = walljumprightkickanim;
3596 XYZ rotatetarget = victim->coords - coords;
3597 Normalise(&rotatetarget);
3598 yaw = -asin(0 - rotatetarget.x);
3600 if (rotatetarget.z < 0)
3602 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3603 velocity = (victim->coords - coords) * 4;
3608 if (animTarget == walljumpbackanim) {
3609 animTarget = backflipanim;
3611 velocity = facing * -8;
3614 resume_stream(whooshsound);
3616 if (animTarget == walljumprightanim) {
3617 animTarget = rightflipanim;
3621 velocity = DoRotation(facing, 0, 30, 0) * -8;
3624 if (animTarget == walljumpfrontanim) {
3625 animTarget = frontflipanim;
3629 velocity = facing * 8;
3633 resume_stream(whooshsound);
3635 if (animTarget == walljumpleftanim) {
3636 if (attackkeydown) {
3638 float closestdist = -1;
3640 if (Person::players.size() > 1)
3641 for (unsigned i = 0; i < Person::players.size(); i++) {
3642 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3643 distance = distsq(&Person::players[i]->coords, &coords);
3644 if (closestdist == -1 || distance < closestdist) {
3645 closestdist = distance;
3650 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3651 victim = Person::players[closest];
3652 animTarget = walljumpleftkickanim;
3654 XYZ rotatetarget = victim->coords - coords;
3655 Normalise(&rotatetarget);
3656 yaw = -asin(0 - rotatetarget.x);
3658 if (rotatetarget.z < 0)
3660 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3661 velocity = (victim->coords - coords) * 4;
3666 if (animTarget != walljumpleftkickanim) {
3667 animTarget = leftflipanim;
3671 velocity = DoRotation(facing, 0, -30, 0) * -8;
3675 resume_stream(whooshsound);
3677 if (animTarget == sneakattackanim) {
3678 animCurrent = getCrouch();
3679 animTarget = getCrouch();
3686 transspeed = 1000000;
3687 targetheadyaw += 180;
3688 coords -= facing * .7;
3690 coords.y = terrain.getHeight(coords.x, coords.z);
3694 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3695 animTarget = getIdle();
3698 coords.y = terrain.getHeight(coords.x, coords.z);
3702 if (animCurrent == knifefollowanim) {
3703 animTarget = getIdle();
3706 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3707 float ycoords = oldcoords.y;
3708 animTarget = getStop();
3713 transspeed = 1000000;
3714 targetheadyaw += 180;
3715 if (!isnormal(coords.x))
3717 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3718 oldcoords = coords + facing * .5;
3719 else if (animCurrent == sweepreversalanim)
3720 oldcoords = coords + facing * 1.1;
3721 else if (animCurrent == upunchreversalanim) {
3722 oldcoords = coords + facing * 1.5;
3725 targetheadyaw += 180;
3728 } else if (animCurrent == knifeslashreversalanim) {
3729 oldcoords = coords + facing * .5;
3732 targetheadyaw += 90;
3735 } else if (animCurrent == staffspinhitreversalanim) {
3738 targetheadyaw += 180;
3743 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3745 oldcoords.y = ycoords;
3746 currentoffset = coords - oldcoords;
3752 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3757 if (animation[animTarget].attack == reversed) {
3759 if (animTarget == sweepreversedanim)
3761 animTarget = backhandspringanim;
3763 emit_sound_at(landsound, coords, 128);
3765 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3766 animTarget = rollanim;
3769 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3770 coords.y = oldcoords.y;
3772 if (animCurrent == knifeslashreversedanim) {
3773 animTarget = rollanim;
3778 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3779 coords.y = oldcoords.y;
3783 animTarget = jumpdownanim;
3786 animTarget = getIdle();
3788 animTarget = getIdle();
3789 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3790 animTarget = getIdle();
3792 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3793 coords.y = oldcoords.y;
3794 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3795 targetoffset.y = coords.y;
3797 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3798 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3799 currentoffset.y -= (coords.y - targetoffset.y);
3800 coords.y = targetoffset.y;
3802 normalsupdatedelay = 0;
3804 if (animCurrent == upunchanim) {
3805 animTarget = getStop();
3806 normalsupdatedelay = 0;
3809 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3813 if (num_weapons > 0)
3814 if (weapons[0].getType() == staff)
3820 rabbitkickragdoll = 1;
3822 if (animCurrent == rabbitkickreversedanim) {
3828 skeleton.spinny = 0;
3829 SolidHitBonus(!id); // FIXME: tricky id
3833 animTarget = rollanim;
3836 pause_sound(whooshsound);
3840 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3844 skeleton.spinny = 0;
3846 if (animCurrent == jumpreversedanim) {
3852 skeleton.spinny = 0;
3853 SolidHitBonus(!id); // FIXME: tricky id
3857 animTarget = rollanim;
3858 coords += facing * 2;
3860 pause_sound(whooshsound);
3865 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) {
3866 animTarget = getupfromfrontanim;
3868 } else if (animation[animCurrent].attack == normalattack) {
3869 animTarget = getIdle();
3872 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3873 animTarget = blockhighleftstrikeanim;
3875 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3876 animTarget = getIdle();
3879 if (animCurrent == spinkickanim && victim->skeleton.free) {
3880 if (creature == rabbittype)
3881 animTarget = fightidleanim;
3886 if (isIdle() && !wasIdle())
3887 normalsupdatedelay = 0;
3889 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3890 animTarget = jumpdownanim;
3893 if (!skeleton.free) {
3895 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
3896 if (!isRun() || !wasRun()) {
3897 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3898 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
3899 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3900 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
3902 if (isRun() && wasRun()) {
3904 tempspeed = velspeed;
3905 if (tempspeed < 10 * speedmult)
3906 tempspeed = 10 * speedmult;
3907 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
3909 } else if (transspeed)
3910 target += multiplier * transspeed * speed * 2;
3912 if (!isRun() || !wasRun()) {
3913 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3914 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
3915 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3916 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
3920 if (animCurrent != animTarget)
3921 target = (target + oldtarget) / 2;
3924 frameCurrent = frameTarget;
3928 rot = targetrot * target;
3929 yaw += rot - oldrot;
3935 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
3937 for (int i = 0; i < skeleton.num_joints; i++) {
3938 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
3941 skeleton.FindForwards();
3943 for (int i = 0; i < skeleton.num_muscles; i++) {
3944 if (skeleton.muscles[i].visible) {
3945 skeleton.FindRotationMuscle(i, animTarget);
3948 for (int i = 0; i < skeleton.num_muscles; i++) {
3949 if (skeleton.muscles[i].visible) {
3950 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3951 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3952 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3953 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3954 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3955 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3960 for (int i = 0; i < skeleton.num_joints; i++) {
3961 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
3964 skeleton.FindForwards();
3966 for (int i = 0; i < skeleton.num_muscles; i++) {
3967 if (skeleton.muscles[i].visible) {
3968 skeleton.FindRotationMuscle(i, animTarget);
3971 for (int i = 0; i < skeleton.num_muscles; i++) {
3972 if (skeleton.muscles[i].visible) {
3973 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3974 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3975 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3976 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3977 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3978 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3979 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
3980 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
3981 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
3982 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
3983 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
3984 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
3988 if (frameCurrent >= animation[animCurrent].numframes)
3989 frameCurrent = animation[animCurrent].numframes - 1;
3991 oldanimCurrent = animCurrent;
3992 oldanimTarget = animTarget;
3993 oldframeTarget = frameTarget;
3994 oldframeCurrent = frameCurrent;
3996 for (int i = 0; i < skeleton.num_joints; i++) {
3997 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
3998 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
4000 offset = currentoffset * (1 - target) + targetoffset * target;
4001 for (int i = 0; i < skeleton.num_muscles; i++) {
4002 if (skeleton.muscles[i].visible) {
4003 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
4004 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
4005 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
4010 if (isLanding() && landhard) {
4013 animTarget = getLandhard();
4026 void Person::DoStuff()
4028 static XYZ terrainnormal;
4029 static XYZ flatfacing;
4030 static XYZ flatvelocity;
4031 static float flatvelspeed;
4035 static int bloodsize;
4036 static int startx, starty, endx, endy;
4037 static GLubyte color;
4038 static XYZ bloodvel;
4040 onfiredelay -= multiplier;
4041 if (onfiredelay < 0 && onfire) {
4042 if (Random() % 2 == 0) {
4048 crouchkeydowntime += multiplier;
4050 crouchkeydowntime = 0;
4051 jumpkeydowntime += multiplier;
4052 if (!jumpkeydown && skeleton.free)
4053 jumpkeydowntime = 0;
4055 if (hostile || damage > 0 || bloodloss > 0)
4058 if (isIdle() || isRun())
4061 if (num_weapons == 1 && weaponactive != -1)
4065 blooddimamount -= multiplier * .3;
4066 speechdelay -= multiplier;
4067 texupdatedelay -= multiplier;
4068 interestdelay -= multiplier;
4069 flamedelay -= multiplier;
4070 parriedrecently -= multiplier;
4072 victim = this->shared_from_this();
4077 speed = 1.1 * speedmult;
4079 speed = 1.0 * speedmult;
4081 rabbitkickragdoll = 0;
4085 if (id != 0 && (creature == rabbittype || difficulty != 2))
4087 if (id != 0 && creature == wolftype && difficulty == 2) {
4089 if (aitype != passivetype) {
4091 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) {
4097 if (animTarget == wolfrunninganim && !superruntoggle) {
4098 animTarget = getRun();
4102 if (weaponactive == -1 && num_weapons > 0) {
4103 if (weapons[weaponids[0]].getType() == staff) {
4109 burnt += multiplier;
4113 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4115 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4121 vel[0] = velocity.x;
4122 vel[1] = velocity.y;
4123 vel[2] = velocity.z;
4126 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4127 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4131 while (flamedelay < 0 && onfire) {
4133 howmany = abs(Random() % (skeleton.num_joints));
4135 flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4137 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4139 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4141 flatfacing = skeleton.joints[howmany].position * scale + coords;
4142 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4145 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4147 howmany = abs(Random() % (skeleton.num_joints));
4149 flatvelocity = (coords - oldcoords) / multiplier / 2; //velocity/2;
4151 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4153 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4155 flatfacing = skeleton.joints[howmany].position * scale + coords;
4156 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4160 bleeding -= multiplier * .3;
4161 if (bloodtoggle == 2) {
4162 skeleton.drawmodel.textureptr.bind();
4163 if ((bleeding <= 0) && (detail != 2))
4168 if (neckspurtamount > 0) {
4169 neckspurtamount -= multiplier;
4170 neckspurtdelay -= multiplier * 3;
4171 neckspurtparticledelay -= multiplier * 3;
4172 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4175 if (!skeleton.free) {
4176 bloodvel.z = 5 * neckspurtamount;
4177 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4179 if (skeleton.free) {
4180 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4183 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4185 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4187 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4189 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4190 neckspurtparticledelay = .05;
4192 if (neckspurtdelay < 0) {
4197 if (deathbleeding > 0 && dead != 2) {
4198 if (deathbleeding < 5)
4199 bleeddelay -= deathbleeding * multiplier / 4;
4201 bleeddelay -= 5 * multiplier / 4;
4202 if (bleeddelay < 0 && bloodtoggle) {
4208 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4210 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4212 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4214 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4217 bloodloss += deathbleeding * multiplier * 80;
4218 deathbleeding -= multiplier * 1.6;
4219 if (deathbleeding < 0)
4221 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4222 if (weaponactive != -1) {
4223 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4224 weapons[weaponids[0]].velocity.x += .01;
4227 weaponids[0] = weaponids[num_weapons];
4228 if (weaponstuck == num_weapons)
4232 for (unsigned i = 0; i < Person::players.size(); i++) {
4233 Person::players[i]->wentforweapon = 0;
4245 if (!dead && creature == wolftype) {
4246 award_bonus(0, Wolfbonus);
4249 if (animTarget == knifefollowedanim && !skeleton.free) {
4250 for (int i = 0; i < skeleton.num_joints; i++) {
4251 skeleton.joints[i].velocity = 0;
4252 skeleton.joints[i].velocity.y = -2;
4255 if (id != 0 && unconscioustime > .1) {
4263 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4264 texupdatedelay = .12;
4266 bloodsize = 5 - realtexdetail;
4270 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4271 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4272 endx = startx + bloodsize;
4273 endy = starty + bloodsize;
4283 if (endx > skeleton.skinsize - 1) {
4284 endx = skeleton.skinsize - 1;
4287 if (endy > skeleton.skinsize - 1) {
4288 endy = skeleton.skinsize - 1;
4296 for (i = startx; i < endx; i++) {
4297 for (j = starty; j < endy; j++) {
4298 if (Random() % 2 == 0) {
4299 color = Random() % 85 + 170;
4300 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4301 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4302 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4303 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4308 skeleton.drawmodel.textureptr.bind();
4312 if (!skeleton.free) {
4313 bleedy -= 4 / realtexdetail;
4315 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4317 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4319 if (skeleton.free) {
4320 bleedx += 4 * direction / realtexdetail;
4322 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4324 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4328 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4329 righthandmorphness = targetrighthandmorphness;
4330 righthandmorphstart = righthandmorphend;
4331 } else if (righthandmorphness > targetrighthandmorphness) {
4332 righthandmorphness -= multiplier * 4;
4333 } else if (righthandmorphness < targetrighthandmorphness) {
4334 righthandmorphness += multiplier * 4;
4337 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4338 lefthandmorphness = targetlefthandmorphness;
4339 lefthandmorphstart = lefthandmorphend;
4340 } else if (lefthandmorphness > targetlefthandmorphness) {
4341 lefthandmorphness -= multiplier * 4;
4342 } else if (lefthandmorphness < targetlefthandmorphness) {
4343 lefthandmorphness += multiplier * 4;
4346 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4347 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4348 tailmorphness = targettailmorphness;
4349 tailmorphstart = tailmorphend;
4350 } else if (tailmorphness > targettailmorphness) {
4351 tailmorphness -= multiplier * 10;
4352 } else if (tailmorphness < targettailmorphness) {
4353 tailmorphness += multiplier * 10;
4357 if (creature == wolftype) {
4358 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4359 tailmorphness = targettailmorphness;
4360 tailmorphstart = tailmorphend;
4361 } else if (tailmorphness > targettailmorphness) {
4362 tailmorphness -= multiplier * 2;
4363 } else if (tailmorphness < targettailmorphness) {
4364 tailmorphness += multiplier * 2;
4368 if (headmorphend == 3 || headmorphstart == 3) {
4369 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4370 headmorphness = targetheadmorphness;
4371 headmorphstart = headmorphend;
4372 } else if (headmorphness > targetheadmorphness) {
4373 headmorphness -= multiplier * 7;
4374 } else if (headmorphness < targetheadmorphness) {
4375 headmorphness += multiplier * 7;
4377 } else if (headmorphend == 5 || headmorphstart == 5) {
4378 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4379 headmorphness = targetheadmorphness;
4380 headmorphstart = headmorphend;
4381 } else if (headmorphness > targetheadmorphness) {
4382 headmorphness -= multiplier * 10;
4383 } else if (headmorphness < targetheadmorphness) {
4384 headmorphness += multiplier * 10;
4387 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4388 headmorphness = targetheadmorphness;
4389 headmorphstart = headmorphend;
4390 } else if (headmorphness > targetheadmorphness) {
4391 headmorphness -= multiplier * 4;
4392 } else if (headmorphness < targetheadmorphness) {
4393 headmorphness += multiplier * 4;
4397 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4398 chestmorphness = targetchestmorphness;
4399 chestmorphstart = chestmorphend;
4400 } else if (chestmorphness > targetchestmorphness) {
4401 chestmorphness -= multiplier;
4402 } else if (chestmorphness < targetchestmorphness) {
4403 chestmorphness += multiplier;
4406 if (dead != 2 && howactive <= typesleeping) {
4407 if (chestmorphstart == 0 && chestmorphend == 0) {
4409 targetchestmorphness = 1;
4412 if (chestmorphstart != 0 && chestmorphend != 0) {
4414 targetchestmorphness = 1;
4416 if (environment == snowyenvironment) {
4420 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4422 footvel = skeleton.specialforward[0] * -1;
4424 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4426 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4427 if (animTarget == sleepanim)
4428 footvel = DoRotation(footvel, 0, 90, 0);
4429 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4433 if (!dead && howactive < typesleeping) {
4434 blinkdelay -= multiplier * 2;
4435 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4437 targetheadmorphness = 1;
4439 blinkdelay = (float)(abs(Random() % 40)) / 5;
4441 if (headmorphstart == 3 && headmorphend == 3) {
4443 targetheadmorphness = 1;
4448 twitchdelay -= multiplier * 1.5;
4449 if (animTarget != hurtidleanim) {
4450 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4452 targetheadmorphness = 1;
4454 twitchdelay = (float)(abs(Random() % 40)) / 5;
4456 if (headmorphstart == 5 && headmorphend == 5) {
4458 targetheadmorphness = 1;
4462 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4463 twitchdelay3 -= multiplier * 1;
4464 if (Random() % 2 == 0) {
4465 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4466 righthandmorphness = 0;
4467 targetrighthandmorphness = 1;
4468 righthandmorphend = 1;
4469 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4471 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4472 righthandmorphness = 0;
4473 targetrighthandmorphness = 1;
4474 righthandmorphend = 0;
4477 if (Random() % 2 == 0) {
4478 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4479 lefthandmorphness = 0;
4480 targetlefthandmorphness = 1;
4481 lefthandmorphend = 1;
4482 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4484 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4485 lefthandmorphness = 0;
4486 targetlefthandmorphness = 1;
4487 lefthandmorphend = 0;
4493 if (creature == rabbittype) {
4494 if (howactive < typesleeping)
4495 twitchdelay2 -= multiplier * 1.5;
4497 twitchdelay2 -= multiplier * 0.5;
4498 if (howactive <= typesleeping) {
4499 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4501 targettailmorphness = 1;
4503 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4505 if (tailmorphstart == 1 && tailmorphend == 1) {
4507 targettailmorphness = 1;
4510 if (tailmorphstart == 2 && tailmorphend == 2) {
4512 targettailmorphness = 1;
4519 if (creature == wolftype) {
4520 twitchdelay2 -= multiplier * 1.5;
4521 if (tailmorphend != 0)
4522 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4524 targettailmorphness = 1;
4528 if (tailmorphend != 5)
4529 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4531 targettailmorphness = 1;
4535 if (twitchdelay2 <= 0) {
4536 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4538 targettailmorphness = 1;
4541 if (tailmorphstart == 1 && tailmorphend == 1) {
4543 targettailmorphness = 1;
4546 if (tailmorphstart == 2 && tailmorphend == 2) {
4548 targettailmorphness = 1;
4551 if (tailmorphstart == 3 && tailmorphend == 3) {
4553 targettailmorphness = 1;
4556 if (tailmorphstart == 4 && tailmorphend == 4) {
4558 targettailmorphness = 1;
4565 unconscioustime = 0;
4567 if (dead == 1 || howactive == typesleeping) {
4568 unconscioustime += multiplier;
4569 //If unconscious, close eyes and mouth
4570 if (righthandmorphend != 0)
4571 righthandmorphness = 0;
4572 righthandmorphend = 0;
4573 targetrighthandmorphness = 1;
4575 if (lefthandmorphend != 0)
4576 lefthandmorphness = 0;
4577 lefthandmorphend = 0;
4578 targetlefthandmorphness = 1;
4580 if (headmorphend != 3 && headmorphend != 5)
4583 targetheadmorphness = 1;
4587 if (howactive > typesleeping) {
4590 if (bloodtoggle && !bled) {
4591 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4593 if (bloodtoggle && !bled)
4594 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4595 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4596 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4600 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4605 if (dead == 2 || howactive > typesleeping) {
4606 //If dead, open mouth and hands
4607 if (righthandmorphend != 0)
4608 righthandmorphness = 0;
4609 righthandmorphend = 0;
4610 targetrighthandmorphness = 1;
4612 if (lefthandmorphend != 0)
4613 lefthandmorphness = 0;
4614 lefthandmorphend = 0;
4615 targetlefthandmorphness = 1;
4617 if (headmorphend != 2)
4620 targetheadmorphness = 1;
4623 if (stunned > 0 && !dead && headmorphend != 2) {
4624 if (headmorphend != 4)
4627 targetheadmorphness = 1;
4630 if (damage > damagetolerance && !dead) {
4633 unconscioustime = 0;
4635 if (creature == wolftype) {
4636 award_bonus(0, Wolfbonus);
4641 if (weaponactive != -1) {
4642 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4643 weapons[weaponids[0]].velocity.x += .01;
4646 weaponids[0] = weaponids[num_weapons];
4647 if (weaponstuck == num_weapons)
4651 for (unsigned i = 0; i < Person::players.size(); i++) {
4652 Person::players[i]->wentforweapon = 0;
4658 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4667 damage -= multiplier * 13;
4669 permanentdamage -= multiplier * 4;
4670 if (isIdle() || isCrouch()) {
4672 permanentdamage -= multiplier * 4;
4676 if (permanentdamage < 0)
4677 permanentdamage = 0;
4678 if (superpermanentdamage < 0)
4679 superpermanentdamage = 0;
4680 if (permanentdamage < superpermanentdamage) {
4681 permanentdamage = superpermanentdamage;
4683 if (damage < permanentdamage) {
4684 damage = permanentdamage;
4686 if (dead == 1 && damage < damagetolerance) {
4690 for (int i = 0; i < skeleton.num_joints; i++) {
4691 skeleton.joints[i].velocity = 0;
4694 if (permanentdamage > damagetolerance && dead != 2) {
4697 if (weaponactive != -1) {
4698 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4699 weapons[weaponids[0]].velocity.x += .01;
4702 weaponids[0] = weaponids[num_weapons];
4703 if (weaponstuck == num_weapons)
4707 for (unsigned i = 0; i < Person::players.size(); i++) {
4708 Person::players[i]->wentforweapon = 0;
4714 if (!dead && creature == wolftype) {
4715 award_bonus(0, Wolfbonus);
4718 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4719 award_bonus(id, touchofdeath);
4720 if (id != 0 && unconscioustime > .1) {
4728 emit_sound_at(breaksound, coords);
4731 if (skeleton.free == 1) {
4733 pause_sound(whooshsound);
4736 //If knocked over, open hands and close mouth
4737 if (righthandmorphend != 0)
4738 righthandmorphness = 0;
4739 righthandmorphend = 0;
4740 targetrighthandmorphness = 1;
4742 if (lefthandmorphend != 0)
4743 lefthandmorphness = 0;
4744 lefthandmorphend = 0;
4745 targetlefthandmorphness = 1;
4747 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4748 if (headmorphend != 0)
4751 targetheadmorphness = 1;
4755 skeleton.DoGravity(&scale);
4757 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4758 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4759 award_bonus(id, deepimpact);
4760 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4764 for (j = 0; j < skeleton.num_joints; j++) {
4765 average += skeleton.joints[j].position;
4769 coords += average * scale;
4770 for (j = 0; j < skeleton.num_joints; j++) {
4771 skeleton.joints[j].position -= average;
4773 average /= multiplier;
4775 //velocity=jointVel(groin)*scale;
4777 for (int i = 0; i < skeleton.num_joints; i++) {
4778 velocity += skeleton.joints[i].velocity * scale;
4780 velocity /= skeleton.num_joints;
4782 if (!isnormal(velocity.x) && velocity.x) {
4786 if (findLength(&average) < 10 && dead && skeleton.free) {
4787 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4788 if (skeleton.longdead > 2000) {
4789 if (skeleton.longdead > 6000) {
4791 pause_sound(whooshsound);
4796 if (dead == 2 && bloodloss < damagetolerance) {
4798 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4800 if (bloodtoggle && !bled) {
4801 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4803 if (bloodtoggle && !bled)
4804 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4805 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4806 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4807 float size = .2 * 1.2;
4810 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4814 if (dead == 2 && bloodloss >= damagetolerance) {
4816 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4819 if (bloodtoggle && !bled) {
4820 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4822 if (bloodtoggle && !bled)
4823 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4824 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4825 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4829 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4836 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4837 bool canrecover = 1;
4838 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4839 startpoint = coords;
4842 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4844 if (velocity.y < -30)
4846 for (i = 0; i < objects.numobjects; i++) {
4847 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4848 colviewer = startpoint;
4849 coltarget = endpoint;
4850 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4859 terrainnormal = jointPos(groin) - jointPos(abdomen);
4860 if (joint(groin).locked && joint(abdomen).locked) {
4861 terrainnormal = jointPos(groin) - jointPos(abdomen);
4862 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4864 if (joint(abdomen).locked && joint(neck).locked) {
4865 terrainnormal = jointPos(abdomen) - jointPos(neck);
4866 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4868 if (joint(groin).locked && joint(neck).locked) {
4869 terrainnormal = jointPos(groin) - jointPos(neck);
4870 middle = (jointPos(groin) + jointPos(neck)) / 2;
4872 Normalise(&terrainnormal);
4874 targetyaw = -asin(0 - terrainnormal.x);
4875 targetyaw *= 360 / 6.28;
4876 if (terrainnormal.z < 0)
4877 targetyaw = 180 - targetyaw;
4881 animTarget = flipanim;
4882 crouchtogglekeydown = 1;
4887 animCurrent = tempanim;
4891 for (int i = 0; i < skeleton.num_joints; i++) {
4892 tempanimation.position[i][0] = skeleton.joints[i].position;
4893 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4898 if (findLength(&average) < 10 && !dead && skeleton.free) {
4899 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4900 if (skeleton.longdead > (damage + 500) * 1.5) {
4902 pause_sound(whooshsound);
4908 terrainnormal = jointPos(groin) - jointPos(abdomen);
4909 if (joint(groin).locked && joint(abdomen).locked) {
4910 terrainnormal = jointPos(groin) - jointPos(abdomen);
4911 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4913 if (joint(abdomen).locked && joint(neck).locked) {
4914 terrainnormal = jointPos(abdomen) - jointPos(neck);
4915 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4917 if (joint(groin).locked && joint(neck).locked) {
4918 terrainnormal = jointPos(groin) - jointPos(neck);
4919 middle = (jointPos(groin) + jointPos(neck)) / 2;
4921 Normalise(&terrainnormal);
4923 targetyaw = -asin(0 - terrainnormal.x);
4924 targetyaw *= 360 / 6.28;
4925 if (terrainnormal.z < 0)
4926 targetyaw = 180 - targetyaw;
4929 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
4932 if (skeleton.forward.y < 0) {
4933 animTarget = getupfrombackanim;
4937 if (skeleton.forward.y > -.3) {
4938 animTarget = getupfromfrontanim;
4946 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
4947 animTarget = rollanim;
4948 targetyaw = lookyaw;
4965 if ( !leftkeydown && !rightkeydown)
4972 if (abs(targettilt2) > 50)
4974 animCurrent = tempanim;
4977 tilt2 = targettilt2;
4979 if (middle.y > 0 && animTarget != rollanim)
4980 targetoffset.y = middle.y + 1;
4982 for (int i = 0; i < skeleton.num_joints; i++) {
4983 tempanimation.position[i][0] = skeleton.joints[i].position;
4984 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4991 if (num_weapons > 0)
4992 if (weapons[0].getType() == staff)
4994 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
4995 if (velocity.y > -30) {
4997 tempvelocity = velocity;
4998 Normalise(&tempvelocity);
4999 targetyaw = -asin(0 - tempvelocity.x);
5000 targetyaw *= 360 / 6.28;
5002 targetyaw = 180 - targetyaw;
5006 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
5007 animTarget = rollanim;
5010 animTarget = backhandspringanim;
5016 emit_sound_at(movewhooshsound, coords, 128.);
5018 animCurrent = animTarget;
5019 frameCurrent = frameTarget - 1;
5031 if (skeleton.freefall == 0)
5036 if (aitype != passivetype || skeleton.free == 1)
5037 if (findLengthfast(&velocity) > .1)
5038 for (i = 0; i < objects.numobjects; i++) {
5039 if (objects.type[i] == firetype)
5040 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) {
5042 if (!objects.onfire[i]) {
5043 emit_sound_at(firestartsound, objects.position[i]);
5045 objects.onfire[i] = 1;
5048 if (objects.onfire[i]) {
5053 if (objects.type[i] == bushtype)
5054 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) {
5056 if (!objects.onfire[i]) {
5057 emit_sound_at(firestartsound, objects.position[i]);
5059 objects.onfire[i] = 1;
5063 if (objects.onfire[i]) {
5067 if (objects.messedwith[i] <= 0) {
5071 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5074 envsound[numenvsounds] = coords;
5075 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5076 envsoundlife[numenvsounds] = .4;
5081 if (environment == grassyenvironment)
5082 howmany = findLength(&velocity) * 4;
5083 if (environment == snowyenvironment)
5084 howmany = findLength(&velocity) * 2;
5086 if (environment != desertenvironment)
5087 for (j = 0; j < howmany; j++) {
5088 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5089 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5090 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5093 pos.x += float(abs(Random() % 100) - 50) / 200;
5094 pos.y += float(abs(Random() % 100) - 50) / 200;
5095 pos.z += float(abs(Random() % 100) - 50) / 200;
5096 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);
5097 Sprite::setLastSpriteSpecial(1);
5099 howmany = findLength(&velocity) * 4;
5101 if (environment == snowyenvironment)
5102 for (j = 0; j < howmany; j++) {
5103 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5104 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5105 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5108 pos.x += float(abs(Random() % 100) - 50) / 200;
5109 pos.y += float(abs(Random() % 100) - 50) / 200;
5110 pos.z += float(abs(Random() % 100) - 50) / 200;
5111 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5112 Sprite::setLastSpriteSpecial(2);
5115 objects.rotx[i] += velocity.x * multiplier * 6;
5116 objects.roty[i] += velocity.z * multiplier * 6;
5117 objects.messedwith[i] = .5;
5120 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5121 if (objects.pitch[i] == 0)
5124 tempcoord = coords - objects.position[i];
5125 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5126 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5127 tempcoord += objects.position[i];
5129 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]) {
5130 if (objects.messedwith[i] <= 0) {
5134 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5137 envsound[numenvsounds] = coords;
5138 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5139 envsoundlife[numenvsounds] = .4;
5144 if (environment == grassyenvironment)
5145 howmany = findLength(&velocity) * 4;
5146 if (environment == snowyenvironment)
5147 howmany = findLength(&velocity) * 2;
5149 if (environment != desertenvironment)
5150 for (j = 0; j < howmany; j++) {
5151 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5152 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5153 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5155 pos += velocity * .1;
5157 pos.x += float(abs(Random() % 100) - 50) / 150;
5158 pos.y += float(abs(Random() % 100) - 50) / 150;
5159 pos.z += float(abs(Random() % 100) - 50) / 150;
5160 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);
5161 Sprite::setLastSpriteSpecial(1);
5163 howmany = findLength(&velocity) * 4;
5165 if (environment == snowyenvironment)
5166 for (j = 0; j < howmany; j++) {
5167 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5168 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5169 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5171 pos += velocity * .1;
5173 pos.x += float(abs(Random() % 100) - 50) / 150;
5174 pos.y += float(abs(Random() % 100) - 50) / 150;
5175 pos.z += float(abs(Random() % 100) - 50) / 150;
5176 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5177 Sprite::setLastSpriteSpecial(2);
5180 objects.messedwith[i] = .5;
5185 if (!skeleton.free) {
5188 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5191 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5193 if (tutoriallevel == 1 && id != 0)
5195 if (play && aitype != playercontrolled) {
5196 int whichsound = -1;
5197 i = abs(Random() % 4);
5198 if (speechdelay <= 0) {
5199 if (creature == rabbittype) {
5201 whichsound = rabbitchitter;
5203 whichsound = rabbitchitter2;
5205 if (creature == wolftype) {
5207 whichsound = growlsound;
5209 whichsound = growl2sound;
5214 if (whichsound != -1) {
5215 emit_sound_at(whichsound, coords);
5219 if (animTarget == staggerbackhighanim)
5221 if (animTarget == staggerbackhardanim)
5223 staggerdelay -= multiplier;
5224 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5226 if (velocity.y < -30 && animTarget == jumpdownanim)
5228 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5229 animTarget = getIdle();
5233 weaponmissdelay -= multiplier;
5234 highreversaldelay -= multiplier;
5235 lowreversaldelay -= multiplier;
5236 lastcollide -= multiplier;
5237 skiddelay -= multiplier;
5238 if (!isnormal(velocity.x) && velocity.x) {
5241 if (!isnormal(targettilt) && targettilt) {
5244 if (!isnormal(targettilt2) && targettilt2) {
5247 if (!isnormal(targetyaw) && targetyaw) {
5251 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5252 //open hands and close mouth
5253 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5254 righthandmorphness = 0;
5255 righthandmorphend = 0;
5256 targetrighthandmorphness = 1;
5259 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5260 lefthandmorphness = 0;
5261 lefthandmorphend = 0;
5262 targetlefthandmorphness = 1;
5265 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5268 targetheadmorphness = 1;
5272 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) {
5273 //open hands and mouth
5274 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5275 righthandmorphness = 0;
5276 righthandmorphend = 0;
5277 targetrighthandmorphness = 1;
5280 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5281 lefthandmorphness = 0;
5282 lefthandmorphend = 0;
5283 targetlefthandmorphness = 1;
5286 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5289 targetheadmorphness = 1;
5293 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5294 //close hands and mouth
5295 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5296 righthandmorphness = 0;
5297 righthandmorphend = 1;
5298 targetrighthandmorphness = 1;
5301 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5302 lefthandmorphness = 0;
5303 lefthandmorphend = 1;
5304 targetlefthandmorphness = 1;
5307 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5310 targetheadmorphness = 1;
5314 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) {
5315 //close hands and yell
5316 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5317 righthandmorphness = 0;
5318 righthandmorphend = 1;
5319 targetrighthandmorphness = 1;
5322 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5323 lefthandmorphness = 0;
5324 lefthandmorphend = 1;
5325 targetlefthandmorphness = 1;
5328 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5331 targetheadmorphness = 1;
5338 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5339 (victim->aitype != searchtype) && (aitype != passivetype) &&
5340 (aitype != searchtype) && (victim->id < Person::players.size()) && (aitype != passivetype)) {
5341 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5345 if (!dead && animTarget != hurtidleanim)
5346 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5347 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5350 targetheadmorphness = 1;
5354 if (weaponactive != -1) {
5355 if (weapons[weaponids[weaponactive]].getType() != staff) {
5356 righthandmorphstart = 1;
5357 righthandmorphend = 1;
5359 if (weapons[weaponids[weaponactive]].getType() == staff) {
5360 righthandmorphstart = 2;
5361 righthandmorphend = 2;
5363 targetrighthandmorphness = 1;
5366 terrainnormal = terrain.getNormal(coords.x, coords.z);
5368 if (animation[animTarget].attack != reversal) {
5369 if (!isnormal(coords.x))
5377 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5378 facing = flatfacing;
5379 ReflectVector(&facing, terrainnormal);
5382 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5384 targettilt2 = -facing.y * 20;
5389 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5391 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5392 flatvelocity = velocity;
5394 flatvelspeed = findLength(&flatvelocity);
5395 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5396 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5401 if (targettilt > 25)
5403 if (targettilt < -25)
5407 if (targettilt2 > 45)
5409 if (targettilt2 < -45)
5411 if (abs(tilt2 - targettilt2) < multiplier * 400)
5412 tilt2 = targettilt2;
5413 else if (tilt2 > targettilt2) {
5414 tilt2 -= multiplier * 400;
5415 } else if (tilt2 < targettilt2) {
5416 tilt2 += multiplier * 400;
5418 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5425 if (!isnormal(targettilt) && targettilt) {
5428 if (!isnormal(targettilt2) && targettilt2) {
5433 if (animTarget == rabbittackleanim) {
5434 velocity += facing * multiplier * speed * 700 * scale;
5435 velspeed = findLength(&velocity);
5436 if (velspeed > speed * 65 * scale) {
5437 velocity /= velspeed;
5438 velspeed = speed * 65 * scale;
5439 velocity *= velspeed;
5441 velocity.y += gravity * multiplier * 20;
5442 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5443 velspeed = findLength(&velocity);
5444 velocity = flatfacing * velspeed;
5446 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5447 if (isRun() || animTarget == rabbitkickanim) {
5448 velocity += facing * multiplier * speed * 700 * scale;
5449 velspeed = findLength(&velocity);
5450 if (velspeed > speed * 45 * scale) {
5451 velocity /= velspeed;
5452 velspeed = speed * 45 * scale;
5453 velocity *= velspeed;
5455 velocity.y += gravity * multiplier * 20;
5456 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5457 velspeed = findLength(&velocity);
5458 if (velspeed < speed * 30 * scale)
5459 velspeed = speed * 30 * scale;
5460 velocity = flatfacing * velspeed;
5462 } else if (isRun()) {
5463 velocity += facing * multiplier * speed * 700 * scale;
5464 velspeed = findLength(&velocity);
5465 if (creature == rabbittype) {
5466 if (velspeed > speed * 55 * scale) {
5467 velocity /= velspeed;
5468 velspeed = speed * 55 * scale;
5469 velocity *= velspeed;
5472 if (creature == wolftype) {
5473 if (velspeed > speed * 75 * scale) {
5474 velocity /= velspeed;
5475 velspeed = speed * 75 * scale;
5476 velocity *= velspeed;
5479 velocity.y += gravity * multiplier * 20;
5480 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5481 velspeed = findLength(&velocity);
5482 velocity = flatfacing * velspeed;
5485 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5486 velocity += facing * multiplier * speed * 700 * scale;
5487 velspeed = findLength(&velocity);
5488 if (velspeed > speed * 45 * scale) {
5489 velocity /= velspeed;
5490 velspeed = speed * 45 * scale;
5491 velocity *= velspeed;
5493 velocity.y += gravity * multiplier * 20;
5494 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5495 velspeed = findLength(&velocity);
5496 velocity = flatfacing * velspeed;
5499 if (animTarget == sneakanim || animTarget == walkanim) {
5500 velocity += facing * multiplier * speed * 700 * scale;
5501 velspeed = findLength(&velocity);
5502 if (velspeed > speed * 12 * scale) {
5503 velocity /= velspeed;
5504 velspeed = speed * 12 * scale;
5505 velocity *= velspeed;
5507 velocity.y += gravity * multiplier * 20;
5508 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5509 velspeed = findLength(&velocity);
5510 velocity = flatfacing * velspeed;
5513 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5514 velocity += facing * multiplier * speed * 700 * scale;
5515 velspeed = findLength(&velocity);
5516 if (velspeed > speed * 2 * scale) {
5517 velocity /= velspeed;
5518 velspeed = speed * 2 * scale;
5519 velocity *= velspeed;
5521 velocity.y += gravity * multiplier * 20;
5522 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5523 velspeed = findLength(&velocity);
5524 velocity = flatfacing * velspeed;
5528 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5529 velocity -= facing * multiplier * speed * 700 * scale;
5530 velspeed = findLength(&velocity);
5531 if (velspeed > speed * 2 * scale) {
5532 velocity /= velspeed;
5533 velspeed = speed * 2 * scale;
5534 velocity *= velspeed;
5536 velocity.y += gravity * multiplier * 20;
5537 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5538 velspeed = findLength(&velocity);
5539 velocity = flatfacing * velspeed * -1;
5542 if (animTarget == fightsidestep) {
5543 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5544 velspeed = findLength(&velocity);
5545 if (velspeed > speed * 12 * scale) {
5546 velocity /= velspeed;
5547 velspeed = speed * 12 * scale;
5548 velocity *= velspeed;
5550 velocity.y += gravity * multiplier * 20;
5551 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5552 velspeed = findLength(&velocity);
5553 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5556 if (animTarget == staggerbackhighanim) {
5557 coords -= facing * multiplier * speed * 16 * scale;
5560 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5561 coords -= facing * multiplier * speed * 20 * scale;
5565 if (animTarget == backhandspringanim) {
5566 //coords-=facing*multiplier*50*scale;
5567 velocity += facing * multiplier * speed * 700 * scale * -1;
5568 velspeed = findLength(&velocity);
5569 if (velspeed > speed * 50 * scale) {
5570 velocity /= velspeed;
5571 velspeed = speed * 50 * scale;
5572 velocity *= velspeed;
5574 velocity.y += gravity * multiplier * 20;
5575 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5576 velspeed = findLength(&velocity);
5577 velocity = flatfacing * velspeed * -1;
5579 if (animTarget == dodgebackanim) {
5580 //coords-=facing*multiplier*50*scale;
5581 velocity += facing * multiplier * speed * 700 * scale * -1;
5582 velspeed = findLength(&velocity);
5583 if (velspeed > speed * 60 * scale) {
5584 velocity /= velspeed;
5585 velspeed = speed * 60 * scale;
5586 velocity *= velspeed;
5588 velocity.y += gravity * multiplier * 20;
5589 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5590 velspeed = findLength(&velocity);
5591 velocity = flatfacing * velspeed * -1;
5594 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5595 velspeed = findLength(&velocity);
5599 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5600 velocity.y += gravity * multiplier;
5603 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5604 coords += velocity * multiplier;
5606 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5607 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5610 if (animTarget == jumpupanim) {
5612 animTarget = getIdle();
5619 pause_sound(whooshsound);
5620 OPENAL_SetVolume(channels[whooshsound], 0);
5623 if (animTarget == jumpdownanim || isFlip()) {
5624 if (isFlip())jumppower = -4;
5625 animTarget = getLanding();
5626 emit_sound_at(landsound, coords, 128.);
5629 envsound[numenvsounds] = coords;
5630 envsoundvol[numenvsounds] = 16;
5631 envsoundlife[numenvsounds] = .4;
5637 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5638 coords.y += gravity * multiplier * 2;
5639 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5640 coords.y = terrain.getHeight(coords.x, coords.z);
5645 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)) {
5646 velspeed = findLength(&velocity);
5648 if (velspeed < multiplier * 300 * scale) {
5651 velocity -= velocity / velspeed * multiplier * 300 * scale;
5652 if (velspeed > 5 && (isLanding() || isLandhard())) {
5653 skiddingdelay += multiplier;
5654 if (skiddelay <= 0) {
5664 velspeed = findLength(&velocity);
5666 if (velspeed < multiplier * 600 * scale) {
5669 velocity -= velocity / velspeed * multiplier * 600 * scale;
5671 if (velspeed > 5 && (isLanding() || isLandhard())) {
5672 skiddingdelay += multiplier;
5673 if (skiddelay <= 0) {
5682 if (skiddingdelay < 0)
5683 skiddingdelay += multiplier;
5684 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5686 if (!onterrain || environment == grassyenvironment) {
5687 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5689 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5693 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5694 terrainnormal = victim->coords - coords;
5695 Normalise(&terrainnormal);
5696 targetyaw = -asin(0 - terrainnormal.x);
5697 targetyaw *= 360 / 6.28;
5698 if (terrainnormal.z < 0)
5699 targetyaw = 180 - targetyaw;
5700 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5703 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5704 targetyaw = victim->targetyaw;
5706 if (animTarget == rabbittacklinganim) {
5707 coords = victim->coords;
5710 skeleton.oldfree = skeleton.free;
5714 midterrain.x = terrain.size * terrain.scale / 2;
5715 midterrain.z = terrain.size * terrain.scale / 2;
5716 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5718 tempposit = coords - midterrain;
5720 Normalise(&tempposit);
5721 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5722 coords.x = tempposit.x + midterrain.x;
5723 coords.z = tempposit.z + midterrain.z;
5729 * inverse kinematics helper function
5731 void IKHelper(Person *p, float interp)
5733 XYZ point, newpoint, change, change2;
5734 float heightleft, heightright;
5736 // TODO: implement localToWorld and worldToLocal
5737 // but keep in mind it won't be the same math if player is ragdolled or something
5738 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5739 // then comb through code for places where to use it
5741 // point = localToWorld(jointPos(leftfoot))
5742 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5743 // adjust height of foot
5744 heightleft = terrain.getHeight(point.x, point.z) + .04;
5745 point.y = heightleft;
5746 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5747 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5748 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5749 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5750 // move ankle along with foot
5751 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5752 // average knee pos between old and new pos
5753 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5755 // do same as above for right leg
5756 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5757 heightright = terrain.getHeight(point.x, point.z) + .04;
5758 point.y = heightright;
5759 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5760 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5761 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5762 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5763 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5765 // fix up skeleton now that we've moved body parts?
5766 p->skeleton.DoConstraints(&p->coords, &p->scale);
5773 int Person::DrawSkeleton()
5775 int oldplayerdetail;
5776 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5777 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5787 glAlphaFunc(GL_GREATER, 0.0001);
5789 float terrainheight;
5793 if (!isnormal(tilt))
5795 if (!isnormal(tilt2))
5797 oldplayerdetail = playerdetail;
5799 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5802 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5805 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5810 if (playerdetail != oldplayerdetail) {
5812 normalsupdatedelay = 0;
5814 static float updatedelaychange;
5815 static float morphness;
5816 static float framemult;
5818 skeleton.FindForwards();
5819 if (howactive == typesittingwall) {
5820 skeleton.specialforward[1] = 0;
5821 skeleton.specialforward[1].z = 1;
5827 static int weaponattachmuscle;
5828 static int weaponrotatemuscle;
5829 static XYZ weaponpoint;
5830 static int start, endthing;
5831 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5832 if (!isSleeping() && !isSitting()) {
5833 // TODO: give these meaningful names
5834 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5835 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5836 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5837 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5839 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5841 if (creature == wolftype)
5845 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5846 IKHelper(this, target);
5847 if (creature == wolftype)
5848 IKHelper(this, target);
5851 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5852 IKHelper(this, 1 - target);
5853 if (creature == wolftype)
5854 IKHelper(this, 1 - target);
5858 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()))
5861 targetheadyaw = -targetyaw;
5862 targetheadpitch = 0;
5863 if (animation[animTarget].attack == 3)
5864 targetheadyaw += 180;
5866 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5867 skeleton.drawmodel.vertex[i] = 0;
5868 skeleton.drawmodel.vertex[i].y = 999;
5870 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5871 skeleton.drawmodellow.vertex[i] = 0;
5872 skeleton.drawmodellow.vertex[i].y = 999;
5874 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5875 skeleton.drawmodelclothes.vertex[i] = 0;
5876 skeleton.drawmodelclothes.vertex[i].y = 999;
5878 for (int i = 0; i < skeleton.num_muscles; i++) {
5879 // convenience renames
5880 const int p1 = skeleton.muscles[i].parent1->label;
5881 const int p2 = skeleton.muscles[i].parent2->label;
5883 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
5888 if (p1 == righthand || p2 == righthand) {
5889 morphness = righthandmorphness;
5890 start = righthandmorphstart;
5891 endthing = righthandmorphend;
5893 if (p1 == lefthand || p2 == lefthand) {
5894 morphness = lefthandmorphness;
5895 start = lefthandmorphstart;
5896 endthing = lefthandmorphend;
5898 if (p1 == head || p2 == head) {
5899 morphness = headmorphness;
5900 start = headmorphstart;
5901 endthing = headmorphend;
5903 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
5904 morphness = chestmorphness;
5905 start = chestmorphstart;
5906 endthing = chestmorphend;
5908 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
5909 morphness = tailmorphness;
5910 start = tailmorphstart;
5911 endthing = tailmorphend;
5914 skeleton.FindRotationMuscle(i, animTarget);
5915 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5916 glMatrixMode(GL_MODELVIEW);
5920 glRotatef(tilt2, 1, 0, 0);
5922 glRotatef(tilt, 0, 0, 1);
5925 glTranslatef(mid.x, mid.y, mid.z);
5927 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5928 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5930 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
5931 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
5933 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
5934 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
5936 if (playerdetail || skeleton.free == 3) {
5937 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
5938 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
5939 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
5940 glMatrixMode(GL_MODELVIEW);
5942 if (p1 == abdomen || p2 == abdomen)
5943 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
5944 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
5945 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
5946 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5947 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
5948 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
5949 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
5950 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5951 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
5952 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
5953 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
5954 if (p1 == head || p2 == head)
5955 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
5956 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
5957 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
5958 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5959 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
5960 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
5961 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
5965 if (!playerdetail || skeleton.free == 3) {
5966 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
5967 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
5968 glMatrixMode(GL_MODELVIEW);
5970 if (p1 == abdomen || p2 == abdomen)
5971 glTranslatef(v0.x * proportionbody.x,
5972 v0.y * proportionbody.y,
5973 v0.z * proportionbody.z);
5974 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5975 glTranslatef(v0.x * proportionarms.x,
5976 v0.y * proportionarms.y,
5977 v0.z * proportionarms.z);
5978 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5979 glTranslatef(v0.x * proportionlegs.x,
5980 v0.y * proportionlegs.y,
5981 v0.z * proportionlegs.z);
5982 if (p1 == head || p2 == head)
5983 glTranslatef(v0.x * proportionhead.x,
5984 v0.y * proportionhead.y,
5985 v0.z * proportionhead.z);
5987 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5988 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
5989 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
5990 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
5996 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
5997 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5999 glMatrixMode(GL_MODELVIEW);
6003 glRotatef(tilt2, 1, 0, 0);
6005 glRotatef(tilt, 0, 0, 1);
6006 glTranslatef(mid.x, mid.y, mid.z);
6007 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
6008 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
6010 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
6011 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
6013 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
6014 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
6016 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
6017 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
6018 glMatrixMode(GL_MODELVIEW);
6020 if (p1 == abdomen || p2 == abdomen)
6021 glTranslatef(v0.x * proportionbody.x,
6022 v0.y * proportionbody.y,
6023 v0.z * proportionbody.z);
6024 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
6025 glTranslatef(v0.x * proportionarms.x,
6026 v0.y * proportionarms.y,
6027 v0.z * proportionarms.z);
6028 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
6029 glTranslatef(v0.x * proportionlegs.x,
6030 v0.y * proportionlegs.y,
6031 v0.z * proportionlegs.z);
6032 if (p1 == head || p2 == head)
6033 glTranslatef(v0.x * proportionhead.x,
6034 v0.y * proportionhead.y,
6035 v0.z * proportionhead.z);
6036 glGetFloatv(GL_MODELVIEW_MATRIX, M);
6037 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
6038 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
6039 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
6044 updatedelay = 1 + (float)(Random() % 100) / 1000;
6046 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
6047 normalsupdatedelay = 1;
6048 if (playerdetail || skeleton.free == 3)
6049 skeleton.drawmodel.CalculateNormals(0);
6050 if (!playerdetail || skeleton.free == 3)
6051 skeleton.drawmodellow.CalculateNormals(0);
6052 if (skeleton.clothes)
6053 skeleton.drawmodelclothes.CalculateNormals(0);
6055 if (playerdetail || skeleton.free == 3)
6056 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
6057 if (!playerdetail || skeleton.free == 3)
6058 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
6059 if (skeleton.clothes) {
6060 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
6065 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
6066 if (updatedelaychange > -realmultiplier * 30)
6067 updatedelaychange = -realmultiplier * 30;
6068 if (updatedelaychange > -framemult * 4)
6069 updatedelaychange = -framemult * 4;
6070 if (skeleton.free == 1)
6071 updatedelaychange *= 6;
6073 updatedelaychange *= 8;
6074 updatedelay += updatedelaychange;
6076 glMatrixMode(GL_MODELVIEW);
6079 glTranslatef(coords.x, coords.y - .02, coords.z);
6081 glTranslatef(coords.x, coords.y - .02, coords.z);
6083 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6085 glRotatef(yaw, 0, 1, 0);
6088 glColor4f(.4, 1, .4, 1);
6089 glDisable(GL_LIGHTING);
6090 glDisable(GL_TEXTURE_2D);
6093 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6094 XYZ &v0 = skeleton.drawmodel.vertex[i];
6095 glVertex3f(v0.x, v0.y, v0.z);
6101 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6102 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6103 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6104 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6105 glVertex3f(v0.x, v0.y, v0.z);
6106 glVertex3f(v1.x, v1.y, v1.z);
6107 glVertex3f(v1.x, v1.y, v1.z);
6108 glVertex3f(v2.x, v2.y, v2.z);
6109 glVertex3f(v2.x, v2.y, v2.z);
6110 glVertex3f(v0.x, v0.y, v0.z);
6116 terrainlight = terrain.getLighting(coords.x, coords.z);
6117 distance = distsq(&viewer, &coords);
6118 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6122 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6123 if (terrainheight < 1)
6125 if (terrainheight > 1.7)
6126 terrainheight = 1.7;
6129 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6130 glDisable(GL_BLEND);
6131 glAlphaFunc(GL_GREATER, 0.0001);
6132 glEnable(GL_TEXTURE_2D);
6134 glDisable(GL_TEXTURE_2D);
6135 glColor4f(.7, .35, 0, .5);
6137 glEnable(GL_LIGHTING);
6140 if (tutoriallevel && id != 0) {
6141 glColor4f(.7, .7, .7, 0.6);
6143 glEnable(GL_LIGHTING);
6145 if (canattack && cananger)
6146 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6147 glDisable(GL_TEXTURE_2D);
6148 glColor4f(1, 0, 0, 0.8);
6150 glMatrixMode(GL_TEXTURE);
6152 glTranslatef(0, -smoketex, 0);
6153 glTranslatef(-smoketex, 0, 0);
6157 if ((tutoriallevel && id != 0))
6158 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6160 skeleton.drawmodel.draw();
6163 if (!playerdetail) {
6164 if ((tutoriallevel && id != 0))
6165 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6167 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6170 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6171 if (tutoriallevel && id != 0) {
6173 glMatrixMode(GL_MODELVIEW);
6174 glEnable(GL_TEXTURE_2D);
6175 glColor4f(.7, .7, .7, 0.6);
6177 glEnable(GL_LIGHTING);
6179 if (canattack && cananger)
6180 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6181 glDisable(GL_TEXTURE_2D);
6182 glColor4f(1, 0, 0, 0.8);
6184 glMatrixMode(GL_TEXTURE);
6186 glTranslatef(0, -smoketex * .6, 0);
6187 glTranslatef(smoketex * .6, 0, 0);
6190 if ((tutoriallevel && id != 0))
6191 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6193 skeleton.drawmodel.draw();
6196 if (!playerdetail) {
6197 if ((tutoriallevel && id != 0))
6198 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6200 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6205 if (tutoriallevel && id != 0) {
6207 glMatrixMode(GL_MODELVIEW);
6208 glEnable(GL_TEXTURE_2D);
6210 if (skeleton.clothes) {
6214 skeleton.drawmodelclothes.draw();
6216 skeleton.drawmodelclothes.drawimmediate();
6222 if (num_weapons > 0) {
6223 for (k = 0; k < num_weapons; k++) {
6225 if (weaponactive == k) {
6226 if (weapons[i].getType() != staff) {
6227 for (j = 0; j < skeleton.num_muscles; j++) {
6228 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6229 weaponattachmuscle = j;
6232 for (j = 0; j < skeleton.num_muscles; j++) {
6233 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) {
6234 weaponrotatemuscle = j;
6237 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6238 if (creature == wolftype)
6239 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6241 if (weapons[i].getType() == staff) {
6242 for (j = 0; j < skeleton.num_muscles; j++) {
6243 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6244 weaponattachmuscle = j;
6247 for (j = 0; j < skeleton.num_muscles; j++) {
6248 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) {
6249 weaponrotatemuscle = j;
6252 //weaponpoint=jointPos(rightwrist);
6253 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6254 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6255 XYZ tempnormthing, vec1, vec2;
6256 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6257 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6258 CrossProduct(&vec1, &vec2, &tempnormthing);
6259 Normalise(&tempnormthing);
6260 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6261 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6264 if (weaponactive != k && weaponstuck != k) {
6265 if (weapons[i].getType() == knife)
6266 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6267 if (weapons[i].getType() == sword)
6268 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6269 if (weapons[i].getType() == staff)
6270 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6271 for (j = 0; j < skeleton.num_muscles; j++) {
6272 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) {
6273 weaponrotatemuscle = j;
6277 if (weaponstuck == k) {
6278 if (weaponstuckwhere == 0)
6279 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6281 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6282 for (j = 0; j < skeleton.num_muscles; j++) {
6283 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) {
6284 weaponrotatemuscle = j;
6288 if (skeleton.free) {
6289 weapons[i].position = weaponpoint * scale + coords;
6290 weapons[i].bigrotation = 0;
6291 weapons[i].bigtilt = 0;
6292 weapons[i].bigtilt2 = 0;
6294 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;
6295 weapons[i].bigrotation = yaw;
6296 weapons[i].bigtilt = tilt;
6297 weapons[i].bigtilt2 = tilt2;
6299 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6300 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6301 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6302 if (weaponactive == k) {
6303 if (weapons[i].getType() == knife) {
6304 weapons[i].smallrotation = 180;
6305 weapons[i].smallrotation2 = 0;
6306 if (isCrouch() || wasCrouch()) {
6307 weapons[i].smallrotation2 = 20;
6309 if (animTarget == hurtidleanim) {
6310 weapons[i].smallrotation2 = 50;
6312 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6313 XYZ temppoint1, temppoint2, tempforward;
6316 temppoint1 = jointPos(righthand);
6317 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6318 distance = findDistance(&temppoint1, &temppoint2);
6319 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6320 weapons[i].rotation2 *= 360 / 6.28;
6323 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6324 weapons[i].rotation1 *= 360 / 6.28;
6325 weapons[i].rotation3 = 0;
6326 weapons[i].smallrotation = -90;
6327 weapons[i].smallrotation2 = 0;
6328 if (temppoint1.x > temppoint2.x)
6329 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6331 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6332 XYZ temppoint1, temppoint2, tempforward;
6335 temppoint1 = jointPos(righthand);
6336 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6337 distance = findDistance(&temppoint1, &temppoint2);
6338 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6339 weapons[i].rotation2 *= 360 / 6.28;
6342 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6343 weapons[i].rotation1 *= 360 / 6.28;
6344 weapons[i].rotation3 = 0;
6345 weapons[i].smallrotation = 90;
6346 weapons[i].smallrotation2 = 0;
6347 if (temppoint1.x > temppoint2.x)
6348 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6350 if (animTarget == knifethrowanim) {
6351 weapons[i].smallrotation = 90;
6352 //weapons[i].smallrotation2=-90;
6353 weapons[i].smallrotation2 = 0;
6354 weapons[i].rotation1 = 0;
6355 weapons[i].rotation2 = 0;
6356 weapons[i].rotation3 = 0;
6358 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6359 weapons[i].smallrotation = -90;
6360 weapons[i].rotation1 = 0;
6361 weapons[i].rotation2 = 0;
6362 weapons[i].rotation3 = 0;
6365 if (weapons[i].getType() == sword) {
6366 weapons[i].smallrotation = 0;
6367 weapons[i].smallrotation2 = 0;
6368 if (animTarget == knifethrowanim) {
6369 weapons[i].smallrotation = -90;
6370 weapons[i].smallrotation2 = 0;
6371 weapons[i].rotation1 = 0;
6372 weapons[i].rotation2 = 0;
6373 weapons[i].rotation3 = 0;
6375 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)) {
6376 XYZ temppoint1, temppoint2, tempforward;
6379 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6380 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6381 distance = findDistance(&temppoint1, &temppoint2);
6382 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6383 weapons[i].rotation2 *= 360 / 6.28;
6386 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6387 weapons[i].rotation1 *= 360 / 6.28;
6388 weapons[i].rotation3 = 0;
6389 weapons[i].smallrotation = 90;
6390 weapons[i].smallrotation2 = 0;
6391 if (temppoint1.x > temppoint2.x)
6392 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6395 if (weapons[i].getType() == staff) {
6396 weapons[i].smallrotation = 100;
6397 weapons[i].smallrotation2 = 0;
6398 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6399 XYZ temppoint1, temppoint2, tempforward;
6402 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6403 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6404 distance = findDistance(&temppoint1, &temppoint2);
6405 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6406 weapons[i].rotation2 *= 360 / 6.28;
6409 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6410 weapons[i].rotation1 *= 360 / 6.28;
6411 weapons[i].rotation3 = 0;
6412 weapons[i].smallrotation = 90;
6413 weapons[i].smallrotation2 = 0;
6414 if (temppoint1.x > temppoint2.x)
6415 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6419 if (weaponactive != k && weaponstuck != k) {
6420 if (weapons[i].getType() == knife) {
6421 weapons[i].smallrotation = -70;
6422 weapons[i].smallrotation2 = 10;
6424 if (weapons[i].getType() == sword) {
6425 weapons[i].smallrotation = -100;
6426 weapons[i].smallrotation2 = -8;
6428 if (weapons[i].getType() == staff) {
6429 weapons[i].smallrotation = -100;
6430 weapons[i].smallrotation2 = -8;
6433 if (weaponstuck == k) {
6434 if (weaponstuckwhere == 0)
6435 weapons[i].smallrotation = 180;
6437 weapons[i].smallrotation = 0;
6438 weapons[i].smallrotation2 = 10;
6447 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isFlip() || isWallJump())
6449 if (animCurrent != animTarget)
6451 if (skeleton.free == 2)
6460 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6463 static float distance;
6464 static float olddistance;
6465 static int intersecting;
6466 static int firstintersecting;
6469 static XYZ start, end;
6470 static float slopethreshold = -.4;
6472 firstintersecting = -1;
6476 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6479 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6480 for (i = 0; i < 4; i++) {
6481 for (j = 0; j < model->TriangleNum; j++) {
6482 if (model->facenormals[j].y <= slopethreshold) {
6484 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)));
6485 if (distance < radius) {
6486 point = *p1 - model->facenormals[j] * distance;
6487 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]]))
6490 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6491 &model->vertex[model->Triangles[j].vertex[1]],
6494 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6495 &model->vertex[model->Triangles[j].vertex[2]],
6498 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6499 &model->vertex[model->Triangles[j].vertex[2]],
6502 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6506 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)) {
6507 p1->y = point.y + radius;
6508 if ((animTarget == jumpdownanim || isFlip())) {
6509 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6512 if (animTarget == jumpupanim) {
6514 animTarget = getIdle();
6521 pause_sound(whooshsound);
6522 OPENAL_SetVolume(channels[whooshsound], 0);
6525 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6528 animTarget = getLanding();
6529 emit_sound_at(landsound, coords, 128.);
6532 envsound[numenvsounds] = coords;
6533 envsoundvol[numenvsounds] = 16;
6534 envsoundlife[numenvsounds] = .4;
6542 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6543 olddistance = distance;
6544 firstintersecting = j;
6549 for (j = 0; j < model->TriangleNum; j++) {
6550 if (model->facenormals[j].y > slopethreshold) {
6553 start.y -= radius / 4;
6554 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6555 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6556 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6557 distance = abs((model->facenormals[j].x * start.x)
6558 + (model->facenormals[j].y * start.y)
6559 + (model->facenormals[j].z * start.z)
6560 - ((model->facenormals[j].x * v0.x)
6561 + (model->facenormals[j].y * v0.y)
6562 + (model->facenormals[j].z * v0.z)));
6563 if (distance < radius * .5) {
6564 point = start - model->facenormals[j] * distance;
6565 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6568 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6570 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6572 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6574 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6575 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6577 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6578 if (findLengthfast(&start) < findLengthfast(&velocity))
6581 *p1 += model->facenormals[j] * (distance - radius * .5);
6584 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6585 olddistance = distance;
6586 firstintersecting = j;
6593 *p = DoRotation(*p, 0, *rotate, 0);
6596 *p1 = DoRotation(*p1, 0, *rotate, 0);
6598 return firstintersecting;