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 = skeleton.joints[howmany].velocity;
165 flatfacing = skeleton.joints[howmany].position * scale + coords;
167 flatvelocity = velocity;
168 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
170 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1);
175 emit_sound_at(firestartsound, coords);
177 emit_stream_at(stream_firesound, coords);
185 * idle animation for this creature (depending on status)
187 int Person::getIdle()
189 if (indialogue != -1 && howactive == typeactive && creature == rabbittype)
191 if (hasvictim && (victim != this->shared_from_this())/*||(id==0&&attackkeydown)*/)
192 if (/*(id==0&&attackkeydown)||*/(!victim->dead && victim->aitype != passivetype &&
193 victim->aitype != searchtype && aitype != passivetype && aitype != searchtype &&
194 victim->id < Person::players.size())) {
195 if ((aitype == playercontrolled && stunned <= 0 && weaponactive == -1) || pause) {
196 if (creature == rabbittype)
197 return fightidleanim;
198 if (creature == wolftype)
201 if (aitype == playercontrolled && stunned <= 0 && weaponactive != -1) {
202 if (weapons[weaponids[weaponactive]].getType() == knife)
203 return knifefightidleanim;
204 if (weapons[weaponids[weaponactive]].getType() == sword && victim->weaponactive != -1)
205 return swordfightidlebothanim;
206 if (weapons[weaponids[weaponactive]].getType() == sword)
207 return swordfightidleanim;
208 if (weapons[weaponids[weaponactive]].getType() == staff)
209 return swordfightidleanim;
211 if (aitype != playercontrolled && stunned <= 0 && creature != wolftype && !pause)
212 return fightsidestep;
214 if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && creature != wolftype)
216 if (howactive == typesitting) return sitanim;
217 if (howactive == typesittingwall) return sitwallanim;
218 if (howactive == typesleeping) return sleepanim;
219 if (howactive == typedead1) return dead1anim;
220 if (howactive == typedead2) return dead2anim;
221 if (howactive == typedead3) return dead3anim;
222 if (howactive == typedead4) return dead4anim;
223 if (creature == rabbittype) return bounceidleanim;
224 if (creature == wolftype) return wolfidle;
229 * crouch animation for this creature
231 int Person::getCrouch()
233 if (creature == rabbittype)
235 if (creature == wolftype)
236 return wolfcrouchanim;
241 * running animation for this creature (can be upright or all fours)
245 if (creature == rabbittype && (!superruntoggle || weaponactive != -1))
247 if (creature == wolftype && (!superruntoggle))
250 if (creature == rabbittype && (superruntoggle && weaponactive == -1))
251 return rabbitrunninganim;
252 if (creature == wolftype && (superruntoggle))
253 return wolfrunninganim;
259 int Person::getStop()
261 if (creature == rabbittype)
263 if (creature == wolftype)
270 int Person::getLanding()
272 if (creature == rabbittype)
274 if (creature == wolftype)
281 int Person::getLandhard()
283 if (creature == rabbittype)
285 if (creature == wolftype)
286 return wolflandhardanim;
293 * Person::DoAnimations
296 SolidHitBonus(int playerid)
298 if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo)
299 award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1);
301 award_bonus(playerid, solidhit);
305 * spawns blood effects
307 void Person::DoBlood(float howmuch, int which)
309 // FIXME: should abstract out inputs
310 static int bleedxint, bleedyint;
312 if (bloodtoggle && tutoriallevel != 1) {
313 if (bleeding <= 0 && spurt) {
315 for (int i = 0; i < 3; i++) {
316 // emit blood particles
319 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
320 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
321 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
322 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
325 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
326 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
327 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
328 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
331 if (Random() % 2 == 0) // 50% chance
332 for (int i = 0; i < 3; i++) {
333 if (Random() % 2 != 0) {
334 // emit teeth particles
337 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
338 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
341 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
342 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
346 Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
348 Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
350 Sprite::setLastSpriteSpecial(3); // sets it to teeth
355 // FIXME: manipulating attributes
356 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
359 if (creature == rabbittype)
360 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) {
361 bleedxint = abs(Random() % 512);
362 bleedyint = abs(Random() % 512);
364 if (creature == wolftype)
365 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) {
366 bleedxint = abs(Random() % 512);
367 bleedyint = abs(Random() % 512);
371 bleedy /= realtexdetail;
372 bleedx /= realtexdetail;
373 direction = abs(Random() % 2) * 2 - 1;
382 * spawns big blood effects and ???
383 * modifies character's skin texture
385 void Person::DoBloodBig(float howmuch, int which)
387 static int bleedxint, bleedyint, i, j;
389 if (howmuch && id == 0)
392 if (tutoriallevel != 1 || id == 0)
393 if (aitype != playercontrolled && howmuch > 0) {
397 // FIXME: seems to be spawning sounds by manipulating attributes... MESSY!
398 if (creature == wolftype) {
399 int i = abs(Random() % 2);
401 whichsound = snarlsound;
403 whichsound = snarl2sound;
404 envsound[numenvsounds] = coords;
405 envsoundvol[numenvsounds] = 16;
406 envsoundlife[numenvsounds] = .4;
409 if (creature == rabbittype) {
410 int i = abs(Random() % 2);
412 whichsound = rabbitpainsound;
413 if (i == 1 && howmuch >= 2)
414 whichsound = rabbitpain1sound;
415 envsound[numenvsounds] = coords;
416 envsoundvol[numenvsounds] = 16;
417 envsoundlife[numenvsounds] = .4;
421 if (whichsound != -1)
422 emit_sound_at(whichsound, coords);
425 if (id == 0 && howmuch > 0) {
426 // FIXME: manipulating attributes
434 if (bloodtoggle && decals && tutoriallevel != 1) {
435 if (bleeding <= 0 && spurt) {
437 for (int i = 0; i < 3; i++) {
438 // emit blood particles
439 // FIXME: copypaste from above
442 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
443 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
444 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
445 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
448 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
449 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
450 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
451 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
456 // weird texture manipulation code follows.
457 // looks like this is painting blood onto the character's skin texture
458 // FIXME: surely there's a better way
460 int offsetx = 0, offsety = 0;
462 offsety = Random() % 40;
463 offsetx = abs(Random() % 60);
465 if (which == 190 || which == 185) {
466 offsety = Random() % 40;
467 offsetx = abs(Random() % 100) - 20;
470 offsety = Random() % 10;
471 offsetx = Random() % 10;
474 offsety = Random() % 20;
475 offsetx = Random() % 20;
477 if (which == 220 || which == 215) {
487 if (creature == rabbittype)
488 for (i = 0; i < 512; i++) {
489 for (j = 0; j < 512; j++) {
490 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
491 if (i < startx) startx = i;
492 if (j < starty) starty = j;
493 if (i > endx) endx = i;
494 if (j > endy) endy = j;
498 if (creature == wolftype)
499 for (i = 0; i < 512; i++) {
500 for (j = 0; j < 512; j++) {
501 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
502 if (i < startx) startx = i;
503 if (j < starty) starty = j;
504 if (i > endx) endx = i;
505 if (j > endy) endy = j;
515 if (startx < 0) startx = 0;
516 if (starty < 0) starty = 0;
517 if (endx > 512 - 1) endx = 512 - 1;
518 if (endy > 512 - 1) endy = 512 - 1;
519 if (endx < startx) endx = startx;
520 if (endy < starty) endy = starty;
522 startx /= realtexdetail;
523 starty /= realtexdetail;
524 endx /= realtexdetail;
525 endy /= realtexdetail;
527 int texdetailint = realtexdetail;
529 if (creature == rabbittype)
530 for (i = startx; i < endx; i++) {
531 for (j = starty; j < endy; j++) {
532 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) {
533 color = Random() % 85 + 170;
534 where = i * skeleton.skinsize * 3 + j * 3;
535 if (skeleton.skinText[where + 0] > color / 2)
536 skeleton.skinText[where + 0] = color / 2;
537 skeleton.skinText[where + 1] = 0;
538 skeleton.skinText[where + 2] = 0;
542 if (creature == wolftype)
543 for (i = startx; i < endx; i++) {
544 for (j = starty; j < endy; j++) {
545 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) {
546 color = Random() % 85 + 170;
547 where = i * skeleton.skinsize * 3 + j * 3;
548 if (skeleton.skinText[where + 0] > color / 2)
549 skeleton.skinText[where + 0] = color / 2;
550 skeleton.skinText[where + 1] = 0;
551 skeleton.skinText[where + 2] = 0;
555 skeleton.drawmodel.textureptr.bind();
560 if (creature == rabbittype)
561 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) {
562 bleedxint = abs(Random() % 512);
563 bleedyint = abs(Random() % 512);
565 if (creature == wolftype)
566 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) {
567 bleedxint = abs(Random() % 512);
568 bleedyint = abs(Random() % 512);
570 bleedy = bleedxint + offsetx;
571 bleedx = bleedyint + offsety;
572 bleedy /= realtexdetail;
573 bleedx /= realtexdetail;
578 if (bleedx > skeleton.skinsize - 1)
579 bleedx = skeleton.skinsize - 1;
580 if (bleedy > skeleton.skinsize - 1)
581 bleedy = skeleton.skinsize - 1;
582 direction = abs(Random() % 2) * 2 - 1;
585 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
586 deathbleeding += bleeding;
587 bloodloss += bleeding * 3;
589 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
590 if (abs(Random() % 2) == 0) {
591 aitype = gethelptype;
594 aitype = attacktypecutoff;
602 * similar to DoBloodBig
604 bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where)
608 static XYZ startpoint, endpoint, colpoint, movepoint;
609 static float rotationpoint;
611 static XYZ p1, p2, p3, p0;
614 float coordsx, coordsy;
617 if (bloodtoggle && decals && tutoriallevel != 1) {
620 where = DoRotation(where, 0, -yaw, 0);
628 // ray testing for a tri in the character model
629 whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
630 if (whichtri != -1) {
631 // low level geometry math
633 p1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
634 p2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
635 p3 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
637 bary.x = distsq(&p0, &p1);
638 bary.y = distsq(&p0, &p2);
639 bary.z = distsq(&p0, &p3);
641 total = bary.x + bary.y + bary.z;
650 total = bary.x + bary.y + bary.z;
656 gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0];
657 gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1];
658 gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2];
659 gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0];
660 gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1];
661 gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2];
662 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;
663 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;
665 if (bleeding <= 0 && spurt) {
667 for (int i = 0; i < 3; i++) {
668 // emit blood particles
669 // FIXME: more copypaste code
672 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0);
673 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
674 Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
675 Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1);
678 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
679 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
680 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
681 Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .3, 1);
686 // texture manipulation follows
688 int offsetx = 0, offsety = 0;
689 offsetx = (1 + coordsy) * 512 - 291;
690 offsety = coordsx * 512 - 437;
697 if (creature == rabbittype)
698 for (i = 0; i < 512; i++) {
699 for (j = 0; j < 512; j++) {
700 if (bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
701 if (i < startx) startx = i;
702 if (j < starty) starty = j;
703 if (i > endx) endx = i;
704 if (j > endy) endy = j;
708 if (creature == wolftype)
709 for (i = 0; i < 512; i++) {
710 for (j = 0; j < 512; j++) {
711 if (wolfbloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && wolfbloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) {
712 if (i < startx) startx = i;
713 if (j < starty) starty = j;
714 if (i > endx) endx = i;
715 if (j > endy) endy = j;
724 if (startx < 0) startx = 0;
725 if (starty < 0) starty = 0;
726 if (endx > 512 - 1) endx = 512 - 1;
727 if (endy > 512 - 1) endy = 512 - 1;
728 if (endx < startx) endx = startx;
729 if (endy < starty) endy = starty;
731 startx /= realtexdetail;
732 starty /= realtexdetail;
733 endx /= realtexdetail;
734 endy /= realtexdetail;
736 int texdetailint = realtexdetail;
738 if (creature == rabbittype)
739 for (i = startx; i < endx; i++) {
740 for (j = starty; j < endy; j++) {
741 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) {
742 color = Random() % 85 + 170;
743 where = i * skeleton.skinsize * 3 + j * 3;
744 if (skeleton.skinText[where + 0] > color / 2)
745 skeleton.skinText[where + 0] = color / 2;
746 skeleton.skinText[where + 1] = 0;
747 skeleton.skinText[where + 2] = 0;
748 } 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) {
749 color = Random() % 85 + 170;
750 where = i * skeleton.skinsize * 3 + j * 3;
751 if (skeleton.skinText[where + 0] > color / 2)
752 skeleton.skinText[where + 0] = color / 2;
753 skeleton.skinText[where + 1] = 0;
754 skeleton.skinText[where + 2] = 0;
758 if (creature == wolftype)
759 for (i = startx; i < endx; i++) {
760 for (j = starty; j < endy; j++) {
761 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) {
762 color = Random() % 85 + 170;
763 where = i * skeleton.skinsize * 3 + j * 3;
764 if (skeleton.skinText[where + 0] > color / 2)
765 skeleton.skinText[where + 0] = color / 2;
766 skeleton.skinText[where + 1] = 0;
767 skeleton.skinText[where + 2] = 0;
768 } 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) {
769 color = Random() % 85 + 170;
770 where = i * skeleton.skinsize * 3 + j * 3;
771 if (skeleton.skinText[where + 0] > color / 2)
772 skeleton.skinText[where + 0] = color / 2;
773 skeleton.skinText[where + 1] = 0;
774 skeleton.skinText[where + 2] = 0;
778 skeleton.drawmodel.textureptr.bind();
781 bleedy = (1 + coordsy) * 512;
782 bleedx = coordsx * 512;
783 bleedy /= realtexdetail;
784 bleedx /= realtexdetail;
789 if (bleedx > skeleton.skinsize - 1)
790 bleedx = skeleton.skinsize - 1;
791 if (bleedy > skeleton.skinsize - 1)
792 bleedy = skeleton.skinsize - 1;
793 direction = abs(Random() % 2) * 2 - 1;
798 bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25;
799 deathbleeding += bleeding;
800 bloodloss += bleeding * 3;
802 if (tutoriallevel != 1 && aitype != playercontrolled && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) {
803 if (abs(Random() % 2) == 0) {
804 aitype = gethelptype;
807 aitype = attacktypecutoff;
818 * guessing this performs a reversal
820 void Person::Reverse()
822 if (!((victim->aitype == playercontrolled
824 || staggerdelay <= 0)
825 && victim->animTarget != jumpupanim
826 && victim->animTarget != jumpdownanim
827 && (tutoriallevel != 1 || cananger)
831 if (normaldotproduct (victim->facing, victim->coords - coords) > 0
832 && (victim->id != 0 || difficulty >= 2)
833 && (creature != wolftype || victim->creature == wolftype))
836 if (animTarget == sweepanim) {
837 animTarget = sweepreversedanim;
838 animCurrent = sweepreversedanim;
839 victim->animCurrent = sweepreversalanim;
840 victim->animTarget = sweepreversalanim;
842 if (animTarget == spinkickanim) {
843 animTarget = spinkickreversedanim;
844 animCurrent = spinkickreversedanim;
845 victim->animCurrent = spinkickreversalanim;
846 victim->animTarget = spinkickreversalanim;
848 if (animTarget == upunchanim || animTarget == rabbittacklinganim) {
849 if (animTarget == rabbittacklinganim) {
852 victim->frameCurrent = 6;
853 victim->frameTarget = 7;
855 animTarget = upunchreversedanim;
856 animCurrent = upunchreversedanim;
857 victim->animCurrent = upunchreversalanim;
858 victim->animTarget = upunchreversalanim;
860 if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
861 if (victim->weaponactive != -1) {
862 victim->throwtogglekeydown = 1;
863 XYZ tempVelocity = victim->velocity * .2;
864 if (tempVelocity.x == 0)
866 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
867 victim->num_weapons--;
868 if (victim->num_weapons) {
869 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
870 if (victim->weaponstuck == victim->num_weapons)
871 victim->weaponstuck = 0;
874 victim->weaponactive = -1;
875 for (unsigned j = 0; j < Person::players.size(); j++) {
876 Person::players[j]->wentforweapon = 0;
880 animTarget = staffhitreversedanim;
881 animCurrent = staffhitreversedanim;
882 victim->animCurrent = staffhitreversalanim;
883 victim->animTarget = staffhitreversalanim;
885 if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) {
886 if (victim->weaponactive != -1) {
887 victim->throwtogglekeydown = 1;
888 XYZ tempVelocity = victim->velocity * .2;
889 if (tempVelocity.x == 0)
891 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
892 victim->num_weapons--;
893 if (victim->num_weapons) {
894 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
895 if (victim->weaponstuck == victim->num_weapons)
896 victim->weaponstuck = 0;
899 victim->weaponactive = -1;
900 for (unsigned j = 0; j < Person::players.size(); j++) {
901 Person::players[j]->wentforweapon = 0;
904 animTarget = staffspinhitreversedanim;
905 animCurrent = staffspinhitreversedanim;
906 victim->animCurrent = staffspinhitreversalanim;
907 victim->animTarget = staffspinhitreversalanim;
909 if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) {
910 if (victim->weaponactive != -1) {
911 victim->throwtogglekeydown = 1;
912 XYZ tempVelocity = victim->velocity * .2;
913 if (tempVelocity.x == 0)
915 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
916 victim->num_weapons--;
917 if (victim->num_weapons) {
918 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
919 if (victim->weaponstuck == victim->num_weapons)
920 victim->weaponstuck = 0;
923 victim->weaponactive = -1;
924 for (unsigned j = 0; j < Person::players.size(); j++) {
925 Person::players[j]->wentforweapon = 0;
928 animTarget = swordslashreversedanim;
929 animCurrent = swordslashreversedanim;
930 victim->animCurrent = swordslashreversalanim;
931 victim->animTarget = swordslashreversalanim;
933 if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) {
934 if (victim->weaponactive != -1) {
935 victim->throwtogglekeydown = 1;
936 XYZ tempVelocity = victim->velocity * .2;
937 if (tempVelocity.x == 0)
939 weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false);
940 victim->num_weapons--;
941 if (victim->num_weapons) {
942 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
943 if (victim->weaponstuck == victim->num_weapons)
944 victim->weaponstuck = 0;
947 victim->weaponactive = -1;
948 for (unsigned j = 0; j < Person::players.size(); j++) {
949 Person::players[j]->wentforweapon = 0;
952 animTarget = knifeslashreversedanim;
953 animCurrent = knifeslashreversedanim;
954 victim->animCurrent = knifeslashreversalanim;
955 victim->animTarget = knifeslashreversalanim;
957 if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) {
958 victim->targettilt2 = targettilt2;
959 victim->frameCurrent = frameCurrent;
960 victim->frameTarget = frameTarget;
961 victim->target = target;
962 victim->velocity = 0;
963 victim->oldcoords = victim->coords;
964 victim->coords = coords;
965 victim->targetyaw = targetyaw;
966 victim->yaw = targetyaw;
967 victim->victim = this->shared_from_this();
969 if (animTarget == winduppunchanim) {
970 animTarget = winduppunchblockedanim;
971 victim->animTarget = blockhighleftanim;
972 victim->frameTarget = 1;
974 victim->victim = this->shared_from_this();
975 victim->targetyaw = targetyaw + 180;
977 if (animTarget == wolfslapanim) {
978 animTarget = winduppunchblockedanim;
979 victim->animTarget = blockhighleftanim;
980 victim->frameTarget = 1;
982 victim->victim = this->shared_from_this();
983 victim->targetyaw = targetyaw + 180;
985 if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->weaponactive != -1) {
986 animTarget = swordslashparriedanim;
987 parriedrecently = .4;
988 victim->parriedrecently = 0;
989 victim->animTarget = swordslashparryanim;
990 victim->frameTarget = 1;
992 victim->victim = this->shared_from_this();
993 victim->targetyaw = targetyaw + 180;
995 if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) {
996 if (victim->weaponactive != -1) {
997 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
998 if (weapons[victim->weaponids[0]].getType() == staff)
999 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1000 if (weapons[weaponids[0]].getType() == staff)
1001 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1002 emit_sound_at(swordstaffsound, victim->coords);
1004 emit_sound_at(metalhitsound, victim->coords);
1008 victim->Puff(righthand);
1010 victim->frameTarget = 0;
1011 victim->animTarget = staggerbackhighanim;
1012 victim->targetyaw = targetyaw + 180;
1014 aim = DoRotation(facing, 0, 90, 0) * 21;
1016 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1017 victim->num_weapons--;
1018 if (victim->num_weapons) {
1019 victim->weaponids[0] = victim->weaponids[num_weapons];
1020 if (victim->weaponstuck == victim->num_weapons)
1021 victim->weaponstuck = 0;
1023 victim->weaponactive = -1;
1024 for (unsigned i = 0; i < Person::players.size(); i++) {
1025 Person::players[i]->wentforweapon = 0;
1029 if (abs(Random() % 20) == 0) {
1030 if (weaponactive != -1) {
1031 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
1032 if (weapons[victim->weaponids[0]].getType() == staff)
1033 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1034 if (weapons[weaponids[0]].getType() == staff)
1035 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
1037 emit_sound_at(swordstaffsound, coords);
1039 emit_sound_at(metalhitsound, coords);
1047 animTarget = staggerbackhighanim;
1048 targetyaw = targetyaw + 180;
1050 aim = DoRotation(facing, 0, 90, 0) * 21;
1052 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
1055 weaponids[0] = weaponids[num_weapons];
1056 if (weaponstuck == num_weapons)
1060 for (unsigned i = 0; i < Person::players.size(); i++) {
1061 Person::players[i]->wentforweapon = 0;
1068 if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) {
1069 if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) {
1070 victim->animTarget = dodgebackanim;
1071 victim->frameTarget = 0;
1075 rotatetarget = coords - victim->coords;
1076 Normalise(&rotatetarget);
1077 victim->targetyaw = -asin(0 - rotatetarget.x);
1078 victim->targetyaw *= 360 / 6.28;
1079 if (rotatetarget.z < 0)
1080 victim->targetyaw = 180 - victim->targetyaw;
1082 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1084 victim->lastattack3 = victim->lastattack2;
1085 victim->lastattack2 = victim->lastattack;
1086 victim->lastattack = victim->animTarget;
1088 victim->animTarget = sweepanim;
1089 victim->frameTarget = 0;
1093 rotatetarget = coords - victim->coords;
1094 Normalise(&rotatetarget);
1095 victim->targetyaw = -asin(0 - rotatetarget.x);
1096 victim->targetyaw *= 360 / 6.28;
1097 if (rotatetarget.z < 0)
1098 victim->targetyaw = 180 - victim->targetyaw;
1100 victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70;
1102 victim->lastattack3 = victim->lastattack2;
1103 victim->lastattack2 = victim->lastattack;
1104 victim->lastattack = victim->animTarget;
1109 victim->velocity = 0;
1111 if (aitype != playercontrolled)
1113 if (aitype != playercontrolled && Random() % 3 == 0 && escapednum < 2 && difficulty == 2)
1115 if (aitype != playercontrolled && Random() % 5 == 0 && escapednum < 2 && difficulty == 1)
1117 if (aitype != playercontrolled && Random() % 10 == 0 && escapednum < 2 && difficulty == 0)
1120 if (victim->id == 0 && animation[victim->animTarget].attack == reversal)
1127 void Person::DoDamage(float howmuch)
1129 // subtract health (temporary?)
1130 if (tutoriallevel != 1)
1131 damage += howmuch / power;
1134 damagedealt += howmuch / power;
1136 damagetaken += howmuch / power;
1139 if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo))
1142 if (tutoriallevel != 1)
1143 permanentdamage += howmuch / 2 / power;
1144 if (tutoriallevel != 1)
1145 superpermanentdamage += howmuch / 4 / power;
1147 if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2)
1149 if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt)
1153 camerashake += howmuch / 100;
1154 if (id == 0 && ((howmuch > 50 && damage > damagetolerance / 2)))
1155 blackout = damage / damagetolerance;
1160 if (aitype == passivetype && damage < damagetolerance && ((tutoriallevel != 1 || cananger) && hostile))
1161 aitype = attacktypecutoff;
1162 if (tutoriallevel != 1 && aitype != playercontrolled && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) {
1163 if (abs(Random() % 2) == 0) {
1164 aitype = gethelptype;
1167 aitype = attacktypecutoff;
1171 if (howmuch > damagetolerance * 50 && skeleton.free != 2) {
1174 for (int i = 0; i < skeleton.num_joints; i++) {
1175 if (skeleton.free) {
1176 flatvelocity2 = skeleton.joints[i].velocity;
1177 flatfacing2 = skeleton.joints[i].position * scale + coords;
1179 flatvelocity2 = velocity;
1180 flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
1182 flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10;
1183 flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10;
1184 flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10;
1185 Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1);
1186 Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1);
1187 Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5);
1190 emit_sound_at(splattersound, coords);
1195 if (!dead && creature == wolftype) {
1196 award_bonus(0, Wolfbonus);
1203 if (tutoriallevel != 1 || id == 0)
1204 if (speechdelay <= 0 && !dead && aitype != playercontrolled) {
1205 int whichsound = -1;
1207 if (creature == wolftype) {
1208 int i = abs(Random() % 2);
1210 whichsound = snarlsound;
1212 whichsound = snarl2sound;
1213 envsound[numenvsounds] = coords;
1214 envsoundvol[numenvsounds] = 16;
1215 envsoundlife[numenvsounds] = .4;
1218 if (creature == rabbittype) {
1219 int i = abs(Random() % 2);
1221 whichsound = rabbitpainsound;
1222 if (i == 1 && damage > damagetolerance)
1223 whichsound = rabbitpain1sound;
1224 envsound[numenvsounds] = coords;
1225 envsoundvol[numenvsounds] = 16;
1226 envsoundlife[numenvsounds] = .4;
1230 if (whichsound != -1) {
1231 emit_sound_at(whichsound, coords);
1238 * calculate/animate head facing direction?
1240 void Person::DoHead()
1242 static XYZ rotatearound;
1244 static float lookspeed = 500;
1246 if (!freeze && !winfreeze) {
1249 targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100;
1250 targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100;
1252 while (targetheadyaw > 180)targetheadyaw -= 360;
1253 while (targetheadyaw < -180)targetheadyaw += 360;
1255 if (targetheadyaw > 160)
1256 targetheadpitch = targetheadpitch * -1;
1257 if (targetheadyaw < -160)
1258 targetheadpitch = targetheadpitch * -1;
1259 if (targetheadyaw > 160)
1260 targetheadyaw = targetheadyaw - 180;
1261 if (targetheadyaw < -160)
1262 targetheadyaw = targetheadyaw + 180;
1264 if (targetheadpitch > 120)
1265 targetheadpitch = 120;
1266 if (targetheadpitch < -120)
1267 targetheadpitch = -120;
1268 if (targetheadyaw > 120)
1269 targetheadyaw = 120;
1270 if (targetheadyaw < -120)
1271 targetheadyaw = -120;
1274 targetheadpitch = 0;
1276 if (targetheadyaw > 80)
1278 if (targetheadyaw < -80)
1279 targetheadyaw = -80;
1280 if (targetheadpitch > 50)
1281 targetheadpitch = 50;
1282 if (targetheadpitch < -50)
1283 targetheadpitch = -50;
1286 if (abs(headyaw - targetheadyaw) < multiplier * lookspeed)
1287 headyaw = targetheadyaw;
1288 else if (headyaw > targetheadyaw) {
1289 headyaw -= multiplier * lookspeed;
1290 } else if (headyaw < targetheadyaw) {
1291 headyaw += multiplier * lookspeed;
1294 if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2)
1295 headpitch = targetheadpitch;
1296 else if (headpitch > targetheadpitch) {
1297 headpitch -= multiplier * lookspeed / 2;
1298 } else if (headpitch < targetheadpitch) {
1299 headpitch += multiplier * lookspeed / 2;
1302 rotatearound = jointPos(neck);
1303 jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0);
1307 if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) {
1308 facing = DoRotation(facing, headpitch * .4, 0, 0);
1309 facing = DoRotation(facing, 0, headyaw * .4, 0);
1312 if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) {
1313 facing = DoRotation(facing, headpitch * .8, 0, 0);
1314 facing = DoRotation(facing, 0, headyaw * .8, 0);
1317 if (animTarget == walkanim) {
1318 facing = DoRotation(facing, headpitch * .6, 0, 0);
1319 facing = DoRotation(facing, 0, headyaw * .6, 0);
1322 skeleton.specialforward[0] = facing;
1323 //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0);
1324 for (int i = 0; i < skeleton.num_muscles; i++) {
1325 if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) {
1326 skeleton.FindRotationMuscle(i, animTarget);
1333 * ragdolls character?
1335 void Person::RagDoll(bool checkcollision)
1340 if (!skeleton.free) {
1343 if (id == 0 && isFlip())
1350 facing = DoRotation(facing, 0, yaw, 0);
1352 skeleton.freetime = 0;
1354 skeleton.longdead = 0;
1357 skeleton.broken = 0;
1358 skeleton.spinny = 1;
1360 skeleton.freefall = 1;
1362 if (!isnormal(velocity.x)) velocity.x = 0;
1363 if (!isnormal(velocity.y)) velocity.y = 0;
1364 if (!isnormal(velocity.z)) velocity.z = 0;
1365 if (!isnormal(yaw)) yaw = 0;
1366 if (!isnormal(coords.x)) coords = 0;
1367 if (!isnormal(tilt)) tilt = 0;
1368 if (!isnormal(tilt2)) tilt2 = 0;
1370 for (int i = 0; i < skeleton.num_joints; i++) {
1371 skeleton.joints[i].delay = 0;
1372 skeleton.joints[i].locked = 0;
1373 skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0);
1374 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0);
1375 if (!isnormal(skeleton.joints[i].position.x)) skeleton.joints[i].position = coords;
1376 skeleton.joints[i].position.y += .1;
1377 skeleton.joints[i].oldposition = skeleton.joints[i].position;
1378 skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords;
1381 for (int i = 0; i < skeleton.num_joints; i++) {
1382 skeleton.joints[i].velocity = 0;
1383 skeleton.joints[i].velchange = 0;
1385 skeleton.DoConstraints(&coords, &scale);
1386 if (animation[animCurrent].height == lowheight || animation[animTarget].height == lowheight) {
1387 skeleton.DoConstraints(&coords, &scale);
1388 skeleton.DoConstraints(&coords, &scale);
1389 skeleton.DoConstraints(&coords, &scale);
1390 skeleton.DoConstraints(&coords, &scale);
1393 speed = animation[animTarget].speed[frameTarget] * 2;
1394 if (animation[animCurrent].speed[frameCurrent] > animation[animTarget].speed[frameTarget]) {
1395 speed = animation[animCurrent].speed[frameCurrent] * 2;
1398 speed = transspeed * 2;
1402 for (int i = 0; i < skeleton.num_joints; i++) {
1403 if ((animation[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && animation[animCurrent].height == animation[animTarget].height)
1404 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);
1406 skeleton.joints[i].velocity = velocity / scale + facing * 5;
1407 change.x = (float)(Random() % 100) / 100;
1408 change.y = (float)(Random() % 100) / 100;
1409 change.z = (float)(Random() % 100) / 100;
1410 skeleton.joints[i].velocity += change;
1411 skeleton.joints[abs(Random() % skeleton.num_joints)].velocity -= change;
1413 change.x = (float)(Random() % 100) / 100;
1414 change.y = (float)(Random() % 100) / 100;
1415 change.z = (float)(Random() % 100) / 100;
1416 skeleton.joints[i].velchange += change;
1417 skeleton.joints[abs(Random() % skeleton.num_joints)].velchange -= change;
1420 if (checkcollision) {
1427 for (j = 0; j < skeleton.num_joints; j++) {
1428 average += skeleton.joints[j].position;
1432 coords += average * scale;
1433 for (j = 0; j < skeleton.num_joints; j++) {
1434 skeleton.joints[j].position -= average;
1437 whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale);
1438 whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale);
1439 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
1440 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
1441 i = terrain.patchobjects[whichpatchx][whichpatchz][l];
1444 if (SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.yaw[i], &objects.model[i]) != -1) {
1445 coords.x = lowpoint.x;
1446 coords.z = lowpoint.z;
1455 for (int i = 0; i < skeleton.num_joints; i++) {
1456 velocity += skeleton.joints[i].velocity * scale;
1458 velocity /= skeleton.num_joints;
1461 if (Random() % 2 == 0) {
1462 if (weaponactive != -1 && animTarget != rabbitkickanim && num_weapons > 0) {
1463 weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale);
1464 weapons[weaponids[0]].velocity.x += .01;
1467 weaponids[0] = weaponids[num_weapons];
1468 if (weaponstuck == num_weapons)
1472 for (unsigned i = 0; i < Person::players.size(); i++) {
1473 Person::players[i]->wentforweapon = 0;
1478 animTarget = bounceidleanim;
1479 animCurrent = bounceidleanim;
1489 void Person::FootLand(int which, float opacity)
1491 static XYZ terrainlight;
1492 static XYZ footvel, footpoint;
1493 if (opacity >= 1 || skiddelay <= 0)
1497 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1499 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1500 //footpoint.y=coords.y;
1501 if (distsq(&footpoint, &viewer))
1502 Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity);
1503 } else if (environment == snowyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1504 footvel = velocity / 5;
1508 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1510 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1511 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1512 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1513 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1514 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity);
1515 if (opacity >= 1 || detail == 2)
1517 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1518 terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw);
1519 } else if (environment == grassyenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1520 footvel = velocity / 5;
1524 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1526 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1527 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1528 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1529 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1530 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity);
1531 } else if (environment == desertenvironment && onterrain && terrain.getOpacity(coords.x, coords.z) < .2) {
1532 footvel = velocity / 5;
1536 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1538 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1539 footpoint.y = terrain.getHeight(footpoint.x, footpoint.z);
1540 terrainlight = terrain.getLighting(footpoint.x, footpoint.z);
1541 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1542 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity);
1543 if (opacity >= 1 || detail == 2)
1545 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1546 terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw);
1547 } else if (isLanding() || animTarget == jumpupanim || isLandhard()) {
1548 footvel = velocity / 5;
1552 footpoint = DoRotation(jointPos(leftfoot), 0, yaw, 0) * scale + coords;
1554 footpoint = DoRotation(jointPos(rightfoot), 0, yaw, 0) * scale + coords;
1555 //footpoint.y=coords.y;
1556 if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4)
1557 Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity);
1562 * make a puff effect at a body part (dust effect?)
1564 void Person::Puff(int whichlabel)
1566 static XYZ footvel, footpoint;
1569 footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords;
1570 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3);
1574 * I think I added this in an attempt to clean up code
1576 void Person::setAnimation(int animation)
1578 animTarget = animation;
1587 void Person::DoAnimations()
1589 if (!skeleton.free) {
1590 static float oldtarget;
1592 if (isIdle() && animCurrent != getIdle())
1593 normalsupdatedelay = 0;
1595 if (animTarget == tempanim || animCurrent == tempanim) {
1596 animation[tempanim] = tempanimation;
1598 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
1604 vel[0] = velocity.x;
1605 vel[1] = velocity.y;
1606 vel[2] = velocity.z;
1609 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
1610 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
1612 if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z))
1614 if (!crouchkeydown && velocity.y >= -15)
1617 if ((animCurrent == jumpupanim || animTarget == jumpdownanim)/*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) {
1622 targfacing = DoRotation(targfacing, 0, targetyaw, 0);
1624 if (normaldotproduct(targfacing, velocity) >= -.3)
1625 animTarget = flipanim;
1627 animTarget = backflipanim;
1628 crouchtogglekeydown = 1;
1636 if (animation[animTarget].attack != reversed)
1638 if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) {
1639 crouchtogglekeydown = 0;
1640 if (aitype == playercontrolled)
1643 if (!crouchtogglekeydown && animation[animTarget].attack == reversed && aitype == playercontrolled && (escapednum < 2 || reversaltrain))
1646 crouchtogglekeydown = 1;
1650 if (animation[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) {
1652 normalsupdatedelay = 0;
1656 if (animTarget == rollanim && frameTarget == 3 && onfire) {
1658 emit_sound_at(fireendsound, coords);
1659 pause_sound(stream_firesound);
1663 if (animTarget == rabbittacklinganim && frameTarget == 1) {
1664 if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0)
1666 if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) {
1667 if (normaldotproduct(victim->facing, facing) > 0)
1668 victim->animTarget = rabbittackledbackanim;
1670 victim->animTarget = rabbittackledfrontanim;
1671 victim->frameTarget = 2;
1674 victim->targetyaw = yaw;
1675 if (victim->aitype == gethelptype)
1676 victim->DoDamage(victim->damagetolerance - victim->damage);
1677 //victim->DoDamage(30);
1678 if (creature == wolftype) {
1680 emit_sound_at(clawslicesound, victim->coords);
1682 victim->DoBloodBig(1 / victim->armorhead, 210);
1684 award_bonus(id, TackleBonus,
1685 victim->aitype == gethelptype ? 50 : 0);
1689 if (!drawtogglekeydown && drawkeydown && (weaponactive == -1 || num_weapons == 1) && (animation[animTarget].label[frameTarget] || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) {
1690 if (weapons[weaponids[0]].getType() == knife) {
1691 if (weaponactive == -1)
1693 else if (weaponactive == 0)
1696 if (weaponactive == -1) {
1697 emit_sound_at(knifesheathesound, coords);
1699 if (weaponactive != -1) {
1700 emit_sound_at(knifedrawsound, coords, 128);
1703 drawtogglekeydown = 1;
1706 if (tutoriallevel != 1 || id == 0)
1707 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1710 if (terrain.getOpacity(coords.x, coords.z) < .2) {
1711 if (animation[animTarget].label[frameTarget] == 1)
1712 whichsound = footstepsound;
1714 whichsound = footstepsound2;
1715 if (animation[animTarget].label[frameTarget] == 1)
1717 if (animation[animTarget].label[frameTarget] == 2)
1719 if (animation[animTarget].label[frameTarget] == 3 && isRun()) {
1725 if (terrain.getOpacity(coords.x, coords.z) >= .2) {
1726 if (animation[animTarget].label[frameTarget] == 1)
1727 whichsound = footstepsound3;
1729 whichsound = footstepsound4;
1733 if (animation[animTarget].label[frameTarget] == 1)
1734 whichsound = footstepsound3;
1736 whichsound = footstepsound4;
1738 if (animation[animTarget].label[frameTarget] == 4 && (weaponactive == -1 || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) {
1739 if (animation[animTarget].attack != neutral) {
1740 unsigned r = abs(Random() % 3);
1742 whichsound = lowwhooshsound;
1744 whichsound = midwhooshsound;
1746 whichsound = highwhooshsound;
1748 if (animation[animTarget].attack == neutral)
1749 whichsound = movewhooshsound;
1750 } else if (animation[animTarget].label[frameTarget] == 4)
1751 whichsound = knifeswishsound;
1752 if (animation[animTarget].label[frameTarget] == 8 && tutoriallevel != 1)
1753 whichsound = landsound2;
1755 emit_sound_at(whichsound, coords, 256.);
1758 if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) {
1759 envsound[numenvsounds] = coords;
1760 if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim)
1761 envsoundvol[numenvsounds] = 15;
1763 envsoundvol[numenvsounds] = 6;
1764 envsoundlife[numenvsounds] = .4;
1768 if (animation[animTarget].label[frameTarget] == 3) {
1770 emit_sound_at(whichsound, coords, 128.);
1775 if (tutoriallevel != 1 || id == 0)
1776 if (speechdelay <= 0)
1777 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
1778 if ((animation[animTarget].label[frameTarget] && (animation[animTarget].label[frameTarget] < 5 || animation[animTarget].label[frameTarget] == 8))/*||(animTarget==rollanim&&frameTarget==animation[rollanim].numframes-1)*/) {
1779 int whichsound = -1;
1780 if (animation[animTarget].label[frameTarget] == 4 && aitype != playercontrolled) {
1781 if (animation[animTarget].attack != neutral) {
1782 unsigned r = abs(Random() % 4);
1783 if (creature == rabbittype) {
1784 if (r == 0) whichsound = rabbitattacksound;
1785 if (r == 1) whichsound = rabbitattack2sound;
1786 if (r == 2) whichsound = rabbitattack3sound;
1787 if (r == 3) whichsound = rabbitattack4sound;
1789 if (creature == wolftype) {
1790 if (r == 0) whichsound = barksound;
1791 if (r == 1) whichsound = bark2sound;
1792 if (r == 2) whichsound = bark3sound;
1793 if (r == 3) whichsound = barkgrowlsound;
1799 if (whichsound != -1) {
1800 emit_sound_at(whichsound, coords);
1806 if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) {
1812 currentoffset = targetoffset;
1813 frameTarget = frameCurrent;
1814 animCurrent = animTarget;
1817 if (animTarget == removeknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1818 for (unsigned i = 0; i < weapons.size(); i++) {
1819 if (weapons[i].owner == -1)
1820 if (distsqflat(&coords, &weapons[i].position) < 4 && weaponactive == -1) {
1821 if (distsq(&coords, &weapons[i].position) >= 1) {
1822 if (weapons[i].getType() != staff) {
1823 emit_sound_at(knifedrawsound, coords, 128.);
1832 if (animTarget == crouchremoveknifeanim && animation[animTarget].label[frameCurrent] == 5) {
1833 for (unsigned i = 0; i < weapons.size(); i++) {
1834 bool willwork = true;
1835 if (weapons[i].owner != -1)
1836 if (Person::players[weapons[i].owner]->weaponstuck != -1)
1837 if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i))
1838 if (Person::players[weapons[i].owner]->num_weapons > 1)
1840 if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free))
1841 if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && weaponactive == -1) {
1842 if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) {
1843 bool fleshstuck = false;
1844 if (weapons[i].owner != -1)
1845 if (victim->weaponstuck != -1) {
1846 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1851 emit_sound_at(fleshstabremovesound, coords, 128.);
1853 if (weapons[i].getType() != staff) {
1854 emit_sound_at(knifedrawsound, coords, 128.);
1857 if (weapons[i].owner != -1) {
1858 victim = Person::players[weapons[i].owner];
1859 if (victim->num_weapons == 1)
1860 victim->num_weapons = 0;
1862 victim->num_weapons = 1;
1864 //victim->weaponactive=-1;
1865 victim->skeleton.longdead = 0;
1866 victim->skeleton.free = 1;
1867 victim->skeleton.broken = 0;
1869 for (int j = 0; j < victim->skeleton.num_joints; j++) {
1870 victim->skeleton.joints[j].velchange = 0;
1871 victim->skeleton.joints[j].locked = 0;
1877 Normalise(&relative);
1878 XYZ footvel, footpoint;
1880 footpoint = weapons[i].position;
1881 if (victim->weaponstuck != -1) {
1882 if (victim->weaponids[victim->weaponstuck] == int(i)) {
1884 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
1885 weapons[i].bloody = 2;
1886 weapons[i].blooddrip = 5;
1887 victim->weaponstuck = -1;
1890 if (victim->num_weapons > 0) {
1891 if (victim->weaponstuck != 0 && victim->weaponstuck != -1)
1892 victim->weaponstuck = 0;
1893 if (victim->weaponids[0] == int(i))
1894 victim->weaponids[0] = victim->weaponids[victim->num_weapons];
1897 victim->jointVel(abdomen) += relative * 6;
1898 victim->jointVel(neck) += relative * 6;
1899 victim->jointVel(rightshoulder) += relative * 6;
1900 victim->jointVel(leftshoulder) += relative * 6;
1908 if (animCurrent == drawleftanim && animation[animTarget].label[frameCurrent] == 5) {
1909 if (weaponactive == -1)
1911 else if (weaponactive == 0) {
1913 if (num_weapons == 2) {
1915 buffer = weaponids[0];
1916 weaponids[0] = weaponids[1];
1917 weaponids[1] = buffer;
1920 if (weaponactive == -1) {
1921 emit_sound_at(knifesheathesound, coords, 128.);
1923 if (weaponactive != -1) {
1924 emit_sound_at(knifedrawsound, coords, 128.);
1929 if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) {
1930 XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0);
1931 Normalise(&rotatetarget);
1932 targetyaw = -asin(0 - rotatetarget.x);
1933 targetyaw *= 360 / 6.28;
1934 if (rotatetarget.z < 0)
1935 targetyaw = 180 - targetyaw;
1937 if (animTarget == walljumprightkickanim)
1939 if (animTarget == walljumpleftkickanim)
1945 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0))
1948 if (distsq(&victim->coords, &/*Person::players[i]->*/coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1)
1953 if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) {
1954 animTarget = rabbittackleanim;
1956 emit_sound_at(jumpsound, coords);
1964 targetloc = velocity;
1965 Normalise(&targetloc);
1966 targetloc += coords;
1967 for (unsigned i = 0; i < Person::players.size(); i++) {
1969 if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) {
1970 closestdist = distsq(&targetloc, &Person::players[i]->coords);
1974 if (closestid != -1)
1975 if (closestdist < 5 && !Person::players[closestid]->dead && animation[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) {
1977 victim = Person::players[closestid];
1978 coords = victim->coords;
1979 animCurrent = rabbittacklinganim;
1980 animTarget = rabbittacklinganim;
1984 if (coords.z != victim->coords.z || coords.x != victim->coords.x) {
1985 rotatetarget = coords - victim->coords;
1986 Normalise(&rotatetarget);
1987 targetyaw = -asin(0 - rotatetarget.x);
1988 targetyaw *= 360 / 6.28;
1989 if (rotatetarget.z < 0)
1990 targetyaw = 180 - targetyaw;
1992 if (animTarget != rabbitrunninganim) {
1993 emit_sound_at(jumpsound, coords, 128.);
1999 float damagemult = 1 * power;
2000 if (creature == wolftype)
2001 damagemult = 2.5 * power;
2003 damagemult /= victim->damagetolerance / 200;
2005 if ((animation[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) {
2006 if (animTarget == spinkickanim && animation[animTarget].label[frameCurrent] == 5) {
2007 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2011 if (Random() % 2 || creature == wolftype) {
2014 if (creature == wolftype)
2017 if (tutoriallevel != 1) {
2018 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2020 if (creature == wolftype) {
2021 emit_sound_at(clawslicesound, victim->coords, 128.);
2023 victim->DoBloodBig(2 / victim->armorhead, 175);
2027 relative = victim->coords - coords;
2029 Normalise(&relative);
2030 relative = DoRotation(relative, 0, -90, 0);
2031 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2032 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2034 victim->jointVel(head) += relative * damagemult * 200;
2037 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2043 if (animTarget == wolfslapanim && animation[animTarget].label[frameCurrent] == 5) {
2044 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && 3 && animation[victim->animTarget].height != lowheight) {
2048 if (Random() % 2 || creature == wolftype) {
2050 if (creature == wolftype)
2053 emit_sound_at(whooshhitsound, victim->coords);
2054 if (creature == wolftype) {
2055 emit_sound_at(clawslicesound, victim->coords, 128.);
2057 victim->DoBloodBig(2, 175);
2061 relative = victim->coords - coords;
2063 Normalise(&relative);
2065 Normalise(&relative);
2066 relative = DoRotation(relative, 0, 90, 0);
2067 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2068 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2070 victim->jointVel(head) += relative * damagemult * 100;
2073 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2077 if (animTarget == walljumprightkickanim && animation[animTarget].label[frameCurrent] == 5) {
2078 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2084 if (tutoriallevel != 1) {
2085 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2087 if (creature == wolftype) {
2088 emit_sound_at(clawslicesound, victim->coords, 128.);
2090 victim->DoBloodBig(2 / victim->armorhead, 175);
2096 Normalise(&relative);
2097 relative = DoRotation(relative, 0, -90, 0);
2098 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2099 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2101 victim->jointVel(head) += relative * damagemult * 200;
2104 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2106 if (victim->damage > victim->damagetolerance)
2107 award_bonus(id, style);
2113 if (animTarget == walljumpleftkickanim && animation[animTarget].label[frameCurrent] == 5) {
2114 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2120 if (tutoriallevel != 1) {
2121 emit_sound_at(heavyimpactsound, victim->coords, 160.);
2123 if (creature == wolftype) {
2124 emit_sound_at(clawslicesound, victim->coords, 128.);
2126 victim->DoBloodBig(2 / victim->armorhead, 175);
2132 Normalise(&relative);
2133 relative = DoRotation(relative, 0, 90, 0);
2134 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2135 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2137 victim->jointVel(head) += relative * damagemult * 200;
2140 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2142 if (victim->damage > victim->damagetolerance)
2143 award_bonus(id, style);
2149 if (animTarget == blockhighleftstrikeanim && animation[animTarget].label[frameCurrent] == 5) {
2150 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != lowheight) {
2158 emit_sound_at(whooshhitsound, victim->coords);
2161 relative = victim->coords - coords;
2163 Normalise(&relative);
2164 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2165 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
2167 victim->jointVel(head) += relative * damagemult * 100;
2170 victim->DoDamage(damagemult * 50 / victim->protectionhead);
2174 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 8) {
2175 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) {
2179 emit_sound_at(whooshhitsound, victim->coords, 128.);
2181 victim->skeleton.longdead = 0;
2182 victim->skeleton.free = 1;
2183 victim->skeleton.broken = 0;
2184 victim->skeleton.spinny = 1;
2186 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2187 victim->skeleton.joints[i].velchange = 0;
2188 victim->skeleton.joints[i].delay = 0;
2189 victim->skeleton.joints[i].locked = 0;
2190 //victim->skeleton.joints[i].velocity=0;
2196 Normalise(&relative);
2197 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2198 victim->skeleton.joints[i].velocity.y = relative.y * 10;
2199 victim->skeleton.joints[i].position.y += relative.y * .3;
2200 victim->skeleton.joints[i].oldposition.y += relative.y * .3;
2201 victim->skeleton.joints[i].realoldposition.y += relative.y * .3;
2203 victim->Puff(abdomen);
2204 victim->jointVel(abdomen).y = relative.y * 400;
2208 if (animTarget == killanim && animation[animTarget].label[frameCurrent] == 5) {
2209 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) {
2213 if (tutoriallevel != 1) {
2214 emit_sound_at(heavyimpactsound, coords, 128.);
2217 relative = victim->coords - coords;
2219 Normalise(&relative);
2220 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2221 victim->skeleton.joints[i].velocity += relative * damagemult * 90;
2223 victim->Puff(abdomen);
2224 if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) {
2228 victim->DoDamage(damagemult * 500 / victim->protectionhigh);
2229 victim->jointVel(abdomen) += relative * damagemult * 300;
2233 if (animTarget == dropkickanim && animation[animTarget].label[frameCurrent] == 7) {
2234 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) {
2238 if (tutoriallevel != 1) {
2239 emit_sound_at(thudsound, coords);
2242 victim->skeleton.longdead = 0;
2243 victim->skeleton.free = 1;
2244 victim->skeleton.broken = 0;
2245 victim->skeleton.spinny = 1;
2247 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2248 victim->skeleton.joints[i].velchange = 0;
2249 //victim->skeleton.joints[i].delay=0;
2250 victim->skeleton.joints[i].locked = 0;
2253 relative = victim->coords - coords;
2254 Normalise(&relative);
2256 Normalise(&relative);
2257 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2258 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
2263 victim->Puff(abdomen);
2264 victim->DoDamage(damagemult * 20 / victim->protectionhigh);
2265 victim->jointVel(abdomen) += relative * damagemult * 200;
2274 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 5) {
2277 if (!victim->skeleton.free)
2281 terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360);
2282 emit_sound_at(knifesheathesound, coords, 128.);
2285 if (victim && hasvictim) {
2286 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2288 XYZ where, startpoint, endpoint, movepoint, colpoint;
2289 float rotationpoint;
2291 if (weapons[weaponids[weaponactive]].getType() == knife) {
2292 where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4);
2293 where -= victim->coords;
2294 if (!victim->skeleton.free)
2295 where = DoRotation(where, 0, -victim->yaw, 0);
2298 startpoint.y += 100;
2302 if (weapons[weaponids[weaponactive]].getType() == sword) {
2303 where = weapons[weaponids[weaponactive]].position;
2304 where -= victim->coords;
2305 if (!victim->skeleton.free)
2306 where = DoRotation(where, 0, -victim->yaw, 0);
2308 where = weapons[weaponids[weaponactive]].tippoint;
2309 where -= victim->coords;
2310 if (!victim->skeleton.free)
2311 where = DoRotation(where, 0, -victim->yaw, 0);
2314 if (weapons[weaponids[weaponactive]].getType() == staff) {
2315 where = weapons[weaponids[weaponactive]].position;
2316 where -= victim->coords;
2317 if (!victim->skeleton.free)
2318 where = DoRotation(where, 0, -victim->yaw, 0);
2320 where = weapons[weaponids[weaponactive]].tippoint;
2321 where -= victim->coords;
2322 if (!victim->skeleton.free)
2323 where = DoRotation(where, 0, -victim->yaw, 0);
2328 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint);
2330 if (whichtri != -1) {
2331 if (victim->dead != 2) {
2332 victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2));
2334 award_bonus(id, FinishedBonus);
2337 weapons[weaponids[weaponactive]].bloody = 2;
2339 victim->skeleton.longdead = 0;
2340 victim->skeleton.free = 1;
2341 victim->skeleton.broken = 0;
2343 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2344 victim->skeleton.joints[i].velchange = 0;
2345 victim->skeleton.joints[i].locked = 0;
2346 //victim->skeleton.joints[i].velocity=0;
2348 emit_sound_at(fleshstabsound, coords, 128);
2351 if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) {
2352 weapons[weaponids[weaponactive]].blooddrip += 5;
2353 weapons[weaponids[weaponactive]].blooddripdelay = 0;
2355 if (whichtri == -1) {
2357 emit_sound_at(knifesheathesound, coords, 128.);
2363 if ((animTarget == crouchstabanim || animTarget == swordgroundstabanim) && animation[animTarget].label[frameCurrent] == 6) {
2365 emit_sound_at(knifedrawsound, coords, 128);
2368 if (victim && hasvictim) {
2369 XYZ footvel, footpoint;
2371 emit_sound_at(fleshstabremovesound, coords, 128.);
2374 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2376 if (weapons[weaponids[weaponactive]].getType() == sword) {
2377 XYZ where, startpoint, endpoint, movepoint;
2378 float rotationpoint;
2381 where = weapons[weaponids[weaponactive]].position;
2382 where -= victim->coords;
2383 if (!victim->skeleton.free)
2384 where = DoRotation(where, 0, -victim->yaw, 0);
2386 where = weapons[weaponids[weaponactive]].tippoint;
2387 where -= victim->coords;
2388 if (!victim->skeleton.free)
2389 where = DoRotation(where, 0, -victim->yaw, 0);
2394 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2395 footpoint += victim->coords;
2397 if (whichtri == -1) {
2398 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2401 if (weapons[weaponids[weaponactive]].getType() == staff) {
2402 XYZ where, startpoint, endpoint, movepoint;
2403 float rotationpoint;
2406 where = weapons[weaponids[weaponactive]].position;
2407 where -= victim->coords;
2408 if (!victim->skeleton.free)
2409 where = DoRotation(where, 0, -victim->yaw, 0);
2411 where = weapons[weaponids[weaponactive]].tippoint;
2412 where -= victim->coords;
2413 if (!victim->skeleton.free)
2414 where = DoRotation(where, 0, -victim->yaw, 0);
2419 whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
2420 footpoint += victim->coords;
2422 if (whichtri == -1) {
2423 footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2);
2426 hasvictim = victim->DoBloodBigWhere(2, 220, footpoint);
2428 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2429 victim->skeleton.longdead = 0;
2430 victim->skeleton.free = 1;
2431 victim->skeleton.broken = 0;
2433 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2434 victim->skeleton.joints[i].velchange = 0;
2435 victim->skeleton.joints[i].locked = 0;
2436 //victim->skeleton.joints[i].velocity=0;
2442 Normalise(&relative);
2443 //victim->Puff(abdomen);
2445 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3);
2447 if (victim->bloodloss < victim->damagetolerance) {
2448 victim->bloodloss += 1000;
2452 victim->jointVel(abdomen) += relative * damagemult * 20;
2456 if (!hasvictim && onterrain) {
2457 weapons[weaponids[weaponactive]].bloody = 0;
2458 weapons[weaponids[weaponactive]].blooddrip = 0;
2462 if (animTarget == upunchanim && animation[animTarget].label[frameCurrent] == 5) {
2463 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) {
2471 if (tutoriallevel != 1) {
2472 emit_sound_at(heavyimpactsound, victim->coords, 128);
2477 relative = victim->coords - coords;
2479 Normalise(&relative);
2480 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2481 victim->skeleton.joints[i].velocity = relative * 30;
2483 victim->jointVel(head) += relative * damagemult * 150;
2485 victim->frameTarget = 0;
2486 victim->animTarget = staggerbackhardanim;
2487 victim->targetyaw = targetyaw + 180;
2489 victim->stunned = 1;
2492 victim->Puff(abdomen);
2493 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2500 if (animTarget == winduppunchanim && animation[animTarget].label[frameCurrent] == 5) {
2501 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) {
2505 if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height != lowheight) {
2506 if (tutoriallevel != 1) {
2507 emit_sound_at(thudsound, victim->coords);
2509 } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && animation[victim->animTarget].height == lowheight) {
2510 if (tutoriallevel != 1) {
2511 emit_sound_at(whooshhitsound, victim->coords);
2514 if (tutoriallevel != 1) {
2515 emit_sound_at(heavyimpactsound, victim->coords);
2519 if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || animation[victim->animTarget].height == lowheight)
2522 relative = victim->coords - coords;
2524 Normalise(&relative);
2526 Normalise(&relative);
2527 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2528 victim->skeleton.joints[i].velocity = relative * 5;
2530 victim->jointVel(abdomen) += relative * damagemult * 400;
2532 victim->frameTarget = 0;
2533 victim->animTarget = staggerbackhardanim;
2534 victim->targetyaw = targetyaw + 180;
2536 victim->stunned = 1;
2538 victim->Puff(abdomen);
2539 victim->DoDamage(damagemult * 60 / victim->protectionhigh);
2545 if (animTarget == blockhighleftanim && animation[animTarget].label[frameCurrent] == 5) {
2546 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2547 if (victim->id == 0)
2549 emit_sound_at(landsound2, victim->coords);
2555 if (animTarget == swordslashparryanim && animation[animTarget].label[frameCurrent] == 5) {
2556 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) {
2557 if (victim->id == 0)
2560 if (weaponactive != -1) {
2561 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2562 if (weapons[victim->weaponids[0]].getType() == staff)
2563 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2564 if (weapons[weaponids[0]].getType() == staff)
2565 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2567 emit_sound_at(swordstaffsound, victim->coords);
2569 emit_sound_at(metalhitsound, victim->coords);
2577 if (animTarget == knifethrowanim && animation[animTarget].label[frameCurrent] == 5) {
2578 if (weaponactive != -1) {
2581 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);
2583 weapons[weaponids[0]].thrown(aim * 50);
2586 weaponids[0] = weaponids[num_weapons];
2592 if (animTarget == knifeslashstartanim && animation[animTarget].label[frameCurrent] == 5) {
2594 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 &&/*animation[victim->animTarget].height!=lowheight&&*/victim->animTarget != dodgebackanim && victim->animTarget != rollanim) {
2596 if (tutoriallevel != 1)
2597 victim->DoBloodBig(1.5 / victim->armorhigh, 225);
2599 award_bonus(id, Slicebonus);
2600 if (tutoriallevel != 1) {
2601 emit_sound_at(knifeslicesound, victim->coords);
2603 //victim->jointVel(abdomen)+=relative*damagemult*200;
2604 if (animation[victim->animTarget].attack && (victim->aitype != playercontrolled || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) {
2605 if (victim->id != 0 || difficulty == 2) {
2606 victim->frameTarget = 0;
2607 victim->animTarget = staggerbackhardanim;
2608 victim->targetyaw = targetyaw + 180;
2612 victim->lowreversaldelay = 0;
2613 victim->highreversaldelay = 0;
2614 if (aitype != playercontrolled)
2615 weaponmissdelay = .6;
2617 if (tutoriallevel != 1)
2618 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2619 weapons[weaponids[weaponactive]].bloody = 1;
2620 if (tutoriallevel != 1)
2621 weapons[weaponids[weaponactive]].blooddrip += 3;
2623 XYZ footvel, footpoint;
2625 if (skeleton.free) {
2626 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2628 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2630 if (tutoriallevel != 1) {
2632 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3);
2633 footvel = DoRotation(facing, 0, 90, 0) * .8;
2635 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2636 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2637 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
2638 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
2640 if (tutoriallevel == 1) {
2641 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3);
2643 victim->DoDamage(damagemult * 0);
2646 if (animTarget == swordslashanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2647 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) {
2648 if (victim->weaponactive == -1 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) {
2649 award_bonus(id, Slashbonus);
2651 if (tutoriallevel != 1) {
2652 if (normaldotproduct(victim->facing, victim->coords - coords) < 0)
2653 victim->DoBloodBig(2 / victim->armorhigh, 190);
2655 victim->DoBloodBig(2 / victim->armorhigh, 185);
2656 victim->deathbleeding = 1;
2657 emit_sound_at(swordslicesound, victim->coords);
2659 //victim->jointVel(abdomen)+=relative*damagemult*200;
2660 if (tutoriallevel != 1) {
2661 victim->frameTarget = 0;
2662 victim->animTarget = staggerbackhardanim;
2663 victim->targetyaw = targetyaw + 180;
2667 if (tutoriallevel != 1) {
2668 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
2669 weapons[weaponids[weaponactive]].bloody = 1;
2670 weapons[weaponids[weaponactive]].blooddrip += 3;
2672 float bloodlossamount;
2673 bloodlossamount = 200 + abs((float)(Random() % 40)) - 20;
2674 victim->bloodloss += bloodlossamount / victim->armorhigh;
2675 //victim->bloodloss+=100*(6.5-distsq(&coords,&victim->coords));
2676 victim->DoDamage(damagemult * 0);
2678 XYZ footvel, footpoint;
2680 if (skeleton.free) {
2681 footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords;
2683 footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords;
2686 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
2687 footvel = DoRotation(facing, 0, 90, 0) * .8;
2689 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2690 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
2691 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
2692 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
2695 if (victim->weaponactive != -1) {
2696 if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) {
2697 if (weapons[victim->weaponids[0]].getType() == staff)
2698 weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2699 if (weapons[weaponids[0]].getType() == staff)
2700 weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250;
2702 emit_sound_at(swordstaffsound, victim->coords);
2704 emit_sound_at(metalhitsound, victim->coords);
2710 victim->Puff(righthand);
2712 victim->frameTarget = 0;
2713 victim->animTarget = staggerbackhighanim;
2714 victim->targetyaw = targetyaw + 180;
2716 aim = DoRotation(facing, 0, 90, 0) * 21;
2718 weapons[victim->weaponids[0]].drop(aim * -.2, aim);
2719 victim->num_weapons--;
2720 if (victim->num_weapons) {
2721 victim->weaponids[0] = victim->weaponids[num_weapons];
2722 if (victim->weaponstuck == victim->num_weapons)
2723 victim->weaponstuck = 0;
2725 victim->weaponactive = -1;
2726 for (unsigned i = 0; i < Person::players.size(); i++) {
2727 Person::players[i]->wentforweapon = 0;
2734 if (animTarget == staffhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2735 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2736 if (tutoriallevel != 1) {
2737 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250;
2741 if (Random() % 2 || creature == wolftype) {
2744 emit_sound_at(staffheadsound, victim->coords);
2748 relative = victim->coords - coords;
2750 Normalise(&relative);
2751 relative = DoRotation(relative, 0, 90, 0);
2753 Normalise(&relative);
2754 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2755 victim->skeleton.joints[i].velocity += relative * damagemult * 60;
2757 victim->jointVel(head) += relative * damagemult * 230;
2758 victim->jointVel(neck) += relative * damagemult * 230;
2761 if (tutoriallevel != 1) {
2762 victim->DoDamage(damagemult * 120 / victim->protectionhigh);
2764 award_bonus(id, solidhit, 30);
2769 if (animTarget == staffspinhitanim && animation[animTarget].label[frameCurrent] == 5 && victim->animTarget != rollanim) {
2770 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) {
2771 if (tutoriallevel != 1) {
2772 weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250;
2776 if (Random() % 2 || creature == wolftype) {
2779 emit_sound_at(staffheadsound, victim->coords);
2783 relative = victim->coords - coords;
2785 Normalise(&relative);
2786 relative = DoRotation(relative, 0, -90, 0);
2787 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2788 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2790 victim->jointVel(head) += relative * damagemult * 220;
2791 victim->jointVel(neck) += relative * damagemult * 220;
2794 if (tutoriallevel != 1) {
2795 victim->DoDamage(damagemult * 350 / victim->protectionhead);
2797 award_bonus(id, solidhit, 60);
2802 if (animTarget == staffgroundsmashanim && animation[animTarget].label[frameCurrent] == 5) {
2803 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) {
2805 if (tutoriallevel != 1) {
2807 weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500;
2810 if (Random() % 2 || creature == wolftype) {
2813 emit_sound_at(staffbodysound, victim->coords);
2815 victim->skeleton.longdead = 0;
2816 victim->skeleton.free = 1;
2817 victim->skeleton.broken = 0;
2819 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2820 victim->skeleton.joints[i].velchange = 0;
2821 victim->skeleton.joints[i].locked = 0;
2822 //victim->skeleton.joints[i].velocity=0;
2828 /*relative=victim->coords-coords;
2830 Normalise(&relative);
2831 relative=DoRotation(relative,0,90,0);*/
2833 Normalise(&relative);
2834 if (!victim->dead) {
2835 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2836 victim->skeleton.joints[i].velocity = relative * damagemult * 40;
2839 victim->jointVel(abdomen) += relative * damagemult * 40;
2842 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2843 victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20);
2846 //victim->jointVel(abdomen)+=relative*damagemult*20;
2848 victim->Puff(abdomen);
2849 if (tutoriallevel != 1) {
2850 victim->DoDamage(damagemult * 100 / victim->protectionhigh);
2852 if (!victim->dead) {
2853 award_bonus(id, solidhit, 40);
2859 if (animTarget == lowkickanim && animation[animTarget].label[frameCurrent] == 5) {
2860 if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && animation[victim->animTarget].height != highheight) {
2865 relative = victim->coords - coords;
2867 Normalise(&relative);
2871 if (animation[victim->animTarget].height == lowheight) {
2877 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2878 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
2880 victim->jointVel(head) += relative * damagemult * 200;
2881 if (tutoriallevel != 1) {
2882 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2885 victim->DoDamage(damagemult * 100 / victim->protectionhead);
2886 if (victim->howactive == typesleeping)
2887 victim->DoDamage(damagemult * 150 / victim->protectionhead);
2888 if (creature == wolftype) {
2889 emit_sound_at(clawslicesound, victim->coords, 128.);
2891 victim->DoBloodBig(2 / victim->armorhead, 175);
2894 if (victim->damage >= victim->damagetolerance)
2896 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2897 victim->skeleton.joints[i].velocity += relative * damagemult * 10;
2899 victim->jointVel(abdomen) += relative * damagemult * 200;
2900 victim->frameTarget = 0;
2901 victim->animTarget = staggerbackhighanim;
2902 victim->targetyaw = targetyaw + 180;
2904 if (tutoriallevel != 1) {
2905 emit_sound_at(landsound2, victim->coords, 128.);
2907 victim->Puff(abdomen);
2908 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
2909 if (creature == wolftype) {
2910 emit_sound_at(clawslicesound, victim->coords, 128.);
2912 victim->DoBloodBig(2 / victim->armorhigh, 170);
2919 if (animTarget == sweepanim && animation[animTarget].label[frameCurrent] == 5) {
2920 if ((victim->animTarget != jumpupanim) &&
2921 (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) &&
2922 (victim != this->shared_from_this())) {
2926 if (tutoriallevel != 1) {
2927 emit_sound_at(landsound2, victim->coords, 128.);
2930 relative = victim->coords - coords;
2932 Normalise(&relative);
2934 if (animation[victim->animTarget].height == middleheight || animation[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) {
2937 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2938 victim->skeleton.joints[i].velocity += relative * damagemult * 15;
2940 relative = DoRotation(relative, 0, -90, 0);
2942 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2943 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)
2944 victim->skeleton.joints[i].velocity = relative * 80;
2946 victim->Puff(rightankle);
2947 victim->Puff(leftankle);
2948 victim->DoDamage(damagemult * 40 / victim->protectionlow);
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 relative = DoRotation(relative, 0, -90, 0);
2956 for (int i = 0; i < victim->skeleton.num_joints; i++) {
2957 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)
2958 victim->skeleton.joints[i].velocity += relative * damagemult * 80;
2960 victim->jointVel(abdomen) += relative * damagemult * 200;
2961 victim->frameTarget = 0;
2962 victim->animTarget = staggerbackhighanim;
2963 victim->targetyaw = targetyaw + 180;
2965 if (tutoriallevel != 1) {
2966 emit_sound_at(landsound2, victim->coords, 128.);
2968 victim->Puff(abdomen);
2969 victim->DoDamage(damagemult * 30 / victim->protectionlow);
2977 if (animation[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) {
2978 if (animTarget == spinkickreversalanim && animation[animTarget].label[frameCurrent] == 7) {
2986 if (tutoriallevel != 1) {
2987 emit_sound_at(heavyimpactsound, victim->coords, 128.);
2989 if (creature == wolftype) {
2990 emit_sound_at(clawslicesound, victim->coords, 128);
2992 victim->DoBloodBig(2 / victim->armorhigh, 170);
2996 relative = victim->coords - oldcoords;
2998 Normalise(&relative);
2999 //relative=DoRotation(relative,0,-90,0);
3000 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3001 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3003 victim->jointVel(abdomen) += relative * damagemult * 200;
3005 victim->Puff(abdomen);
3006 victim->DoDamage(damagemult * 150 / victim->protectionhigh);
3008 award_bonus(id, Reversal);
3011 if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && animation[animTarget].label[frameCurrent] == 5) {
3012 if (victim->weaponactive != -1 && victim->num_weapons > 0) {
3013 if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) {
3014 takeWeapon(victim->weaponids[victim->weaponactive]);
3015 victim->num_weapons--;
3016 if (victim->num_weapons > 0) {
3017 victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons];
3019 victim->weaponactive = -1;
3024 if (animTarget == staffhitreversalanim && animation[animTarget].label[frameCurrent] == 5) {
3032 emit_sound_at(whooshhitsound, victim->coords, 128.);
3035 relative = victim->coords - oldcoords;
3037 Normalise(&relative);
3038 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3039 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3041 victim->jointVel(abdomen) += relative * damagemult * 200;
3043 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3046 if (animTarget == staffspinhitreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3055 award_bonus(id, staffreversebonus);
3057 if (tutoriallevel != 1) {
3058 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3061 award_bonus(id, staffreversebonus); // Huh, again?
3064 relative = victim->coords - oldcoords;
3066 Normalise(&relative);
3067 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3068 victim->skeleton.joints[i].velocity += relative * damagemult * 30;
3070 victim->jointVel(abdomen) += relative * damagemult * 200;
3072 victim->DoDamage(damagemult * 70 / victim->protectionhigh);
3075 if (animTarget == upunchreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3081 Normalise(&relative);
3083 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3084 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3086 victim->jointVel(lefthand) *= .1;
3087 victim->jointVel(leftwrist) *= .2;
3088 victim->jointVel(leftelbow) *= .5;
3089 victim->jointVel(leftshoulder) *= .7;
3090 victim->jointVel(righthand) *= .1;
3091 victim->jointVel(rightwrist) *= .2;
3092 victim->jointVel(rightelbow) *= .5;
3093 victim->jointVel(rightshoulder) *= .7;
3095 victim->Puff(abdomen);
3096 victim->DoDamage(damagemult * 90 / victim->protectionhigh);
3098 award_bonus(id, Reversal);
3102 if (weaponactive != -1 || creature == wolftype)
3104 if (creature == rabbittype && weaponactive != -1)
3105 if (weapons[weaponids[0]].getType() == staff)
3108 if (weaponactive != -1) {
3109 victim->DoBloodBig(2 / victim->armorhigh, 225);
3110 emit_sound_at(knifeslicesound, victim->coords);
3111 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3112 weapons[weaponids[weaponactive]].bloody = 1;
3113 weapons[weaponids[weaponactive]].blooddrip += 3;
3115 if (weaponactive == -1 && creature == wolftype) {
3117 emit_sound_at(clawslicesound, victim->coords, 128.);
3119 victim->DoBloodBig(2 / victim->armorhigh, 175);
3126 if (animTarget == swordslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3132 Normalise(&relative);
3134 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3135 victim->skeleton.joints[i].velocity += relative * damagemult * 70;
3137 victim->jointVel(lefthand) *= .1 - 1;
3138 victim->jointVel(leftwrist) *= .2 - 1;
3139 victim->jointVel(leftelbow) *= .5 - 1;
3140 victim->jointVel(leftshoulder) *= .7 - 1;
3141 victim->jointVel(righthand) *= .1 - 1;
3142 victim->jointVel(rightwrist) *= .2 - 1;
3143 victim->jointVel(rightelbow) *= .5 - 1;
3144 victim->jointVel(rightshoulder) *= .7 - 1;
3146 award_bonus(id, swordreversebonus);
3149 if (hasvictim && animTarget == knifeslashreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3157 if (tutoriallevel != 1) {
3158 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3162 relative = victim->coords - oldcoords;
3164 Normalise(&relative);
3165 relative = DoRotation(relative, 0, -90, 0);
3166 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3167 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3169 victim->jointVel(abdomen) += relative * damagemult * 200;
3170 victim->Puff(abdomen);
3171 victim->DoDamage(damagemult * 30 / victim->protectionhigh);
3173 award_bonus(id, Reversal);
3176 if (hasvictim && animTarget == sneakattackanim && animation[animTarget].label[frameCurrent] == 7) {
3179 victim->skeleton.spinny = 0;
3181 relative = facing * -1;
3183 Normalise(&relative);
3184 if (victim->id == 0)
3186 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3187 victim->skeleton.joints[i].velocity += relative * damagemult * 40;
3189 victim->damage = victim->damagetolerance;
3190 victim->permanentdamage = victim->damagetolerance - 1;
3193 if (weaponactive != -1 || creature == wolftype)
3195 if (creature == rabbittype && weaponactive != -1)
3196 if (weapons[weaponids[0]].getType() == staff)
3199 if (weaponactive != -1) {
3200 victim->DoBloodBig(200, 225);
3201 emit_sound_at(knifeslicesound, victim->coords);
3203 weapons[weaponids[weaponactive]].bloody = 2;
3204 weapons[weaponids[weaponactive]].blooddrip += 5;
3207 if (creature == wolftype && weaponactive == -1) {
3208 emit_sound_at(clawslicesound, victim->coords, 128.);
3210 victim->DoBloodBig(2, 175);
3213 award_bonus(id, spinecrusher);
3216 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3217 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3219 if (animTarget == knifefollowanim)
3220 victim->DoBloodBig(200, 210);
3221 if (animTarget == knifesneakattackanim) {
3222 XYZ footvel, footpoint;
3224 footpoint = weapons[weaponids[0]].tippoint;
3226 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3227 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3228 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3229 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3230 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3231 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3232 victim->DoBloodBig(200, 195);
3233 award_bonus(id, tracheotomy);
3235 if (animTarget == knifefollowanim) {
3236 award_bonus(id, Stabbonus);
3237 XYZ footvel, footpoint;
3239 footpoint = weapons[weaponids[0]].tippoint;
3241 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3242 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3243 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3244 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3245 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1);
3246 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1);
3249 victim->bloodloss += 10000;
3250 victim->velocity = 0;
3251 emit_sound_at(fleshstabsound, victim->coords);
3253 weapons[weaponids[weaponactive]].bloody = 2;
3254 weapons[weaponids[weaponactive]].blooddrip += 5;
3258 if (hasvictim && (animTarget == knifefollowanim || animTarget == knifesneakattackanim) && animation[animTarget].label[frameCurrent] == 6) {
3260 victim->velocity = 0;
3261 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3262 victim->skeleton.joints[i].velocity = 0;
3264 if (animTarget == knifefollowanim) {
3266 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3267 victim->skeleton.joints[i].velocity = 0;
3270 if (weaponactive != -1 && animation[victim->animTarget].attack != reversal) {
3271 emit_sound_at(fleshstabremovesound, victim->coords);
3273 weapons[weaponids[weaponactive]].bloody = 2;
3274 weapons[weaponids[weaponactive]].blooddrip += 5;
3276 XYZ footvel, footpoint;
3278 footpoint = weapons[weaponids[0]].tippoint;
3280 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3281 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3282 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3283 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3284 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3285 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3289 if (hasvictim && (animTarget == swordsneakattackanim) && animation[animTarget].label[frameCurrent] == 5) {
3290 if (weaponactive != -1 && victim->bloodloss < victim->damagetolerance) {
3291 award_bonus(id, backstab);
3295 XYZ footvel, footpoint;
3297 footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2;
3299 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3300 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position);
3301 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3302 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3303 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3304 Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1);
3305 victim->DoBloodBig(200, 180);
3306 victim->DoBloodBig(200, 215);
3307 victim->bloodloss += 10000;
3308 victim->velocity = 0;
3309 emit_sound_at(fleshstabsound, victim->coords);
3311 weapons[weaponids[weaponactive]].bloody = 2;
3312 weapons[weaponids[weaponactive]].blooddrip += 5;
3316 if (hasvictim && animTarget == swordsneakattackanim && animation[animTarget].label[frameCurrent] == 6) {
3318 victim->velocity = 0;
3319 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3320 victim->skeleton.joints[i].velocity = 0;
3322 if (weaponactive != -1) {
3323 emit_sound_at(fleshstabremovesound, victim->coords);
3325 weapons[weaponids[weaponactive]].bloody = 2;
3326 weapons[weaponids[weaponactive]].blooddrip += 5;
3328 XYZ footvel, footpoint;
3330 footpoint = weapons[weaponids[0]].tippoint;
3332 Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3);
3333 footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1;
3334 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3335 Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9);
3336 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1);
3337 Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1);
3341 if (animTarget == sweepreversalanim && animation[animTarget].label[frameCurrent] == 7) {
3349 if (weaponactive == -1) {
3350 if (tutoriallevel != 1) {
3351 emit_sound_at(heavyimpactsound, victim->coords, 128.);
3356 if (weaponactive != -1 || creature == wolftype)
3358 if (creature == rabbittype && weaponactive != -1)
3359 if (weapons[weaponids[0]].getType() == staff)
3362 if (weaponactive != -1) {
3363 victim->DoBloodBig(2 / victim->armorhead, 225);
3364 emit_sound_at(knifeslicesound, victim->coords);
3365 if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody)
3366 weapons[weaponids[weaponactive]].bloody = 1;
3367 weapons[weaponids[weaponactive]].blooddrip += 3;
3369 if (weaponactive == -1 && creature == wolftype) {
3370 emit_sound_at(clawslicesound, victim->coords, 128.);
3372 victim->DoBloodBig(2 / victim->armorhead, 175);
3376 award_bonus(id, Reversal);
3381 relative = facing * -1;
3383 Normalise(&relative);
3384 relative = DoRotation(relative, 0, 90, 0);
3386 Normalise(&relative);
3387 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3388 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3390 victim->jointVel(head) += relative * damagemult * 200;
3391 if (victim->damage < victim->damagetolerance - 100)
3392 victim->velocity = relative * 200;
3393 victim->DoDamage(damagemult * 100 / victim->protectionhead);
3394 victim->velocity = 0;
3397 if (animTarget == sweepreversalanim && ((animation[animTarget].label[frameCurrent] == 9 && victim->damage < victim->damagetolerance) || (animation[animTarget].label[frameCurrent] == 7 && victim->damage > victim->damagetolerance))) {
3401 relative = facing * -1;
3403 Normalise(&relative);
3404 relative = DoRotation(relative, 0, 90, 0);
3406 Normalise(&relative);
3407 for (int i = 0; i < victim->skeleton.num_joints; i++) {
3408 victim->skeleton.joints[i].velocity += relative * damagemult * 20;
3410 victim->jointVel(head) += relative * damagemult * 200;
3413 if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim))
3414 if (victim->damage > victim->damagetolerance && bonus != reverseko) {
3415 award_bonus(id, reverseko);
3421 if (frameTarget > animation[animCurrent].numframes - 1) {
3424 animTarget = getIdle();
3428 if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) {
3429 animTarget = rollanim;
3431 emit_sound_at(movewhooshsound, coords, 128.);
3433 if (animCurrent == staggerbackhighanim) {
3434 animTarget = getIdle();
3436 if (animCurrent == staggerbackhardanim) {
3437 animTarget = getIdle();
3439 if (animCurrent == removeknifeanim) {
3440 animTarget = getIdle();
3442 if (animCurrent == crouchremoveknifeanim) {
3443 animTarget = getCrouch();
3445 if (animCurrent == backhandspringanim) {
3446 animTarget = getIdle();
3448 if (animCurrent == dodgebackanim) {
3449 animTarget = getIdle();
3451 if (animCurrent == drawleftanim) {
3452 animTarget = getIdle();
3454 if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) {
3455 animTarget = getIdle();
3456 if (animCurrent == crouchdrawrightanim) {
3457 animTarget = getCrouch();
3459 if (weaponactive == -1)
3461 else if (weaponactive == 0) {
3463 if (num_weapons == 2) {
3465 buffer = weaponids[0];
3466 weaponids[0] = weaponids[1];
3467 weaponids[1] = buffer;
3471 if (weaponactive == -1) {
3472 emit_sound_at(knifesheathesound, coords, 128.);
3474 if (weaponactive != -1) {
3475 emit_sound_at(knifedrawsound, coords, 128.);
3478 if (animCurrent == rollanim) {
3479 animTarget = getCrouch();
3484 if (animTarget == walljumprightkickanim) {
3487 if (animTarget == walljumpleftkickanim) {
3490 animTarget = jumpdownanim;
3492 if (animCurrent == climbanim) {
3493 animTarget = getCrouch();
3495 coords += facing * .1;
3496 if (!isnormal(coords.x))
3507 if (animTarget == rabbitkickreversalanim) {
3508 animTarget = getCrouch();
3511 if (animTarget == jumpreversalanim) {
3512 animTarget = getCrouch();
3515 if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) {
3516 if (attackkeydown && animTarget != walljumpfrontanim) {
3518 float closestdist = -1;
3520 if (Person::players.size() > 1)
3521 for (unsigned i = 0; i < Person::players.size(); i++) {
3522 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3523 distance = distsq(&Person::players[i]->coords, &coords);
3524 if (closestdist == -1 || distance < closestdist) {
3525 closestdist = distance;
3530 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3531 victim = Person::players[closest];
3532 animTarget = walljumprightkickanim;
3534 XYZ rotatetarget = victim->coords - coords;
3535 Normalise(&rotatetarget);
3536 yaw = -asin(0 - rotatetarget.x);
3538 if (rotatetarget.z < 0)
3540 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3541 velocity = (victim->coords - coords) * 4;
3546 if (animTarget == walljumpbackanim) {
3547 animTarget = backflipanim;
3549 velocity = facing * -8;
3552 resume_stream(whooshsound);
3554 if (animTarget == walljumprightanim) {
3555 animTarget = rightflipanim;
3559 velocity = DoRotation(facing, 0, 30, 0) * -8;
3562 if (animTarget == walljumpfrontanim) {
3563 animTarget = frontflipanim;
3567 velocity = facing * 8;
3571 resume_stream(whooshsound);
3573 if (animTarget == walljumpleftanim) {
3574 if (attackkeydown) {
3576 float closestdist = -1;
3578 if (Person::players.size() > 1)
3579 for (unsigned i = 0; i < Person::players.size(); i++) {
3580 if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) {
3581 distance = distsq(&Person::players[i]->coords, &coords);
3582 if (closestdist == -1 || distance < closestdist) {
3583 closestdist = distance;
3588 if (closestdist > 0 && closest >= 0 && closestdist < 16) {
3589 victim = Person::players[closest];
3590 animTarget = walljumpleftkickanim;
3592 XYZ rotatetarget = victim->coords - coords;
3593 Normalise(&rotatetarget);
3594 yaw = -asin(0 - rotatetarget.x);
3596 if (rotatetarget.z < 0)
3598 targettilt2 = -asin(rotatetarget.y) * 360 / 6.28;
3599 velocity = (victim->coords - coords) * 4;
3604 if (animTarget != walljumpleftkickanim) {
3605 animTarget = leftflipanim;
3609 velocity = DoRotation(facing, 0, -30, 0) * -8;
3613 resume_stream(whooshsound);
3615 if (animTarget == sneakattackanim) {
3616 animCurrent = getCrouch();
3617 animTarget = getCrouch();
3624 transspeed = 1000000;
3625 targetheadyaw += 180;
3626 coords -= facing * .7;
3628 coords.y = terrain.getHeight(coords.x, coords.z);
3632 if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) {
3633 animTarget = getIdle();
3636 coords.y = terrain.getHeight(coords.x, coords.z);
3640 if (animCurrent == knifefollowanim) {
3641 animTarget = getIdle();
3644 if (animation[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) {
3645 float ycoords = oldcoords.y;
3646 animTarget = getStop();
3651 transspeed = 1000000;
3652 targetheadyaw += 180;
3653 if (!isnormal(coords.x))
3655 if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim)
3656 oldcoords = coords + facing * .5;
3657 else if (animCurrent == sweepreversalanim)
3658 oldcoords = coords + facing * 1.1;
3659 else if (animCurrent == upunchreversalanim) {
3660 oldcoords = coords + facing * 1.5;
3663 targetheadyaw += 180;
3666 } else if (animCurrent == knifeslashreversalanim) {
3667 oldcoords = coords + facing * .5;
3670 targetheadyaw += 90;
3673 } else if (animCurrent == staffspinhitreversalanim) {
3676 targetheadyaw += 180;
3681 oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z);
3683 oldcoords.y = ycoords;
3684 currentoffset = coords - oldcoords;
3690 if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) {
3695 if (animation[animTarget].attack == reversed) {
3697 if (animTarget == sweepreversedanim)
3699 animTarget = backhandspringanim;
3701 emit_sound_at(landsound, coords, 128);
3703 if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) {
3704 animTarget = rollanim;
3707 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3708 coords.y = oldcoords.y;
3710 if (animCurrent == knifeslashreversedanim) {
3711 animTarget = rollanim;
3716 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3717 coords.y = oldcoords.y;
3721 animTarget = jumpdownanim;
3724 animTarget = getIdle();
3726 animTarget = getIdle();
3727 if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) {
3728 animTarget = getIdle();
3730 coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale;
3731 coords.y = oldcoords.y;
3732 //coords+=DoRotation(animation[animCurrent].offset,0,yaw,0)*scale;
3733 targetoffset.y = coords.y;
3735 targetoffset.y = terrain.getHeight(coords.x, coords.z);
3736 currentoffset = DoRotation(animation[animCurrent].offset * -1, 0, yaw, 0) * scale;
3737 currentoffset.y -= (coords.y - targetoffset.y);
3738 coords.y = targetoffset.y;
3740 normalsupdatedelay = 0;
3742 if (animCurrent == upunchanim) {
3743 animTarget = getStop();
3744 normalsupdatedelay = 0;
3747 if (animCurrent == rabbitkickanim && animTarget != backflipanim) {
3751 if (num_weapons > 0)
3752 if (weapons[0].getType() == staff)
3758 rabbitkickragdoll = 1;
3760 if (animCurrent == rabbitkickreversedanim) {
3766 skeleton.spinny = 0;
3767 SolidHitBonus(!id); // FIXME: tricky id
3771 animTarget = rollanim;
3774 pause_sound(whooshsound);
3778 if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) {
3782 skeleton.spinny = 0;
3784 if (animCurrent == jumpreversedanim) {
3790 skeleton.spinny = 0;
3791 SolidHitBonus(!id); // FIXME: tricky id
3795 animTarget = rollanim;
3796 coords += facing * 2;
3798 pause_sound(whooshsound);
3803 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) {
3804 animTarget = getupfromfrontanim;
3806 } else if (animation[animCurrent].attack == normalattack) {
3807 animTarget = getIdle();
3810 if (animCurrent == blockhighleftanim && aitype != playercontrolled) {
3811 animTarget = blockhighleftstrikeanim;
3813 if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) {
3814 animTarget = getIdle();
3817 if (animCurrent == spinkickanim && victim->skeleton.free) {
3818 if (creature == rabbittype)
3819 animTarget = fightidleanim;
3824 if (isIdle() && !wasIdle())
3825 normalsupdatedelay = 0;
3827 if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) {
3828 animTarget = jumpdownanim;
3831 if (!skeleton.free) {
3833 if (!transspeed && animation[animTarget].attack != 2 && animation[animTarget].attack != 3) {
3834 if (!isRun() || !wasRun()) {
3835 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3836 target += multiplier * animation[animTarget].speed[frameTarget] * speed * 2;
3837 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3838 target += multiplier * animation[animCurrent].speed[frameCurrent] * speed * 2;
3840 if (isRun() && wasRun()) {
3842 tempspeed = velspeed;
3843 if (tempspeed < 10 * speedmult)
3844 tempspeed = 10 * speedmult;
3845 target += multiplier * animation[animTarget].speed[frameCurrent] * speed * 1.7 * tempspeed / (speed * 45 * scale);
3847 } else if (transspeed)
3848 target += multiplier * transspeed * speed * 2;
3850 if (!isRun() || !wasRun()) {
3851 if (animation[animTarget].speed[frameTarget] > animation[animCurrent].speed[frameCurrent])
3852 target += multiplier * animation[animTarget].speed[frameTarget] * 2;
3853 if (animation[animTarget].speed[frameTarget] <= animation[animCurrent].speed[frameCurrent])
3854 target += multiplier * animation[animCurrent].speed[frameCurrent] * 2;
3858 if (animCurrent != animTarget)
3859 target = (target + oldtarget) / 2;
3862 frameCurrent = frameTarget;
3866 rot = targetrot * target;
3867 yaw += rot - oldrot;
3873 if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) {
3875 for (int i = 0; i < skeleton.num_joints; i++) {
3876 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent];
3879 skeleton.FindForwards();
3881 for (int i = 0; i < skeleton.num_muscles; i++) {
3882 if (skeleton.muscles[i].visible) {
3883 skeleton.FindRotationMuscle(i, animTarget);
3886 for (int i = 0; i < skeleton.num_muscles; i++) {
3887 if (skeleton.muscles[i].visible) {
3888 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3889 skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3890 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3891 skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3892 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3893 skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3898 for (int i = 0; i < skeleton.num_joints; i++) {
3899 skeleton.joints[i].position = animation[animTarget].position[i][frameTarget];
3902 skeleton.FindForwards();
3904 for (int i = 0; i < skeleton.num_muscles; i++) {
3905 if (skeleton.muscles[i].visible) {
3906 skeleton.FindRotationMuscle(i, animTarget);
3909 for (int i = 0; i < skeleton.num_muscles; i++) {
3910 if (skeleton.muscles[i].visible) {
3911 if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100))
3912 skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100;
3913 if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100))
3914 skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100;
3915 if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100))
3916 skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100;
3917 if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) skeleton.muscles[i].newrotate3 -= 360;
3918 if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) skeleton.muscles[i].newrotate3 += 360;
3919 if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) skeleton.muscles[i].newrotate2 -= 360;
3920 if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) skeleton.muscles[i].newrotate2 += 360;
3921 if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) skeleton.muscles[i].newrotate1 -= 360;
3922 if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) skeleton.muscles[i].newrotate1 += 360;
3926 if (frameCurrent >= animation[animCurrent].numframes)
3927 frameCurrent = animation[animCurrent].numframes - 1;
3929 oldanimCurrent = animCurrent;
3930 oldanimTarget = animTarget;
3931 oldframeTarget = frameTarget;
3932 oldframeCurrent = frameCurrent;
3934 for (int i = 0; i < skeleton.num_joints; i++) {
3935 skeleton.joints[i].velocity = (animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target) - skeleton.joints[i].position) / multiplier;
3936 skeleton.joints[i].position = animation[animCurrent].position[i][frameCurrent] * (1 - target) + animation[animTarget].position[i][frameTarget] * (target);
3938 offset = currentoffset * (1 - target) + targetoffset * target;
3939 for (int i = 0; i < skeleton.num_muscles; i++) {
3940 if (skeleton.muscles[i].visible) {
3941 skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * (target);
3942 skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * (target);
3943 skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * (target);
3948 if (isLanding() && landhard) {
3951 animTarget = getLandhard();
3964 void Person::DoStuff()
3966 static XYZ terrainnormal;
3967 static XYZ flatfacing;
3968 static XYZ flatvelocity;
3969 static float flatvelspeed;
3973 static int bloodsize;
3974 static int startx, starty, endx, endy;
3975 static GLubyte color;
3976 static XYZ bloodvel;
3978 onfiredelay -= multiplier;
3979 if (onfiredelay < 0 && onfire) {
3980 if (Random() % 2 == 0) {
3986 crouchkeydowntime += multiplier;
3988 crouchkeydowntime = 0;
3989 jumpkeydowntime += multiplier;
3990 if (!jumpkeydown && skeleton.free)
3991 jumpkeydowntime = 0;
3993 if (hostile || damage > 0 || bloodloss > 0)
3996 if (isIdle() || isRun())
3999 if (num_weapons == 1 && weaponactive != -1)
4003 blooddimamount -= multiplier * .3;
4004 speechdelay -= multiplier;
4005 texupdatedelay -= multiplier;
4006 interestdelay -= multiplier;
4007 flamedelay -= multiplier;
4008 parriedrecently -= multiplier;
4010 victim = this->shared_from_this();
4015 speed = 1.1 * speedmult;
4017 speed = 1.0 * speedmult;
4019 rabbitkickragdoll = 0;
4023 if (id != 0 && (creature == rabbittype || difficulty != 2))
4025 if (id != 0 && creature == wolftype && difficulty == 2) {
4027 if (aitype != passivetype) {
4029 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) {
4035 if (animTarget == wolfrunninganim && !superruntoggle) {
4036 animTarget = getRun();
4040 if (weaponactive == -1 && num_weapons > 0) {
4041 if (weapons[weaponids[0]].getType() == staff) {
4047 burnt += multiplier;
4051 OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3);
4053 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
4059 vel[0] = velocity.x;
4060 vel[1] = velocity.y;
4061 vel[2] = velocity.z;
4064 OPENAL_3D_SetAttributes(channels[whooshsound], gLoc, vel);
4065 OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5);
4069 while (flamedelay < 0 && onfire) {
4071 howmany = abs(Random() % (skeleton.num_joints));
4072 if (skeleton.free) {
4073 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4074 flatfacing = skeleton.joints[howmany].position * scale + coords;
4076 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4077 flatvelocity = (coords - oldcoords) / multiplier / 2;
4079 Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1);
4082 while (flamedelay < 0 && !onfire && tutoriallevel == 1 && id != 0) {
4084 howmany = abs(Random() % (skeleton.num_joints));
4085 if (skeleton.free) {
4086 flatvelocity = skeleton.joints[howmany].velocity * scale / 2;
4087 flatfacing = skeleton.joints[howmany].position * scale + coords;
4089 flatvelocity = (coords - oldcoords) / multiplier / 2;
4090 flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords;
4092 Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3);
4096 bleeding -= multiplier * .3;
4097 if (bloodtoggle == 2) {
4098 skeleton.drawmodel.textureptr.bind();
4099 if ((bleeding <= 0) && (detail != 2))
4104 if (neckspurtamount > 0) {
4105 neckspurtamount -= multiplier;
4106 neckspurtdelay -= multiplier * 3;
4107 neckspurtparticledelay -= multiplier * 3;
4108 if (neckspurtparticledelay < 0 && neckspurtdelay > 2) {
4111 if (skeleton.free) {
4112 bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0);
4113 bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4114 Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4116 bloodvel.z = 5 * neckspurtamount;
4117 bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale;
4118 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale;
4119 Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, .9);
4121 neckspurtparticledelay = .05;
4123 if (neckspurtdelay < 0) {
4128 if (deathbleeding > 0 && dead != 2) {
4129 if (deathbleeding < 5)
4130 bleeddelay -= deathbleeding * multiplier / 4;
4132 bleeddelay -= 5 * multiplier / 4;
4133 if (bleeddelay < 0 && bloodtoggle) {
4138 if (skeleton.free) {
4139 bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale;
4140 Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1);
4142 bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale;
4143 Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0)*scale + coords, bloodvel, 1, 1, 1, .05, 1);
4147 bloodloss += deathbleeding * multiplier * 80;
4148 deathbleeding -= multiplier * 1.6;
4149 if (deathbleeding < 0)
4151 if (bloodloss > damagetolerance && animation[animTarget].attack == neutral) {
4152 if (weaponactive != -1) {
4153 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4154 weapons[weaponids[0]].velocity.x += .01;
4157 weaponids[0] = weaponids[num_weapons];
4158 if (weaponstuck == num_weapons)
4162 for (unsigned i = 0; i < Person::players.size(); i++) {
4163 Person::players[i]->wentforweapon = 0;
4175 if (!dead && creature == wolftype) {
4176 award_bonus(0, Wolfbonus);
4179 if (animTarget == knifefollowedanim && !skeleton.free) {
4180 for (int i = 0; i < skeleton.num_joints; i++) {
4181 skeleton.joints[i].velocity = 0;
4182 skeleton.joints[i].velocity.y = -2;
4185 if (id != 0 && unconscioustime > .1) {
4193 if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) {
4194 texupdatedelay = .12;
4196 bloodsize = 5 - realtexdetail;
4200 startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4201 starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1));
4202 endx = startx + bloodsize;
4203 endy = starty + bloodsize;
4213 if (endx > skeleton.skinsize - 1) {
4214 endx = skeleton.skinsize - 1;
4217 if (endy > skeleton.skinsize - 1) {
4218 endy = skeleton.skinsize - 1;
4226 for (i = startx; i < endx; i++) {
4227 for (j = starty; j < endy; j++) {
4228 if (Random() % 2 == 0) {
4229 color = Random() % 85 + 170;
4230 if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2)
4231 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2;
4232 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0;
4233 skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0;
4238 skeleton.drawmodel.textureptr.bind();
4242 if (skeleton.free) {
4243 bleedx += 4 * direction / realtexdetail;
4245 bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4247 bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4249 bleedy -= 4 / realtexdetail;
4251 bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail;
4253 bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail;
4257 if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) {
4258 righthandmorphness = targetrighthandmorphness;
4259 righthandmorphstart = righthandmorphend;
4260 } else if (righthandmorphness > targetrighthandmorphness) {
4261 righthandmorphness -= multiplier * 4;
4262 } else if (righthandmorphness < targetrighthandmorphness) {
4263 righthandmorphness += multiplier * 4;
4266 if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) {
4267 lefthandmorphness = targetlefthandmorphness;
4268 lefthandmorphstart = lefthandmorphend;
4269 } else if (lefthandmorphness > targetlefthandmorphness) {
4270 lefthandmorphness -= multiplier * 4;
4271 } else if (lefthandmorphness < targetlefthandmorphness) {
4272 lefthandmorphness += multiplier * 4;
4275 if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) {
4276 if (abs(tailmorphness - targettailmorphness) < multiplier * 10) {
4277 tailmorphness = targettailmorphness;
4278 tailmorphstart = tailmorphend;
4279 } else if (tailmorphness > targettailmorphness) {
4280 tailmorphness -= multiplier * 10;
4281 } else if (tailmorphness < targettailmorphness) {
4282 tailmorphness += multiplier * 10;
4286 if (creature == wolftype) {
4287 if (abs(tailmorphness - targettailmorphness) < multiplier * 4) {
4288 tailmorphness = targettailmorphness;
4289 tailmorphstart = tailmorphend;
4290 } else if (tailmorphness > targettailmorphness) {
4291 tailmorphness -= multiplier * 2;
4292 } else if (tailmorphness < targettailmorphness) {
4293 tailmorphness += multiplier * 2;
4297 if (headmorphend == 3 || headmorphstart == 3) {
4298 if (abs(headmorphness - targetheadmorphness) < multiplier * 7) {
4299 headmorphness = targetheadmorphness;
4300 headmorphstart = headmorphend;
4301 } else if (headmorphness > targetheadmorphness) {
4302 headmorphness -= multiplier * 7;
4303 } else if (headmorphness < targetheadmorphness) {
4304 headmorphness += multiplier * 7;
4306 } else if (headmorphend == 5 || headmorphstart == 5) {
4307 if (abs(headmorphness - targetheadmorphness) < multiplier * 10) {
4308 headmorphness = targetheadmorphness;
4309 headmorphstart = headmorphend;
4310 } else if (headmorphness > targetheadmorphness) {
4311 headmorphness -= multiplier * 10;
4312 } else if (headmorphness < targetheadmorphness) {
4313 headmorphness += multiplier * 10;
4316 if (abs(headmorphness - targetheadmorphness) < multiplier * 4) {
4317 headmorphness = targetheadmorphness;
4318 headmorphstart = headmorphend;
4319 } else if (headmorphness > targetheadmorphness) {
4320 headmorphness -= multiplier * 4;
4321 } else if (headmorphness < targetheadmorphness) {
4322 headmorphness += multiplier * 4;
4326 if (abs(chestmorphness - targetchestmorphness) < multiplier) {
4327 chestmorphness = targetchestmorphness;
4328 chestmorphstart = chestmorphend;
4329 } else if (chestmorphness > targetchestmorphness) {
4330 chestmorphness -= multiplier;
4331 } else if (chestmorphness < targetchestmorphness) {
4332 chestmorphness += multiplier;
4335 if (dead != 2 && howactive <= typesleeping) {
4336 if (chestmorphstart == 0 && chestmorphend == 0) {
4338 targetchestmorphness = 1;
4341 if (chestmorphstart != 0 && chestmorphend != 0) {
4343 targetchestmorphness = 1;
4345 if (environment == snowyenvironment) {
4348 if (skeleton.free) {
4349 footvel = skeleton.specialforward[0] * -1;
4350 footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords;
4352 footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1;
4353 footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords;
4355 if (animTarget == sleepanim)
4356 footvel = DoRotation(footvel, 0, 90, 0);
4357 Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3);
4361 if (!dead && howactive < typesleeping) {
4362 blinkdelay -= multiplier * 2;
4363 if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) {
4365 targetheadmorphness = 1;
4367 blinkdelay = (float)(abs(Random() % 40)) / 5;
4369 if (headmorphstart == 3 && headmorphend == 3) {
4371 targetheadmorphness = 1;
4376 twitchdelay -= multiplier * 1.5;
4377 if (animTarget != hurtidleanim) {
4378 if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) {
4380 targetheadmorphness = 1;
4382 twitchdelay = (float)(abs(Random() % 40)) / 5;
4384 if (headmorphstart == 5 && headmorphend == 5) {
4386 targetheadmorphness = 1;
4390 if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) {
4391 twitchdelay3 -= multiplier * 1;
4392 if (Random() % 2 == 0) {
4393 if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) {
4394 righthandmorphness = 0;
4395 targetrighthandmorphness = 1;
4396 righthandmorphend = 1;
4397 if (Random() % 2 == 0)twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4399 if (righthandmorphstart == 1 && righthandmorphend == 1) {
4400 righthandmorphness = 0;
4401 targetrighthandmorphness = 1;
4402 righthandmorphend = 0;
4405 if (Random() % 2 == 0) {
4406 if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) {
4407 lefthandmorphness = 0;
4408 targetlefthandmorphness = 1;
4409 lefthandmorphend = 1;
4410 twitchdelay3 = (float)(abs(Random() % 40)) / 5;
4412 if (lefthandmorphstart == 1 && lefthandmorphend == 1) {
4413 lefthandmorphness = 0;
4414 targetlefthandmorphness = 1;
4415 lefthandmorphend = 0;
4421 if (creature == rabbittype) {
4422 if (howactive < typesleeping)
4423 twitchdelay2 -= multiplier * 1.5;
4425 twitchdelay2 -= multiplier * 0.5;
4426 if (howactive <= typesleeping) {
4427 if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) {
4429 targettailmorphness = 1;
4431 twitchdelay2 = (float)(abs(Random() % 40)) / 5;
4433 if (tailmorphstart == 1 && tailmorphend == 1) {
4435 targettailmorphness = 1;
4438 if (tailmorphstart == 2 && tailmorphend == 2) {
4440 targettailmorphness = 1;
4447 if (creature == wolftype) {
4448 twitchdelay2 -= multiplier * 1.5;
4449 if (tailmorphend != 0)
4450 if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) {
4452 targettailmorphness = 1;
4456 if (tailmorphend != 5)
4457 if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) {
4459 targettailmorphness = 1;
4463 if (twitchdelay2 <= 0) {
4464 if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) {
4466 targettailmorphness = 1;
4469 if (tailmorphstart == 1 && tailmorphend == 1) {
4471 targettailmorphness = 1;
4474 if (tailmorphstart == 2 && tailmorphend == 2) {
4476 targettailmorphness = 1;
4479 if (tailmorphstart == 3 && tailmorphend == 3) {
4481 targettailmorphness = 1;
4484 if (tailmorphstart == 4 && tailmorphend == 4) {
4486 targettailmorphness = 1;
4493 unconscioustime = 0;
4495 if (dead == 1 || howactive == typesleeping) {
4496 unconscioustime += multiplier;
4497 //If unconscious, close eyes and mouth
4498 if (righthandmorphend != 0)
4499 righthandmorphness = 0;
4500 righthandmorphend = 0;
4501 targetrighthandmorphness = 1;
4503 if (lefthandmorphend != 0)
4504 lefthandmorphness = 0;
4505 lefthandmorphend = 0;
4506 targetlefthandmorphness = 1;
4508 if (headmorphend != 3 && headmorphend != 5)
4511 targetheadmorphness = 1;
4515 if (howactive > typesleeping) {
4518 if (bloodtoggle && !bled) {
4519 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4521 if (bloodtoggle && !bled)
4522 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4523 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4524 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4528 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4533 if (dead == 2 || howactive > typesleeping) {
4534 //If dead, open mouth and hands
4535 if (righthandmorphend != 0)
4536 righthandmorphness = 0;
4537 righthandmorphend = 0;
4538 targetrighthandmorphness = 1;
4540 if (lefthandmorphend != 0)
4541 lefthandmorphness = 0;
4542 lefthandmorphend = 0;
4543 targetlefthandmorphness = 1;
4545 if (headmorphend != 2)
4548 targetheadmorphness = 1;
4551 if (stunned > 0 && !dead && headmorphend != 2) {
4552 if (headmorphend != 4)
4555 targetheadmorphness = 1;
4558 if (damage > damagetolerance && !dead) {
4561 unconscioustime = 0;
4563 if (creature == wolftype) {
4564 award_bonus(0, Wolfbonus);
4569 if (weaponactive != -1) {
4570 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4571 weapons[weaponids[0]].velocity.x += .01;
4574 weaponids[0] = weaponids[num_weapons];
4575 if (weaponstuck == num_weapons)
4579 for (unsigned i = 0; i < Person::players.size(); i++) {
4580 Person::players[i]->wentforweapon = 0;
4586 if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) {
4595 damage -= multiplier * 13;
4597 permanentdamage -= multiplier * 4;
4598 if (isIdle() || isCrouch()) {
4600 permanentdamage -= multiplier * 4;
4604 if (permanentdamage < 0)
4605 permanentdamage = 0;
4606 if (superpermanentdamage < 0)
4607 superpermanentdamage = 0;
4608 if (permanentdamage < superpermanentdamage) {
4609 permanentdamage = superpermanentdamage;
4611 if (damage < permanentdamage) {
4612 damage = permanentdamage;
4614 if (dead == 1 && damage < damagetolerance) {
4618 for (int i = 0; i < skeleton.num_joints; i++) {
4619 skeleton.joints[i].velocity = 0;
4622 if (permanentdamage > damagetolerance && dead != 2) {
4625 if (weaponactive != -1) {
4626 weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale);
4627 weapons[weaponids[0]].velocity.x += .01;
4630 weaponids[0] = weaponids[num_weapons];
4631 if (weaponstuck == num_weapons)
4635 for (unsigned i = 0; i < Person::players.size(); i++) {
4636 Person::players[i]->wentforweapon = 0;
4642 if (!dead && creature == wolftype) {
4643 award_bonus(0, Wolfbonus);
4646 if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance)
4647 award_bonus(id, touchofdeath);
4648 if (id != 0 && unconscioustime > .1) {
4656 emit_sound_at(breaksound, coords);
4659 if (skeleton.free == 1) {
4661 pause_sound(whooshsound);
4664 //If knocked over, open hands and close mouth
4665 if (righthandmorphend != 0)
4666 righthandmorphness = 0;
4667 righthandmorphend = 0;
4668 targetrighthandmorphness = 1;
4670 if (lefthandmorphend != 0)
4671 lefthandmorphness = 0;
4672 lefthandmorphend = 0;
4673 targetlefthandmorphness = 1;
4675 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) {
4676 if (headmorphend != 0)
4679 targetheadmorphness = 1;
4683 skeleton.DoGravity(&scale);
4685 damageamount = skeleton.DoConstraints(&coords, &scale) * 5;
4686 if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1))
4687 award_bonus(id, deepimpact);
4688 DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3));
4692 for (j = 0; j < skeleton.num_joints; j++) {
4693 average += skeleton.joints[j].position;
4697 coords += average * scale;
4698 for (j = 0; j < skeleton.num_joints; j++) {
4699 skeleton.joints[j].position -= average;
4701 average /= multiplier;
4704 for (int i = 0; i < skeleton.num_joints; i++) {
4705 velocity += skeleton.joints[i].velocity * scale;
4707 velocity /= skeleton.num_joints;
4709 if (!isnormal(velocity.x) && velocity.x) {
4713 if (findLength(&average) < 10 && dead && skeleton.free) {
4714 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4715 if (skeleton.longdead > 2000) {
4716 if (skeleton.longdead > 6000) {
4718 pause_sound(whooshsound);
4723 if (dead == 2 && bloodloss < damagetolerance) {
4725 headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords;
4727 if (bloodtoggle && !bled) {
4728 terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0);
4730 if (bloodtoggle && !bled)
4731 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4732 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4733 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4734 float size = .2 * 1.2;
4737 objects.model[j].MakeDecal(blooddecal, &point, &size, &opacity, &yaw);
4741 if (dead == 2 && bloodloss >= damagetolerance) {
4743 headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords;
4746 if (bloodtoggle && !bled) {
4747 terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0);
4749 if (bloodtoggle && !bled)
4750 for (l = 0; l < terrain.patchobjectnum[whichpatchx][whichpatchz]; l++) {
4751 j = terrain.patchobjects[whichpatchx][whichpatchz][l];
4752 XYZ point = DoRotation(headpoint - objects.position[j], 0, -objects.yaw[j], 0);
4756 objects.model[j].MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw);
4763 if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) {
4764 bool canrecover = 1;
4765 XYZ startpoint, endpoint, colpoint, colviewer, coltarget;
4766 startpoint = coords;
4769 if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1)
4771 if (velocity.y < -30)
4773 for (i = 0; i < objects.numobjects; i++) {
4774 if (objects.type[i] != treeleavestype && objects.type[i] != bushtype && objects.type[i] != firetype) {
4775 colviewer = startpoint;
4776 coltarget = endpoint;
4777 if (objects.model[i].LineCheck(&colviewer, &coltarget, &colpoint, &objects.position[i], &objects.yaw[i]) != -1)
4786 terrainnormal = jointPos(groin) - jointPos(abdomen);
4787 if (joint(groin).locked && joint(abdomen).locked) {
4788 terrainnormal = jointPos(groin) - jointPos(abdomen);
4789 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4791 if (joint(abdomen).locked && joint(neck).locked) {
4792 terrainnormal = jointPos(abdomen) - jointPos(neck);
4793 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4795 if (joint(groin).locked && joint(neck).locked) {
4796 terrainnormal = jointPos(groin) - jointPos(neck);
4797 middle = (jointPos(groin) + jointPos(neck)) / 2;
4799 Normalise(&terrainnormal);
4801 targetyaw = -asin(0 - terrainnormal.x);
4802 targetyaw *= 360 / 6.28;
4803 if (terrainnormal.z < 0)
4804 targetyaw = 180 - targetyaw;
4808 animTarget = flipanim;
4809 crouchtogglekeydown = 1;
4814 animCurrent = tempanim;
4818 for (int i = 0; i < skeleton.num_joints; i++) {
4819 tempanimation.position[i][0] = skeleton.joints[i].position;
4820 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4825 if (findLength(&average) < 10 && !dead && skeleton.free) {
4826 skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier;
4827 if (skeleton.longdead > (damage + 500) * 1.5) {
4829 pause_sound(whooshsound);
4835 terrainnormal = jointPos(groin) - jointPos(abdomen);
4836 if (joint(groin).locked && joint(abdomen).locked) {
4837 terrainnormal = jointPos(groin) - jointPos(abdomen);
4838 middle = (jointPos(groin) + jointPos(abdomen)) / 2;
4840 if (joint(abdomen).locked && joint(neck).locked) {
4841 terrainnormal = jointPos(abdomen) - jointPos(neck);
4842 middle = (jointPos(neck) + jointPos(abdomen)) / 2;
4844 if (joint(groin).locked && joint(neck).locked) {
4845 terrainnormal = jointPos(groin) - jointPos(neck);
4846 middle = (jointPos(groin) + jointPos(neck)) / 2;
4848 Normalise(&terrainnormal);
4850 targetyaw = -asin(0 - terrainnormal.x);
4851 targetyaw *= 360 / 6.28;
4852 if (terrainnormal.z < 0)
4853 targetyaw = 180 - targetyaw;
4856 targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1;
4859 if (skeleton.forward.y < 0) {
4860 animTarget = getupfrombackanim;
4864 if (skeleton.forward.y > -.3) {
4865 animTarget = getupfromfrontanim;
4873 if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) {
4874 animTarget = rollanim;
4875 targetyaw = lookyaw;
4892 if ( !leftkeydown && !rightkeydown)
4899 if (abs(targettilt2) > 50)
4901 animCurrent = tempanim;
4904 tilt2 = targettilt2;
4906 if (middle.y > 0 && animTarget != rollanim)
4907 targetoffset.y = middle.y + 1;
4909 for (int i = 0; i < skeleton.num_joints; i++) {
4910 tempanimation.position[i][0] = skeleton.joints[i].position;
4911 tempanimation.position[i][0] = DoRotation(tempanimation.position[i][0], 0, -yaw, 0);
4918 if (num_weapons > 0)
4919 if (weapons[0].getType() == staff)
4921 if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) {
4922 if (velocity.y > -30) {
4924 tempvelocity = velocity;
4925 Normalise(&tempvelocity);
4926 targetyaw = -asin(0 - tempvelocity.x);
4927 targetyaw *= 360 / 6.28;
4929 targetyaw = 180 - targetyaw;
4933 if (dotproduct(&skeleton.forward, &tempvelocity) < 0) {
4934 animTarget = rollanim;
4937 animTarget = backhandspringanim;
4943 emit_sound_at(movewhooshsound, coords, 128.);
4945 animCurrent = animTarget;
4946 frameCurrent = frameTarget - 1;
4958 if (skeleton.freefall == 0)
4963 if (aitype != passivetype || skeleton.free == 1)
4964 if (findLengthfast(&velocity) > .1)
4965 for (i = 0; i < objects.numobjects; i++) {
4966 if (objects.type[i] == firetype)
4967 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) {
4969 if (!objects.onfire[i]) {
4970 emit_sound_at(firestartsound, objects.position[i]);
4972 objects.onfire[i] = 1;
4975 if (objects.onfire[i]) {
4980 if (objects.type[i] == bushtype)
4981 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) {
4983 if (!objects.onfire[i]) {
4984 emit_sound_at(firestartsound, objects.position[i]);
4986 objects.onfire[i] = 1;
4990 if (objects.onfire[i]) {
4994 if (objects.messedwith[i] <= 0) {
4998 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5001 envsound[numenvsounds] = coords;
5002 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5003 envsoundlife[numenvsounds] = .4;
5008 if (environment == grassyenvironment)
5009 howmany = findLength(&velocity) * 4;
5010 if (environment == snowyenvironment)
5011 howmany = findLength(&velocity) * 2;
5013 if (environment != desertenvironment)
5014 for (j = 0; j < howmany; j++) {
5015 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5016 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5017 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5020 pos.x += float(abs(Random() % 100) - 50) / 200;
5021 pos.y += float(abs(Random() % 100) - 50) / 200;
5022 pos.z += float(abs(Random() % 100) - 50) / 200;
5023 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);
5024 Sprite::setLastSpriteSpecial(1);
5026 howmany = findLength(&velocity) * 4;
5028 if (environment == snowyenvironment)
5029 for (j = 0; j < howmany; j++) {
5030 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5031 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5032 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5035 pos.x += float(abs(Random() % 100) - 50) / 200;
5036 pos.y += float(abs(Random() % 100) - 50) / 200;
5037 pos.z += float(abs(Random() % 100) - 50) / 200;
5038 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5039 Sprite::setLastSpriteSpecial(2);
5042 objects.rotx[i] += velocity.x * multiplier * 6;
5043 objects.roty[i] += velocity.z * multiplier * 6;
5044 objects.messedwith[i] = .5;
5047 if (objects.type[i] == treeleavestype && environment != desertenvironment) {
5048 if (objects.pitch[i] == 0)
5051 tempcoord = coords - objects.position[i];
5052 tempcoord = DoRotation(tempcoord, 0, -objects.yaw[i], 0);
5053 tempcoord = DoRotation(tempcoord, -objects.pitch[i], 0, 0);
5054 tempcoord += objects.position[i];
5056 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]) {
5057 if (objects.messedwith[i] <= 0) {
5061 emit_sound_at(bushrustle, coords, 40 * findLength(&velocity));
5064 envsound[numenvsounds] = coords;
5065 envsoundvol[numenvsounds] = 4 * findLength(&velocity);
5066 envsoundlife[numenvsounds] = .4;
5071 if (environment == grassyenvironment)
5072 howmany = findLength(&velocity) * 4;
5073 if (environment == snowyenvironment)
5074 howmany = findLength(&velocity) * 2;
5076 if (environment != desertenvironment)
5077 for (j = 0; j < howmany; j++) {
5078 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5079 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5080 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5082 pos += velocity * .1;
5084 pos.x += float(abs(Random() % 100) - 50) / 150;
5085 pos.y += float(abs(Random() % 100) - 50) / 150;
5086 pos.z += float(abs(Random() % 100) - 50) / 150;
5087 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);
5088 Sprite::setLastSpriteSpecial(1);
5090 howmany = findLength(&velocity) * 4;
5092 if (environment == snowyenvironment)
5093 for (j = 0; j < howmany; j++) {
5094 tempvel.x = float(abs(Random() % 100) - 50) / 20;
5095 tempvel.y = float(abs(Random() % 100) - 50) / 20;
5096 tempvel.z = float(abs(Random() % 100) - 50) / 20;
5098 pos += velocity * .1;
5100 pos.x += float(abs(Random() % 100) - 50) / 150;
5101 pos.y += float(abs(Random() % 100) - 50) / 150;
5102 pos.z += float(abs(Random() % 100) - 50) / 150;
5103 Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1);
5104 Sprite::setLastSpriteSpecial(2);
5107 objects.messedwith[i] = .5;
5112 if (!skeleton.free) {
5115 if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype)
5118 if (aitype != passivetype && victim->skeleton.free && !victim->dead)
5120 if (tutoriallevel == 1 && id != 0)
5122 if (play && aitype != playercontrolled) {
5123 int whichsound = -1;
5124 i = abs(Random() % 4);
5125 if (speechdelay <= 0) {
5126 if (creature == rabbittype) {
5128 whichsound = rabbitchitter;
5130 whichsound = rabbitchitter2;
5132 if (creature == wolftype) {
5134 whichsound = growlsound;
5136 whichsound = growl2sound;
5141 if (whichsound != -1) {
5142 emit_sound_at(whichsound, coords);
5146 if (animTarget == staggerbackhighanim)
5148 if (animTarget == staggerbackhardanim)
5150 staggerdelay -= multiplier;
5151 if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim)
5153 if (velocity.y < -30 && animTarget == jumpdownanim)
5155 if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) {
5156 animTarget = getIdle();
5160 weaponmissdelay -= multiplier;
5161 highreversaldelay -= multiplier;
5162 lowreversaldelay -= multiplier;
5163 lastcollide -= multiplier;
5164 skiddelay -= multiplier;
5165 if (!isnormal(velocity.x) && velocity.x) {
5168 if (!isnormal(targettilt) && targettilt) {
5171 if (!isnormal(targettilt2) && targettilt2) {
5174 if (!isnormal(targetyaw) && targetyaw) {
5178 if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) {
5179 //open hands and close mouth
5180 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5181 righthandmorphness = 0;
5182 righthandmorphend = 0;
5183 targetrighthandmorphness = 1;
5186 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5187 lefthandmorphness = 0;
5188 lefthandmorphend = 0;
5189 targetlefthandmorphness = 1;
5192 if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) {
5195 targetheadmorphness = 1;
5199 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) {
5200 //open hands and mouth
5201 if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) {
5202 righthandmorphness = 0;
5203 righthandmorphend = 0;
5204 targetrighthandmorphness = 1;
5207 if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) {
5208 lefthandmorphness = 0;
5209 lefthandmorphend = 0;
5210 targetlefthandmorphness = 1;
5213 if (headmorphend != 1 && headmorphness == targetheadmorphness) {
5216 targetheadmorphness = 1;
5220 if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) {
5221 //close hands and mouth
5222 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5223 righthandmorphness = 0;
5224 righthandmorphend = 1;
5225 targetrighthandmorphness = 1;
5228 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5229 lefthandmorphness = 0;
5230 lefthandmorphend = 1;
5231 targetlefthandmorphness = 1;
5234 if (headmorphend != 0 && headmorphness == targetheadmorphness) {
5237 targetheadmorphness = 1;
5241 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) {
5242 //close hands and yell
5243 if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) {
5244 righthandmorphness = 0;
5245 righthandmorphend = 1;
5246 targetrighthandmorphness = 1;
5249 if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) {
5250 lefthandmorphness = 0;
5251 lefthandmorphend = 1;
5252 targetlefthandmorphness = 1;
5255 if (headmorphend != 2 && headmorphness == targetheadmorphness) {
5258 targetheadmorphness = 1;
5265 if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) &&
5266 (victim->aitype != searchtype) && (aitype != passivetype) &&
5267 (aitype != searchtype) && (victim->id < Person::players.size())) {
5268 behind = (normaldotproduct(facing, coords - victim->coords) > 0);
5272 if (!dead && animTarget != hurtidleanim)
5273 if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) {
5274 if (headmorphend != 4 || headmorphness == targetheadmorphness) {
5277 targetheadmorphness = 1;
5281 if (weaponactive != -1) {
5282 if (weapons[weaponids[weaponactive]].getType() != staff) {
5283 righthandmorphstart = 1;
5284 righthandmorphend = 1;
5286 if (weapons[weaponids[weaponactive]].getType() == staff) {
5287 righthandmorphstart = 2;
5288 righthandmorphend = 2;
5290 targetrighthandmorphness = 1;
5293 terrainnormal = terrain.getNormal(coords.x, coords.z);
5295 if (animation[animTarget].attack != reversal) {
5296 if (!isnormal(coords.x))
5304 flatfacing = DoRotation(flatfacing, 0, yaw, 0);
5305 facing = flatfacing;
5306 ReflectVector(&facing, terrainnormal);
5309 if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) {
5311 targettilt2 = -facing.y * 20;
5316 if (!isRun() && !animation[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim)
5318 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5319 flatvelocity = velocity;
5321 flatvelspeed = findLength(&flatvelocity);
5322 targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity);
5323 targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity);
5328 if (targettilt > 25)
5330 if (targettilt < -25)
5334 if (targettilt2 > 45)
5336 if (targettilt2 < -45)
5338 if (abs(tilt2 - targettilt2) < multiplier * 400)
5339 tilt2 = targettilt2;
5340 else if (tilt2 > targettilt2) {
5341 tilt2 -= multiplier * 400;
5342 } else if (tilt2 < targettilt2) {
5343 tilt2 += multiplier * 400;
5345 if (!animation[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) {
5352 if (!isnormal(targettilt) && targettilt) {
5355 if (!isnormal(targettilt2) && targettilt2) {
5360 if (animTarget == rabbittackleanim) {
5361 velocity += facing * multiplier * speed * 700 * scale;
5362 velspeed = findLength(&velocity);
5363 if (velspeed > speed * 65 * scale) {
5364 velocity /= velspeed;
5365 velspeed = speed * 65 * scale;
5366 velocity *= velspeed;
5368 velocity.y += gravity * multiplier * 20;
5369 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5370 velspeed = findLength(&velocity);
5371 velocity = flatfacing * velspeed;
5373 if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) {
5374 if (isRun() || animTarget == rabbitkickanim) {
5375 velocity += facing * multiplier * speed * 700 * scale;
5376 velspeed = findLength(&velocity);
5377 if (velspeed > speed * 45 * scale) {
5378 velocity /= velspeed;
5379 velspeed = speed * 45 * scale;
5380 velocity *= velspeed;
5382 velocity.y += gravity * multiplier * 20;
5383 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5384 velspeed = findLength(&velocity);
5385 if (velspeed < speed * 30 * scale)
5386 velspeed = speed * 30 * scale;
5387 velocity = flatfacing * velspeed;
5389 } else if (isRun()) {
5390 velocity += facing * multiplier * speed * 700 * scale;
5391 velspeed = findLength(&velocity);
5392 if (creature == rabbittype) {
5393 if (velspeed > speed * 55 * scale) {
5394 velocity /= velspeed;
5395 velspeed = speed * 55 * scale;
5396 velocity *= velspeed;
5399 if (creature == wolftype) {
5400 if (velspeed > speed * 75 * scale) {
5401 velocity /= velspeed;
5402 velspeed = speed * 75 * scale;
5403 velocity *= velspeed;
5406 velocity.y += gravity * multiplier * 20;
5407 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5408 velspeed = findLength(&velocity);
5409 velocity = flatfacing * velspeed;
5412 if (animTarget == rollanim && animation[animTarget].label[frameTarget] != 6) {
5413 velocity += facing * multiplier * speed * 700 * scale;
5414 velspeed = findLength(&velocity);
5415 if (velspeed > speed * 45 * scale) {
5416 velocity /= velspeed;
5417 velspeed = speed * 45 * scale;
5418 velocity *= velspeed;
5420 velocity.y += gravity * multiplier * 20;
5421 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5422 velspeed = findLength(&velocity);
5423 velocity = flatfacing * velspeed;
5426 if (animTarget == sneakanim || animTarget == walkanim) {
5427 velocity += facing * multiplier * speed * 700 * scale;
5428 velspeed = findLength(&velocity);
5429 if (velspeed > speed * 12 * scale) {
5430 velocity /= velspeed;
5431 velspeed = speed * 12 * scale;
5432 velocity *= velspeed;
5434 velocity.y += gravity * multiplier * 20;
5435 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5436 velspeed = findLength(&velocity);
5437 velocity = flatfacing * velspeed;
5440 if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) {
5441 velocity += facing * multiplier * speed * 700 * scale;
5442 velspeed = findLength(&velocity);
5443 if (velspeed > speed * 2 * scale) {
5444 velocity /= velspeed;
5445 velspeed = speed * 2 * scale;
5446 velocity *= velspeed;
5448 velocity.y += gravity * multiplier * 20;
5449 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5450 velspeed = findLength(&velocity);
5451 velocity = flatfacing * velspeed;
5455 if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) {
5456 velocity -= facing * multiplier * speed * 700 * scale;
5457 velspeed = findLength(&velocity);
5458 if (velspeed > speed * 2 * scale) {
5459 velocity /= velspeed;
5460 velspeed = speed * 2 * scale;
5461 velocity *= velspeed;
5463 velocity.y += gravity * multiplier * 20;
5464 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5465 velspeed = findLength(&velocity);
5466 velocity = flatfacing * velspeed * -1;
5469 if (animTarget == fightsidestep) {
5470 velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0);
5471 velspeed = findLength(&velocity);
5472 if (velspeed > speed * 12 * scale) {
5473 velocity /= velspeed;
5474 velspeed = speed * 12 * scale;
5475 velocity *= velspeed;
5477 velocity.y += gravity * multiplier * 20;
5478 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5479 velspeed = findLength(&velocity);
5480 velocity = DoRotation(flatfacing * velspeed, 0, -90, 0);
5483 if (animTarget == staggerbackhighanim) {
5484 coords -= facing * multiplier * speed * 16 * scale;
5487 if (animTarget == staggerbackhardanim && animation[staggerbackhardanim].label[frameTarget] != 6) {
5488 coords -= facing * multiplier * speed * 20 * scale;
5492 if (animTarget == backhandspringanim) {
5493 //coords-=facing*multiplier*50*scale;
5494 velocity += facing * multiplier * speed * 700 * scale * -1;
5495 velspeed = findLength(&velocity);
5496 if (velspeed > speed * 50 * scale) {
5497 velocity /= velspeed;
5498 velspeed = speed * 50 * scale;
5499 velocity *= velspeed;
5501 velocity.y += gravity * multiplier * 20;
5502 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5503 velspeed = findLength(&velocity);
5504 velocity = flatfacing * velspeed * -1;
5506 if (animTarget == dodgebackanim) {
5507 //coords-=facing*multiplier*50*scale;
5508 velocity += facing * multiplier * speed * 700 * scale * -1;
5509 velspeed = findLength(&velocity);
5510 if (velspeed > speed * 60 * scale) {
5511 velocity /= velspeed;
5512 velspeed = speed * 60 * scale;
5513 velocity *= velspeed;
5515 velocity.y += gravity * multiplier * 20;
5516 ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z));
5517 velspeed = findLength(&velocity);
5518 velocity = flatfacing * velspeed * -1;
5521 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5522 velspeed = findLength(&velocity);
5526 if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) {
5527 velocity.y += gravity * multiplier;
5530 if (animTarget != climbanim && animTarget != hanganim && !isWallJump())
5531 coords += velocity * multiplier;
5533 if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
5534 if (isFlip() && animation[animTarget].label[frameTarget] == 7)
5537 if (animTarget == jumpupanim) {
5539 animTarget = getIdle();
5546 pause_sound(whooshsound);
5547 OPENAL_SetVolume(channels[whooshsound], 0);
5550 if (animTarget == jumpdownanim || isFlip()) {
5551 if (isFlip())jumppower = -4;
5552 animTarget = getLanding();
5553 emit_sound_at(landsound, coords, 128.);
5556 envsound[numenvsounds] = coords;
5557 envsoundvol[numenvsounds] = 16;
5558 envsoundlife[numenvsounds] = .4;
5564 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump())
5565 coords.y += gravity * multiplier * 2;
5566 if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) {
5567 coords.y = terrain.getHeight(coords.x, coords.z);
5572 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)) {
5573 velspeed = findLength(&velocity);
5575 if (velspeed < multiplier * 300 * scale) {
5578 velocity -= velocity / velspeed * multiplier * 300 * scale;
5579 if (velspeed > 5 && (isLanding() || isLandhard())) {
5580 skiddingdelay += multiplier;
5581 if (skiddelay <= 0) {
5591 velspeed = findLength(&velocity);
5593 if (velspeed < multiplier * 600 * scale) {
5596 velocity -= velocity / velspeed * multiplier * 600 * scale;
5598 if (velspeed > 5 && (isLanding() || isLandhard())) {
5599 skiddingdelay += multiplier;
5600 if (skiddelay <= 0) {
5609 if (skiddingdelay < 0)
5610 skiddingdelay += multiplier;
5611 if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) {
5613 if (!onterrain || environment == grassyenvironment) {
5614 emit_sound_at(skidsound, coords, 128 * velspeed / 10);
5616 emit_sound_at(snowskidsound, coords, 128 * velspeed / 10);
5620 if (animation[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) {
5621 terrainnormal = victim->coords - coords;
5622 Normalise(&terrainnormal);
5623 targetyaw = -asin(0 - terrainnormal.x);
5624 targetyaw *= 360 / 6.28;
5625 if (terrainnormal.z < 0)
5626 targetyaw = 180 - targetyaw;
5627 targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70;
5630 if (animation[animTarget].attack == reversal && animTarget != rabbittacklinganim) {
5631 targetyaw = victim->targetyaw;
5633 if (animTarget == rabbittacklinganim) {
5634 coords = victim->coords;
5637 skeleton.oldfree = skeleton.free;
5641 midterrain.x = terrain.size * terrain.scale / 2;
5642 midterrain.z = terrain.size * terrain.scale / 2;
5643 if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) {
5645 tempposit = coords - midterrain;
5647 Normalise(&tempposit);
5648 tempposit *= (terrain.size * terrain.scale / 2 - viewdistance);
5649 coords.x = tempposit.x + midterrain.x;
5650 coords.z = tempposit.z + midterrain.z;
5656 * inverse kinematics helper function
5658 void IKHelper(Person *p, float interp)
5660 XYZ point, change, change2;
5661 float heightleft, heightright;
5663 // TODO: implement localToWorld and worldToLocal
5664 // but keep in mind it won't be the same math if player is ragdolled or something
5665 // - localToWorldStanding / worldToLocalStanding (or crouching or...?)
5666 // then comb through code for places where to use it
5668 // point = localToWorld(jointPos(leftfoot))
5669 point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords;
5670 // adjust height of foot
5671 heightleft = terrain.getHeight(point.x, point.z) + .04;
5672 point.y = heightleft;
5673 change = p->jointPos(leftankle) - p->jointPos(leftfoot);
5674 change2 = p->jointPos(leftknee) - p->jointPos(leftfoot);
5675 // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp)
5676 p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp);
5677 // move ankle along with foot
5678 p->jointPos(leftankle) = p->jointPos(leftfoot) + change;
5679 // average knee pos between old and new pos
5680 p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2;
5682 // do same as above for right leg
5683 point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords;
5684 heightright = terrain.getHeight(point.x, point.z) + .04;
5685 point.y = heightright;
5686 change = p->jointPos(rightankle) - p->jointPos(rightfoot);
5687 change2 = p->jointPos(rightknee) - p->jointPos(rightfoot);
5688 p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp);
5689 p->jointPos(rightankle) = p->jointPos(rightfoot) + change;
5690 p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2;
5692 // fix up skeleton now that we've moved body parts?
5693 p->skeleton.DoConstraints(&p->coords, &p->scale);
5700 int Person::DrawSkeleton()
5702 int oldplayerdetail;
5703 if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) {
5704 if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) {
5714 glAlphaFunc(GL_GREATER, 0.0001);
5716 float terrainheight;
5720 if (!isnormal(tilt))
5722 if (!isnormal(tilt2))
5724 oldplayerdetail = playerdetail;
5726 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) {
5729 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) {
5732 if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) {
5737 if (playerdetail != oldplayerdetail) {
5739 normalsupdatedelay = 0;
5741 static float updatedelaychange;
5742 static float morphness;
5743 static float framemult;
5745 skeleton.FindForwards();
5746 if (howactive == typesittingwall) {
5747 skeleton.specialforward[1] = 0;
5748 skeleton.specialforward[1].z = 1;
5754 static int weaponattachmuscle;
5755 static int weaponrotatemuscle;
5756 static XYZ weaponpoint;
5757 static int start, endthing;
5758 if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) {
5759 if (!isSleeping() && !isSitting()) {
5760 // TODO: give these meaningful names
5761 const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard()
5762 || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim);
5763 const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard()
5764 || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim);
5766 if (onterrain && (cond1 && cond2) && !skeleton.free) {
5768 if (creature == wolftype)
5772 if (onterrain && (cond1 && !cond2) && !skeleton.free) {
5773 IKHelper(this, target);
5774 if (creature == wolftype)
5775 IKHelper(this, target);
5778 if (onterrain && (!cond1 && cond2) && !skeleton.free) {
5779 IKHelper(this, 1 - target);
5780 if (creature == wolftype)
5781 IKHelper(this, 1 - target);
5785 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()))
5788 targetheadyaw = -targetyaw;
5789 targetheadpitch = 0;
5790 if (animation[animTarget].attack == 3)
5791 targetheadyaw += 180;
5793 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
5794 skeleton.drawmodel.vertex[i] = 0;
5795 skeleton.drawmodel.vertex[i].y = 999;
5797 for (i = 0; i < skeleton.drawmodellow.vertexNum; i++) {
5798 skeleton.drawmodellow.vertex[i] = 0;
5799 skeleton.drawmodellow.vertex[i].y = 999;
5801 for (i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) {
5802 skeleton.drawmodelclothes.vertex[i] = 0;
5803 skeleton.drawmodelclothes.vertex[i].y = 999;
5805 for (int i = 0; i < skeleton.num_muscles; i++) {
5806 // convenience renames
5807 const int p1 = skeleton.muscles[i].parent1->label;
5808 const int p2 = skeleton.muscles[i].parent2->label;
5810 if ((skeleton.muscles[i].numvertices > 0 && playerdetail) || (skeleton.muscles[i].numverticeslow > 0 && !playerdetail)) {
5815 if (p1 == righthand || p2 == righthand) {
5816 morphness = righthandmorphness;
5817 start = righthandmorphstart;
5818 endthing = righthandmorphend;
5820 if (p1 == lefthand || p2 == lefthand) {
5821 morphness = lefthandmorphness;
5822 start = lefthandmorphstart;
5823 endthing = lefthandmorphend;
5825 if (p1 == head || p2 == head) {
5826 morphness = headmorphness;
5827 start = headmorphstart;
5828 endthing = headmorphend;
5830 if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) {
5831 morphness = chestmorphness;
5832 start = chestmorphstart;
5833 endthing = chestmorphend;
5835 if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) {
5836 morphness = tailmorphness;
5837 start = tailmorphstart;
5838 endthing = tailmorphend;
5841 skeleton.FindRotationMuscle(i, animTarget);
5842 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5843 glMatrixMode(GL_MODELVIEW);
5847 glRotatef(tilt2, 1, 0, 0);
5849 glRotatef(tilt, 0, 0, 1);
5852 glTranslatef(mid.x, mid.y, mid.z);
5854 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5855 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5857 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
5858 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
5860 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
5861 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
5863 if (playerdetail || skeleton.free == 3) {
5864 for (j = 0; j < skeleton.muscles[i].numvertices; j++) {
5865 XYZ &v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]];
5866 XYZ &v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]];
5867 glMatrixMode(GL_MODELVIEW);
5869 if (p1 == abdomen || p2 == abdomen)
5870 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionbody.x,
5871 (v0.y * (1 - morphness) + v1.y * morphness) * proportionbody.y,
5872 (v0.z * (1 - morphness) + v1.z * morphness) * proportionbody.z);
5873 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5874 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionarms.x,
5875 (v0.y * (1 - morphness) + v1.y * morphness) * proportionarms.y,
5876 (v0.z * (1 - morphness) + v1.z * morphness) * proportionarms.z);
5877 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5878 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionlegs.x,
5879 (v0.y * (1 - morphness) + v1.y * morphness) * proportionlegs.y,
5880 (v0.z * (1 - morphness) + v1.z * morphness) * proportionlegs.z);
5881 if (p1 == head || p2 == head)
5882 glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * proportionhead.x,
5883 (v0.y * (1 - morphness) + v1.y * morphness) * proportionhead.y,
5884 (v0.z * (1 - morphness) + v1.z * morphness) * proportionhead.z);
5885 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5886 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale;
5887 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale;
5888 skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale;
5892 if (!playerdetail || skeleton.free == 3) {
5893 for (j = 0; j < skeleton.muscles[i].numverticeslow; j++) {
5894 XYZ &v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]];
5895 glMatrixMode(GL_MODELVIEW);
5897 if (p1 == abdomen || p2 == abdomen)
5898 glTranslatef(v0.x * proportionbody.x,
5899 v0.y * proportionbody.y,
5900 v0.z * proportionbody.z);
5901 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5902 glTranslatef(v0.x * proportionarms.x,
5903 v0.y * proportionarms.y,
5904 v0.z * proportionarms.z);
5905 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5906 glTranslatef(v0.x * proportionlegs.x,
5907 v0.y * proportionlegs.y,
5908 v0.z * proportionlegs.z);
5909 if (p1 == head || p2 == head)
5910 glTranslatef(v0.x * proportionhead.x,
5911 v0.y * proportionhead.y,
5912 v0.z * proportionhead.z);
5914 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5915 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale;
5916 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale;
5917 skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale;
5923 if (skeleton.clothes && skeleton.muscles[i].numverticesclothes > 0) {
5924 mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2;
5926 glMatrixMode(GL_MODELVIEW);
5930 glRotatef(tilt2, 1, 0, 0);
5932 glRotatef(tilt, 0, 0, 1);
5933 glTranslatef(mid.x, mid.y, mid.z);
5934 skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1;
5935 glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0);
5937 skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2;
5938 glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1);
5940 skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3;
5941 glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0);
5943 for (j = 0; j < skeleton.muscles[i].numverticesclothes; j++) {
5944 XYZ &v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]];
5945 glMatrixMode(GL_MODELVIEW);
5947 if (p1 == abdomen || p2 == abdomen)
5948 glTranslatef(v0.x * proportionbody.x,
5949 v0.y * proportionbody.y,
5950 v0.z * proportionbody.z);
5951 if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow)
5952 glTranslatef(v0.x * proportionarms.x,
5953 v0.y * proportionarms.y,
5954 v0.z * proportionarms.z);
5955 if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee)
5956 glTranslatef(v0.x * proportionlegs.x,
5957 v0.y * proportionlegs.y,
5958 v0.z * proportionlegs.z);
5959 if (p1 == head || p2 == head)
5960 glTranslatef(v0.x * proportionhead.x,
5961 v0.y * proportionhead.y,
5962 v0.z * proportionhead.z);
5963 glGetFloatv(GL_MODELVIEW_MATRIX, M);
5964 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale;
5965 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale;
5966 skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale;
5971 updatedelay = 1 + (float)(Random() % 100) / 1000;
5973 if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) {
5974 normalsupdatedelay = 1;
5975 if (playerdetail || skeleton.free == 3)
5976 skeleton.drawmodel.CalculateNormals(0);
5977 if (!playerdetail || skeleton.free == 3)
5978 skeleton.drawmodellow.CalculateNormals(0);
5979 if (skeleton.clothes)
5980 skeleton.drawmodelclothes.CalculateNormals(0);
5982 if (playerdetail || skeleton.free == 3)
5983 skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
5984 if (!playerdetail || skeleton.free == 3)
5985 skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
5986 if (skeleton.clothes) {
5987 skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
5992 updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1);
5993 if (updatedelaychange > -realmultiplier * 30)
5994 updatedelaychange = -realmultiplier * 30;
5995 if (updatedelaychange > -framemult * 4)
5996 updatedelaychange = -framemult * 4;
5997 if (skeleton.free == 1)
5998 updatedelaychange *= 6;
6000 updatedelaychange *= 8;
6001 updatedelay += updatedelaychange;
6003 glMatrixMode(GL_MODELVIEW);
6005 glTranslatef(coords.x, coords.y - .02, coords.z);
6006 if (!skeleton.free) {
6007 glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale);
6008 glRotatef(yaw, 0, 1, 0);
6012 glColor4f(.4, 1, .4, 1);
6013 glDisable(GL_LIGHTING);
6014 glDisable(GL_TEXTURE_2D);
6017 for (i = 0; i < skeleton.drawmodel.vertexNum; i++) {
6018 XYZ &v0 = skeleton.drawmodel.vertex[i];
6019 glVertex3f(v0.x, v0.y, v0.z);
6025 for (i = 0; i < skeleton.drawmodel.TriangleNum; i++) {
6026 XYZ &v0 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]];
6027 XYZ &v1 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]];
6028 XYZ &v2 = skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]];
6029 glVertex3f(v0.x, v0.y, v0.z);
6030 glVertex3f(v1.x, v1.y, v1.z);
6031 glVertex3f(v1.x, v1.y, v1.z);
6032 glVertex3f(v2.x, v2.y, v2.z);
6033 glVertex3f(v2.x, v2.y, v2.z);
6034 glVertex3f(v0.x, v0.y, v0.z);
6040 terrainlight = terrain.getLighting(coords.x, coords.z);
6041 distance = distsq(&viewer, &coords);
6042 distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance;
6046 terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1;
6047 if (terrainheight < 1)
6049 if (terrainheight > 1.7)
6050 terrainheight = 1.7;
6053 glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance);
6054 glDisable(GL_BLEND);
6055 glAlphaFunc(GL_GREATER, 0.0001);
6056 glEnable(GL_TEXTURE_2D);
6058 glDisable(GL_TEXTURE_2D);
6059 glColor4f(.7, .35, 0, .5);
6061 glEnable(GL_LIGHTING);
6064 if (tutoriallevel && id != 0) {
6065 glColor4f(.7, .7, .7, 0.6);
6067 glEnable(GL_LIGHTING);
6069 if (canattack && cananger)
6070 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6071 glDisable(GL_TEXTURE_2D);
6072 glColor4f(1, 0, 0, 0.8);
6074 glMatrixMode(GL_TEXTURE);
6076 glTranslatef(0, -smoketex, 0);
6077 glTranslatef(-smoketex, 0, 0);
6081 if ((tutoriallevel && id != 0))
6082 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6084 skeleton.drawmodel.draw();
6087 if (!playerdetail) {
6088 if ((tutoriallevel && id != 0))
6089 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6091 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6094 if (!(animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed))
6095 if (tutoriallevel && id != 0) {
6097 glMatrixMode(GL_MODELVIEW);
6098 glEnable(GL_TEXTURE_2D);
6099 glColor4f(.7, .7, .7, 0.6);
6101 glEnable(GL_LIGHTING);
6103 if (canattack && cananger)
6104 if (animation[animTarget].attack == normalattack || animation[animTarget].attack == reversed) {
6105 glDisable(GL_TEXTURE_2D);
6106 glColor4f(1, 0, 0, 0.8);
6108 glMatrixMode(GL_TEXTURE);
6110 glTranslatef(0, -smoketex * .6, 0);
6111 glTranslatef(smoketex * .6, 0, 0);
6114 if ((tutoriallevel && id != 0))
6115 skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture);
6117 skeleton.drawmodel.draw();
6120 if (!playerdetail) {
6121 if ((tutoriallevel && id != 0))
6122 skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture);
6124 skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
6129 if (tutoriallevel && id != 0) {
6131 glMatrixMode(GL_MODELVIEW);
6132 glEnable(GL_TEXTURE_2D);
6134 if (skeleton.clothes) {
6138 skeleton.drawmodelclothes.draw();
6140 skeleton.drawmodelclothes.drawimmediate();
6146 if (num_weapons > 0) {
6147 for (k = 0; k < num_weapons; k++) {
6149 if (weaponactive == k) {
6150 if (weapons[i].getType() != staff) {
6151 for (j = 0; j < skeleton.num_muscles; j++) {
6152 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6153 weaponattachmuscle = j;
6156 for (j = 0; j < skeleton.num_muscles; j++) {
6157 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) {
6158 weaponrotatemuscle = j;
6161 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6162 if (creature == wolftype)
6163 weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3);
6165 if (weapons[i].getType() == staff) {
6166 for (j = 0; j < skeleton.num_muscles; j++) {
6167 if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].numvertices > 0) {
6168 weaponattachmuscle = j;
6171 for (j = 0; j < skeleton.num_muscles; j++) {
6172 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) {
6173 weaponrotatemuscle = j;
6176 //weaponpoint=jointPos(rightwrist);
6177 weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2;
6178 //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow));
6179 XYZ tempnormthing, vec1, vec2;
6180 vec1 = (jointPos(rightwrist) - jointPos(rightelbow));
6181 vec2 = (jointPos(rightwrist) - jointPos(rightshoulder));
6182 CrossProduct(&vec1, &vec2, &tempnormthing);
6183 Normalise(&tempnormthing);
6184 if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim)
6185 weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow));
6188 if (weaponactive != k && weaponstuck != k) {
6189 if (weapons[i].getType() == knife)
6190 weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35;
6191 if (weapons[i].getType() == sword)
6192 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6193 if (weapons[i].getType() == staff)
6194 weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33;
6195 for (j = 0; j < skeleton.num_muscles; j++) {
6196 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) {
6197 weaponrotatemuscle = j;
6201 if (weaponstuck == k) {
6202 if (weaponstuckwhere == 0)
6203 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8;
6205 weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8;
6206 for (j = 0; j < skeleton.num_muscles; j++) {
6207 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) {
6208 weaponrotatemuscle = j;
6212 if (skeleton.free) {
6213 weapons[i].position = weaponpoint * scale + coords;
6214 weapons[i].bigrotation = 0;
6215 weapons[i].bigtilt = 0;
6216 weapons[i].bigtilt2 = 0;
6218 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;
6219 weapons[i].bigrotation = yaw;
6220 weapons[i].bigtilt = tilt;
6221 weapons[i].bigtilt2 = tilt2;
6223 weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1;
6224 weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2;
6225 weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3;
6226 if (weaponactive == k) {
6227 if (weapons[i].getType() == knife) {
6228 weapons[i].smallrotation = 180;
6229 weapons[i].smallrotation2 = 0;
6230 if (isCrouch() || wasCrouch()) {
6231 weapons[i].smallrotation2 = 20;
6233 if (animTarget == hurtidleanim) {
6234 weapons[i].smallrotation2 = 50;
6236 if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) {
6237 XYZ temppoint1, temppoint2;
6240 temppoint1 = jointPos(righthand);
6241 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6242 distance = findDistance(&temppoint1, &temppoint2);
6243 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6244 weapons[i].rotation2 *= 360 / 6.28;
6247 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6248 weapons[i].rotation1 *= 360 / 6.28;
6249 weapons[i].rotation3 = 0;
6250 weapons[i].smallrotation = -90;
6251 weapons[i].smallrotation2 = 0;
6252 if (temppoint1.x > temppoint2.x)
6253 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6255 if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) {
6256 XYZ temppoint1, temppoint2;
6259 temppoint1 = jointPos(righthand);
6260 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6261 distance = findDistance(&temppoint1, &temppoint2);
6262 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6263 weapons[i].rotation2 *= 360 / 6.28;
6266 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6267 weapons[i].rotation1 *= 360 / 6.28;
6268 weapons[i].rotation3 = 0;
6269 weapons[i].smallrotation = 90;
6270 weapons[i].smallrotation2 = 0;
6271 if (temppoint1.x > temppoint2.x)
6272 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6274 if (animTarget == knifethrowanim) {
6275 weapons[i].smallrotation = 90;
6276 //weapons[i].smallrotation2=-90;
6277 weapons[i].smallrotation2 = 0;
6278 weapons[i].rotation1 = 0;
6279 weapons[i].rotation2 = 0;
6280 weapons[i].rotation3 = 0;
6282 if (animTarget == knifesneakattackanim && frameTarget < 5) {
6283 weapons[i].smallrotation = -90;
6284 weapons[i].rotation1 = 0;
6285 weapons[i].rotation2 = 0;
6286 weapons[i].rotation3 = 0;
6289 if (weapons[i].getType() == sword) {
6290 weapons[i].smallrotation = 0;
6291 weapons[i].smallrotation2 = 0;
6292 if (animTarget == knifethrowanim) {
6293 weapons[i].smallrotation = -90;
6294 weapons[i].smallrotation2 = 0;
6295 weapons[i].rotation1 = 0;
6296 weapons[i].rotation2 = 0;
6297 weapons[i].rotation3 = 0;
6299 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)) {
6300 XYZ temppoint1, temppoint2;
6303 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6304 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6305 distance = findDistance(&temppoint1, &temppoint2);
6306 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6307 weapons[i].rotation2 *= 360 / 6.28;
6310 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6311 weapons[i].rotation1 *= 360 / 6.28;
6312 weapons[i].rotation3 = 0;
6313 weapons[i].smallrotation = 90;
6314 weapons[i].smallrotation2 = 0;
6315 if (temppoint1.x > temppoint2.x)
6316 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6319 if (weapons[i].getType() == staff) {
6320 weapons[i].smallrotation = 100;
6321 weapons[i].smallrotation2 = 0;
6322 if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) {
6323 XYZ temppoint1, temppoint2;
6326 temppoint1 = animation[animCurrent].position[skeleton.jointlabels[righthand]][frameCurrent] * (1 - target) + animation[animTarget].position[skeleton.jointlabels[righthand]][frameTarget] * (target); //jointPos(righthand);
6327 temppoint2 = animation[animCurrent].weapontarget[frameCurrent] * (1 - target) + animation[animTarget].weapontarget[frameTarget] * (target);
6328 distance = findDistance(&temppoint1, &temppoint2);
6329 weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance);
6330 weapons[i].rotation2 *= 360 / 6.28;
6333 weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2));
6334 weapons[i].rotation1 *= 360 / 6.28;
6335 weapons[i].rotation3 = 0;
6336 weapons[i].smallrotation = 90;
6337 weapons[i].smallrotation2 = 0;
6338 if (temppoint1.x > temppoint2.x)
6339 weapons[i].rotation1 = 360 - weapons[i].rotation1;
6343 if (weaponactive != k && weaponstuck != k) {
6344 if (weapons[i].getType() == knife) {
6345 weapons[i].smallrotation = -70;
6346 weapons[i].smallrotation2 = 10;
6348 if (weapons[i].getType() == sword) {
6349 weapons[i].smallrotation = -100;
6350 weapons[i].smallrotation2 = -8;
6352 if (weapons[i].getType() == staff) {
6353 weapons[i].smallrotation = -100;
6354 weapons[i].smallrotation2 = -8;
6357 if (weaponstuck == k) {
6358 if (weaponstuckwhere == 0)
6359 weapons[i].smallrotation = 180;
6361 weapons[i].smallrotation = 0;
6362 weapons[i].smallrotation2 = 10;
6371 if (animation[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump())
6373 if (animCurrent != animTarget)
6375 if (skeleton.free == 2)
6384 int Person::SphereCheck(XYZ *p1, float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
6387 static float distance;
6388 static float olddistance;
6389 static int intersecting;
6390 static int firstintersecting;
6393 static XYZ start, end;
6394 static float slopethreshold = -.4;
6396 firstintersecting = -1;
6400 if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius)
6403 *p1 = DoRotation(*p1, 0, -*rotate, 0);
6404 for (i = 0; i < 4; i++) {
6405 for (j = 0; j < model->TriangleNum; j++) {
6406 if (model->facenormals[j].y <= slopethreshold) {
6408 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)));
6409 if (distance < radius) {
6410 point = *p1 - model->facenormals[j] * distance;
6411 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]]))
6414 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6415 &model->vertex[model->Triangles[j].vertex[1]],
6418 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
6419 &model->vertex[model->Triangles[j].vertex[2]],
6422 intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
6423 &model->vertex[model->Triangles[j].vertex[2]],
6426 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6430 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)) {
6431 p1->y = point.y + radius;
6432 if ((animTarget == jumpdownanim || isFlip())) {
6433 if (isFlip() && (frameTarget < 5 || animation[animTarget].label[frameTarget] == 7 || animation[animTarget].label[frameTarget] == 4))
6436 if (animTarget == jumpupanim) {
6438 animTarget = getIdle();
6445 pause_sound(whooshsound);
6446 OPENAL_SetVolume(channels[whooshsound], 0);
6449 if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) {
6452 animTarget = getLanding();
6453 emit_sound_at(landsound, coords, 128.);
6456 envsound[numenvsounds] = coords;
6457 envsoundvol[numenvsounds] = 16;
6458 envsoundlife[numenvsounds] = .4;
6466 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6467 olddistance = distance;
6468 firstintersecting = j;
6473 for (j = 0; j < model->TriangleNum; j++) {
6474 if (model->facenormals[j].y > slopethreshold) {
6477 start.y -= radius / 4;
6478 XYZ &v0 = model->vertex[model->Triangles[j].vertex[0]];
6479 XYZ &v1 = model->vertex[model->Triangles[j].vertex[1]];
6480 XYZ &v2 = model->vertex[model->Triangles[j].vertex[2]];
6481 distance = abs((model->facenormals[j].x * start.x)
6482 + (model->facenormals[j].y * start.y)
6483 + (model->facenormals[j].z * start.z)
6484 - ((model->facenormals[j].x * v0.x)
6485 + (model->facenormals[j].y * v0.y)
6486 + (model->facenormals[j].z * v0.z)));
6487 if (distance < radius * .5) {
6488 point = start - model->facenormals[j] * distance;
6489 if (PointInTriangle( &point, model->facenormals[j], &v0, &v1, &v2))
6492 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2);
6494 intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6496 intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2);
6498 if (dotproduct(&model->facenormals[j], &end) > 0 && intersecting) {
6499 if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) {
6501 velocity -= DoRotation(model->facenormals[j], 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->facenormals[j], 0, *rotate, 0))); //(distance-radius*.5)/multiplier;
6502 if (findLengthfast(&start) < findLengthfast(&velocity))
6505 *p1 += model->facenormals[j] * (distance - radius * .5);
6508 if ((distance < olddistance || firstintersecting == -1) && intersecting) {
6509 olddistance = distance;
6510 firstintersecting = j;
6517 *p = DoRotation(*p, 0, *rotate, 0);
6520 *p1 = DoRotation(*p1, 0, *rotate, 0);
6522 return firstintersecting;
6525 void Person::takeWeapon(int weaponId)
6528 weapons[weaponId].owner = id;
6529 if (num_weapons > 0) {
6530 weaponids[num_weapons] = weaponids[0];
6533 weaponids[0] = weaponId;
6536 void Person::addClothes()
6538 if (numclothes > 0) {
6539 for (int i = 0; i < numclothes; i++) {
6546 bool Person::addClothes(const int& clothesId)
6549 const char* fileName = clothes[clothesId];
6551 GLubyte* array = &skeleton.skinText[0];
6555 bool opened = load_image(fileName, texture);
6560 float tintr = clothestintr[clothesId];
6561 float tintg = clothestintg[clothesId];
6562 float tintb = clothestintb[clothesId];
6564 if (tintr > 1) tintr = 1;
6565 if (tintg > 1) tintg = 1;
6566 if (tintb > 1) tintb = 1;
6568 if (tintr < 0) tintr = 0;
6569 if (tintg < 0) tintg = 0;
6570 if (tintb < 0) tintb = 0;
6572 int bytesPerPixel = texture.bpp / 8;
6576 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
6577 if (bytesPerPixel == 3)
6579 else if ((i + 1) % 4 == 0)
6580 alphanum = texture.data[i];
6581 if ((i + 1) % 4 || bytesPerPixel == 3) {
6583 texture.data[i] *= tintr;
6585 texture.data[i] *= tintg;
6587 texture.data[i] *= tintb;
6588 array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255);