/* Copyright (C) 2003, 2010 - Wolfire Games Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file) This file is part of Lugaru. Lugaru is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Lugaru is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Lugaru. If not, see <http://www.gnu.org/licenses/>. */ #include "Objects/Person.hpp" #include "Animation/Animation.hpp" #include "Audio/Sounds.hpp" #include "Audio/openal_wrapper.hpp" #include "Game.hpp" #include "Level/Awards.hpp" #include "Level/Dialog.hpp" #include "Tutorial.hpp" #include "Utils/Folders.hpp" extern float multiplier; extern Terrain terrain; extern float gravity; extern int environment; extern int detail; extern FRUSTUM frustum; extern XYZ viewer; extern float realmultiplier; extern int slomo; extern float slomodelay; extern bool cellophane; extern float texdetail; extern float realtexdetail; extern int bloodtoggle; extern bool autoslomo; extern float camerashake; extern float woozy; extern float viewdistance; extern float blackout; extern int difficulty; extern bool decalstoggle; extern float fadestart; extern bool freeze; extern bool winfreeze; extern bool showpoints; extern bool immediate; extern float smoketex; extern bool reversaltrain; extern bool canattack; extern bool cananger; extern float damagedealt; extern int hostile; extern float hostiletime; extern bool gamestarted; extern XYZ envsound[30]; extern float envsoundvol[30]; extern int numenvsounds; extern float envsoundlife[30]; extern XYZ windvector; std::vector<std::shared_ptr<Person>> Person::players; Person::Person() : whichpatchx(0) , whichpatchz(0) , animCurrent(bounceidleanim) , animTarget(bounceidleanim) , frameCurrent(0) , frameTarget(1) , oldanimCurrent(0) , oldanimTarget(0) , oldframeCurrent(0) , oldframeTarget(0) , howactive(typeactive) , parriedrecently(0) , superruntoggle(false) , lastattack(0) , lastattack2(0) , lastattack3(0) , currentoffset() , targetoffset() , offset() , target(0) , transspeed(0) , realoldcoords() , oldcoords() , coords() , velocity() , unconscioustime(0) , immobile(false) , velspeed(0) , targetyaw(0) , targetrot(0) , rot(0) , oldrot(0) , lookyaw(0) , lookpitch(0) , yaw(0) , pitch(0) , lowyaw(0) , tilt(0) , targettilt(0) , tilt2(0) , targettilt2(0) , rabbitkickenabled(false) , bloodloss(0) , bleeddelay(0) , skiddelay(0) , skiddingdelay(0) , deathbleeding(0) , tempdeltav(0) , damagetolerance(0) , damage(0) , permanentdamage(0) , superpermanentdamage(0) , lastcollide(0) , dead(0) , jumppower(5) , onground(false) , wentforweapon(0) , calcrot(false) , facing() , bleeding(0) , bleedx(0) , bleedy(0) , direction(0) , texupdatedelay(0) , headyaw(0) , headpitch(0) , targetheadyaw(0) , targetheadpitch(0) , onterrain(false) , pause(false) , grabdelay(0) , victim(nullptr) , hasvictim(false) , updatedelay(0) , normalsupdatedelay(0) , jumpstart(false) , forwardkeydown(false) , forwardstogglekeydown(false) , rightkeydown(false) , leftkeydown(false) , backkeydown(false) , jumpkeydown(false) , jumptogglekeydown(false) , crouchkeydown(false) , crouchtogglekeydown(false) , drawkeydown(false) , drawtogglekeydown(false) , throwkeydown(false) , throwtogglekeydown(false) , attackkeydown(false) , feint(false) , lastfeint(false) , headless(false) , crouchkeydowntime(0) , jumpkeydowntime(0) , freefall(false) , turnspeed(0) , aitype(passivetype) , aiupdatedelay(0) , losupdatedelay(0) , ally(0) , collide(0) , collided(-10) , avoidcollided(0) , loaded(false) , whichdirection(false) , whichdirectiondelay(0) , avoidsomething(false) , avoidwhere() , blooddimamount(0) , staggerdelay(0) , blinkdelay(0) , twitchdelay(0) , twitchdelay2(0) , twitchdelay3(0) , lefthandmorphness(0) , righthandmorphness(0) , headmorphness(0) , chestmorphness(0) , tailmorphness(0) , targetlefthandmorphness(0) , targetrighthandmorphness(0) , targetheadmorphness(1) , targetchestmorphness(0) , targettailmorphness(0) , lefthandmorphstart(0) , lefthandmorphend(0) , righthandmorphstart(0) , righthandmorphend(0) , headmorphstart(0) , headmorphend(0) , chestmorphstart(0) , chestmorphend(0) , tailmorphstart(0) , tailmorphend(0) , weaponmissdelay(0) , highreversaldelay(0) , lowreversaldelay(0) , creature(rabbittype) , id(0) , skeleton() , speed(0) , scale(-1) , power(0) , speedmult(0) , protectionhead(0) , protectionhigh(0) , protectionlow(0) , armorhead(0) , armorhigh(0) , armorlow(0) , metalhead(false) , metalhigh(false) , metallow(false) , landhard(false) , bled(false) , spurt(false) , onfire(false) , onfiredelay(0) , burnt(0) , flamedelay(0) , playerdetail(0) , num_weapons(0) , weaponactive(-1) , weaponstuck(-1) , weaponstuckwhere(0) , numwaypoints(0) , pausetime(0) , headtarget() , interestdelay(0) , finalfinaltarget() , finaltarget() , finalpathfindpoint(0) , targetpathfindpoint(0) , lastpathfindpoint(0) , lastpathfindpoint2(0) , lastpathfindpoint3(0) , lastpathfindpoint4(0) , waypoint(0) , lastseen() , lastseentime(0) , lastchecktime(0) , stunned(0) , surprised(0) , runninghowlong(0) , occluded(0) , lastoccluded(0) , laststanding(0) , escapednum(0) , speechdelay(0) , neckspurtdelay(0) , neckspurtparticledelay(0) , neckspurtamount(0) , whichskin(0) , rabbitkickragdoll(false) , tempanimation("Tempanim", lowheight, neutral) , jumpclimb(false) { damagetolerance = PersonType::types[creature].defaultDamageTolerance; setProportions(1, 1, 1, 1); } /* Read a person in tfile. Throws an error if it’s not valid */ Person::Person(FILE* tfile, int mapvers, unsigned i) : Person() { id = i; funpackf(tfile, "Bi Bi Bf Bf Bf Bi", &whichskin, &creature, &coords.x, &coords.y, &coords.z, &num_weapons); if (mapvers >= 5) { funpackf(tfile, "Bi", &howactive); } else { howactive = typeactive; } if (mapvers >= 3) { funpackf(tfile, "Bf", &scale); } else { scale = -1; } if (mapvers >= 11) { funpackf(tfile, "Bb", &immobile); } else { immobile = 0; } if (mapvers >= 12) { funpackf(tfile, "Bf", &yaw); } else { yaw = 0; } targetyaw = yaw; if (num_weapons < 0 || num_weapons > 5) { throw InvalidPersonException(); } if (num_weapons > 0 && num_weapons < 5) { for (int j = 0; j < num_weapons; j++) { weaponids[j] = weapons.size(); int type; funpackf(tfile, "Bi", &type); weapons.push_back(Weapon(type, id)); } } funpackf(tfile, "Bi", &numwaypoints); for (int j = 0; j < numwaypoints; j++) { funpackf(tfile, "Bf", &waypoints[j].x); funpackf(tfile, "Bf", &waypoints[j].y); funpackf(tfile, "Bf", &waypoints[j].z); if (mapvers >= 5) { funpackf(tfile, "Bi", &waypointtype[j]); } else { waypointtype[j] = wpkeepwalking; } } funpackf(tfile, "Bi", &waypoint); if (waypoint > (numwaypoints - 1)) { waypoint = 0; } funpackf(tfile, "Bf Bf Bf", &armorhead, &armorhigh, &armorlow); funpackf(tfile, "Bf Bf Bf", &protectionhead, &protectionhigh, &protectionlow); funpackf(tfile, "Bf Bf Bf", &metalhead, &metalhigh, &metallow); funpackf(tfile, "Bf Bf", &power, &speedmult); if (mapvers >= 4) { funpackf(tfile, "Bf Bf Bf Bf", &proportions[0], &proportions[1], &proportions[2], &proportions[3]); } else { setProportions(1, 1, 1, 1); } int numclothes; float tintr, tintg, tintb; funpackf(tfile, "Bi", &numclothes); for (int k = 0; k < numclothes; k++) { char clothespath[256]; int templength; funpackf(tfile, "Bi", &templength); for (int l = 0; l < templength; l++) { funpackf(tfile, "Bb", &clothespath[l]); } clothespath[templength] = '\0'; clothes.push_back(std::string(clothespath)); funpackf(tfile, "Bf Bf Bf", &tintr, &tintg, &tintb); clothestintr.push_back(tintr); clothestintg.push_back(tintg); clothestintb.push_back(tintb); } loaded = true; damagetolerance = PersonType::types[creature].defaultDamageTolerance; if (scale < 0) { scale = PersonType::types[creature].defaultScale; } oldcoords = coords; realoldcoords = coords; } void Person::changeCreatureType(person_type type) { creature = type; whichskin = 0; skeletonLoad(); scale = PersonType::types[creature].defaultScale; damagetolerance = PersonType::types[creature].defaultDamageTolerance; } void Person::skeletonLoad() { skeleton.id = id; skeleton.Load( PersonType::types[creature].figureFileName, PersonType::types[creature].lowFigureFileName, PersonType::types[creature].clothesFileName, PersonType::types[creature].modelFileNames[0], PersonType::types[creature].modelFileNames[1], PersonType::types[creature].modelFileNames[2], PersonType::types[creature].modelFileNames[3], PersonType::types[creature].modelFileNames[4], PersonType::types[creature].modelFileNames[5], PersonType::types[creature].modelFileNames[6], PersonType::types[creature].lowModelFileName, PersonType::types[creature].modelClothesFileName, PersonType::types[creature].clothes); skeleton.drawmodel.textureptr.load(PersonType::types[creature].skins[whichskin], 1, &skeleton.skinText[0], &skeleton.skinsize); } void Person::setProportions(float head, float body, float arms, float legs) { proportions[0] = head; proportions[1] = body; proportions[2] = arms; proportions[3] = legs; } float Person::getProportion(int part) const { return proportions[part]; } XYZ Person::getProportionXYZ(int part) const { XYZ prop = PersonType::types[creature].proportions[part] * proportions[part]; if (cellophane) { prop.z = 0; } return prop; } /* EFFECT * * USES: * GameTick/doPlayerCollisions */ void Person::CheckKick() { if (!(hasvictim && (animTarget == rabbitkickanim && victim && victim != this->shared_from_this() && frameCurrent >= 2 && animCurrent == rabbitkickanim) && distsq(&coords, &victim->coords) < 1.2 && !victim->skeleton.free)) { return; } if (Animation::animations[victim->animTarget].height != lowheight) { float damagemult = PersonType::types[creature].power * power * power; XYZ relative = velocity; relative.y = 0; Normalise(&relative); victim->spurt = 1; DoBlood(.2, 250); if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords); } victim->RagDoll(0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * 120 * damagemult; } victim->Puff(neck); victim->DoDamage(100 * damagemult / victim->protectionhigh); if (id == 0) { camerashake += .4; } target = 0; frameCurrent = 3; animTarget = backflipanim; frameTarget = 4; velocity = facing * -10; velocity.y = 5; skeleton.free = 0; if (id == 0) { resume_stream(whooshsound); } award_bonus(id, cannon); } else if (victim->isCrouch()) { animTarget = rabbitkickreversedanim; animCurrent = rabbitkickreversedanim; victim->animCurrent = rabbitkickreversalanim; victim->animTarget = rabbitkickreversalanim; targettilt2 = 0; frameCurrent = 0; frameTarget = 1; target = 0; velocity = 0; victim->oldcoords = victim->coords; coords = victim->coords; victim->targetyaw = targetyaw; victim->victim = this->shared_from_this(); } } /* EFFECT * * USES: * GameTick::doPlayerCollisions - spread fire between players * GameTick::ProcessDevKeys - press f to ignite * Person::DoStuff - spread fire from lit campfires and bushes */ void Person::CatchFire() { XYZ flatfacing, flatvelocity; int howmany; for (int i = 0; i < 10; i++) { howmany = fabs(Random() % (skeleton.joints.size())); if (skeleton.free) { flatvelocity = skeleton.joints[howmany].velocity; flatfacing = skeleton.joints[howmany].position * scale + coords; } else { flatvelocity = velocity; flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords; } Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, 2, 1); } onfiredelay = 0.5; emit_sound_at(firestartsound, coords); emit_stream_at(stream_firesound, coords); flamedelay = 0; onfire = 1; } /* FUNCTION * idle animation for this creature (depending on status) */ int Person::getIdle() { if (Dialog::inDialog() && (howactive == typeactive) && PersonType::types[creature].hasAnimTalkIdle()) { return PersonType::types[creature].animTalkIdle; } if (hasvictim && (victim != this->shared_from_this())) { if ((!victim->dead && victim->aitype != passivetype && victim->aitype != searchtype && aitype != passivetype && aitype != searchtype && victim->id < Person::players.size())) { if ((isPlayerControlled() && (stunned <= 0) && !hasWeapon()) || pause) { return PersonType::types[creature].animFightIdle; } if (isPlayerControlled() && (stunned <= 0) && hasWeapon()) { if (weapons[weaponids[weaponactive]].getType() == knife) { return knifefightidleanim; } if (weapons[weaponids[weaponactive]].getType() == sword && victim->hasWeapon()) { return swordfightidlebothanim; } if (weapons[weaponids[weaponactive]].getType() == sword) { return swordfightidleanim; } if (weapons[weaponids[weaponactive]].getType() == staff) { return swordfightidleanim; } } if (!isPlayerControlled() && (stunned <= 0) && creature != wolftype) { return fightsidestep; } } } if ((damage > permanentdamage || damage > damagetolerance * .8 || deathbleeding > 0) && PersonType::types[creature].hasAnimHurtIdle()) { return PersonType::types[creature].animHurtIdle; } if (howactive == typesitting) { return sitanim; } if (howactive == typesittingwall) { return sitwallanim; } if (howactive == typesleeping) { return sleepanim; } if (howactive == typedead1) { return dead1anim; } if (howactive == typedead2) { return dead2anim; } if (howactive == typedead3) { return dead3anim; } if (howactive == typedead4) { return dead4anim; } return PersonType::types[creature].animBounceIdle; } /* FUNCTION * crouch animation for this creature */ int Person::getCrouch() { return PersonType::types[creature].animCrouch; } /* FUNCTION * running animation for this creature (can be upright or all fours) */ int Person::getRun() { if (superruntoggle && (!hasWeapon())) { return PersonType::types[creature].animRunning; } else { return PersonType::types[creature].animRun; } } /* FUNCTION */ int Person::getStop() { return PersonType::types[creature].animStop; } /* FUNCTION */ int Person::getLanding() { return PersonType::types[creature].animLanding; } /* FUNCTION */ int Person::getLandhard() { return PersonType::types[creature].animLandingHard; } /* EFFECT * * USES: * Person::DoAnimations */ static void SolidHitBonus(int playerid) { if (bonustime < 1.5 && bonus >= solidhit && bonus <= megacombo) { award_bonus(playerid, bonus == megacombo ? bonus : bonus + 1); } else { award_bonus(playerid, solidhit); } } /* EFFECT * spawns blood effects */ void Person::DoBlood(float howmuch, int which) { // FIXME: should abstract out inputs static int bleedxint, bleedyint; static XYZ bloodvel; if (bloodtoggle && !Tutorial::active) { if (bleeding <= 0 && spurt) { spurt = 0; for (int i = 0; i < 3; i++) { // emit blood particles bloodvel = 0; if (skeleton.free) { bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0); bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } else { bloodvel.z = 10; bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } } if (Random() % 2 == 0) { // 50% chance for (int i = 0; i < 3; i++) { if (Random() % 2 != 0) { // emit teeth particles bloodvel = 0; if (skeleton.free) { bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0); bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; } else { bloodvel.z = 10; bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale; } bloodvel *= .2; if (skeleton.free) { Sprite::MakeSprite(splintersprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1); } else { Sprite::MakeSprite(splintersprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1); } Sprite::setLastSpriteSpecial(3); // sets it to teeth } } } } if (decalstoggle) { // FIXME: manipulating attributes bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25; bleedxint = 0; bleedyint = 0; while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) { bleedxint = abs(Random() % 512); bleedyint = abs(Random() % 512); } bleedy = bleedxint; bleedx = bleedyint; bleedy /= realtexdetail; bleedx /= realtexdetail; direction = abs(Random() % 2) * 2 - 1; } } if (bleeding > 2) { bleeding = 2; } } /* EFFECT * spawns big blood effects and ??? * modifies character's skin texture */ void Person::DoBloodBig(float howmuch, int which) { static int bleedxint, bleedyint, i, j; static XYZ bloodvel; if (howmuch && id == 0) { blooddimamount = 1; } if (!Tutorial::active || id == 0) { if (!isPlayerControlled() && howmuch > 0) { // play pain sounds int whichsound = -1; if (creature == wolftype) { int i = abs(Random() % 2); if (i == 0) { whichsound = snarlsound; } if (i == 1) { whichsound = snarl2sound; } } if (creature == rabbittype) { int i = abs(Random() % 2); if (i == 0) { whichsound = rabbitpainsound; } if (i == 1 && howmuch >= 2) { whichsound = rabbitpain1sound; } } if (whichsound != -1) { emit_sound_at(whichsound, coords); addEnvSound(coords); } } } if (id == 0 && howmuch > 0) { Game::flash(.5, 0); } if (bloodtoggle && decalstoggle && !Tutorial::active) { if (bleeding <= 0 && spurt) { spurt = 0; for (int i = 0; i < 3; i++) { // emit blood particles // FIXME: copypaste from above bloodvel = 0; if (skeleton.free) { bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0); bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } else { bloodvel.z = 10; bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } } } // weird texture manipulation code follows. // looks like this is painting blood onto the character's skin texture // FIXME: surely there's a better way int offsetx = 0, offsety = 0; if (which == 225) { offsety = Random() % 40; offsetx = abs(Random() % 60); } if (which == 190 || which == 185) { offsety = Random() % 40; offsetx = abs(Random() % 100) - 20; } if (which == 175) { offsety = Random() % 10; offsetx = Random() % 10; } if (which == 170) { offsety = Random() % 20; offsetx = Random() % 20; } if (which == 220 || which == 215) { offsetx = 20; } int startx = 512; int starty = 512; int endx = 0; int endy = 0; GLubyte color; for (i = 0; i < 512; i++) { for (j = 0; j < 512; j++) { if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) { if (i < startx) { startx = i; } if (j < starty) { starty = j; } if (i > endx) { endx = i; } if (j > endy) { endy = j; } } } } startx += offsetx; endx += offsetx; starty += offsety; endy += offsety; if (startx < 0) { startx = 0; } if (starty < 0) { starty = 0; } if (endx > 512 - 1) { endx = 512 - 1; } if (endy > 512 - 1) { endy = 512 - 1; } if (endx < startx) { endx = startx; } if (endy < starty) { endy = starty; } startx /= realtexdetail; starty /= realtexdetail; endx /= realtexdetail; endy /= realtexdetail; int texdetailint = realtexdetail; int where; for (i = startx; i < endx; i++) { for (j = starty; j < endy; j++) { if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) { color = Random() % 85 + 170; where = i * skeleton.skinsize * 3 + j * 3; if (skeleton.skinText[where + 0] > color / 2) { skeleton.skinText[where + 0] = color / 2; } skeleton.skinText[where + 1] = 0; skeleton.skinText[where + 2] = 0; } } } skeleton.drawmodel.textureptr.bind(); DoMipmaps(); bleedxint = 0; bleedyint = 0; while (PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] > which + 4 || PersonType::types[creature].bloodText[bleedxint * 512 * 3 + bleedyint * 3 + 0] < which - 4 || bleedxint < 10 || bleedyint < 10 || bleedxint > 500 || bleedyint > 500) { bleedxint = abs(Random() % 512); bleedyint = abs(Random() % 512); } bleedy = bleedxint + offsetx; bleedx = bleedyint + offsety; bleedy /= realtexdetail; bleedx /= realtexdetail; if (bleedx < 0) { bleedx = 0; } if (bleedy < 0) { bleedy = 0; } if (bleedx > skeleton.skinsize - 1) { bleedx = skeleton.skinsize - 1; } if (bleedy > skeleton.skinsize - 1) { bleedy = skeleton.skinsize - 1; } direction = abs(Random() % 2) * 2 - 1; } bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25; deathbleeding += bleeding; bloodloss += bleeding * 3; if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) { if (abs(Random() % 2) == 0) { aitype = gethelptype; lastseentime = 12; } else { aitype = attacktypecutoff; } ally = 0; } if (bleeding > 2) { bleeding = 2; } } /* EFFECT * similar to DoBloodBig */ bool Person::DoBloodBigWhere(float howmuch, int which, XYZ where) { static int i, j; static XYZ bloodvel; static XYZ startpoint, endpoint, colpoint, movepoint; static float rotationpoint; static int whichtri; static XYZ p1, p2, p3, p0; XYZ bary; XYZ gxx, gyy; float coordsx, coordsy; float total; if (bloodtoggle && decalstoggle && !Tutorial::active) { where -= coords; if (!skeleton.free) { where = DoRotation(where, 0, -yaw, 0); } //where=scale; startpoint = where; startpoint.y += 100; endpoint = where; endpoint.y -= 100; movepoint = 0; rotationpoint = 0; // ray testing for a tri in the character model whichtri = skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint); if (whichtri == -1) { return 0; } // low level geometry math p0 = colpoint; p1 = skeleton.drawmodel.getTriangleVertex(whichtri, 0); p2 = skeleton.drawmodel.getTriangleVertex(whichtri, 1); p3 = skeleton.drawmodel.getTriangleVertex(whichtri, 2); bary.x = distsq(&p0, &p1); bary.y = distsq(&p0, &p2); bary.z = distsq(&p0, &p3); total = bary.x + bary.y + bary.z; bary.x /= total; bary.y /= total; bary.z /= total; bary.x = 1 - bary.x; bary.y = 1 - bary.y; bary.z = 1 - bary.z; total = bary.x + bary.y + bary.z; bary.x /= total; bary.y /= total; bary.z /= total; gxx.x = skeleton.drawmodel.Triangles[whichtri].gx[0]; gxx.y = skeleton.drawmodel.Triangles[whichtri].gx[1]; gxx.z = skeleton.drawmodel.Triangles[whichtri].gx[2]; gyy.x = skeleton.drawmodel.Triangles[whichtri].gy[0]; gyy.y = skeleton.drawmodel.Triangles[whichtri].gy[1]; gyy.z = skeleton.drawmodel.Triangles[whichtri].gy[2]; 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; 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; if (bleeding <= 0 && spurt) { spurt = 0; for (int i = 0; i < 3; i++) { // emit blood particles // FIXME: more copypaste code bloodvel = 0; if (skeleton.free) { bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0); bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, jointPos(head) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } else { bloodvel.z = 10; bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1); Sprite::MakeSprite(bloodflamesprite, DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .3, 1); } } } // texture manipulation follows int offsetx = 0, offsety = 0; offsetx = (1 + coordsy) * 512 - 291; offsety = coordsx * 512 - 437; int startx = 512; int starty = 512; int endx = 0; int endy = 0; GLubyte color; for (i = 0; i < 512; i++) { for (j = 0; j < 512; j++) { if (PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[i * 512 * 3 + j * 3 + 0] >= which - 4) { if (i < startx) { startx = i; } if (j < starty) { starty = j; } if (i > endx) { endx = i; } if (j > endy) { endy = j; } } } } startx += offsetx; endx += offsetx; starty += offsety; endy += offsety; if (startx < 0) { startx = 0; } if (starty < 0) { starty = 0; } if (endx > 512 - 1) { endx = 512 - 1; } if (endy > 512 - 1) { endy = 512 - 1; } if (endx < startx) { endx = startx; } if (endy < starty) { endy = starty; } startx /= realtexdetail; starty /= realtexdetail; endx /= realtexdetail; endy /= realtexdetail; int texdetailint = realtexdetail; int where; for (i = startx; i < endx; i++) { for (j = starty; j < endy; j++) { if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= which + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= which - 4) { color = Random() % 85 + 170; where = i * skeleton.skinsize * 3 + j * 3; if (skeleton.skinText[where + 0] > color / 2) { skeleton.skinText[where + 0] = color / 2; } skeleton.skinText[where + 1] = 0; skeleton.skinText[where + 2] = 0; } else if (PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] <= 160 + 4 && PersonType::types[creature].bloodText[(i * texdetailint - offsetx) * 512 * 3 + (j * texdetailint - offsety) * 3 + 0] >= 160 - 4) { color = Random() % 85 + 170; where = i * skeleton.skinsize * 3 + j * 3; if (skeleton.skinText[where + 0] > color / 2) { skeleton.skinText[where + 0] = color / 2; } skeleton.skinText[where + 1] = 0; skeleton.skinText[where + 2] = 0; } } } skeleton.drawmodel.textureptr.bind(); DoMipmaps(); bleedy = (1 + coordsy) * 512; bleedx = coordsx * 512; bleedy /= realtexdetail; bleedx /= realtexdetail; if (bleedx < 0) { bleedx = 0; } if (bleedy < 0) { bleedy = 0; } if (bleedx > skeleton.skinsize - 1) { bleedx = skeleton.skinsize - 1; } if (bleedy > skeleton.skinsize - 1) { bleedy = skeleton.skinsize - 1; } direction = abs(Random() % 2) * 2 - 1; } bleeding = howmuch + (float)abs(Random() % 100) / 200 - .25; deathbleeding += bleeding; bloodloss += bleeding * 3; if (!Tutorial::active && !isPlayerControlled() && bloodloss > damagetolerance * 2 / 3 && bloodloss < damagetolerance && creature == rabbittype) { if (abs(Random() % 2) == 0) { aitype = gethelptype; lastseentime = 12; } else { aitype = attacktypecutoff; } ally = 0; } if (bleeding > 2) { bleeding = 2; } return 1; } /* EFFECT * guessing this performs a reversal */ void Person::Reverse() { if (!((victim->isPlayerControlled() || hostiletime > 1 || staggerdelay <= 0) && victim->animTarget != jumpupanim && victim->animTarget != jumpdownanim && (!Tutorial::active || cananger) && hostile)) { return; } if (normaldotproduct(victim->facing, victim->coords - coords) > 0 && (victim->id != 0 || difficulty >= 2) && (creature != wolftype || victim->creature == wolftype)) { return; } if (animTarget == sweepanim) { animTarget = sweepreversedanim; animCurrent = sweepreversedanim; victim->animCurrent = sweepreversalanim; victim->animTarget = sweepreversalanim; } if (animTarget == spinkickanim) { animTarget = spinkickreversedanim; animCurrent = spinkickreversedanim; victim->animCurrent = spinkickreversalanim; victim->animTarget = spinkickreversalanim; } if (animTarget == upunchanim || animTarget == rabbittacklinganim) { if (animTarget == rabbittacklinganim) { frameCurrent = 6; frameTarget = 7; victim->frameCurrent = 6; victim->frameTarget = 7; } animTarget = upunchreversedanim; animCurrent = upunchreversedanim; victim->animCurrent = upunchreversalanim; victim->animTarget = upunchreversalanim; } if (animTarget == staffhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) { if (victim->hasWeapon()) { victim->throwtogglekeydown = 1; XYZ tempVelocity = victim->velocity * .2; if (tempVelocity.x == 0) { tempVelocity.x = .1; } weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[victim->num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned j = 0; j < Person::players.size(); j++) { Person::players[j]->wentforweapon = 0; } } animTarget = staffhitreversedanim; animCurrent = staffhitreversedanim; victim->animCurrent = staffhitreversalanim; victim->animTarget = staffhitreversalanim; } if (animTarget == staffspinhitanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 2 == 0)) { if (victim->hasWeapon()) { victim->throwtogglekeydown = 1; XYZ tempVelocity = victim->velocity * .2; if (tempVelocity.x == 0) { tempVelocity.x = .1; } weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[victim->num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned j = 0; j < Person::players.size(); j++) { Person::players[j]->wentforweapon = 0; } } animTarget = staffspinhitreversedanim; animCurrent = staffspinhitreversedanim; victim->animCurrent = staffspinhitreversalanim; victim->animTarget = staffspinhitreversalanim; } if (animTarget == swordslashanim && distsq(&victim->coords, &coords) < 2 && ((victim->id == 0 && victim->crouchkeydown) || Random() % 4 == 0)) { if (victim->hasWeapon()) { victim->throwtogglekeydown = 1; XYZ tempVelocity = victim->velocity * .2; if (tempVelocity.x == 0) { tempVelocity.x = .1; } weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[victim->num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned j = 0; j < Person::players.size(); j++) { Person::players[j]->wentforweapon = 0; } } animTarget = swordslashreversedanim; animCurrent = swordslashreversedanim; victim->animCurrent = swordslashreversalanim; victim->animTarget = swordslashreversalanim; } if (animTarget == knifeslashstartanim && distsq(&victim->coords, &coords) < 2 && (victim->id == 0 || Random() % 4 == 0)) { if (victim->hasWeapon()) { victim->throwtogglekeydown = 1; XYZ tempVelocity = victim->velocity * .2; if (tempVelocity.x == 0) { tempVelocity.x = .1; } weapons[victim->weaponids[0]].drop(tempVelocity, tempVelocity, false); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[victim->num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned j = 0; j < Person::players.size(); j++) { Person::players[j]->wentforweapon = 0; } } animTarget = knifeslashreversedanim; animCurrent = knifeslashreversedanim; victim->animCurrent = knifeslashreversalanim; victim->animTarget = knifeslashreversalanim; } if (animTarget != knifeslashstartanim && animTarget != staffhitanim && animTarget != staffspinhitanim && animTarget != winduppunchanim && animTarget != wolfslapanim && animTarget != swordslashanim) { victim->targettilt2 = targettilt2; victim->frameCurrent = frameCurrent; victim->frameTarget = frameTarget; victim->target = target; victim->velocity = 0; victim->oldcoords = victim->coords; victim->coords = coords; victim->targetyaw = targetyaw; victim->yaw = targetyaw; victim->victim = this->shared_from_this(); } if (animTarget == winduppunchanim) { animTarget = winduppunchblockedanim; victim->animTarget = blockhighleftanim; victim->frameTarget = 1; victim->target = .5; victim->victim = this->shared_from_this(); victim->targetyaw = targetyaw + 180; } if (animTarget == wolfslapanim) { animTarget = winduppunchblockedanim; victim->animTarget = blockhighleftanim; victim->frameTarget = 1; victim->target = .5; victim->victim = this->shared_from_this(); victim->targetyaw = targetyaw + 180; } if ((animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) && victim->hasWeapon()) { animTarget = swordslashparriedanim; parriedrecently = .4; victim->parriedrecently = 0; victim->animTarget = swordslashparryanim; victim->frameTarget = 1; victim->target = .5; victim->victim = this->shared_from_this(); victim->targetyaw = targetyaw + 180; if (abs(Random() % 20) == 0 || weapons[victim->weaponids[victim->weaponactive]].getType() == knife) { if (victim->hasWeapon()) { if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) { if (weapons[victim->weaponids[0]].getType() == staff) { weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } if (weapons[weaponids[0]].getType() == staff) { weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } emit_sound_at(swordstaffsound, victim->coords); } else { emit_sound_at(metalhitsound, victim->coords); } } XYZ aim; victim->Puff(righthand); victim->target = 0; victim->frameTarget = 0; victim->animTarget = staggerbackhighanim; victim->targetyaw = targetyaw + 180; victim->target = 0; aim = DoRotation(facing, 0, 90, 0) * 21; aim.y += 7; weapons[victim->weaponids[0]].drop(aim * -.2, aim); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } if (abs(Random() % 20) == 0) { if (hasWeapon()) { if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) { if (weapons[victim->weaponids[0]].getType() == staff) { weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } if (weapons[weaponids[0]].getType() == staff) { weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } emit_sound_at(swordstaffsound, coords); } else { emit_sound_at(metalhitsound, coords); } } XYZ aim; Puff(righthand); target = 0; frameTarget = 0; animTarget = staggerbackhighanim; targetyaw = targetyaw + 180; target = 0; aim = DoRotation(facing, 0, 90, 0) * 21; aim.y += 7; weapons[victim->weaponids[0]].drop(aim * -.2, aim); num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; if (weaponstuck == num_weapons) { weaponstuck = 0; } } weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } } if (hasvictim) { if (animTarget == knifeslashstartanim || animTarget == swordslashanim || animTarget == staffhitanim || animTarget == staffspinhitanim) { if ((animTarget != staffhitanim && animTarget != staffspinhitanim) || distsq(&coords, &victim->coords) > .2) { victim->animTarget = dodgebackanim; victim->frameTarget = 0; victim->target = 0; XYZ rotatetarget; rotatetarget = coords - victim->coords; Normalise(&rotatetarget); victim->targetyaw = -asin(0 - rotatetarget.x); victim->targetyaw *= 360 / 6.28; if (rotatetarget.z < 0) { victim->targetyaw = 180 - victim->targetyaw; } victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70; victim->lastattack3 = victim->lastattack2; victim->lastattack2 = victim->lastattack; victim->lastattack = victim->animTarget; } else { victim->animTarget = sweepanim; victim->frameTarget = 0; victim->target = 0; XYZ rotatetarget; rotatetarget = coords - victim->coords; Normalise(&rotatetarget); victim->targetyaw = -asin(0 - rotatetarget.x); victim->targetyaw *= 360 / 6.28; if (rotatetarget.z < 0) { victim->targetyaw = 180 - victim->targetyaw; } victim->targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; //*-70; victim->lastattack3 = victim->lastattack2; victim->lastattack2 = victim->lastattack; victim->lastattack = victim->animTarget; } } } velocity = 0; victim->velocity = 0; if (!isPlayerControlled()) { feint = 0; if (escapednum < 2) { int chances = ((difficulty == 2) ? 3 : ((difficulty == 1) ? 5 : 10)); if ((Random() % chances) == 0) { feint = 1; } } } if (victim->id == 0 && Animation::animations[victim->animTarget].attack == reversal) { numreversals++; } } /* EFFECT * get hurt */ void Person::DoDamage(float howmuch) { // stats? if (id == 0) { damagetaken += howmuch / power; } else { damagedealt += howmuch / power; } // reset bonuses if (id == 0 && (bonus == solidhit || bonus == twoxcombo || bonus == threexcombo || bonus == fourxcombo || bonus == megacombo)) { bonus = 0; } // subtract health if (!Tutorial::active) { damage += howmuch / power; permanentdamage += howmuch / 2 / power; superpermanentdamage += howmuch / 4 / power; } // visual effects if (permanentdamage > damagetolerance / 2 && permanentdamage - howmuch < damagetolerance / 2 && Random() % 2) { DoBlood(1, 255); } if ((permanentdamage > damagetolerance * .8 && Random() % 2 && !deathbleeding) || spurt) { DoBlood(1, 255); } spurt = 0; if (id == 0) { camerashake += howmuch / 100; if ((howmuch > 50 && damage > damagetolerance / 2)) { blackout = damage / damagetolerance; if (blackout > 1) { blackout = 1; } } } // cancel attack? if (aitype == passivetype && damage < damagetolerance && ((!Tutorial::active || cananger) && hostile)) { aitype = attacktypecutoff; } if (!Tutorial::active && !isPlayerControlled() && damage < damagetolerance && damage > damagetolerance * 2 / 3 && creature == rabbittype) { if (abs(Random() % 2) == 0) { aitype = gethelptype; lastseentime = 12; } else { aitype = attacktypecutoff; } ally = 0; } if (howmuch > damagetolerance * 50 && skeleton.free != 2) { XYZ flatvelocity2; XYZ flatfacing2; for (unsigned i = 0; i < skeleton.joints.size(); i++) { if (skeleton.free) { flatvelocity2 = skeleton.joints[i].velocity; flatfacing2 = skeleton.joints[i].position * scale + coords; } else { flatvelocity2 = velocity; flatfacing2 = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords; } flatvelocity2.x += (float)(abs(Random() % 100) - 50) / 10; flatvelocity2.y += (float)(abs(Random() % 100) - 50) / 10; flatvelocity2.z += (float)(abs(Random() % 100) - 50) / 10; Sprite::MakeSprite(bloodflamesprite, flatfacing2, flatvelocity2, 1, 1, 1, 3, 1); Sprite::MakeSprite(bloodsprite, flatfacing2, flatvelocity2, 1, 1, 1, .4, 1); Sprite::MakeSprite(cloudsprite, flatfacing2, flatvelocity2 * 0, .6, 0, 0, 1, .5); } emit_sound_at(splattersound, coords); skeleton.free = 2; DoDamage(10000); RagDoll(0); if (!dead && (creature == wolftype) && (aitype != playercontrolled)) { award_bonus(0, Wolfbonus); } dead = 2; coords = 20; } // play sounds if (!Tutorial::active || id == 0) { if (speechdelay <= 0 && !dead && !isPlayerControlled()) { int whichsound = -1; if (creature == wolftype) { int i = abs(Random() % 2); if (i == 0) { whichsound = snarlsound; } if (i == 1) { whichsound = snarl2sound; } } if (creature == rabbittype) { int i = abs(Random() % 2); if (i == 0) { whichsound = rabbitpainsound; } if (i == 1 && damage > damagetolerance) { whichsound = rabbitpain1sound; } } if (whichsound != -1) { emit_sound_at(whichsound, coords); addEnvSound(coords); } } } speechdelay = .3; } /* EFFECT * calculate/animate head facing direction? */ void Person::DoHead() { static XYZ rotatearound; static XYZ facing; static float lookspeed = 500; if (!freeze && !winfreeze) { //head facing targetheadyaw = (float)((int)((0 - yaw - targetheadyaw + 180) * 100) % 36000) / 100; targetheadpitch = (float)((int)(targetheadpitch * 100) % 36000) / 100; while (targetheadyaw > 180) { targetheadyaw -= 360; } while (targetheadyaw < -180) { targetheadyaw += 360; } if (targetheadyaw > 160) { targetheadpitch = targetheadpitch * -1; } if (targetheadyaw < -160) { targetheadpitch = targetheadpitch * -1; } if (targetheadyaw > 160) { targetheadyaw = targetheadyaw - 180; } if (targetheadyaw < -160) { targetheadyaw = targetheadyaw + 180; } if (targetheadpitch > 120) { targetheadpitch = 120; } if (targetheadpitch < -120) { targetheadpitch = -120; } if (targetheadyaw > 120) { targetheadyaw = 120; } if (targetheadyaw < -120) { targetheadyaw = -120; } if (!isIdle()) { targetheadpitch = 0; } if (isIdle()) { if (targetheadyaw > 80) { targetheadyaw = 80; } if (targetheadyaw < -80) { targetheadyaw = -80; } if (targetheadpitch > 50) { targetheadpitch = 50; } if (targetheadpitch < -50) { targetheadpitch = -50; } } if (abs(headyaw - targetheadyaw) < multiplier * lookspeed) { headyaw = targetheadyaw; } else if (headyaw > targetheadyaw) { headyaw -= multiplier * lookspeed; } else if (headyaw < targetheadyaw) { headyaw += multiplier * lookspeed; } if (abs(headpitch - targetheadpitch) < multiplier * lookspeed / 2) { headpitch = targetheadpitch; } else if (headpitch > targetheadpitch) { headpitch -= multiplier * lookspeed / 2; } else if (headpitch < targetheadpitch) { headpitch += multiplier * lookspeed / 2; } rotatearound = jointPos(neck); jointPos(head) = rotatearound + DoRotation(jointPos(head) - rotatearound, headpitch, 0, 0); facing = 0; facing.z = -1; if (animTarget != bounceidleanim && animTarget != fightidleanim && animTarget != wolfidle && animTarget != knifefightidleanim && animTarget != drawrightanim && animTarget != drawleftanim && animTarget != walkanim) { facing = DoRotation(facing, headpitch * .4, 0, 0); facing = DoRotation(facing, 0, headyaw * .4, 0); } if (animTarget == bounceidleanim || animTarget == fightidleanim || animTarget == wolfidle || animTarget == knifefightidleanim || animTarget == drawrightanim || animTarget == drawleftanim) { facing = DoRotation(facing, headpitch * .8, 0, 0); facing = DoRotation(facing, 0, headyaw * .8, 0); } if (animTarget == walkanim) { facing = DoRotation(facing, headpitch * .6, 0, 0); facing = DoRotation(facing, 0, headyaw * .6, 0); } skeleton.specialforward[0] = facing; //skeleton.specialforward[0]=DoRotation(facing,0,yaw,0); for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible && (skeleton.muscles[i].parent1->label == head || skeleton.muscles[i].parent2->label == head)) { skeleton.FindRotationMuscle(i, animTarget); } } } } /* EFFECT * ragdolls character? */ void Person::RagDoll(bool checkcollision) { static XYZ change; static int i; static float speed; if (!skeleton.free) { if (id == 0) { numfalls++; } if (id == 0 && isFlip()) { numflipfail++; } escapednum = 0; facing = 0; facing.z = 1; facing = DoRotation(facing, 0, yaw, 0); skeleton.freetime = 0; skeleton.longdead = 0; skeleton.free = 1; skeleton.broken = 0; skeleton.spinny = 1; freefall = 1; skeleton.freefall = 1; if (!isnormal(velocity.x)) { velocity.x = 0; } if (!isnormal(velocity.y)) { velocity.y = 0; } if (!isnormal(velocity.z)) { velocity.z = 0; } if (!isnormal(yaw)) { yaw = 0; } if (!isnormal(coords.x)) { coords = 0; } if (!isnormal(tilt)) { tilt = 0; } if (!isnormal(tilt2)) { tilt2 = 0; } for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].delay = 0; skeleton.joints[i].locked = 0; skeleton.joints[i].position = DoRotation(DoRotation(DoRotation(skeleton.joints[i].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0); if (!isnormal(skeleton.joints[i].position.x)) { skeleton.joints[i].position = DoRotation(skeleton.joints[i].position, 0, yaw, 0); } if (!isnormal(skeleton.joints[i].position.x)) { skeleton.joints[i].position = coords; } skeleton.joints[i].position.y += .1; skeleton.joints[i].oldposition = skeleton.joints[i].position; skeleton.joints[i].realoldposition = skeleton.joints[i].position * scale + coords; } for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].velocity = 0; skeleton.joints[i].velchange = 0; } skeleton.DoConstraints(&coords, &scale); if (Animation::animations[animCurrent].height == lowheight || Animation::animations[animTarget].height == lowheight) { skeleton.DoConstraints(&coords, &scale); skeleton.DoConstraints(&coords, &scale); skeleton.DoConstraints(&coords, &scale); skeleton.DoConstraints(&coords, &scale); } speed = targetFrame().speed * 2; if (currentFrame().speed > targetFrame().speed) { speed = currentFrame().speed * 2; } if (transspeed) { speed = transspeed * 2; } speed *= speedmult; for (unsigned i = 0; i < skeleton.joints.size(); i++) { if ((Animation::animations[animCurrent].attack != reversed || animCurrent == swordslashreversedanim) && animCurrent != rabbitkickanim && !isLanding() && !wasLanding() && Animation::animations[animCurrent].height == Animation::animations[animTarget].height) { skeleton.joints[i].velocity = velocity / scale + facing * 5 + DoRotation(DoRotation(DoRotation((targetFrame().joints[i].position - currentFrame().joints[i].position) * speed, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0); } else { skeleton.joints[i].velocity = velocity / scale + facing * 5; } change.x = (float)(Random() % 100) / 100; change.y = (float)(Random() % 100) / 100; change.z = (float)(Random() % 100) / 100; skeleton.joints[i].velocity += change; skeleton.joints[fabs(Random() % skeleton.joints.size())].velocity -= change; change.x = (float)(Random() % 100) / 100; change.y = (float)(Random() % 100) / 100; change.z = (float)(Random() % 100) / 100; skeleton.joints[i].velchange += change; skeleton.joints[fabs(Random() % skeleton.joints.size())].velchange -= change; } if (checkcollision) { XYZ lowpoint; XYZ colpoint; if (!skeleton.joints.empty()) { XYZ average; average = 0; for (unsigned j = 0; j < skeleton.joints.size(); j++) { average += skeleton.joints[j].position; } average /= skeleton.joints.size(); coords += average * scale; for (unsigned j = 0; j < skeleton.joints.size(); j++) { skeleton.joints[j].position -= average; } } whichpatchx = coords.x / (terrain.size / subdivision * terrain.scale); whichpatchz = coords.z / (terrain.size / subdivision * terrain.scale); for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { i = terrain.patchobjects[whichpatchx][whichpatchz][l]; lowpoint = coords; lowpoint.y += 1; if (SphereCheck(&lowpoint, 3, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw, &Object::objects[i]->model) != -1) { coords.x = lowpoint.x; coords.z = lowpoint.z; } } } yaw = 0; updatedelay = 0; velocity = 0; for (unsigned i = 0; i < skeleton.joints.size(); i++) { velocity += skeleton.joints[i].velocity * scale; } velocity /= skeleton.joints.size(); // drop weapon if (Random() % 2 == 0) { if (hasWeapon() && animTarget != rabbitkickanim && num_weapons > 0) { weapons[weaponids[0]].drop(jointVel(righthand) * scale * -.3, jointVel(righthand) * scale); weapons[weaponids[0]].velocity.x += .01; num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; if (weaponstuck == num_weapons) { weaponstuck = 0; } } weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } } animTarget = bounceidleanim; animCurrent = bounceidleanim; frameTarget = 0; frameCurrent = 0; } } /* EFFECT */ void Person::FootLand(bodypart whichfoot, float opacity) { if ((whichfoot != leftfoot) && (whichfoot != rightfoot)) { cerr << "FootLand called on wrong bodypart" << endl; return; } static XYZ terrainlight; static XYZ footvel, footpoint; if (opacity >= 1 || skiddelay <= 0) { if (opacity > 1) { footvel = 0; footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords; if (distsq(&footpoint, &viewer)) { Sprite::MakeSprite(cloudsprite, footpoint, footvel, 1, 1, 1, .5, .2 * opacity); } } else if (onterrain && terrain.getOpacity(coords.x, coords.z) < .2) { footvel = velocity / 5; if (footvel.y < .8) { footvel.y = .8; } footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords; footpoint.y = terrain.getHeight(footpoint.x, footpoint.z); terrainlight = terrain.getLighting(footpoint.x, footpoint.z); if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) { if (environment == snowyenvironment) { Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7 * opacity); if (detail == 2) { terrain.MakeDecal(footprintdecal, footpoint, .2, 1 * opacity, yaw); } } else if (environment == grassyenvironment) { Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5 * opacity); } else if (environment == desertenvironment) { Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7 * opacity); if (detail == 2) { terrain.MakeDecal(footprintdecal, footpoint, .2, .25 * opacity, yaw); } } } } else if (isLanding() || (animTarget == jumpupanim) || isLandhard()) { footvel = velocity / 5; if (footvel.y < .8) { footvel.y = .8; } footpoint = DoRotation(jointPos(whichfoot), 0, yaw, 0) * scale + coords; if (distsq(&footpoint, &viewer) < viewdistance * viewdistance / 4) { Sprite::MakeSprite(cloudsprite, footpoint, footvel * .6, 1, 1, 1, .5, .2 * opacity); } } } } /* EFFECT * make a puff effect at a body part (dust effect?) */ void Person::Puff(int whichlabel) { static XYZ footvel, footpoint; footvel = 0; footpoint = DoRotation(jointPos(whichlabel), 0, yaw, 0) * scale + coords; Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .9, .3); } /* EFFECT * I think I added this in an attempt to clean up code */ void Person::setTargetAnimation(int animation) { animTarget = animation; frameTarget = 0; target = 0; } /* EFFECT * MONSTER * TODO: ??? */ void Person::DoAnimations() { if (!skeleton.free) { static float oldtarget; if (isIdle() && animCurrent != getIdle()) { normalsupdatedelay = 0; } if (animTarget == tempanim || animCurrent == tempanim) { Animation::animations[tempanim] = tempanimation; } if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) { float gLoc[3]; gLoc[0] = coords.x; gLoc[1] = coords.y; gLoc[2] = coords.z; if (id == 0) { OPENAL_3D_SetAttributes(channels[whooshsound], gLoc); OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5); } if (((velocity.y < -15) || (crouchkeydown && velocity.y < -8)) && abs(velocity.y) * 4 > fast_sqrt(velocity.x * velocity.x * velocity.z * velocity.z)) { landhard = 1; } if (!crouchkeydown && velocity.y >= -15) { landhard = 0; } } if ((animCurrent == jumpupanim || animTarget == jumpdownanim) /*&&velocity.y<40*/ && !isFlip() && (!isLanding() && !isLandhard()) && ((crouchkeydown && !crouchtogglekeydown))) { XYZ targfacing; targfacing = 0; targfacing.z = 1; targfacing = DoRotation(targfacing, 0, targetyaw, 0); if (normaldotproduct(targfacing, velocity) >= -.3) { animTarget = flipanim; } else { animTarget = backflipanim; } crouchtogglekeydown = 1; frameTarget = 0; target = 0; if (id == 0) { numflipped++; } } if (Animation::animations[animTarget].attack != reversed) { feint = 0; } if (!crouchkeydown || (isLanding() || isLandhard()) || (wasLanding() || wasLandhard())) { crouchtogglekeydown = 0; if (isPlayerControlled()) { feint = 0; } } else { if (!crouchtogglekeydown && Animation::animations[animTarget].attack == reversed && isPlayerControlled() && (escapednum < 2 || reversaltrain)) { feint = 1; } if (!isFlip()) { crouchtogglekeydown = 1; } } if (Animation::animations[animTarget].attack || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim) { if (detail) { normalsupdatedelay = 0; } } if (target >= 1) { if (animTarget == rollanim && frameTarget == 3 && onfire) { onfire = 0; emit_sound_at(fireendsound, coords); pause_sound(stream_firesound); deathbleeding = 0; } if (animTarget == rabbittacklinganim && frameTarget == 1) { if (victim->aitype == attacktypecutoff && victim->stunned <= 0 && victim->surprised <= 0 && victim->id != 0) { Reverse(); } if (animTarget == rabbittacklinganim && frameTarget == 1 && !victim->isCrouch() && victim->animTarget != backhandspringanim) { if (normaldotproduct(victim->facing, facing) > 0) { victim->animTarget = rabbittackledbackanim; } else { victim->animTarget = rabbittackledfrontanim; } victim->frameTarget = 2; victim->target = 0; victim->yaw = yaw; victim->targetyaw = yaw; if (victim->aitype == gethelptype) { victim->DoDamage(victim->damagetolerance - victim->damage); } if (PersonType::types[creature].hasClaws) { DoBloodBig(0, 255); emit_sound_at(clawslicesound, victim->coords); victim->spurt = 1; victim->DoBloodBig(1 / victim->armorhead, 210); } award_bonus(id, TackleBonus, victim->aitype == gethelptype ? 50 : 0); } } if (!drawtogglekeydown && drawkeydown && (!hasWeapon() || num_weapons == 1) && (targetFrame().label || (animTarget != animCurrent && animCurrent == rollanim)) && num_weapons > 0 && creature != wolftype) { if (weapons[weaponids[0]].getType() == knife) { if (!hasWeapon()) { weaponactive = 0; emit_sound_at(knifedrawsound, coords, 128); } else if (weaponactive == 0) { weaponactive = -1; emit_sound_at(knifesheathesound, coords); } } drawtogglekeydown = 1; } //Footstep sounds if (!Tutorial::active || id == 0) { if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) { int whichsound = -1; if (onterrain) { if (terrain.getOpacity(coords.x, coords.z) < .2) { if (targetFrame().label == 1) { whichsound = footstepsound; } else { whichsound = footstepsound2; } if (targetFrame().label == 1) { FootLand(leftfoot, 1); } if (targetFrame().label == 2) { FootLand(rightfoot, 1); } if (targetFrame().label == 3 && isRun()) { FootLand(rightfoot, 1); FootLand(leftfoot, 1); } } if (terrain.getOpacity(coords.x, coords.z) >= .2) { if (targetFrame().label == 1) { whichsound = footstepsound3; } else { whichsound = footstepsound4; } } } if (!onterrain) { if (targetFrame().label == 1) { whichsound = footstepsound3; } else { whichsound = footstepsound4; } } if (targetFrame().label == 4 && (!hasWeapon() || (animTarget != knifeslashstartanim && animTarget != knifethrowanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != knifefollowanim))) { if (Animation::animations[animTarget].attack != neutral) { unsigned r = abs(Random() % 3); if (r == 0) { whichsound = lowwhooshsound; } if (r == 1) { whichsound = midwhooshsound; } if (r == 2) { whichsound = highwhooshsound; } } if (Animation::animations[animTarget].attack == neutral) { whichsound = movewhooshsound; } } else if (targetFrame().label == 4) { whichsound = knifeswishsound; } if (targetFrame().label == 8 && !Tutorial::active) { whichsound = landsound2; } if (whichsound != -1) { emit_sound_at(whichsound, coords, 256.); if (id == 0) { if (whichsound == footstepsound || whichsound == footstepsound2 || whichsound == footstepsound3 || whichsound == footstepsound4) { if (animTarget == wolfrunninganim || animTarget == rabbitrunninganim) { addEnvSound(coords, 15); } else { addEnvSound(coords, 6); } } } if (targetFrame().label == 3) { whichsound--; emit_sound_at(whichsound, coords, 128.); } } } } //Combat sounds if (!Tutorial::active || id == 0) { if (speechdelay <= 0) { if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) { if ((targetFrame().label && (targetFrame().label < 5 || targetFrame().label == 8))) { int whichsound = -1; if (targetFrame().label == 4 && !isPlayerControlled()) { if (Animation::animations[animTarget].attack != neutral) { unsigned r = abs(Random() % 4); whichsound = PersonType::types[creature].soundsAttack[r]; speechdelay = .3; } } if (whichsound != -1) { emit_sound_at(whichsound, coords); } } } } } if ((!wasLanding() && !wasLandhard()) && animCurrent != getIdle() && (isLanding() || isLandhard())) { FootLand(leftfoot, 1); FootLand(rightfoot, 1); } transspeed = 0; currentoffset = targetoffset; frameTarget = frameCurrent; animCurrent = animTarget; frameTarget++; if (animCurrent == removeknifeanim && currentFrame().label == 5) { for (unsigned i = 0; i < weapons.size(); i++) { if (weapons[i].owner == -1) { if (distsqflat(&coords, &weapons[i].position) < 4 && !hasWeapon()) { if (distsq(&coords, &weapons[i].position) >= 1) { if (weapons[i].getType() != staff) { emit_sound_at(knifedrawsound, coords, 128.); } takeWeapon(i); } } } } } if (animCurrent == crouchremoveknifeanim && currentFrame().label == 5) { for (unsigned i = 0; i < weapons.size(); i++) { bool willwork = true; if (weapons[i].owner != -1) { if (Person::players[weapons[i].owner]->weaponstuck != -1) { if (Person::players[weapons[i].owner]->weaponids[Person::players[weapons[i].owner]->weaponstuck] == int(i)) { if (Person::players[weapons[i].owner]->num_weapons > 1) { willwork = 0; } } } } if ((weapons[i].owner == -1) || (hasvictim && (weapons[i].owner == int(victim->id)) && victim->skeleton.free)) { if (willwork && distsqflat(&coords, &weapons[i].position) < 3 && !hasWeapon()) { if (distsq(&coords, &weapons[i].position) < 1 || hasvictim) { bool fleshstuck = false; if (weapons[i].owner != -1) { if (victim->weaponstuck != -1) { if (victim->weaponids[victim->weaponstuck] == int(i)) { fleshstuck = true; } } } if (fleshstuck) { emit_sound_at(fleshstabremovesound, coords, 128.); } else { if (weapons[i].getType() != staff) { emit_sound_at(knifedrawsound, coords, 128.); } } if (weapons[i].owner != -1) { victim = Person::players[weapons[i].owner]; if (victim->num_weapons == 1) { victim->num_weapons = 0; } else { victim->num_weapons = 1; } //victim->weaponactive=-1; victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; for (unsigned j = 0; j < victim->skeleton.joints.size(); j++) { victim->skeleton.joints[j].velchange = 0; victim->skeleton.joints[j].locked = 0; } XYZ relative; relative = 0; relative.y = 10; Normalise(&relative); XYZ footvel, footpoint; footvel = 0; footpoint = weapons[i].position; if (victim->weaponstuck != -1) { if (victim->weaponids[victim->weaponstuck] == int(i)) { if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3); } weapons[i].bloody = 2; weapons[i].blooddrip = 5; victim->weaponstuck = -1; } } if (victim->num_weapons > 0) { if (victim->weaponstuck != 0 && victim->weaponstuck != -1) { victim->weaponstuck = 0; } if (victim->weaponids[0] == int(i)) { victim->weaponids[0] = victim->weaponids[victim->num_weapons]; } } victim->jointVel(abdomen) += relative * 6; victim->jointVel(neck) += relative * 6; victim->jointVel(rightshoulder) += relative * 6; victim->jointVel(leftshoulder) += relative * 6; } takeWeapon(i); } } } } } if (animCurrent == drawleftanim && currentFrame().label == 5) { if (!hasWeapon()) { weaponactive = 0; emit_sound_at(knifedrawsound, coords, 128.); } else if (weaponactive == 0) { weaponactive = -1; if (num_weapons == 2) { int buffer; buffer = weaponids[0]; weaponids[0] = weaponids[1]; weaponids[1] = buffer; } emit_sound_at(knifesheathesound, coords, 128.); } } if ((animCurrent == walljumprightkickanim && animTarget == walljumprightkickanim) || (animCurrent == walljumpleftkickanim && animTarget == walljumpleftkickanim)) { XYZ rotatetarget = DoRotation(skeleton.forward, 0, yaw, 0); Normalise(&rotatetarget); targetyaw = -asin(0 - rotatetarget.x); targetyaw *= 360 / 6.28; if (rotatetarget.z < 0) { targetyaw = 180 - targetyaw; } if (animTarget == walljumprightkickanim) { targetyaw += 40; } if (animTarget == walljumpleftkickanim) { targetyaw -= 40; } } bool dojumpattack; dojumpattack = 0; if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && frameTarget == 3 && (jumpkeydown || attackkeydown || id != 0)) { dojumpattack = 1; } if (hasvictim) { if (distsq(&victim->coords, &/*Person::players[i]->*/ coords) < 5 && victim->aitype == gethelptype && (attackkeydown) && !victim->skeleton.free && victim->isRun() && victim->runninghowlong >= 1) { dojumpattack = 1; } } if (!hostile) { dojumpattack = 0; } if (dojumpattack) { if ((animTarget == rabbitrunninganim || animTarget == wolfrunninganim) && id == 0) { animTarget = rabbittackleanim; frameTarget = 0; emit_sound_at(jumpsound, coords); } float closestdist; closestdist = 0; int closestid; closestid = -1; XYZ targetloc; targetloc = velocity; Normalise(&targetloc); targetloc += coords; for (unsigned i = 0; i < Person::players.size(); i++) { if (i != id) { if (distsq(&targetloc, &Person::players[i]->coords) < closestdist || closestdist == 0) { closestdist = distsq(&targetloc, &Person::players[i]->coords); closestid = i; } } } if (closestid != -1) { if (closestdist < 5 && !Person::players[closestid]->dead && Animation::animations[Person::players[closestid]->animTarget].height != lowheight && Person::players[closestid]->animTarget != backhandspringanim) { hasvictim = 1; victim = Person::players[closestid]; coords = victim->coords; animCurrent = rabbittacklinganim; animTarget = rabbittacklinganim; frameCurrent = 0; frameTarget = 1; XYZ rotatetarget; if (coords.z != victim->coords.z || coords.x != victim->coords.x) { rotatetarget = coords - victim->coords; Normalise(&rotatetarget); targetyaw = -asin(0 - rotatetarget.x); targetyaw *= 360 / 6.28; if (rotatetarget.z < 0) { targetyaw = 180 - targetyaw; } } if (animTarget != rabbitrunninganim) { emit_sound_at(jumpsound, coords, 128.); } } } } //Move impacts float damagemult = PersonType::types[creature].power * power; if (hasvictim) { damagemult /= victim->damagetolerance / 200; } if ((Animation::animations[animTarget].attack == normalattack || animTarget == walljumprightkickanim || animTarget == walljumpleftkickanim) && (!feint) && (victim->skeleton.free != 2 || animTarget == killanim || animTarget == dropkickanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == staffgroundsmashanim)) { if (animCurrent == spinkickanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2 || PersonType::types[creature].hasClaws) { victim->spurt = 1; DoBlood(.2, 250); if (PersonType::types[creature].hasClaws) { DoBloodBig(0, 250); } } if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhead, 175); } victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, -90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(head) += relative * damagemult * 200; victim->Puff(head); victim->DoDamage(damagemult * 100 / victim->protectionhead); SolidHitBonus(id); } } if (animCurrent == wolfslapanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2 || PersonType::types[creature].hasClaws) { victim->spurt = 1; if (PersonType::types[creature].hasClaws) { DoBloodBig(0, 235); } } emit_sound_at(whooshhitsound, victim->coords); if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2, 175); } victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); relative.y -= 1; Normalise(&relative); relative = DoRotation(relative, 0, 90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 20; } victim->jointVel(head) += relative * damagemult * 100; victim->Puff(head); victim->DoDamage(damagemult * 50 / victim->protectionhead); } } if (animCurrent == walljumprightkickanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) { camerashake += .4; } victim->spurt = 1; DoBlood(.2, 250); if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 160.); } if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhead, 175); } victim->RagDoll(0); XYZ relative; relative = facing; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, -90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(head) += relative * damagemult * 200; victim->Puff(head); victim->DoDamage(damagemult * 150 / victim->protectionhead); if (victim->damage > victim->damagetolerance) { award_bonus(id, style); } else { SolidHitBonus(id); } } } if (animCurrent == walljumpleftkickanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) { camerashake += .4; } victim->spurt = 1; DoBlood(.2, 250); if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 160.); } if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhead, 175); } victim->RagDoll(0); XYZ relative; relative = facing; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, 90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(head) += relative * damagemult * 200; victim->Puff(head); victim->DoDamage(damagemult * 150 / victim->protectionhead); if (victim->damage > victim->damagetolerance) { award_bonus(id, style); } else { SolidHitBonus(id); } } } if (animCurrent == blockhighleftstrikeanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != lowheight) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 235); } emit_sound_at(whooshhitsound, victim->coords); victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 30; } victim->jointVel(head) += relative * damagemult * 100; victim->Puff(head); victim->DoDamage(damagemult * 50 / victim->protectionhead); } } if (animCurrent == killanim && currentFrame().label == 8) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && victim->dead) { escapednum = 0; if (id == 0) { camerashake += .2; } emit_sound_at(whooshhitsound, victim->coords, 128.); victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; victim->skeleton.spinny = 1; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velchange = 0; victim->skeleton.joints[i].delay = 0; victim->skeleton.joints[i].locked = 0; //victim->skeleton.joints[i].velocity=0; } XYZ relative; relative = 0; relative.y = 1; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity.y = relative.y * 10; victim->skeleton.joints[i].position.y += relative.y * .3; victim->skeleton.joints[i].oldposition.y += relative.y * .3; victim->skeleton.joints[i].realoldposition.y += relative.y * .3; } victim->Puff(abdomen); victim->jointVel(abdomen).y = relative.y * 400; } } if (animCurrent == killanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->dead) { escapednum = 0; if (id == 0) { camerashake += .4; } if (!Tutorial::active) { emit_sound_at(heavyimpactsound, coords, 128.); } XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 90; } victim->Puff(abdomen); if (victim->dead != 2 && victim->permanentdamage > victim->damagetolerance - 250 && autoslomo) { slomo = 1; slomodelay = .2; } victim->DoDamage(damagemult * 500 / victim->protectionhigh); victim->jointVel(abdomen) += relative * damagemult * 300; } } if (animCurrent == dropkickanim && currentFrame().label == 7) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 9 && victim->skeleton.free) { escapednum = 0; if (id == 0) { camerashake += .4; } if (!Tutorial::active) { emit_sound_at(thudsound, coords); } victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; victim->skeleton.spinny = 1; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velchange = 0; //victim->skeleton.joints[i].delay=0; victim->skeleton.joints[i].locked = 0; } XYZ relative; relative = victim->coords - coords; Normalise(&relative); relative.y += .3; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 20; } if (!victim->dead) { SolidHitBonus(id); } victim->Puff(abdomen); victim->DoDamage(damagemult * 20 / victim->protectionhigh); victim->jointVel(abdomen) += relative * damagemult * 200; staggerdelay = .5; if (!victim->dead) { staggerdelay = 1.2; } } } if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 5) { if (hasvictim) { if (!victim->skeleton.free) { hasvictim = 0; } } if (!hasvictim) { terrain.MakeDecal(blooddecalfast, (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2), .08, .6, Random() % 360); emit_sound_at(knifesheathesound, coords, 128.); } if (victim && hasvictim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) { XYZ where, startpoint, endpoint, movepoint, colpoint; float rotationpoint; int whichtri; if (weapons[weaponids[weaponactive]].getType() == knife) { where = (weapons[weaponids[weaponactive]].tippoint * .6 + weapons[weaponids[weaponactive]].position * .4); where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } //where=scale; startpoint = where; startpoint.y += 100; endpoint = where; endpoint.y -= 100; } if (weapons[weaponids[weaponactive]].getType() == sword) { where = weapons[weaponids[weaponactive]].position; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } startpoint = where; where = weapons[weaponids[weaponactive]].tippoint; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } endpoint = where; } if (weapons[weaponids[weaponactive]].getType() == staff) { where = weapons[weaponids[weaponactive]].position; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } startpoint = where; where = weapons[weaponids[weaponactive]].tippoint; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } endpoint = where; } movepoint = 0; rotationpoint = 0; whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &colpoint, &movepoint, &rotationpoint); if (whichtri != -1) { if (victim->dead != 2) { victim->DoDamage(abs((victim->damagetolerance - victim->permanentdamage) * 2)); if (!victim->dead) { award_bonus(id, FinishedBonus); } } if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velchange = 0; victim->skeleton.joints[i].locked = 0; //victim->skeleton.joints[i].velocity=0; } emit_sound_at(fleshstabsound, coords, 128); } if (whichtri != -1 || weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].blooddrip += 5; weapons[weaponids[weaponactive]].blooddripdelay = 0; } if (whichtri == -1) { hasvictim = 0; emit_sound_at(knifesheathesound, coords, 128.); } } } } if ((animCurrent == crouchstabanim || animCurrent == swordgroundstabanim) && currentFrame().label == 6) { if (!hasvictim) { emit_sound_at(knifedrawsound, coords, 128); } if (victim && hasvictim) { XYZ footvel, footpoint; emit_sound_at(fleshstabremovesound, coords, 128.); footvel = 0; footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2); if (weapons[weaponids[weaponactive]].getType() == sword) { XYZ where, startpoint, endpoint, movepoint; float rotationpoint; int whichtri; where = weapons[weaponids[weaponactive]].position; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } startpoint = where; where = weapons[weaponids[weaponactive]].tippoint; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } endpoint = where; movepoint = 0; rotationpoint = 0; whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint); footpoint += victim->coords; if (whichtri == -1) { footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2); } } if (weapons[weaponids[weaponactive]].getType() == staff) { XYZ where, startpoint, endpoint, movepoint; float rotationpoint; int whichtri; where = weapons[weaponids[weaponactive]].position; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } startpoint = where; where = weapons[weaponids[weaponactive]].tippoint; where -= victim->coords; if (!victim->skeleton.free) { where = DoRotation(where, 0, -victim->yaw, 0); } endpoint = where; movepoint = 0; rotationpoint = 0; whichtri = victim->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint); footpoint += victim->coords; if (whichtri == -1) { footpoint = (weapons[weaponids[weaponactive]].tippoint * .8 + weapons[weaponids[weaponactive]].position * .2); } } hasvictim = victim->DoBloodBigWhere(2, 220, footpoint); if (hasvictim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) { victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velchange = 0; victim->skeleton.joints[i].locked = 0; //victim->skeleton.joints[i].velocity=0; } XYZ relative; relative = 0; relative.y = 10; Normalise(&relative); //victim->Puff(abdomen); if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .8, .3); } if (victim->bloodloss < victim->damagetolerance) { victim->bloodloss += 1000; victim->bled = 0; } victim->jointVel(abdomen) += relative * damagemult * 20; } } } if (!hasvictim && onterrain) { weapons[weaponids[weaponactive]].bloody = 0; weapons[weaponids[weaponactive]].blooddrip = 0; } } if (animCurrent == upunchanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 235); } if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128); } victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = relative * 30; } victim->jointVel(head) += relative * damagemult * 150; victim->frameTarget = 0; victim->animTarget = staggerbackhardanim; victim->targetyaw = targetyaw + 180; victim->target = 0; victim->stunned = 1; victim->Puff(head); victim->Puff(abdomen); victim->DoDamage(damagemult * 60 / victim->protectionhigh); SolidHitBonus(id); } } if (animCurrent == winduppunchanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 2) { escapednum = 0; if (id == 0) { camerashake += .4; } if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height != lowheight) { if (!Tutorial::active) { emit_sound_at(thudsound, victim->coords); } } else if (victim->damage <= victim->damagetolerance - 60 && normaldotproduct(victim->facing, victim->coords - coords) < (scale * 5) * (scale * 5) * 0 && Animation::animations[victim->animTarget].height == lowheight) { if (!Tutorial::active) { emit_sound_at(whooshhitsound, victim->coords); } } else { if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords); } } if (victim->damage > victim->damagetolerance - 60 || normaldotproduct(victim->facing, victim->coords - coords) > 0 || Animation::animations[victim->animTarget].height == lowheight) { victim->RagDoll(0); } XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); relative.y = .3; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = relative * 5; } victim->jointVel(abdomen) += relative * damagemult * 400; victim->frameTarget = 0; victim->animTarget = staggerbackhardanim; victim->targetyaw = targetyaw + 180; victim->target = 0; victim->stunned = 1; victim->Puff(abdomen); victim->DoDamage(damagemult * 60 / victim->protectionhigh); SolidHitBonus(id); } } if (animCurrent == blockhighleftanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) { if (victim->id == 0) { camerashake += .4; } emit_sound_at(landsound2, victim->coords); Puff(righthand); } } if (animCurrent == swordslashparryanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4) { if (victim->id == 0) { camerashake += .4; } if (hasWeapon()) { if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) { if (weapons[victim->weaponids[0]].getType() == staff) { weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } if (weapons[weaponids[0]].getType() == staff) { weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } emit_sound_at(swordstaffsound, victim->coords); } else { emit_sound_at(metalhitsound, victim->coords); } } //Puff(righthand); } } if (animCurrent == knifethrowanim && currentFrame().label == 5) { if (hasWeapon()) { escapednum = 0; XYZ aim; 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); Normalise(&aim); weapons[weaponids[0]].thrown(aim * 50); num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; } weaponactive = -1; } } if (animCurrent == knifeslashstartanim && currentFrame().label == 5) { if (hasvictim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 4.5 && victim->animTarget != dodgebackanim && victim->animTarget != rollanim) { escapednum = 0; if (!Tutorial::active) { victim->DoBloodBig(1.5 / victim->armorhigh, 225); } award_bonus(id, Slicebonus); if (!Tutorial::active) { emit_sound_at(knifeslicesound, victim->coords); } //victim->jointVel(abdomen)+=relative*damagemult*200; if (Animation::animations[victim->animTarget].attack && (!victim->isPlayerControlled() || victim->animTarget == knifeslashstartanim) && (victim->creature == rabbittype || victim->deathbleeding <= 0)) { if (victim->id != 0 || difficulty == 2) { victim->frameTarget = 0; victim->animTarget = staggerbackhardanim; victim->targetyaw = targetyaw + 180; victim->target = 0; } } victim->lowreversaldelay = 0; victim->highreversaldelay = 0; if (!isPlayerControlled()) { weaponmissdelay = .6; } if (!Tutorial::active) { if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; } weapons[weaponids[weaponactive]].blooddrip += 3; } XYZ footvel, footpoint; footvel = 0; if (skeleton.free) { footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords; } else { footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords; } if (Tutorial::active) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 1, 1, .6, .3); } else { if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .6, .3); } footvel = DoRotation(facing, 0, 90, 0) * .8; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1); } victim->DoDamage(damagemult * 0); } } } if (animCurrent == swordslashanim && currentFrame().label == 5 && victim->animTarget != rollanim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim) { if (!victim->hasWeapon() || normaldotproduct(victim->facing, victim->coords - coords) > 0 || (Random() % 2 == 0)) { award_bonus(id, Slashbonus); escapednum = 0; if (!Tutorial::active) { if (normaldotproduct(victim->facing, victim->coords - coords) < 0) { victim->DoBloodBig(2 / victim->armorhigh, 190); } else { victim->DoBloodBig(2 / victim->armorhigh, 185); } victim->deathbleeding = 1; emit_sound_at(swordslicesound, victim->coords); victim->frameTarget = 0; victim->animTarget = staggerbackhardanim; victim->targetyaw = targetyaw + 180; victim->target = 0; if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; } weapons[weaponids[weaponactive]].blooddrip += 3; float bloodlossamount; bloodlossamount = 200 + abs((float)(Random() % 40)) - 20; victim->bloodloss += bloodlossamount / victim->armorhigh; victim->DoDamage(damagemult * 0); XYZ footvel, footpoint; footvel = 0; if (skeleton.free) { footpoint = (victim->jointPos(abdomen) + victim->jointPos(neck)) / 2 * victim->scale + victim->coords; } else { footpoint = DoRotation((victim->jointPos(abdomen) + victim->jointPos(neck)) / 2, 0, victim->yaw, 0) * victim->scale + victim->coords; } if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = DoRotation(facing, 0, 90, 0) * .8; footvel.y -= .3; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1); } } else { if (victim->hasWeapon()) { if (weapons[victim->weaponids[0]].getType() == staff || weapons[weaponids[0]].getType() == staff) { if (weapons[victim->weaponids[0]].getType() == staff) { weapons[victim->weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } if (weapons[weaponids[0]].getType() == staff) { weapons[weaponids[0]].damage += .2 + float(abs(Random() % 100) - 50) / 250; } emit_sound_at(swordstaffsound, victim->coords); } else { emit_sound_at(metalhitsound, victim->coords); } } XYZ aim; victim->Puff(righthand); victim->target = 0; victim->frameTarget = 0; victim->animTarget = staggerbackhighanim; victim->targetyaw = targetyaw + 180; victim->target = 0; aim = DoRotation(facing, 0, 90, 0) * 21; aim.y += 7; weapons[victim->weaponids[0]].drop(aim * -.2, aim); victim->num_weapons--; if (victim->num_weapons) { victim->weaponids[0] = victim->weaponids[num_weapons]; if (victim->weaponstuck == victim->num_weapons) { victim->weaponstuck = 0; } } victim->weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } } } if (animCurrent == staffhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) { if (!Tutorial::active) { weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 250; escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2 || PersonType::types[creature].hasClaws) { victim->spurt = 1; } emit_sound_at(staffheadsound, victim->coords); } victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, 90, 0); relative.y -= 1; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 60; } victim->jointVel(head) += relative * damagemult * 230; victim->jointVel(neck) += relative * damagemult * 230; victim->Puff(head); if (!Tutorial::active) { victim->DoDamage(damagemult * 120 / victim->protectionhigh); award_bonus(id, solidhit, 30); } } } if (animCurrent == staffspinhitanim && currentFrame().label == 5 && victim->animTarget != rollanim) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5 && victim->animTarget != dodgebackanim && victim->animTarget != sweepanim) { if (!Tutorial::active) { weapons[weaponids[0]].damage += .6 + float(abs(Random() % 100) - 50) / 250; escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2 || PersonType::types[creature].hasClaws) { victim->spurt = 1; } emit_sound_at(staffheadsound, victim->coords); } victim->RagDoll(0); XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, -90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(head) += relative * damagemult * 220; victim->jointVel(neck) += relative * damagemult * 220; victim->Puff(head); if (!Tutorial::active) { victim->DoDamage(damagemult * 350 / victim->protectionhead); award_bonus(id, solidhit, 60); } } } if (animCurrent == staffgroundsmashanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 6.5) { escapednum = 0; if (!Tutorial::active) { if (!victim->dead) { weapons[weaponids[0]].damage += .4 + float(abs(Random() % 100) - 50) / 500; } if (id == 0) { camerashake += .4; } if (Random() % 2 || PersonType::types[creature].hasClaws) { victim->spurt = 1; } emit_sound_at(staffbodysound, victim->coords); } victim->skeleton.longdead = 0; victim->skeleton.free = 1; victim->skeleton.broken = 0; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velchange = 0; victim->skeleton.joints[i].locked = 0; //victim->skeleton.joints[i].velocity=0; } victim->RagDoll(0); XYZ relative; relative = 0; relative.y = -1; Normalise(&relative); if (!victim->dead) { for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = relative * damagemult * 40; } victim->jointVel(abdomen) += relative * damagemult * 40; } if (victim->dead) { for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = relative * damagemult * abs(Random() % 20); } } victim->Puff(abdomen); if (!Tutorial::active) { victim->DoDamage(damagemult * 100 / victim->protectionhigh); if (!victim->dead) { award_bonus(id, solidhit, 40); } } } } if (animCurrent == lowkickanim && currentFrame().label == 5) { if (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3 && Animation::animations[victim->animTarget].height != highheight) { escapednum = 0; if (id == 0) { camerashake += .4; } XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); SolidHitBonus(id); if (Animation::animations[victim->animTarget].height == lowheight) { if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 250); } victim->RagDoll(0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(head) += relative * damagemult * 200; if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } victim->Puff(head); victim->DoDamage(damagemult * 100 / victim->protectionhead); if (victim->howactive == typesleeping) { victim->DoDamage(damagemult * 150 / victim->protectionhead); } if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhead, 175); } } else { if (victim->damage >= victim->damagetolerance) { victim->RagDoll(0); } for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 10; } victim->jointVel(abdomen) += relative * damagemult * 200; victim->frameTarget = 0; victim->animTarget = staggerbackhighanim; victim->targetyaw = targetyaw + 180; victim->target = 0; if (!Tutorial::active) { emit_sound_at(landsound2, victim->coords, 128.); } victim->Puff(abdomen); victim->DoDamage(damagemult * 30 / victim->protectionhigh); if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhigh, 170); } } } } if (animCurrent == sweepanim && currentFrame().label == 5) { if ((victim->animTarget != jumpupanim) && (distsq(&coords, &victim->coords) < (scale * 5) * (scale * 5) * 3) && (victim != this->shared_from_this())) { escapednum = 0; if (id == 0) { camerashake += .2; } if (!Tutorial::active) { emit_sound_at(landsound2, victim->coords, 128.); } XYZ relative; relative = victim->coords - coords; relative.y = 0; Normalise(&relative); if (Animation::animations[victim->animTarget].height == middleheight || Animation::animations[victim->animCurrent].height == middleheight || victim->damage >= victim->damagetolerance - 40) { victim->RagDoll(0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 15; } relative = DoRotation(relative, 0, -90, 0); relative.y += .1; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { 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) { victim->skeleton.joints[i].velocity = relative * 80; } } victim->Puff(rightankle); victim->Puff(leftankle); victim->DoDamage(damagemult * 40 / victim->protectionlow); } else { if (victim->damage >= victim->damagetolerance) { victim->RagDoll(0); } for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 10; } relative = DoRotation(relative, 0, -90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { 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) { victim->skeleton.joints[i].velocity += relative * damagemult * 80; } } victim->jointVel(abdomen) += relative * damagemult * 200; victim->frameTarget = 0; victim->animTarget = staggerbackhighanim; victim->targetyaw = targetyaw + 180; victim->target = 0; if (!Tutorial::active) { emit_sound_at(landsound2, victim->coords, 128.); } victim->Puff(abdomen); victim->DoDamage(damagemult * 30 / victim->protectionlow); } SolidHitBonus(id); } } } if (Animation::animations[animTarget].attack == reversal && (!victim->feint || (victim->lastattack == victim->lastattack2 && victim->lastattack2 == victim->lastattack3 && Random() % 2) || animTarget == knifefollowanim)) { if (animCurrent == spinkickreversalanim && currentFrame().label == 7) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 230); } if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } if (PersonType::types[creature].hasClaws) { emit_sound_at(clawslicesound, victim->coords, 128); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhigh, 170); } victim->RagDoll(0); XYZ relative; relative = victim->coords - oldcoords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(abdomen) += relative * damagemult * 200; victim->Puff(abdomen); victim->DoDamage(damagemult * 150 / victim->protectionhigh); award_bonus(id, Reversal); } if ((animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim) && Animation::animations[animTarget].frames[frameCurrent].label == 5) { if (victim->hasWeapon() && victim->num_weapons > 0) { if (weapons[victim->weaponids[victim->weaponactive]].owner == int(victim->id)) { takeWeapon(victim->weaponids[victim->weaponactive]); victim->num_weapons--; if (victim->num_weapons > 0) { victim->weaponids[victim->weaponactive] = victim->weaponids[victim->num_weapons]; } victim->weaponactive = -1; } } } if (animCurrent == staffhitreversalanim && currentFrame().label == 5) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 230); } emit_sound_at(whooshhitsound, victim->coords, 128.); victim->RagDoll(0); XYZ relative; relative = victim->coords - oldcoords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 30; } victim->jointVel(abdomen) += relative * damagemult * 200; victim->Puff(head); victim->DoDamage(damagemult * 70 / victim->protectionhigh); } if (animCurrent == staffspinhitreversalanim && currentFrame().label == 7) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 230); } award_bonus(id, staffreversebonus); if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } victim->RagDoll(0); award_bonus(id, staffreversebonus); // Huh, again? XYZ relative; relative = victim->coords - oldcoords; relative.y = 0; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 30; } victim->jointVel(abdomen) += relative * damagemult * 200; victim->Puff(head); victim->DoDamage(damagemult * 70 / victim->protectionhigh); } if (animCurrent == upunchreversalanim && currentFrame().label == 7) { escapednum = 0; victim->RagDoll(1); XYZ relative; relative = facing; relative.y = 0; Normalise(&relative); relative.y -= .1; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 70; } victim->jointVel(lefthand) *= .1; victim->jointVel(leftwrist) *= .2; victim->jointVel(leftelbow) *= .5; victim->jointVel(leftshoulder) *= .7; victim->jointVel(righthand) *= .1; victim->jointVel(rightwrist) *= .2; victim->jointVel(rightelbow) *= .5; victim->jointVel(rightshoulder) *= .7; victim->Puff(abdomen); victim->DoDamage(damagemult * 90 / victim->protectionhigh); award_bonus(id, Reversal); bool doslice; if (hasWeapon()) { doslice = (weapons[weaponids[0]].getType() != staff); } else { doslice = PersonType::types[creature].hasClaws; } if (doslice) { if (!hasWeapon()) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhigh, 175); } else { victim->DoBloodBig(2 / victim->armorhigh, 225); emit_sound_at(knifeslicesound, victim->coords); if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; } weapons[weaponids[weaponactive]].blooddrip += 3; } } } if (animCurrent == swordslashreversalanim && currentFrame().label == 7) { escapednum = 0; victim->RagDoll(1); XYZ relative; relative = facing; relative.y = 0; Normalise(&relative); relative.y -= .1; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 70; } victim->jointVel(lefthand) *= .1 - 1; victim->jointVel(leftwrist) *= .2 - 1; victim->jointVel(leftelbow) *= .5 - 1; victim->jointVel(leftshoulder) *= .7 - 1; victim->jointVel(righthand) *= .1 - 1; victim->jointVel(rightwrist) *= .2 - 1; victim->jointVel(rightelbow) *= .5 - 1; victim->jointVel(rightshoulder) *= .7 - 1; award_bonus(id, swordreversebonus); } if (hasvictim && animCurrent == knifeslashreversalanim && currentFrame().label == 7) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 230); } if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } victim->RagDoll(0); XYZ relative; relative = victim->coords - oldcoords; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, -90, 0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->jointVel(abdomen) += relative * damagemult * 200; victim->Puff(abdomen); victim->DoDamage(damagemult * 30 / victim->protectionhigh); award_bonus(id, Reversal); } if (hasvictim && animCurrent == sneakattackanim && currentFrame().label == 7) { escapednum = 0; victim->RagDoll(0); victim->skeleton.spinny = 0; XYZ relative; relative = facing * -1; relative.y = -3; Normalise(&relative); if (victim->id == 0) { relative /= 30; } for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 40; } victim->damage = victim->damagetolerance; victim->permanentdamage = victim->damagetolerance - 1; bool doslice; if (hasWeapon()) { doslice = (weapons[weaponids[0]].getType() != staff); } else { doslice = PersonType::types[creature].hasClaws; } if (doslice) { if (!hasWeapon()) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2, 175); } else { victim->DoBloodBig(200, 225); emit_sound_at(knifeslicesound, victim->coords); if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } weapons[weaponids[weaponactive]].blooddrip += 5; } } award_bonus(id, spinecrusher); } if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 5) { if (hasWeapon() && victim->bloodloss < victim->damagetolerance) { escapednum = 0; if (animTarget == knifefollowanim) { victim->DoBloodBig(200, 210); } if (animTarget == knifesneakattackanim) { XYZ footvel, footpoint; footvel = 0; footpoint = weapons[weaponids[0]].tippoint; if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1); victim->DoBloodBig(200, 195); award_bonus(id, tracheotomy); } if (animTarget == knifefollowanim) { award_bonus(id, Stabbonus); XYZ footvel, footpoint; footvel = 0; footpoint = weapons[weaponids[0]].tippoint; if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .2, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .2, 1); } victim->bloodloss += 10000; victim->velocity = 0; emit_sound_at(fleshstabsound, victim->coords); if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } weapons[weaponids[weaponactive]].blooddrip += 5; } } if (hasvictim && (animCurrent == knifefollowanim || animCurrent == knifesneakattackanim) && currentFrame().label == 6) { escapednum = 0; victim->velocity = 0; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = 0; } if (animTarget == knifefollowanim) { victim->RagDoll(0); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = 0; } } if (hasWeapon() && Animation::animations[victim->animTarget].attack != reversal) { emit_sound_at(fleshstabremovesound, victim->coords); if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } weapons[weaponids[weaponactive]].blooddrip += 5; XYZ footvel, footpoint; footvel = 0; footpoint = weapons[weaponids[0]].tippoint; if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1); } } if (hasvictim && (animCurrent == swordsneakattackanim) && currentFrame().label == 5) { if (hasWeapon() && victim->bloodloss < victim->damagetolerance) { award_bonus(id, backstab); escapednum = 0; XYZ footvel, footpoint; footvel = 0; footpoint = (weapons[weaponids[0]].tippoint + weapons[weaponids[0]].position) / 2; if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 5, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .3, 1); victim->DoBloodBig(200, 180); victim->DoBloodBig(200, 215); victim->bloodloss += 10000; victim->velocity = 0; emit_sound_at(fleshstabsound, victim->coords); if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } weapons[weaponids[weaponactive]].blooddrip += 5; } } if (hasvictim && animCurrent == swordsneakattackanim && currentFrame().label == 6) { escapednum = 0; victim->velocity = 0; for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity = 0; } if (hasWeapon()) { emit_sound_at(fleshstabremovesound, victim->coords); if (bloodtoggle) { weapons[weaponids[weaponactive]].bloody = 2; } weapons[weaponids[weaponactive]].blooddrip += 5; XYZ footvel, footpoint; footvel = 0; footpoint = weapons[weaponids[0]].tippoint; if (bloodtoggle) { Sprite::MakeSprite(cloudimpactsprite, footpoint, footvel, 1, 0, 0, .9, .3); } footvel = (weapons[weaponids[0]].tippoint - weapons[weaponids[0]].position) * -1; Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 7, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodsprite, footpoint, DoRotation(footvel * 3, (float)(Random() % 20), (float)(Random() % 20), 0), 1, 1, 1, .05, .9); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 5, 1, 1, 1, .3, 1); Sprite::MakeSprite(bloodflamesprite, footpoint, footvel * 2, 1, 1, 1, .3, 1); } } if (animCurrent == sweepreversalanim && currentFrame().label == 7) { escapednum = 0; if (id == 0) { camerashake += .4; } if (Random() % 2) { victim->spurt = 1; DoBlood(.2, 240); } if (!hasWeapon()) { if (!Tutorial::active) { emit_sound_at(heavyimpactsound, victim->coords, 128.); } } bool doslice; if (hasWeapon()) { doslice = (weapons[weaponids[0]].getType() != staff); } else { doslice = PersonType::types[creature].hasClaws; } if (doslice) { if (!hasWeapon()) { emit_sound_at(clawslicesound, victim->coords, 128.); victim->spurt = 1; victim->DoBloodBig(2 / victim->armorhead, 175); } else { victim->DoBloodBig(2 / victim->armorhead, 225); emit_sound_at(knifeslicesound, victim->coords); if (bloodtoggle && !weapons[weaponids[weaponactive]].bloody) { weapons[weaponids[weaponactive]].bloody = 1; } weapons[weaponids[weaponactive]].blooddrip += 3; } } award_bonus(id, Reversal); victim->Puff(neck); XYZ relative; relative = facing * -1; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, 90, 0); relative.y = .5; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 20; } victim->jointVel(head) += relative * damagemult * 200; if (victim->damage < victim->damagetolerance - 100) { victim->velocity = relative * 200; } victim->DoDamage(damagemult * 100 / victim->protectionhead); victim->velocity = 0; } if (animCurrent == sweepreversalanim && ((currentFrame().label == 9 && victim->damage < victim->damagetolerance) || (currentFrame().label == 7 && victim->damage > victim->damagetolerance))) { escapednum = 0; victim->RagDoll(0); XYZ relative; relative = facing * -1; relative.y = 0; Normalise(&relative); relative = DoRotation(relative, 0, 90, 0); relative.y = .5; Normalise(&relative); for (unsigned i = 0; i < victim->skeleton.joints.size(); i++) { victim->skeleton.joints[i].velocity += relative * damagemult * 20; } victim->jointVel(head) += relative * damagemult * 200; } if (hasvictim && (animTarget == spinkickreversalanim || animTarget == sweepreversalanim || animTarget == rabbitkickreversalanim || animTarget == upunchreversalanim || animTarget == jumpreversalanim || animTarget == swordslashreversalanim || animTarget == knifeslashreversalanim || animTarget == rabbittacklereversal || animTarget == wolftacklereversal || animTarget == staffhitreversalanim || animTarget == staffspinhitreversalanim)) { if (victim->damage > victim->damagetolerance && bonus != reverseko) { award_bonus(id, reverseko); } } } //Animation end if (frameTarget >= int(Animation::animations[animCurrent].frames.size())) { frameTarget = 0; if (wasStop()) { animTarget = getIdle(); FootLand(leftfoot, 1); FootLand(rightfoot, 1); } if (animCurrent == rabbittackleanim || animCurrent == rabbittacklinganim) { animTarget = rollanim; frameTarget = 3; emit_sound_at(movewhooshsound, coords, 128.); } if (animCurrent == staggerbackhighanim) { animTarget = getIdle(); } if (animCurrent == staggerbackhardanim) { animTarget = getIdle(); } if (animCurrent == removeknifeanim) { animTarget = getIdle(); } if (animCurrent == crouchremoveknifeanim) { animTarget = getCrouch(); } if (animCurrent == backhandspringanim) { animTarget = getIdle(); } if (animCurrent == dodgebackanim) { animTarget = getIdle(); } if (animCurrent == drawleftanim) { animTarget = getIdle(); } if (animCurrent == drawrightanim || animCurrent == crouchdrawrightanim) { animTarget = getIdle(); if (animCurrent == crouchdrawrightanim) { animTarget = getCrouch(); } if (!hasWeapon()) { weaponactive = 0; emit_sound_at(knifedrawsound, coords, 128.); } else if (weaponactive == 0) { weaponactive = -1; if (num_weapons == 2) { int buffer; buffer = weaponids[0]; weaponids[0] = weaponids[1]; weaponids[1] = buffer; } emit_sound_at(knifesheathesound, coords, 128.); } } if (animCurrent == rollanim) { animTarget = getCrouch(); FootLand(leftfoot, 1); FootLand(rightfoot, 1); } if (isFlip()) { if (animTarget == walljumprightkickanim) { targetrot = -190; } if (animTarget == walljumpleftkickanim) { targetrot = 190; } animTarget = jumpdownanim; } if (animCurrent == climbanim) { animTarget = getCrouch(); frameTarget = 1; coords += facing * .1; if (!isnormal(coords.x)) { coords = oldcoords; } oldcoords = coords; targetoffset = 0; currentoffset = 0; grabdelay = 1; velocity = 0; collided = 0; avoidcollided = 0; } if (animTarget == rabbitkickreversalanim) { animTarget = getCrouch(); lastfeint = 0; } if (animTarget == jumpreversalanim) { animTarget = getCrouch(); lastfeint = 0; } if (animTarget == walljumprightanim || animTarget == walljumpbackanim || animTarget == walljumpfrontanim) { if (attackkeydown && animTarget != walljumpfrontanim) { int closest = -1; float closestdist = -1; float distance; if (Person::players.size() > 1) { for (unsigned i = 0; i < Person::players.size(); i++) { if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) { distance = distsq(&Person::players[i]->coords, &coords); if (closestdist == -1 || distance < closestdist) { closestdist = distance; closest = i; } } } } if (closestdist > 0 && closest >= 0 && closestdist < 16) { victim = Person::players[closest]; animTarget = walljumprightkickanim; frameTarget = 0; XYZ rotatetarget = victim->coords - coords; Normalise(&rotatetarget); yaw = -asin(0 - rotatetarget.x); yaw *= 360 / 6.28; if (rotatetarget.z < 0) { yaw = 180 - yaw; } targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; velocity = (victim->coords - coords) * 4; velocity.y += 2; transspeed = 40; } } if (animTarget == walljumpbackanim) { animTarget = backflipanim; frameTarget = 3; velocity = facing * -8; velocity.y = 4; if (id == 0) { resume_stream(whooshsound); } } if (animTarget == walljumprightanim) { animTarget = rightflipanim; frameTarget = 4; targetyaw -= 90; yaw -= 90; velocity = DoRotation(facing, 0, 30, 0) * -8; velocity.y = 4; } if (animTarget == walljumpfrontanim) { animTarget = frontflipanim; frameTarget = 2; //targetyaw-=180; ////yaw-=180; velocity = facing * 8; velocity.y = 4; } if (id == 0) { resume_stream(whooshsound); } } if (animTarget == walljumpleftanim) { if (attackkeydown) { int closest = -1; float closestdist = -1; float distance; if (Person::players.size() > 1) { for (unsigned i = 0; i < Person::players.size(); i++) { if (id != i && Person::players[i]->coords.y < coords.y && !Person::players[i]->skeleton.free) { distance = distsq(&Person::players[i]->coords, &coords); if (closestdist == -1 || distance < closestdist) { closestdist = distance; closest = i; } } } } if (closestdist > 0 && closest >= 0 && closestdist < 16) { victim = Person::players[closest]; animTarget = walljumpleftkickanim; frameTarget = 0; XYZ rotatetarget = victim->coords - coords; Normalise(&rotatetarget); yaw = -asin(0 - rotatetarget.x); yaw *= 360 / 6.28; if (rotatetarget.z < 0) { yaw = 180 - yaw; } targettilt2 = -asin(rotatetarget.y) * 360 / 6.28; velocity = (victim->coords - coords) * 4; velocity.y += 2; transspeed = 40; } } if (animTarget != walljumpleftkickanim) { animTarget = leftflipanim; frameTarget = 4; targetyaw += 90; yaw += 90; velocity = DoRotation(facing, 0, -30, 0) * -8; velocity.y = 4; } if (id == 0) { resume_stream(whooshsound); } } if (animTarget == sneakattackanim) { animCurrent = getCrouch(); animTarget = getCrouch(); frameTarget = 1; frameCurrent = 0; targetyaw += 180; yaw += 180; targettilt2 *= -1; tilt2 *= -1; transspeed = 1000000; targetheadyaw += 180; coords -= facing * .7; if (onterrain) { coords.y = terrain.getHeight(coords.x, coords.z); } lastfeint = 0; } if (animTarget == knifesneakattackanim || animTarget == swordsneakattackanim) { animTarget = getIdle(); frameTarget = 0; if (onterrain) { coords.y = terrain.getHeight(coords.x, coords.z); } lastfeint = 0; } if (animCurrent == knifefollowanim) { animTarget = getIdle(); lastfeint = 0; } if (Animation::animations[animTarget].attack == reversal && animCurrent != sneakattackanim && animCurrent != knifesneakattackanim && animCurrent != swordsneakattackanim && animCurrent != knifefollowanim) { float ycoords = oldcoords.y; animTarget = getStop(); targetyaw += 180; yaw += 180; targettilt2 *= -1; tilt2 *= -1; transspeed = 1000000; targetheadyaw += 180; if (!isnormal(coords.x)) { coords = oldcoords; } if (animCurrent == spinkickreversalanim || animCurrent == swordslashreversalanim) { oldcoords = coords + facing * .5; } else if (animCurrent == sweepreversalanim) { oldcoords = coords + facing * 1.1; } else if (animCurrent == upunchreversalanim) { oldcoords = coords + facing * 1.5; targetyaw += 180; yaw += 180; targetheadyaw += 180; targettilt2 *= -1; tilt2 *= -1; } else if (animCurrent == knifeslashreversalanim) { oldcoords = coords + facing * .5; targetyaw += 90; yaw += 90; targetheadyaw += 90; targettilt2 = 0; tilt2 = 0; } else if (animCurrent == staffspinhitreversalanim) { targetyaw += 180; yaw += 180; targetheadyaw += 180; targettilt2 = 0; tilt2 = 0; } if (onterrain) { oldcoords.y = terrain.getHeight(oldcoords.x, oldcoords.z); } else { oldcoords.y = ycoords; } currentoffset = coords - oldcoords; targetoffset = 0; coords = oldcoords; lastfeint = 0; } if (animCurrent == knifesneakattackedanim || animCurrent == swordsneakattackedanim) { velocity = 0; velocity.y = -5; RagDoll(0); } if (Animation::animations[animTarget].attack == reversed) { escapednum++; if (animTarget == sweepreversedanim) { targetyaw += 90; } animTarget = backhandspringanim; frameTarget = 2; emit_sound_at(landsound, coords, 128); if (animCurrent == upunchreversedanim || animCurrent == swordslashreversedanim) { animTarget = rollanim; frameTarget = 5; oldcoords = coords; coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale; coords.y = oldcoords.y; } if (animCurrent == knifeslashreversedanim) { animTarget = rollanim; frameTarget = 0; targetyaw += 90; yaw += 90; oldcoords = coords; coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale; coords.y = oldcoords.y; } } if (wasFlip()) { animTarget = jumpdownanim; } if (wasLanding()) { animTarget = getIdle(); } if (wasLandhard()) { animTarget = getIdle(); } if (animCurrent == spinkickanim || animCurrent == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == lowkickanim) { animTarget = getIdle(); oldcoords = coords; coords += (DoRotation(jointPos(leftfoot), 0, yaw, 0) + DoRotation(jointPos(rightfoot), 0, yaw, 0)) / 2 * scale; coords.y = oldcoords.y; //coords+=DoRotation(Animation::animations[animCurrent].offset,0,yaw,0)*scale; targetoffset.y = coords.y; if (onterrain) { targetoffset.y = terrain.getHeight(coords.x, coords.z); } currentoffset = DoRotation(Animation::animations[animCurrent].offset * -1, 0, yaw, 0) * scale; currentoffset.y -= (coords.y - targetoffset.y); coords.y = targetoffset.y; targetoffset = 0; normalsupdatedelay = 0; } if (animCurrent == upunchanim) { animTarget = getStop(); normalsupdatedelay = 0; lastfeint = 0; } if (animCurrent == rabbitkickanim && animTarget != backflipanim) { targetyaw = yaw; bool hasstaff; hasstaff = 0; if (num_weapons > 0) { if (weapons[0].getType() == staff) { hasstaff = 1; } } if (!hasstaff) { DoDamage(35); } RagDoll(0); lastfeint = 0; rabbitkickragdoll = 1; } if (animCurrent == rabbitkickreversedanim) { if (!feint) { velocity = 0; velocity.y = -10; //DoDamage(100); RagDoll(0); skeleton.spinny = 0; SolidHitBonus(!id); // FIXME: tricky id } if (feint) { escapednum++; animTarget = rollanim; coords += facing; if (id == 0) { pause_sound(whooshsound); } } lastfeint = 0; } if (animCurrent == rabbittackledbackanim || animCurrent == rabbittackledfrontanim) { velocity = 0; velocity.y = -10; RagDoll(0); skeleton.spinny = 0; } if (animCurrent == jumpreversedanim) { if (!feint) { velocity = 0; velocity.y = -10; //DoDamage(100); RagDoll(0); skeleton.spinny = 0; SolidHitBonus(!id); // FIXME: tricky id } if (feint) { escapednum++; animTarget = rollanim; coords += facing * 2; if (id == 0) { pause_sound(whooshsound); } } lastfeint = 0; } if (Animation::animations[animCurrent].attack == normalattack && !victim->skeleton.free && victim->animTarget != staggerbackhighanim && victim->animTarget != staggerbackhardanim && animTarget != winduppunchblockedanim && animTarget != blockhighleftanim && animTarget != swordslashparryanim && animTarget != swordslashparriedanim && animTarget != crouchstabanim && animTarget != swordgroundstabanim) { animTarget = getupfromfrontanim; lastfeint = 0; } else if (Animation::animations[animCurrent].attack == normalattack) { animTarget = getIdle(); lastfeint = 0; } if (animCurrent == blockhighleftanim && !isPlayerControlled()) { animTarget = blockhighleftstrikeanim; } if (animCurrent == knifeslashstartanim || animCurrent == knifethrowanim || animCurrent == swordslashanim || animCurrent == staffhitanim || animCurrent == staffgroundsmashanim || animCurrent == staffspinhitanim) { animTarget = getIdle(); lastfeint = 0; } if (animCurrent == spinkickanim && victim->skeleton.free) { if (creature == rabbittype) { animTarget = fightidleanim; } } } target = 0; if (isIdle() && !wasIdle()) { normalsupdatedelay = 0; } if (animCurrent == jumpupanim && velocity.y < 0 && !isFlip()) { animTarget = jumpdownanim; } } if (!skeleton.free) { oldtarget = target; if (!transspeed && Animation::animations[animTarget].attack != 2 && Animation::animations[animTarget].attack != 3) { if (!isRun() || !wasRun()) { if (targetFrame().speed > currentFrame().speed) { target += multiplier * targetFrame().speed * speed * 2; } if (targetFrame().speed <= currentFrame().speed) { target += multiplier * currentFrame().speed * speed * 2; } } if (isRun() && wasRun()) { float tempspeed; tempspeed = velspeed; if (tempspeed < 10 * speedmult) { tempspeed = 10 * speedmult; } /* FIXME - mixed of target and current here, is that intended? */ target += multiplier * Animation::animations[animTarget].frames[frameCurrent].speed * speed * 1.7 * tempspeed / (speed * 45 * scale); } } else if (transspeed) { target += multiplier * transspeed * speed * 2; } else { if (!isRun() || !wasRun()) { if (targetFrame().speed > currentFrame().speed) { target += multiplier * targetFrame().speed * 2; } if (targetFrame().speed <= currentFrame().speed) { target += multiplier * currentFrame().speed * 2; } } } if (animCurrent != animTarget) { target = (target + oldtarget) / 2; } if (target > 1) { frameCurrent = frameTarget; target = 1; } if (frameCurrent >= int(Animation::animations[animCurrent].frames.size())) { frameCurrent = Animation::animations[animCurrent].frames.size() - 1; } oldrot = rot; rot = targetrot * target; yaw += rot - oldrot; if (target == 1) { rot = 0; oldrot = 0; targetrot = 0; } if (animCurrent != oldanimCurrent || animTarget != oldanimTarget || ((frameCurrent != oldframeCurrent || frameTarget != oldframeTarget) && !calcrot)) { //Old rotates for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].position = currentFrame().joints[i].position; } skeleton.FindForwards(); for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { skeleton.FindRotationMuscle(i, animTarget); } } for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) { skeleton.muscles[i].oldrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100; } if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) { skeleton.muscles[i].oldrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100; } if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) { skeleton.muscles[i].oldrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100; } } } //New rotates for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].position = targetFrame().joints[i].position; } skeleton.FindForwards(); for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { skeleton.FindRotationMuscle(i, animTarget); } } for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { if (isnormal((float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100)) { skeleton.muscles[i].newrotate1 = (float)((int)(skeleton.muscles[i].rotate1 * 100) % 36000) / 100; } if (isnormal((float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100)) { skeleton.muscles[i].newrotate2 = (float)((int)(skeleton.muscles[i].rotate2 * 100) % 36000) / 100; } if (isnormal((float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100)) { skeleton.muscles[i].newrotate3 = (float)((int)(skeleton.muscles[i].rotate3 * 100) % 36000) / 100; } if (skeleton.muscles[i].newrotate3 > skeleton.muscles[i].oldrotate3 + 180) { skeleton.muscles[i].newrotate3 -= 360; } if (skeleton.muscles[i].newrotate3 < skeleton.muscles[i].oldrotate3 - 180) { skeleton.muscles[i].newrotate3 += 360; } if (skeleton.muscles[i].newrotate2 > skeleton.muscles[i].oldrotate2 + 180) { skeleton.muscles[i].newrotate2 -= 360; } if (skeleton.muscles[i].newrotate2 < skeleton.muscles[i].oldrotate2 - 180) { skeleton.muscles[i].newrotate2 += 360; } if (skeleton.muscles[i].newrotate1 > skeleton.muscles[i].oldrotate1 + 180) { skeleton.muscles[i].newrotate1 -= 360; } if (skeleton.muscles[i].newrotate1 < skeleton.muscles[i].oldrotate1 - 180) { skeleton.muscles[i].newrotate1 += 360; } } } } oldanimCurrent = animCurrent; oldanimTarget = animTarget; oldframeTarget = frameTarget; oldframeCurrent = frameCurrent; for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].velocity = (currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target - skeleton.joints[i].position) / multiplier; skeleton.joints[i].position = currentFrame().joints[i].position * (1 - target) + targetFrame().joints[i].position * target; } offset = currentoffset * (1 - target) + targetoffset * target; for (unsigned i = 0; i < skeleton.muscles.size(); i++) { if (skeleton.muscles[i].visible) { skeleton.muscles[i].rotate1 = skeleton.muscles[i].oldrotate1 * (1 - target) + skeleton.muscles[i].newrotate1 * target; skeleton.muscles[i].rotate2 = skeleton.muscles[i].oldrotate2 * (1 - target) + skeleton.muscles[i].newrotate2 * target; skeleton.muscles[i].rotate3 = skeleton.muscles[i].oldrotate3 * (1 - target) + skeleton.muscles[i].newrotate3 * target; } } } if (isLanding() && landhard) { if (id == 0) { camerashake += .4; } animTarget = getLandhard(); frameTarget = 0; target = 0; landhard = 0; transspeed = 15; } } } /* EFFECT * MONSTER * TODO */ void Person::DoStuff() { static XYZ terrainnormal; static XYZ flatfacing; static XYZ flatvelocity; static float flatvelspeed; static int bloodsize; static int startx, starty, endx, endy; static GLubyte color; static XYZ bloodvel; onfiredelay -= multiplier; if (onfiredelay < 0 && onfire) { if (Random() % 2 == 0) { crouchkeydown = 1; } onfiredelay = 0.3; } crouchkeydowntime += multiplier; if (!crouchkeydown) { crouchkeydowntime = 0; } jumpkeydowntime += multiplier; if (!jumpkeydown && skeleton.free) { jumpkeydowntime = 0; } if (hostile || damage > 0 || bloodloss > 0) { immobile = 0; } if (isIdle() || isRun()) { targetoffset = 0; } if (num_weapons == 1 && hasWeapon()) { weaponstuck = -1; } if (id == 0) { blooddimamount -= multiplier * .3; } speechdelay -= multiplier; texupdatedelay -= multiplier; interestdelay -= multiplier; flamedelay -= multiplier; parriedrecently -= multiplier; if (!victim) { victim = this->shared_from_this(); hasvictim = 0; } if (id == 0) { speed = 1.1 * speedmult; } else { speed = 1.0 * speedmult; } if (!skeleton.free) { rabbitkickragdoll = 0; } speed *= speedmult; if (id != 0 && (creature == rabbittype || difficulty != 2)) { superruntoggle = 0; } if (id != 0 && creature == wolftype && difficulty == 2) { superruntoggle = 0; if (aitype != passivetype) { superruntoggle = 1; 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) { superruntoggle = 0; } } if (scale < 0.2) { superruntoggle = 0; } if (animTarget == wolfrunninganim && !superruntoggle) { animTarget = getRun(); frameTarget = 0; } } if (!hasWeapon() && num_weapons > 0) { if (weapons[weaponids[0]].getType() == staff) { weaponactive = 0; } } if (onfire) { burnt += multiplier; deathbleeding = 1; if (burnt > .6) { burnt = .6; } OPENAL_SetVolume(channels[stream_firesound], 256 + 256 * findLength(&velocity) / 3); if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) { float gLoc[3]; gLoc[0] = coords.x; gLoc[1] = coords.y; gLoc[2] = coords.z; if (id == 0) { OPENAL_3D_SetAttributes(channels[whooshsound], gLoc); OPENAL_SetVolume(channels[whooshsound], 64 * findLength(&velocity) / 5); } } } while (flamedelay < 0 && onfire) { flamedelay += .006; int howmany = fabs(Random() % (skeleton.joints.size())); if (skeleton.free) { flatvelocity = skeleton.joints[howmany].velocity * scale / 2; flatfacing = skeleton.joints[howmany].position * scale + coords; } else { flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords; flatvelocity = (coords - oldcoords) / multiplier / 2; } Sprite::MakeSprite(flamesprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, 1); } while (flamedelay < 0 && !onfire && Tutorial::active && id != 0) { flamedelay += .05; int howmany = fabs(Random() % (skeleton.joints.size())); if (skeleton.free) { flatvelocity = skeleton.joints[howmany].velocity * scale / 2; flatfacing = skeleton.joints[howmany].position * scale + coords; } else { flatvelocity = (coords - oldcoords) / multiplier / 2; flatfacing = DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position, 0, 0, tilt), tilt2, 0, 0), 0, yaw, 0) * scale + coords; } Sprite::MakeSprite(breathsprite, flatfacing, flatvelocity, 1, 1, 1, .6 + (float)abs(Random() % 100) / 200 - .25, .3); } if (bleeding > 0) { bleeding -= multiplier * .3; if (bloodtoggle == 2) { skeleton.drawmodel.textureptr.bind(); if ((bleeding <= 0) && (detail != 2)) { DoMipmaps(); } } } if (neckspurtamount > 0) { neckspurtamount -= multiplier; neckspurtdelay -= multiplier * 3; neckspurtparticledelay -= multiplier * 3; if (neckspurtparticledelay < 0 && neckspurtdelay > 2) { spurt = 0; bloodvel = 0; if (skeleton.free) { bloodvel -= DoRotation(skeleton.forward * 10 * scale, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0); bloodvel += DoRotation(jointVel(head), ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale; Sprite::MakeSprite(bloodsprite, (jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5) * scale + coords, bloodvel, 1, 1, 1, .05, .9); } else { bloodvel.z = 5 * neckspurtamount; bloodvel = DoRotation(bloodvel, ((float)(Random() % 100)) / 40, yaw + ((float)(Random() % 100)) / 40, 0) * scale; bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 40, ((float)(Random() % 100)) / 40, 0) * scale; Sprite::MakeSprite(bloodsprite, DoRotation(jointPos(neck) + (jointPos(neck) - jointPos(head)) / 5, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, .9); } neckspurtparticledelay = .05; } if (neckspurtdelay < 0) { neckspurtdelay = 3; } } if (deathbleeding > 0 && dead != 2) { if (deathbleeding < 5) { bleeddelay -= deathbleeding * multiplier / 4; } else { bleeddelay -= 5 * multiplier / 4; } if (bleeddelay < 0 && bloodtoggle) { bleeddelay = 1; XYZ bloodvel; if (bloodtoggle) { bloodvel = 0; if (skeleton.free) { bloodvel += DoRotation(jointVel(abdomen), ((float)(Random() % 100)) / 4, yaw + ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, jointPos(abdomen) * scale + coords, bloodvel, 1, 1, 1, .05, 1); } else { bloodvel += DoRotation(velocity, ((float)(Random() % 100)) / 4, ((float)(Random() % 100)) / 4, 0) * scale; Sprite::MakeSprite(bloodsprite, DoRotation((jointPos(abdomen) + jointPos(abdomen)) / 2, 0, yaw, 0) * scale + coords, bloodvel, 1, 1, 1, .05, 1); } } } bloodloss += deathbleeding * multiplier * 80; deathbleeding -= multiplier * 1.6; if (deathbleeding < 0) { deathbleeding = 0; } if (bloodloss > damagetolerance && Animation::animations[animTarget].attack == neutral) { if (hasWeapon()) { weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale); weapons[weaponids[0]].velocity.x += .01; num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; if (weaponstuck == num_weapons) { weaponstuck = 0; } } weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } if (id == 0) { Game::flash(.5, 0); } } if (!dead && (creature == wolftype) && (aitype != playercontrolled)) { award_bonus(0, Wolfbonus); } dead = 2; if (animTarget == knifefollowedanim && !skeleton.free) { for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].velocity = 0; skeleton.joints[i].velocity.y = -2; } } if (id != 0 && unconscioustime > .1) { numafterkill++; } RagDoll(0); } } if (texupdatedelay < 0 && bleeding > 0 && bloodtoggle == 2 && distsq(&viewer, &coords) < 9) { texupdatedelay = .12; bloodsize = 5 - realtexdetail; startx = 0; starty = 0; startx = bleedy; //abs(Random()%(skeleton.skinsize-bloodsize-1)); starty = bleedx; //abs(Random()%(skeleton.skinsize-bloodsize-1)); endx = startx + bloodsize; endy = starty + bloodsize; if (startx < 0) { startx = 0; bleeding = 0; } if (starty < 0) { starty = 0; bleeding = 0; } if (endx > skeleton.skinsize - 1) { endx = skeleton.skinsize - 1; bleeding = 0; } if (endy > skeleton.skinsize - 1) { endy = skeleton.skinsize - 1; bleeding = 0; } if (endx < startx) { endx = startx; } if (endy < starty) { endy = starty; } for (int i = startx; i < endx; i++) { for (int j = starty; j < endy; j++) { if (Random() % 2 == 0) { color = Random() % 85 + 170; if (skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] > color / 2) { skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 0] = color / 2; } skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 1] = 0; skeleton.skinText[i * skeleton.skinsize * 3 + j * 3 + 2] = 0; } } } if (detail > 1) { skeleton.drawmodel.textureptr.bind(); DoMipmaps(); } if (skeleton.free) { bleedx += 4 * direction / realtexdetail; if (detail == 2) { bleedy += (abs(Random() % 3) - 1) * 2 / realtexdetail; } else { bleedy += (abs(Random() % 3) - 1) * 4 / realtexdetail; } } else { bleedy -= 4 / realtexdetail; if (detail == 2) { bleedx += (abs(Random() % 3) - 1) * 2 / realtexdetail; } else { bleedx += (abs(Random() % 3) - 1) * 4 / realtexdetail; } } } if (abs(righthandmorphness - targetrighthandmorphness) < multiplier * 4) { righthandmorphness = targetrighthandmorphness; righthandmorphstart = righthandmorphend; } else if (righthandmorphness > targetrighthandmorphness) { righthandmorphness -= multiplier * 4; } else if (righthandmorphness < targetrighthandmorphness) { righthandmorphness += multiplier * 4; } if (abs(lefthandmorphness - targetlefthandmorphness) < multiplier * 4) { lefthandmorphness = targetlefthandmorphness; lefthandmorphstart = lefthandmorphend; } else if (lefthandmorphness > targetlefthandmorphness) { lefthandmorphness -= multiplier * 4; } else if (lefthandmorphness < targetlefthandmorphness) { lefthandmorphness += multiplier * 4; } if (creature == rabbittype || targettailmorphness == 5 || targettailmorphness == 0) { if (abs(tailmorphness - targettailmorphness) < multiplier * 10) { tailmorphness = targettailmorphness; tailmorphstart = tailmorphend; } else if (tailmorphness > targettailmorphness) { tailmorphness -= multiplier * 10; } else if (tailmorphness < targettailmorphness) { tailmorphness += multiplier * 10; } } if (creature == wolftype) { if (abs(tailmorphness - targettailmorphness) < multiplier * 4) { tailmorphness = targettailmorphness; tailmorphstart = tailmorphend; } else if (tailmorphness > targettailmorphness) { tailmorphness -= multiplier * 2; } else if (tailmorphness < targettailmorphness) { tailmorphness += multiplier * 2; } } if (headmorphend == 3 || headmorphstart == 3) { if (abs(headmorphness - targetheadmorphness) < multiplier * 7) { headmorphness = targetheadmorphness; headmorphstart = headmorphend; } else if (headmorphness > targetheadmorphness) { headmorphness -= multiplier * 7; } else if (headmorphness < targetheadmorphness) { headmorphness += multiplier * 7; } } else if (headmorphend == 5 || headmorphstart == 5) { if (abs(headmorphness - targetheadmorphness) < multiplier * 10) { headmorphness = targetheadmorphness; headmorphstart = headmorphend; } else if (headmorphness > targetheadmorphness) { headmorphness -= multiplier * 10; } else if (headmorphness < targetheadmorphness) { headmorphness += multiplier * 10; } } else { if (abs(headmorphness - targetheadmorphness) < multiplier * 4) { headmorphness = targetheadmorphness; headmorphstart = headmorphend; } else if (headmorphness > targetheadmorphness) { headmorphness -= multiplier * 4; } else if (headmorphness < targetheadmorphness) { headmorphness += multiplier * 4; } } if (abs(chestmorphness - targetchestmorphness) < multiplier) { chestmorphness = targetchestmorphness; chestmorphstart = chestmorphend; } else if (chestmorphness > targetchestmorphness) { chestmorphness -= multiplier; } else if (chestmorphness < targetchestmorphness) { chestmorphness += multiplier; } if (dead != 2 && howactive <= typesleeping) { if (chestmorphstart == 0 && chestmorphend == 0) { chestmorphness = 0; targetchestmorphness = 1; chestmorphend = 3; } if (chestmorphstart != 0 && chestmorphend != 0) { chestmorphness = 0; targetchestmorphness = 1; chestmorphend = 0; if (environment == snowyenvironment) { XYZ footpoint; XYZ footvel; if (skeleton.free) { footvel = skeleton.specialforward[0] * -1; footpoint = ((jointPos(head) + jointPos(neck)) / 2) * scale + coords; } else { footvel = DoRotation(skeleton.specialforward[0], 0, yaw, 0) * -1; footpoint = DoRotation((jointPos(head) + jointPos(neck)) / 2, 0, yaw, 0) * scale + coords; } if (animTarget == sleepanim) { footvel = DoRotation(footvel, 0, 90, 0); } Sprite::MakeSprite(breathsprite, footpoint + footvel * .2, footvel * .4, 1, 1, 1, .4, .3); } } if (!dead && howactive < typesleeping) { blinkdelay -= multiplier * 2; if (headmorphstart == 0 && headmorphend == 0 && blinkdelay <= 0) { headmorphness = 0; targetheadmorphness = 1; headmorphend = 3; blinkdelay = (float)(abs(Random() % 40)) / 5; } if (headmorphstart == 3 && headmorphend == 3) { headmorphness = 0; targetheadmorphness = 1; headmorphend = 0; } } if (!dead) { twitchdelay -= multiplier * 1.5; if (animTarget != hurtidleanim) { if (headmorphstart == 0 && headmorphend == 0 && twitchdelay <= 0) { headmorphness = 0; targetheadmorphness = 1; headmorphend = 5; twitchdelay = (float)(abs(Random() % 40)) / 5; } if (headmorphstart == 5 && headmorphend == 5) { headmorphness = 0; targetheadmorphness = 1; headmorphend = 0; } } if ((isIdle() || isCrouch()) && animTarget != hurtidleanim) { twitchdelay3 -= multiplier * 1; if (Random() % 2 == 0) { if (righthandmorphstart == 0 && righthandmorphend == 0 && twitchdelay3 <= 0) { righthandmorphness = 0; targetrighthandmorphness = 1; righthandmorphend = 1; if (Random() % 2 == 0) { twitchdelay3 = (float)(abs(Random() % 40)) / 5; } } if (righthandmorphstart == 1 && righthandmorphend == 1) { righthandmorphness = 0; targetrighthandmorphness = 1; righthandmorphend = 0; } } if (Random() % 2 == 0) { if (lefthandmorphstart == 0 && lefthandmorphend == 0 && twitchdelay3 <= 0) { lefthandmorphness = 0; targetlefthandmorphness = 1; lefthandmorphend = 1; twitchdelay3 = (float)(abs(Random() % 40)) / 5; } if (lefthandmorphstart == 1 && lefthandmorphend == 1) { lefthandmorphness = 0; targetlefthandmorphness = 1; lefthandmorphend = 0; } } } } if (!dead) { if (creature == rabbittype) { if (howactive < typesleeping) { twitchdelay2 -= multiplier * 1.5; } else { twitchdelay2 -= multiplier * 0.5; } if (howactive <= typesleeping) { if (tailmorphstart == 0 && tailmorphend == 0 && twitchdelay2 <= 0) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 1; twitchdelay2 = (float)(abs(Random() % 40)) / 5; } if (tailmorphstart == 1 && tailmorphend == 1) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 2; } if (tailmorphstart == 2 && tailmorphend == 2) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 0; } } } } } if (creature == wolftype) { twitchdelay2 -= multiplier * 1.5; if (tailmorphend != 0) { if ((isRun() || animTarget == jumpupanim || animTarget == jumpdownanim || animTarget == backflipanim) && !skeleton.free) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 0; twitchdelay2 = .1; } } if (tailmorphend != 5) { if (animTarget == flipanim || animTarget == frontflipanim || animTarget == rollanim || skeleton.free) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 5; twitchdelay2 = .1; } } if (twitchdelay2 <= 0) { if (((tailmorphstart == 0 && tailmorphend == 0) || (tailmorphstart == 5 && tailmorphend == 5))) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 1; } if (tailmorphstart == 1 && tailmorphend == 1) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 2; } if (tailmorphstart == 2 && tailmorphend == 2) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 3; } if (tailmorphstart == 3 && tailmorphend == 3) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 4; } if (tailmorphstart == 4 && tailmorphend == 4) { tailmorphness = 0; targettailmorphness = 1; tailmorphend = 1; } } } if (dead != 1) { unconscioustime = 0; } if (dead == 1 || howactive == typesleeping) { unconscioustime += multiplier; //If unconscious, close eyes and mouth if (righthandmorphend != 0) { righthandmorphness = 0; } righthandmorphend = 0; targetrighthandmorphness = 1; if (lefthandmorphend != 0) { lefthandmorphness = 0; } lefthandmorphend = 0; targetlefthandmorphness = 1; if (headmorphend != 3 && headmorphend != 5) { headmorphness = 0; } headmorphend = 3; targetheadmorphness = 1; } if (howactive > typesleeping) { XYZ headpoint; headpoint = coords; if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0); for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .8; float opacity = .6; float yaw = 0; Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); } } bled = 1; } if (dead == 2 || howactive > typesleeping) { //If dead, open mouth and hands if (righthandmorphend != 0) { righthandmorphness = 0; } righthandmorphend = 0; targetrighthandmorphness = 1; if (lefthandmorphend != 0) { lefthandmorphness = 0; } lefthandmorphend = 0; targetlefthandmorphness = 1; if (headmorphend != 2) { headmorphness = 0; } headmorphend = 2; targetheadmorphness = 1; } if (stunned > 0 && !dead && headmorphend != 2) { if (headmorphend != 4) { headmorphness = 0; } headmorphend = 4; targetheadmorphness = 1; } if (damage > damagetolerance && !dead) { dead = 1; unconscioustime = 0; if ((creature == wolftype) && (aitype != playercontrolled)) { award_bonus(0, Wolfbonus); } RagDoll(0); if (hasWeapon()) { weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale); weapons[weaponids[0]].velocity.x += .01; num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; if (weaponstuck == num_weapons) { weaponstuck = 0; } } weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } if ((id == 0 || distsq(&coords, &viewer) < 50) && autoslomo) { slomo = 1; slomodelay = .2; } damage += 20; } if (!dead) { damage -= multiplier * 13; permanentdamage -= multiplier * 4; if (isIdle() || isCrouch()) { permanentdamage -= multiplier * 4; } } if (damage < 0) { damage = 0; } if (permanentdamage < 0) { permanentdamage = 0; } if (superpermanentdamage < 0) { superpermanentdamage = 0; } if (permanentdamage < superpermanentdamage) { permanentdamage = superpermanentdamage; } if (damage < permanentdamage) { damage = permanentdamage; } if (dead == 1 && damage < damagetolerance) { dead = 0; skeleton.free = 1; damage -= 20; for (unsigned i = 0; i < skeleton.joints.size(); i++) { skeleton.joints[i].velocity = 0; } } if (permanentdamage > damagetolerance && dead != 2) { DoBlood(1, 255); if (hasWeapon()) { weapons[weaponids[0]].drop(velocity * scale * -.3, velocity * scale); weapons[weaponids[0]].velocity.x += .01; num_weapons--; if (num_weapons) { weaponids[0] = weaponids[num_weapons]; if (weaponstuck == num_weapons) { weaponstuck = 0; } } weaponactive = -1; for (unsigned i = 0; i < Person::players.size(); i++) { Person::players[i]->wentforweapon = 0; } } bled = 0; if (!dead && (creature == wolftype) && (aitype != playercontrolled)) { award_bonus(0, Wolfbonus); } if (unconscioustime < .1 && (bonus != spinecrusher || bonustime > 1) && (bonus != FinishedBonus || bonustime > 1) && bloodloss < damagetolerance) { award_bonus(id, touchofdeath); } if (id != 0 && unconscioustime > .1) { numafterkill++; } dead = 2; skeleton.free = 1; emit_sound_at(breaksound, coords); } if (skeleton.free == 1) { if (id == 0) { pause_sound(whooshsound); } if (!dead) { //If knocked over, open hands and close mouth if (righthandmorphend != 0) { righthandmorphness = 0; } righthandmorphend = 0; targetrighthandmorphness = 1; if (lefthandmorphend != 0) { lefthandmorphness = 0; } lefthandmorphend = 0; targetlefthandmorphness = 1; if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5) { if (headmorphend != 0) { headmorphness = 0; } headmorphend = 0; targetheadmorphness = 1; } } skeleton.DoGravity(&scale); float damageamount; damageamount = skeleton.DoConstraints(&coords, &scale) * 5; if (damage > damagetolerance - damageamount && !dead && (bonus != spinecrusher || bonustime > 1) && (bonus != style || bonustime > 1) && (bonus != cannon || bonustime > 1)) { award_bonus(id, deepimpact); } DoDamage(damageamount / ((protectionhigh + protectionhead + protectionlow) / 3)); XYZ average; average = 0; if (!skeleton.joints.empty()) { for (unsigned j = 0; j < skeleton.joints.size(); j++) { average += skeleton.joints[j].position; } average /= skeleton.joints.size(); coords += average * scale; for (unsigned j = 0; j < skeleton.joints.size(); j++) { skeleton.joints[j].position -= average; } average /= multiplier; } velocity = 0; for (unsigned i = 0; i < skeleton.joints.size(); i++) { velocity += skeleton.joints[i].velocity * scale; } velocity /= skeleton.joints.size(); if (!isnormal(velocity.x) && velocity.x) { velocity = 0; } if (findLength(&average) < 10 && dead && skeleton.free) { skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier; if (skeleton.longdead > 2000) { if (skeleton.longdead > 6000) { if (id == 0) { pause_sound(whooshsound); } skeleton.free = 3; DrawSkeleton(); skeleton.free = 2; } if (dead == 2 && bloodloss < damagetolerance) { XYZ headpoint; headpoint = (jointPos(head) + jointPos(neck)) / 2 * scale + coords; DoBlood(1, 255); if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecal, headpoint, .2 * 1.2, .5, 0); for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .2 * 1.2; float opacity = .6; float yaw = 0; Object::objects[j]->model.MakeDecal(blooddecal, &point, &size, &opacity, &yaw); } } bled = 1; } if (dead == 2 && bloodloss >= damagetolerance) { XYZ headpoint; headpoint = (jointPos(abdomen) + jointPos(neck)) / 2 * scale + coords; if (bleeding <= 0) { DoBlood(1, 255); } if (bloodtoggle && !bled) { terrain.MakeDecal(blooddecalslow, headpoint, .8, .5, 0); for (unsigned int l = 0; l < terrain.patchobjects[whichpatchx][whichpatchz].size(); l++) { unsigned int j = terrain.patchobjects[whichpatchx][whichpatchz][l]; XYZ point = DoRotation(headpoint - Object::objects[j]->position, 0, -Object::objects[j]->yaw, 0); float size = .8; float opacity = .6; float yaw = 0; Object::objects[j]->model.MakeDecal(blooddecalslow, &point, &size, &opacity, &yaw); } } bled = 1; } } } if (!dead && crouchkeydown && skeleton.freetime > .5 && id == 0 && skeleton.free) { bool canrecover = 1; XYZ startpoint, endpoint, colpoint, colviewer, coltarget; startpoint = coords; endpoint = coords; endpoint.y -= .7; if (terrain.lineTerrain(startpoint, endpoint, &colpoint) != -1) { canrecover = 0; } if (velocity.y < -30) { canrecover = 0; } for (unsigned int i = 0; i < Object::objects.size(); i++) { if (Object::objects[i]->type != treeleavestype && Object::objects[i]->type != bushtype && Object::objects[i]->type != firetype) { colviewer = startpoint; coltarget = endpoint; if (Object::objects[i]->model.LineCheck(&colviewer, &coltarget, &colpoint, &Object::objects[i]->position, &Object::objects[i]->yaw) != -1) { canrecover = 0; } } } if (canrecover) { skeleton.free = 0; XYZ middle; middle = 0; terrainnormal = jointPos(groin) - jointPos(abdomen); if (joint(groin).locked && joint(abdomen).locked) { terrainnormal = jointPos(groin) - jointPos(abdomen); middle = (jointPos(groin) + jointPos(abdomen)) / 2; } if (joint(abdomen).locked && joint(neck).locked) { terrainnormal = jointPos(abdomen) - jointPos(neck); middle = (jointPos(neck) + jointPos(abdomen)) / 2; } if (joint(groin).locked && joint(neck).locked) { terrainnormal = jointPos(groin) - jointPos(neck); middle = (jointPos(groin) + jointPos(neck)) / 2; } Normalise(&terrainnormal); targetyaw = -asin(0 - terrainnormal.x); targetyaw *= 360 / 6.28; if (terrainnormal.z < 0) { targetyaw = 180 - targetyaw; } yaw = targetyaw; frameTarget = 0; animTarget = flipanim; crouchtogglekeydown = 1; target = 0; tilt2 = 0; targettilt2 = 0; animCurrent = tempanim; frameCurrent = 0; target = 0; for (unsigned i = 0; i < skeleton.joints.size(); i++) { tempanimation.frames[0].joints[i].position = skeleton.joints[i].position; tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0); } } } if (findLength(&average) < 10 && !dead && skeleton.free) { skeleton.longdead += (2000 - findLength(&average)) * multiplier + multiplier; if (skeleton.longdead > (damage + 500) * 1.5) { if (id == 0) { pause_sound(whooshsound); } skeleton.free = 0; velocity = 0; XYZ middle; middle = 0; terrainnormal = jointPos(groin) - jointPos(abdomen); if (joint(groin).locked && joint(abdomen).locked) { terrainnormal = jointPos(groin) - jointPos(abdomen); middle = (jointPos(groin) + jointPos(abdomen)) / 2; } if (joint(abdomen).locked && joint(neck).locked) { terrainnormal = jointPos(abdomen) - jointPos(neck); middle = (jointPos(neck) + jointPos(abdomen)) / 2; } if (joint(groin).locked && joint(neck).locked) { terrainnormal = jointPos(groin) - jointPos(neck); middle = (jointPos(groin) + jointPos(neck)) / 2; } Normalise(&terrainnormal); targetyaw = -asin(0 - terrainnormal.x); targetyaw *= 360 / 6.28; if (terrainnormal.z < 0) { targetyaw = 180 - targetyaw; } yaw = targetyaw; targettilt2 = asin(terrainnormal.y) * 180 / 3.14 * -1; if (skeleton.forward.y < 0) { animTarget = getupfrombackanim; frameTarget = 0; targettilt2 = 0; } if (skeleton.forward.y > -.3) { animTarget = getupfromfrontanim; yaw += 180; targetyaw += 180; targettilt2 *= -1; frameTarget = 0; targettilt2 = 0; } if ((Random() % 8 == 0 && id != 0 && creature == rabbittype) || (Random() % 2 == 0 && id != 0 && creature == wolftype) || (id == 0 && crouchkeydown && (forwardkeydown || backkeydown || leftkeydown || rightkeydown))) { animTarget = rollanim; targetyaw = lookyaw; if (id == 0) { if (rightkeydown) { targetyaw -= 90; if (forwardkeydown) { targetyaw += 45; } if (backkeydown) { targetyaw -= 45; } } if (leftkeydown) { targetyaw += 90; if (forwardkeydown) { targetyaw -= 45; } if (backkeydown) { targetyaw += 45; } } if (backkeydown) { if (!leftkeydown && !rightkeydown) { targetyaw += 180; } } targetyaw += 180; } } if (abs(targettilt2) > 50) { targettilt2 = 0; } animCurrent = tempanim; frameCurrent = 0; target = 0; tilt2 = targettilt2; if (middle.y > 0 && animTarget != rollanim) { targetoffset.y = middle.y + 1; } for (unsigned i = 0; i < skeleton.joints.size(); i++) { tempanimation.frames[0].joints[i].position = skeleton.joints[i].position; tempanimation.frames[0].joints[i].position = DoRotation(tempanimation.frames[0].joints[i].position, 0, -yaw, 0); } } } bool hasstaff; hasstaff = 0; if (num_weapons > 0) { if (weapons[0].getType() == staff) { hasstaff = 1; } } if (!skeleton.freefall && freefall && ((jumpkeydown && jumpkeydowntime < .2) || (hasstaff && rabbitkickragdoll)) && !dead) { if (velocity.y > -30) { XYZ tempvelocity; tempvelocity = velocity; Normalise(&tempvelocity); targetyaw = -asin(0 - tempvelocity.x); targetyaw *= 360 / 6.28; if (velocity.z < 0) { targetyaw = 180 - targetyaw; } //targetyaw+=180; skeleton.free = 0; if (dotproduct(&skeleton.forward, &tempvelocity) < 0) { animTarget = rollanim; frameTarget = 2; } else { animTarget = backhandspringanim; targetyaw += 180; frameTarget = 6; } target = 0; emit_sound_at(movewhooshsound, coords, 128.); animCurrent = animTarget; frameCurrent = frameTarget - 1; target = 0; velocity = 0; yaw = targetyaw; tilt = 0; targettilt = 0; tilt2 = 0; targettilt2 = 0; } } if (skeleton.freefall == 0) { freefall = 0; } } if (aitype != passivetype || skeleton.free == 1) { if (findLengthfast(&velocity) > .1) { for (unsigned int i = 0; i < Object::objects.size(); i++) { if (Object::objects[i]->type == firetype) { if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) { if (onfire) { if (!Object::objects[i]->onfire) { emit_sound_at(firestartsound, Object::objects[i]->position); } Object::objects[i]->onfire = 1; } if (!onfire) { if (Object::objects[i]->onfire) { CatchFire(); } } } } if (Object::objects[i]->type == bushtype) { if (distsqflat(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 12 && distsq(&coords, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 49) { if (onfire) { if (!Object::objects[i]->onfire) { emit_sound_at(firestartsound, Object::objects[i]->position); } Object::objects[i]->onfire = 1; } if (!onfire) { if (Object::objects[i]->onfire) { CatchFire(); } } if (Object::objects[i]->messedwith <= 0) { XYZ tempvel; XYZ pos; emit_sound_at(bushrustle, coords, 40 * findLength(&velocity)); if (id == 0) { addEnvSound(coords, 4 * findLength(&velocity)); } int howmany = 0; if (environment == grassyenvironment) { howmany = findLength(&velocity) * 4; } if (environment == snowyenvironment) { howmany = findLength(&velocity) * 2; } if (detail == 2) { if (environment != desertenvironment) { for (int j = 0; j < howmany; j++) { tempvel.x = float(abs(Random() % 100) - 50) / 20; tempvel.y = float(abs(Random() % 100) - 50) / 20; tempvel.z = float(abs(Random() % 100) - 50) / 20; pos = coords; pos.y += 1; pos.x += float(abs(Random() % 100) - 50) / 200; pos.y += float(abs(Random() % 100) - 50) / 200; pos.z += float(abs(Random() % 100) - 50) / 200; 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); Sprite::setLastSpriteSpecial(1); } } } howmany = findLength(&velocity) * 4; if (detail == 2) { if (environment == snowyenvironment) { for (int j = 0; j < howmany; j++) { tempvel.x = float(abs(Random() % 100) - 50) / 20; tempvel.y = float(abs(Random() % 100) - 50) / 20; tempvel.z = float(abs(Random() % 100) - 50) / 20; pos = coords; pos.y += 1; pos.x += float(abs(Random() % 100) - 50) / 200; pos.y += float(abs(Random() % 100) - 50) / 200; pos.z += float(abs(Random() % 100) - 50) / 200; Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1); Sprite::setLastSpriteSpecial(2); } } } } Object::objects[i]->rotx += velocity.x * multiplier * 6; Object::objects[i]->roty += velocity.z * multiplier * 6; Object::objects[i]->messedwith = .5; } } XYZ tempcoord; if (Object::objects[i]->type == treeleavestype && environment != desertenvironment) { if (Object::objects[i]->pitch == 0) { tempcoord = coords; } else { tempcoord = coords - Object::objects[i]->position; tempcoord = DoRotation(tempcoord, 0, -Object::objects[i]->yaw, 0); tempcoord = DoRotation(tempcoord, -Object::objects[i]->pitch, 0, 0); tempcoord += Object::objects[i]->position; } if (distsqflat(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 8 && distsq(&tempcoord, &Object::objects[i]->position) < Object::objects[i]->scale * Object::objects[i]->scale * 300 && tempcoord.y > Object::objects[i]->position.y + 3 * Object::objects[i]->scale) { if (Object::objects[i]->messedwith <= 0) { XYZ tempvel; XYZ pos; emit_sound_at(bushrustle, coords, 40 * findLength(&velocity)); if (id == 0) { addEnvSound(coords, 4 * findLength(&velocity)); } int howmany = 0; if (environment == grassyenvironment) { howmany = findLength(&velocity) * 4; } if (environment == snowyenvironment) { howmany = findLength(&velocity) * 2; } if (detail == 2) { if (environment != desertenvironment) { for (int j = 0; j < howmany; j++) { tempvel.x = float(abs(Random() % 100) - 50) / 20; tempvel.y = float(abs(Random() % 100) - 50) / 20; tempvel.z = float(abs(Random() % 100) - 50) / 20; pos = coords; pos += velocity * .1; pos.y += 1; pos.x += float(abs(Random() % 100) - 50) / 150; pos.y += float(abs(Random() % 100) - 50) / 150; pos.z += float(abs(Random() % 100) - 50) / 150; 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); Sprite::setLastSpriteSpecial(1); } } } howmany = findLength(&velocity) * 4; if (detail == 2) { if (environment == snowyenvironment) { for (int j = 0; j < howmany; j++) { tempvel.x = float(abs(Random() % 100) - 50) / 20; tempvel.y = float(abs(Random() % 100) - 50) / 20; tempvel.z = float(abs(Random() % 100) - 50) / 20; pos = coords; pos += velocity * .1; pos.y += 1; pos.x += float(abs(Random() % 100) - 50) / 150; pos.y += float(abs(Random() % 100) - 50) / 150; pos.z += float(abs(Random() % 100) - 50) / 150; Sprite::MakeSprite(splintersprite, pos, tempvel * .3 + velocity * float(abs(Random() % 100)) / 100 / 2, 1, 1, 1, .1, 1); Sprite::setLastSpriteSpecial(2); } } } } Object::objects[i]->messedwith = .5; } } } } } if (!skeleton.free) { bool play; play = 0; if ((stunned > 0 || surprised > 0) && Person::players.size() > 2 && aitype != passivetype) { play = 1; } if (hasvictim) { if (aitype != passivetype && victim->skeleton.free && !victim->dead) { play = 1; } } if (Tutorial::active && id != 0) { play = 0; } if (play && !isPlayerControlled()) { int whichsound = -1; if (speechdelay <= 0) { unsigned int i = abs(Random() % 4); if (i < 2) { whichsound = PersonType::types[creature].soundsTalk[i]; } } speechdelay = .3; if (whichsound != -1) { emit_sound_at(whichsound, coords); } } if (animTarget == staggerbackhighanim) { staggerdelay = 1; } if (animTarget == staggerbackhardanim) { staggerdelay = 1; } staggerdelay -= multiplier; if (animTarget != crouchstabanim && animTarget != swordgroundstabanim && animTarget != staffgroundsmashanim) { hasvictim = 1; } if (velocity.y < -30 && animTarget == jumpdownanim) { RagDoll(0); } if (animCurrent != getIdle() && wasIdle() && animTarget != getIdle() && isIdle()) { animTarget = getIdle(); frameTarget = 0; target = 0; } weaponmissdelay -= multiplier; highreversaldelay -= multiplier; lowreversaldelay -= multiplier; lastcollide -= multiplier; skiddelay -= multiplier; if (!isnormal(velocity.x) && velocity.x) { velocity = 0; } if (!isnormal(targettilt) && targettilt) { targettilt = 0; } if (!isnormal(targettilt2) && targettilt2) { targettilt2 = 0; } if (!isnormal(targetyaw) && targetyaw) { targetyaw = 0; } if (animTarget == bounceidleanim || animTarget == wolfidle || animTarget == walkanim || animTarget == drawrightanim || animTarget == crouchdrawrightanim || animTarget == drawleftanim || animTarget == fightidleanim || animTarget == fightsidestep || animTarget == hanganim || isCrouch() || animTarget == backhandspringanim) { //open hands and close mouth if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) { righthandmorphness = 0; righthandmorphend = 0; targetrighthandmorphness = 1; } if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) { lefthandmorphness = 0; lefthandmorphend = 0; targetlefthandmorphness = 1; } if (headmorphend != 3 && headmorphend != 5 && headmorphstart != 3 && headmorphstart != 5 && headmorphend != 0 && headmorphness == targetheadmorphness) { headmorphness = 0; headmorphend = 0; targetheadmorphness = 1; } } 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) { //open hands and mouth if (righthandmorphend != 0 && righthandmorphness == targetrighthandmorphness) { righthandmorphness = 0; righthandmorphend = 0; targetrighthandmorphness = 1; } if (lefthandmorphend != 0 && lefthandmorphness == targetlefthandmorphness) { lefthandmorphness = 0; lefthandmorphend = 0; targetlefthandmorphness = 1; } if (headmorphend != 1 && headmorphness == targetheadmorphness) { headmorphness = 0; headmorphend = 1; targetheadmorphness = 1; } } if (animTarget == jumpupanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || animTarget == swordfightidlebothanim || animTarget == blockhighleftanim) { //close hands and mouth if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) { righthandmorphness = 0; righthandmorphend = 1; targetrighthandmorphness = 1; } if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) { lefthandmorphness = 0; lefthandmorphend = 1; targetlefthandmorphness = 1; } if (headmorphend != 0 && headmorphness == targetheadmorphness) { headmorphness = 0; headmorphend = 0; targetheadmorphness = 1; } } 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) { //close hands and yell if (righthandmorphend != 1 && righthandmorphness == targetrighthandmorphness) { righthandmorphness = 0; righthandmorphend = 1; targetrighthandmorphness = 1; } if (lefthandmorphend != 1 && lefthandmorphness == targetlefthandmorphness) { lefthandmorphness = 0; lefthandmorphend = 1; targetlefthandmorphness = 1; } if (headmorphend != 2 && headmorphness == targetheadmorphness) { headmorphness = 1; headmorphend = 2; targetheadmorphness = 1; } } bool behind; behind = 0; if (hasvictim) { if ((victim != this->shared_from_this()) && !victim->dead && (victim->aitype != passivetype) && (victim->aitype != searchtype) && (aitype != passivetype) && (aitype != searchtype) && (victim->id < Person::players.size())) { behind = (normaldotproduct(facing, coords - victim->coords) > 0); } } if (!dead && animTarget != hurtidleanim) { if (behind || animTarget == killanim || animTarget == knifethrowanim || animTarget == knifefollowanim || animTarget == spinkickreversalanim || animTarget == rabbitkickreversedanim || animTarget == jumpreversedanim) { if (headmorphend != 4 || headmorphness == targetheadmorphness) { headmorphend = 4; //headmorphness=1; targetheadmorphness = 1; } } } if (hasWeapon()) { if (weapons[weaponids[weaponactive]].getType() != staff) { righthandmorphstart = 1; righthandmorphend = 1; } if (weapons[weaponids[weaponactive]].getType() == staff) { righthandmorphstart = 2; righthandmorphend = 2; } targetrighthandmorphness = 1; } terrainnormal = terrain.getNormal(coords.x, coords.z); if (Animation::animations[animTarget].attack != reversal) { if (!isnormal(coords.x)) { coords = oldcoords; } oldcoords = coords; } flatfacing = 0; flatfacing.z = 1; flatfacing = DoRotation(flatfacing, 0, yaw, 0); facing = flatfacing; ReflectVector(&facing, terrainnormal); Normalise(&facing); if (isRun() || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim) { if (onterrain) { targettilt2 = -facing.y * 20; } else { targettilt2 = 0; } } onterrain = 0; if (!isRun() && !Animation::animations[animTarget].attack && animTarget != getupfromfrontanim && animTarget != getupfrombackanim && animTarget != sneakanim) { targettilt2 = 0; } if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) { flatvelocity = velocity; flatvelocity.y = 0; flatvelspeed = findLength(&flatvelocity); targettilt = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(DoRotation(flatfacing, 0, -90, 0), flatvelocity); targettilt2 = flatvelspeed * fast_sqrt(abs(velocity.y) * .7) * normaldotproduct(flatfacing, flatvelocity); if (velocity.y < 0) { targettilt2 *= -1; } if (velocity.y < 0) { targettilt *= -1; } if (targettilt > 25) { targettilt = 25; } if (targettilt < -25) { targettilt = -25; } } if (targettilt2 > 45) { targettilt2 = 45; } if (targettilt2 < -45) { targettilt2 = -45; } if (abs(tilt2 - targettilt2) < multiplier * 400) { tilt2 = targettilt2; } else if (tilt2 > targettilt2) { tilt2 -= multiplier * 400; } else if (tilt2 < targettilt2) { tilt2 += multiplier * 400; } if (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && animTarget != getupfromfrontanim) { if (tilt2 > 25) { tilt2 = 25; } if (tilt2 < -25) { tilt2 = -25; } } if (!isnormal(targettilt) && targettilt) { targettilt = 0; } if (!isnormal(targettilt2) && targettilt2) { targettilt2 = 0; } //Running velocity if (animTarget == rabbittackleanim) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 65 * scale) { velocity /= velspeed; velspeed = speed * 65 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed; } if (animTarget != rabbitrunninganim && animTarget != wolfrunninganim) { if (isRun() || animTarget == rabbitkickanim) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 45 * scale) { velocity /= velspeed; velspeed = speed * 45 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); if (velspeed < speed * 30 * scale) { velspeed = speed * 30 * scale; } velocity = flatfacing * velspeed; } } else if (isRun()) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * PersonType::types[creature].maxRunSpeed * scale) { velocity /= velspeed; velspeed = speed * PersonType::types[creature].maxRunSpeed * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed; } if (animTarget == rollanim && targetFrame().label != 6) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 45 * scale) { velocity /= velspeed; velspeed = speed * 45 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed; } if (animTarget == sneakanim || animTarget == walkanim) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 12 * scale) { velocity /= velspeed; velspeed = speed * 12 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed; } if ((animTarget == fightidleanim || animTarget == knifefightidleanim) && (animCurrent == bounceidleanim || animCurrent == hurtidleanim)) { velocity += facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 2 * scale) { velocity /= velspeed; velspeed = speed * 2 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed; } if ((animTarget == bounceidleanim || animCurrent == hurtidleanim) && (animCurrent == fightidleanim || animCurrent == knifefightidleanim)) { velocity -= facing * multiplier * speed * 700 * scale; velspeed = findLength(&velocity); if (velspeed > speed * 2 * scale) { velocity /= velspeed; velspeed = speed * 2 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed * -1; } if (animTarget == fightsidestep) { velocity += DoRotation(facing * multiplier * speed * 700 * scale, 0, -90, 0); velspeed = findLength(&velocity); if (velspeed > speed * 12 * scale) { velocity /= velspeed; velspeed = speed * 12 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = DoRotation(flatfacing * velspeed, 0, -90, 0); } if (animTarget == staggerbackhighanim) { coords -= facing * multiplier * speed * 16 * scale; velocity = 0; } if (animTarget == staggerbackhardanim && Animation::animations[staggerbackhardanim].frames[frameTarget].label != 6) { coords -= facing * multiplier * speed * 20 * scale; velocity = 0; } if (animTarget == backhandspringanim) { //coords-=facing*multiplier*50*scale; velocity += facing * multiplier * speed * 700 * scale * -1; velspeed = findLength(&velocity); if (velspeed > speed * 50 * scale) { velocity /= velspeed; velspeed = speed * 50 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed * -1; } if (animTarget == dodgebackanim) { //coords-=facing*multiplier*50*scale; velocity += facing * multiplier * speed * 700 * scale * -1; velspeed = findLength(&velocity); if (velspeed > speed * 60 * scale) { velocity /= velspeed; velspeed = speed * 60 * scale; velocity *= velspeed; } velocity.y += gravity * multiplier * 20; ReflectVector(&velocity, terrain.getNormal(coords.x, coords.z)); velspeed = findLength(&velocity); velocity = flatfacing * velspeed * -1; } if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) { velspeed = findLength(&velocity); } if (animTarget == jumpupanim || animTarget == jumpdownanim || isFlip()) { velocity.y += gravity * multiplier; } if (animTarget != climbanim && animTarget != hanganim && !isWallJump()) { coords += velocity * multiplier; } if (coords.y < terrain.getHeight(coords.x, coords.z) && (animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) { if (isFlip() && targetFrame().label == 7) { RagDoll(0); } if (animTarget == jumpupanim) { jumppower = -4; animTarget = getIdle(); } target = 0; frameTarget = 0; onterrain = 1; if (id == 0) { pause_sound(whooshsound); OPENAL_SetVolume(channels[whooshsound], 0); } if (animTarget == jumpdownanim || isFlip()) { if (isFlip()) { jumppower = -4; } animTarget = getLanding(); emit_sound_at(landsound, coords, 128.); if (id == 0) { addEnvSound(coords); } } } if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && animTarget != climbanim && animTarget != hanganim && !isWallJump()) { coords.y += gravity * multiplier * 2; } if (animTarget != jumpupanim && animTarget != jumpdownanim && !isFlip() && coords.y < terrain.getHeight(coords.x, coords.z)) { coords.y = terrain.getHeight(coords.x, coords.z); onterrain = 1; } if (isIdle() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim || animTarget == crouchstabanim || animTarget == swordgroundstabanim || isStop() || animTarget == removeknifeanim || animTarget == crouchremoveknifeanim || isLanding() || isCrouch() || Animation::animations[animTarget].attack || (animTarget == rollanim && targetFrame().label == 6)) { velspeed = findLength(&velocity); velocity.y = 0; if (velspeed < multiplier * 300 * scale) { velocity = 0; } else { velocity -= velocity / velspeed * multiplier * 300 * scale; } if (velspeed > 5 && (isLanding() || isLandhard())) { skiddingdelay += multiplier; if (skiddelay <= 0) { FootLand(leftfoot, .5); FootLand(rightfoot, .5); skiddelay = .02; } } else { skiddingdelay = 0; } } if (isLandhard()) { velspeed = findLength(&velocity); velocity = 0; if (velspeed > 5 && (isLanding() || isLandhard())) { skiddingdelay += multiplier; if (skiddelay <= 0) { FootLand(leftfoot, .5); FootLand(rightfoot, .5); skiddelay = .02; } } else { skiddingdelay = 0; } } if (skiddingdelay < 0) { skiddingdelay += multiplier; } if (skiddingdelay > .02 && !forwardkeydown && !backkeydown && !leftkeydown && !rightkeydown && !jumpkeydown && isLanding() && !landhard) { skiddingdelay = -1; if (!onterrain || environment == grassyenvironment) { emit_sound_at(skidsound, coords, 128 * velspeed / 10); } else { emit_sound_at(snowskidsound, coords, 128 * velspeed / 10); } } if (Animation::animations[animTarget].attack == normalattack && animTarget != rabbitkickanim && !victim->skeleton.free) { terrainnormal = victim->coords - coords; Normalise(&terrainnormal); targetyaw = -asin(0 - terrainnormal.x); targetyaw *= 360 / 6.28; if (terrainnormal.z < 0) { targetyaw = 180 - targetyaw; } targettilt2 = -asin(terrainnormal.y) * 360 / 6.28; //*-70; } if (Animation::animations[animTarget].attack == reversal && animTarget != rabbittacklinganim) { targetyaw = victim->targetyaw; } if (animTarget == rabbittacklinganim) { coords = victim->coords; } } skeleton.oldfree = skeleton.free; XYZ midterrain; midterrain = 0; midterrain.x = terrain.size * terrain.scale / 2; midterrain.z = terrain.size * terrain.scale / 2; if (distsqflat(&coords, &midterrain) > (terrain.size * terrain.scale / 2 - viewdistance) * (terrain.size * terrain.scale / 2 - viewdistance)) { XYZ tempposit; tempposit = coords - midterrain; tempposit.y = 0; Normalise(&tempposit); tempposit *= (terrain.size * terrain.scale / 2 - viewdistance); coords.x = tempposit.x + midterrain.x; coords.z = tempposit.z + midterrain.z; } } /* EFFECT * inverse kinematics helper function */ void IKHelper(Person* p, float interp) { XYZ point, change, change2; float heightleft, heightright; // TODO: implement localToWorld and worldToLocal // but keep in mind it won't be the same math if player is ragdolled or something // - localToWorldStanding / worldToLocalStanding (or crouching or...?) // then comb through code for places where to use it // point = localToWorld(jointPos(leftfoot)) point = DoRotation(p->jointPos(leftfoot), 0, p->yaw, 0) * p->scale + p->coords; // adjust height of foot heightleft = terrain.getHeight(point.x, point.z) + .04; point.y = heightleft; change = p->jointPos(leftankle) - p->jointPos(leftfoot); change2 = p->jointPos(leftknee) - p->jointPos(leftfoot); // jointPos(leftfoot) = interpolate(worldToLocal(point), jointPos(leftfoot), interp) p->jointPos(leftfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(leftfoot) * (1 - interp); // move ankle along with foot p->jointPos(leftankle) = p->jointPos(leftfoot) + change; // average knee pos between old and new pos p->jointPos(leftknee) = (p->jointPos(leftfoot) + change2) / 2 + (p->jointPos(leftknee)) / 2; // do same as above for right leg point = DoRotation(p->jointPos(rightfoot), 0, p->yaw, 0) * p->scale + p->coords; heightright = terrain.getHeight(point.x, point.z) + .04; point.y = heightright; change = p->jointPos(rightankle) - p->jointPos(rightfoot); change2 = p->jointPos(rightknee) - p->jointPos(rightfoot); p->jointPos(rightfoot) = DoRotation((point - p->coords) / p->scale, 0, -p->yaw, 0) * interp + p->jointPos(rightfoot) * (1 - interp); p->jointPos(rightankle) = p->jointPos(rightfoot) + change; p->jointPos(rightknee) = (p->jointPos(rightfoot) + change2) / 2 + (p->jointPos(rightknee)) / 2; // fix up skeleton now that we've moved body parts? p->skeleton.DoConstraints(&p->coords, &p->scale); } /* EFFECT * MONSTER * TODO: ??? */ int Person::DrawSkeleton() { int oldplayerdetail; if ((frustum.SphereInFrustum(coords.x, coords.y + scale * 3, coords.z, scale * 8) && distsq(&viewer, &coords) < viewdistance * viewdistance) || skeleton.free == 3) { if (onterrain && (isIdle() || isCrouch() || wasIdle() || wasCrouch()) && !skeleton.free) { calcrot = 1; } if (headless) { headmorphness = 0; headmorphstart = 6; headmorphend = 6; } glAlphaFunc(GL_GREATER, 0.0001); XYZ terrainlight; float terrainheight; float distance; if (!isnormal(yaw)) { yaw = 0; } if (!isnormal(tilt)) { tilt = 0; } if (!isnormal(tilt2)) { tilt2 = 0; } oldplayerdetail = playerdetail; playerdetail = 0; if (distsq(&viewer, &coords) < viewdistance * viewdistance / 32 && detail == 2) { playerdetail = 1; } if (distsq(&viewer, &coords) < viewdistance * viewdistance / 128 && detail == 1) { playerdetail = 1; } if (distsq(&viewer, &coords) < viewdistance * viewdistance / 256 && (detail != 1 && detail != 2)) { playerdetail = 1; } if (id == 0) { playerdetail = 1; } if (playerdetail != oldplayerdetail) { updatedelay = 0; normalsupdatedelay = 0; } static float updatedelaychange; static float morphness; static float framemult; if (calcrot) { skeleton.FindForwards(); if (howactive == typesittingwall) { skeleton.specialforward[1] = 0; skeleton.specialforward[1].z = 1; } } static XYZ mid; static float M[16]; static int k; static int weaponattachmuscle; static int weaponrotatemuscle; static XYZ weaponpoint; static int start, endthing; if ((dead != 2 || skeleton.free != 2) && updatedelay <= 0) { if (!isSleeping() && !isSitting()) { // TODO: give these meaningful names const bool cond1 = (isIdle() || isCrouch() || isLanding() || isLandhard() || animTarget == drawrightanim || animTarget == drawleftanim || animTarget == crouchdrawrightanim); const bool cond2 = (wasIdle() || wasCrouch() || wasLanding() || wasLandhard() || animCurrent == drawrightanim || animCurrent == drawleftanim || animCurrent == crouchdrawrightanim); if (onterrain && (cond1 && cond2) && !skeleton.free) { IKHelper(this, 1); if (creature == wolftype) { IKHelper(this, 1); } } if (onterrain && (cond1 && !cond2) && !skeleton.free) { IKHelper(this, target); if (creature == wolftype) { IKHelper(this, target); } } if (onterrain && (!cond1 && cond2) && !skeleton.free) { IKHelper(this, 1 - target); if (creature == wolftype) { IKHelper(this, 1 - target); } } } if (!skeleton.free && (!Animation::animations[animTarget].attack && animTarget != getupfrombackanim && ((animTarget != rollanim && !isFlip()) || targetFrame().label == 6) && animTarget != getupfromfrontanim && animTarget != wolfrunninganim && animTarget != rabbitrunninganim && animTarget != backhandspringanim && animTarget != walljumpfrontanim && animTarget != hurtidleanim && !isLandhard() && !isSleeping())) { DoHead(); } else { targetheadyaw = -targetyaw; targetheadpitch = 0; if (Animation::animations[animTarget].attack == 3) { targetheadyaw += 180; } } for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) { skeleton.drawmodel.vertex[i] = 0; skeleton.drawmodel.vertex[i].y = 999; } for (int i = 0; i < skeleton.drawmodellow.vertexNum; i++) { skeleton.drawmodellow.vertex[i] = 0; skeleton.drawmodellow.vertex[i].y = 999; } for (int i = 0; i < skeleton.drawmodelclothes.vertexNum; i++) { skeleton.drawmodelclothes.vertex[i] = 0; skeleton.drawmodelclothes.vertex[i].y = 999; } for (unsigned int i = 0; i < skeleton.muscles.size(); i++) { // convenience renames const int p1 = skeleton.muscles[i].parent1->label; const int p2 = skeleton.muscles[i].parent2->label; if ((skeleton.muscles[i].vertices.size() > 0 && playerdetail) || (skeleton.muscles[i].verticeslow.size() > 0 && !playerdetail)) { morphness = 0; start = 0; endthing = 0; if (p1 == righthand || p2 == righthand) { morphness = righthandmorphness; start = righthandmorphstart; endthing = righthandmorphend; } if (p1 == lefthand || p2 == lefthand) { morphness = lefthandmorphness; start = lefthandmorphstart; endthing = lefthandmorphend; } if (p1 == head || p2 == head) { morphness = headmorphness; start = headmorphstart; endthing = headmorphend; } if ((p1 == neck && p2 == abdomen) || (p2 == neck && p1 == abdomen)) { morphness = chestmorphness; start = chestmorphstart; endthing = chestmorphend; } if ((p1 == groin && p2 == abdomen) || (p2 == groin && p1 == abdomen)) { morphness = tailmorphness; start = tailmorphstart; endthing = tailmorphend; } if (calcrot) { skeleton.FindRotationMuscle(i, animTarget); } mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if (!skeleton.free) { glRotatef(tilt2, 1, 0, 0); } if (!skeleton.free) { glRotatef(tilt, 0, 0, 1); } glTranslatef(mid.x, mid.y, mid.z); skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1; glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0); skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2; glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1); skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3; glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0); if (playerdetail || skeleton.free == 3) { for (unsigned j = 0; j < skeleton.muscles[i].vertices.size(); j++) { XYZ& v0 = skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]]; XYZ& v1 = skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); if (p1 == abdomen || p2 == abdomen) { glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(1).x, (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(1).y, (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(1).z); } if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) { glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(2).x, (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(2).y, (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(2).z); } if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) { glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(3).x, (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(3).y, (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(3).z); } if (p1 == head || p2 == head) { glTranslatef((v0.x * (1 - morphness) + v1.x * morphness) * getProportionXYZ(0).x, (v0.y * (1 - morphness) + v1.y * morphness) * getProportionXYZ(0).y, (v0.z * (1 - morphness) + v1.z * morphness) * getProportionXYZ(0).z); } glGetFloatv(GL_MODELVIEW_MATRIX, M); skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x = M[12] * scale; skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y = M[13] * scale; skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z = M[14] * scale; glPopMatrix(); } } if (!playerdetail || skeleton.free == 3) { for (unsigned j = 0; j < skeleton.muscles[i].verticeslow.size(); j++) { XYZ& v0 = skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); if (p1 == abdomen || p2 == abdomen) { glTranslatef(v0.x * getProportionXYZ(1).x, v0.y * getProportionXYZ(1).y, v0.z * getProportionXYZ(1).z); } if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) { glTranslatef(v0.x * getProportionXYZ(2).x, v0.y * getProportionXYZ(2).y, v0.z * getProportionXYZ(2).z); } if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) { glTranslatef(v0.x * getProportionXYZ(3).x, v0.y * getProportionXYZ(3).y, v0.z * getProportionXYZ(3).z); } if (p1 == head || p2 == head) { glTranslatef(v0.x * getProportionXYZ(0).x, v0.y * getProportionXYZ(0).y, v0.z * getProportionXYZ(0).z); } glGetFloatv(GL_MODELVIEW_MATRIX, M); skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x = M[12] * scale; skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y = M[13] * scale; skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z = M[14] * scale; glPopMatrix(); } } glPopMatrix(); } if (skeleton.clothes && skeleton.muscles[i].verticesclothes.size() > 0) { mid = (skeleton.muscles[i].parent1->position + skeleton.muscles[i].parent2->position) / 2; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); if (!skeleton.free) { glRotatef(tilt2, 1, 0, 0); } if (!skeleton.free) { glRotatef(tilt, 0, 0, 1); } glTranslatef(mid.x, mid.y, mid.z); skeleton.muscles[i].lastrotate1 = skeleton.muscles[i].rotate1; glRotatef(-skeleton.muscles[i].lastrotate1 + 90, 0, 1, 0); skeleton.muscles[i].lastrotate2 = skeleton.muscles[i].rotate2; glRotatef(-skeleton.muscles[i].lastrotate2 + 90, 0, 0, 1); skeleton.muscles[i].lastrotate3 = skeleton.muscles[i].rotate3; glRotatef(-skeleton.muscles[i].lastrotate3, 0, 1, 0); for (unsigned j = 0; j < skeleton.muscles[i].verticesclothes.size(); j++) { XYZ& v0 = skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); if (p1 == abdomen || p2 == abdomen) { glTranslatef(v0.x * getProportionXYZ(1).x, v0.y * getProportionXYZ(1).y, v0.z * getProportionXYZ(1).z); } if (p1 == lefthand || p1 == righthand || p1 == leftwrist || p1 == rightwrist || p1 == leftelbow || p1 == rightelbow || p2 == leftelbow || p2 == rightelbow) { glTranslatef(v0.x * getProportionXYZ(2).x, v0.y * getProportionXYZ(2).y, v0.z * getProportionXYZ(2).z); } if (p1 == leftfoot || p1 == rightfoot || p1 == leftankle || p1 == rightankle || p1 == leftknee || p1 == rightknee || p2 == leftknee || p2 == rightknee) { glTranslatef(v0.x * getProportionXYZ(3).x, v0.y * getProportionXYZ(3).y, v0.z * getProportionXYZ(3).z); } if (p1 == head || p2 == head) { glTranslatef(v0.x * getProportionXYZ(0).x, v0.y * getProportionXYZ(0).y, v0.z * getProportionXYZ(0).z); } glGetFloatv(GL_MODELVIEW_MATRIX, M); skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x = M[12] * scale; skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y = M[13] * scale; skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z = M[14] * scale; glPopMatrix(); } glPopMatrix(); } updatedelay = 1 + (float)(Random() % 100) / 1000; } if (skeleton.free != 2 && (skeleton.free == 1 || skeleton.free == 3 || id == 0 || (normalsupdatedelay <= 0) || animTarget == getupfromfrontanim || animTarget == getupfrombackanim || animCurrent == getupfromfrontanim || animCurrent == getupfrombackanim)) { normalsupdatedelay = 1; if (playerdetail || skeleton.free == 3) { skeleton.drawmodel.CalculateNormals(0); } if (!playerdetail || skeleton.free == 3) { skeleton.drawmodellow.CalculateNormals(0); } if (skeleton.clothes) { skeleton.drawmodelclothes.CalculateNormals(0); } } else { if (playerdetail || skeleton.free == 3) { skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm(); } if (!playerdetail || skeleton.free == 3) { skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm(); } if (skeleton.clothes) { skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm(); } } } framemult = .01; updatedelaychange = -framemult * 4 * (45 - findDistance(&viewer, &coords) * 1); if (updatedelaychange > -realmultiplier * 30) { updatedelaychange = -realmultiplier * 30; } if (updatedelaychange > -framemult * 4) { updatedelaychange = -framemult * 4; } if (skeleton.free == 1) { updatedelaychange *= 6; } if (id == 0) { updatedelaychange *= 8; } updatedelay += updatedelaychange; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(coords.x, coords.y - .02, coords.z); if (!skeleton.free) { glTranslatef(offset.x * scale, offset.y * scale, offset.z * scale); glRotatef(yaw, 0, 1, 0); } if (showpoints) { glPointSize(5); glColor4f(.4, 1, .4, 1); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glBegin(GL_POINTS); if (playerdetail) { for (int i = 0; i < skeleton.drawmodel.vertexNum; i++) { XYZ& v0 = skeleton.drawmodel.vertex[i]; glVertex3f(v0.x, v0.y, v0.z); } } glEnd(); glBegin(GL_LINES); if (playerdetail) { for (unsigned int i = 0; i < skeleton.drawmodel.Triangles.size(); i++) { const XYZ& v0 = skeleton.drawmodel.getTriangleVertex(i, 0); const XYZ& v1 = skeleton.drawmodel.getTriangleVertex(i, 1); const XYZ& v2 = skeleton.drawmodel.getTriangleVertex(i, 2); glVertex3f(v0.x, v0.y, v0.z); glVertex3f(v1.x, v1.y, v1.z); glVertex3f(v1.x, v1.y, v1.z); glVertex3f(v2.x, v2.y, v2.z); glVertex3f(v2.x, v2.y, v2.z); glVertex3f(v0.x, v0.y, v0.z); } } glEnd(); } terrainlight = terrain.getLighting(coords.x, coords.z); distance = distsq(&viewer, &coords); distance = (viewdistance * viewdistance - (distance - (viewdistance * viewdistance * fadestart)) * (1 / (1 - fadestart))) / viewdistance / viewdistance; if (distance > 1) { distance = 1; } if (distance > 0) { terrainheight = (coords.y - terrain.getHeight(coords.x, coords.z)) / 3 + 1; if (terrainheight < 1) { terrainheight = 1; } if (terrainheight > 1.7) { terrainheight = 1.7; } glColor4f((1 - (1 - terrainlight.x) / terrainheight) - burnt, (1 - (1 - terrainlight.y) / terrainheight) - burnt, (1 - (1 - terrainlight.z) / terrainheight) - burnt, distance); glDisable(GL_BLEND); glAlphaFunc(GL_GREATER, 0.0001); glEnable(GL_TEXTURE_2D); if (cellophane) { glDisable(GL_TEXTURE_2D); glColor4f(.7, .35, 0, .5); glDepthMask(0); glEnable(GL_LIGHTING); glEnable(GL_BLEND); } if (Tutorial::active && id != 0) { glColor4f(.7, .7, .7, 0.6); glDepthMask(0); glEnable(GL_LIGHTING); glEnable(GL_BLEND); if (canattack && cananger) { if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) { glDisable(GL_TEXTURE_2D); glColor4f(1, 0, 0, 0.8); } } glMatrixMode(GL_TEXTURE); glPushMatrix(); glTranslatef(0, -smoketex, 0); glTranslatef(-smoketex, 0, 0); } if (playerdetail) { if (!showpoints) { if (Tutorial::active && (id != 0)) { skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture); } else { skeleton.drawmodel.draw(); } } } if (!playerdetail) { if (Tutorial::active && (id != 0)) { skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture); } else { skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr); } } if (!(Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed)) { if (Tutorial::active && id != 0) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_TEXTURE_2D); glColor4f(.7, .7, .7, 0.6); glDepthMask(0); glEnable(GL_LIGHTING); glEnable(GL_BLEND); if (canattack && cananger) { if (Animation::animations[animTarget].attack == normalattack || Animation::animations[animTarget].attack == reversed) { glDisable(GL_TEXTURE_2D); glColor4f(1, 0, 0, 0.8); } } glMatrixMode(GL_TEXTURE); glPushMatrix(); glTranslatef(0, -smoketex * .6, 0); glTranslatef(smoketex * .6, 0, 0); if (playerdetail) { if (!showpoints) { if (Tutorial::active && (id != 0)) { skeleton.drawmodel.drawdifftex(Sprite::cloudimpacttexture); } else { skeleton.drawmodel.draw(); } } } if (!playerdetail) { if (Tutorial::active && (id != 0)) { skeleton.drawmodellow.drawdifftex(Sprite::cloudimpacttexture); } else { skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr); } } } } if (Tutorial::active && id != 0) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_TEXTURE_2D); } if (skeleton.clothes) { glDepthMask(0); glEnable(GL_BLEND); if (!immediate) { skeleton.drawmodelclothes.draw(); } if (immediate) { skeleton.drawmodelclothes.drawimmediate(); } glDepthMask(1); } } glPopMatrix(); if (num_weapons > 0) { for (k = 0; k < num_weapons; k++) { int i = weaponids[k]; if (weaponactive == k) { if (weapons[i].getType() != staff) { for (unsigned j = 0; j < skeleton.muscles.size(); j++) { if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) { weaponattachmuscle = j; } } for (unsigned j = 0; j < skeleton.muscles.size(); j++) { 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].vertices.size() > 0) { weaponrotatemuscle = j; } } weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2; if (creature == wolftype) { weaponpoint = (jointPos(rightwrist) * .7 + jointPos(righthand) * .3); } } if (weapons[i].getType() == staff) { for (unsigned j = 0; j < skeleton.muscles.size(); j++) { if ((skeleton.muscles[j].parent1->label == righthand || skeleton.muscles[j].parent2->label == righthand) && skeleton.muscles[j].vertices.size() > 0) { weaponattachmuscle = j; } } for (unsigned j = 0; j < skeleton.muscles.size(); j++) { 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].vertices.size() > 0) { weaponrotatemuscle = j; } } //weaponpoint=jointPos(rightwrist); weaponpoint = (skeleton.muscles[weaponattachmuscle].parent1->position + skeleton.muscles[weaponattachmuscle].parent2->position) / 2; //weaponpoint+=skeleton.specialforward[1]*.1+(jointPos(rightwrist)-jointPos(rightelbow)); XYZ tempnormthing, vec1, vec2; vec1 = (jointPos(rightwrist) - jointPos(rightelbow)); vec2 = (jointPos(rightwrist) - jointPos(rightshoulder)); CrossProduct(&vec1, &vec2, &tempnormthing); Normalise(&tempnormthing); if (animTarget != staffhitanim && animCurrent != staffhitanim && animTarget != staffgroundsmashanim && animCurrent != staffgroundsmashanim && animTarget != staffspinhitanim && animCurrent != staffspinhitanim) { weaponpoint += tempnormthing * .1 - skeleton.specialforward[1] * .3 + (jointPos(rightwrist) - jointPos(rightelbow)); } } } if (weaponactive != k && weaponstuck != k) { if (weapons[i].getType() == knife) { weaponpoint = jointPos(abdomen) + (jointPos(righthip) - jointPos(lefthip)) * .1 + (jointPos(rightshoulder) - jointPos(leftshoulder)) * .35; } if (weapons[i].getType() == sword) { weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33; } if (weapons[i].getType() == staff) { weaponpoint = jointPos(abdomen) + (jointPos(lefthip) - jointPos(righthip)) * .09 + (jointPos(leftshoulder) - jointPos(rightshoulder)) * .33; } for (unsigned j = 0; j < skeleton.muscles.size(); j++) { 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].vertices.size() > 0) { weaponrotatemuscle = j; } } } if (weaponstuck == k) { if (weaponstuckwhere == 0) { weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 - skeleton.forward * .8; } else { weaponpoint = jointPos(abdomen) * .5 + jointPos(neck) * .5 + skeleton.forward * .8; } for (unsigned j = 0; j < skeleton.muscles.size(); j++) { 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].vertices.size() > 0) { weaponrotatemuscle = j; } } } if (skeleton.free) { weapons[i].position = weaponpoint * scale + coords; weapons[i].bigrotation = 0; weapons[i].bigtilt = 0; weapons[i].bigtilt2 = 0; } else { 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; weapons[i].bigrotation = yaw; weapons[i].bigtilt = tilt; weapons[i].bigtilt2 = tilt2; } weapons[i].rotation1 = skeleton.muscles[weaponrotatemuscle].lastrotate1; weapons[i].rotation2 = skeleton.muscles[weaponrotatemuscle].lastrotate2; weapons[i].rotation3 = skeleton.muscles[weaponrotatemuscle].lastrotate3; if (weaponactive == k) { if (weapons[i].getType() == knife) { weapons[i].smallrotation = 180; weapons[i].smallrotation2 = 0; if (isCrouch() || wasCrouch()) { weapons[i].smallrotation2 = 20; } if (animTarget == hurtidleanim) { weapons[i].smallrotation2 = 50; } if ((animCurrent == crouchstabanim && animTarget == crouchstabanim) || (animCurrent == backhandspringanim && animTarget == backhandspringanim)) { XYZ temppoint1, temppoint2; float distance; temppoint1 = jointPos(righthand); temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target); distance = findDistance(&temppoint1, &temppoint2); weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance); weapons[i].rotation2 *= 360 / 6.28; temppoint1.y = 0; temppoint2.y = 0; weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2)); weapons[i].rotation1 *= 360 / 6.28; weapons[i].rotation3 = 0; weapons[i].smallrotation = -90; weapons[i].smallrotation2 = 0; if (temppoint1.x > temppoint2.x) { weapons[i].rotation1 = 360 - weapons[i].rotation1; } } if ((animCurrent == knifeslashreversalanim && animTarget == knifeslashreversalanim) || (animCurrent == knifeslashreversedanim && animTarget == knifeslashreversedanim)) { XYZ temppoint1, temppoint2; float distance; temppoint1 = jointPos(righthand); temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target); distance = findDistance(&temppoint1, &temppoint2); weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance); weapons[i].rotation2 *= 360 / 6.28; temppoint1.y = 0; temppoint2.y = 0; weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2)); weapons[i].rotation1 *= 360 / 6.28; weapons[i].rotation3 = 0; weapons[i].smallrotation = 90; weapons[i].smallrotation2 = 0; if (temppoint1.x > temppoint2.x) { weapons[i].rotation1 = 360 - weapons[i].rotation1; } } if (animTarget == knifethrowanim) { weapons[i].smallrotation = 90; //weapons[i].smallrotation2=-90; weapons[i].smallrotation2 = 0; weapons[i].rotation1 = 0; weapons[i].rotation2 = 0; weapons[i].rotation3 = 0; } if (animTarget == knifesneakattackanim && frameTarget < 5) { weapons[i].smallrotation = -90; weapons[i].rotation1 = 0; weapons[i].rotation2 = 0; weapons[i].rotation3 = 0; } } if (weapons[i].getType() == sword) { weapons[i].smallrotation = 0; weapons[i].smallrotation2 = 0; if (animTarget == knifethrowanim) { weapons[i].smallrotation = -90; weapons[i].smallrotation2 = 0; weapons[i].rotation1 = 0; weapons[i].rotation2 = 0; weapons[i].rotation3 = 0; } 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)) { XYZ temppoint1, temppoint2; float distance; temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand); temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target); distance = findDistance(&temppoint1, &temppoint2); weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance); weapons[i].rotation2 *= 360 / 6.28; temppoint1.y = 0; temppoint2.y = 0; weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2)); weapons[i].rotation1 *= 360 / 6.28; weapons[i].rotation3 = 0; weapons[i].smallrotation = 90; weapons[i].smallrotation2 = 0; if (temppoint1.x > temppoint2.x) { weapons[i].rotation1 = 360 - weapons[i].rotation1; } } } if (weapons[i].getType() == staff) { weapons[i].smallrotation = 100; weapons[i].smallrotation2 = 0; if ((animTarget == staffhitanim && animCurrent == staffhitanim) || (animTarget == staffhitreversedanim && animCurrent == staffhitreversedanim) || (animTarget == staffspinhitreversedanim && animCurrent == staffspinhitreversedanim) || (animTarget == staffgroundsmashanim && animCurrent == staffgroundsmashanim) || (animTarget == staffspinhitanim && animCurrent == staffspinhitanim)) { XYZ temppoint1, temppoint2; float distance; temppoint1 = currentFrame().joints[skeleton.jointlabels[righthand]].position * (1 - target) + targetFrame().joints[skeleton.jointlabels[righthand]].position * (target); //jointPos(righthand); temppoint2 = currentFrame().weapontarget * (1 - target) + targetFrame().weapontarget * (target); distance = findDistance(&temppoint1, &temppoint2); weapons[i].rotation2 = asin((temppoint1.y - temppoint2.y) / distance); weapons[i].rotation2 *= 360 / 6.28; temppoint1.y = 0; temppoint2.y = 0; weapons[i].rotation1 = acos((temppoint1.z - temppoint2.z) / findDistance(&temppoint1, &temppoint2)); weapons[i].rotation1 *= 360 / 6.28; weapons[i].rotation3 = 0; weapons[i].smallrotation = 90; weapons[i].smallrotation2 = 0; if (temppoint1.x > temppoint2.x) { weapons[i].rotation1 = 360 - weapons[i].rotation1; } } } } if (weaponactive != k && weaponstuck != k) { if (weapons[i].getType() == knife) { weapons[i].smallrotation = -70; weapons[i].smallrotation2 = 10; } if (weapons[i].getType() == sword) { weapons[i].smallrotation = -100; weapons[i].smallrotation2 = -8; } if (weapons[i].getType() == staff) { weapons[i].smallrotation = -100; weapons[i].smallrotation2 = -8; } } if (weaponstuck == k) { if (weaponstuckwhere == 0) { weapons[i].smallrotation = 180; } else { weapons[i].smallrotation = 0; } weapons[i].smallrotation2 = 10; } } } } calcrot = 0; if (skeleton.free) { calcrot = 1; } if (Animation::animations[animTarget].attack || isRun() || animTarget == staggerbackhardanim || isFlip() || animTarget == climbanim || animTarget == sneakanim || animTarget == rollanim || animTarget == walkanim || animTarget == backhandspringanim || isWallJump()) { calcrot = 1; } if (animCurrent != animTarget) { calcrot = 1; } if (skeleton.free == 2) { calcrot = 0; } return 0; } /* FUNCTION? */ int Person::SphereCheck(XYZ* p1, float radius, XYZ* p, XYZ* move, float* rotate, Model* model) { static float distance; static float olddistance; static int intersecting; static int firstintersecting; static XYZ point; static XYZ oldp1; static XYZ start, end; static float slopethreshold = -.4; firstintersecting = -1; oldp1 = *p1; *p1 = *p1 - *move; if (distsq(p1, &model->boundingspherecenter) > radius * radius + model->boundingsphereradius * model->boundingsphereradius) { return -1; } if (*rotate) { *p1 = DoRotation(*p1, 0, -*rotate, 0); } for (int i = 0; i < 4; i++) { for (unsigned int j = 0; j < model->Triangles.size(); j++) { if (model->Triangles[j].facenormal.y <= slopethreshold) { intersecting = 0; distance = abs((model->Triangles[j].facenormal.x * p1->x) + (model->Triangles[j].facenormal.y * p1->y) + (model->Triangles[j].facenormal.z * p1->z) - ((model->Triangles[j].facenormal.x * model->vertex[model->Triangles[j].vertex[0]].x) + (model->Triangles[j].facenormal.y * model->vertex[model->Triangles[j].vertex[0]].y) + (model->Triangles[j].facenormal.z * model->vertex[model->Triangles[j].vertex[0]].z))); if (distance < radius) { point = *p1 - model->Triangles[j].facenormal * distance; if (PointInTriangle(&point, model->Triangles[j].facenormal, &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]])) { intersecting = 1; } if (!intersecting) { intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], p1, &radius); } if (!intersecting) { intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]], p1, &radius); } if (!intersecting) { intersecting = sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[2]], p1, &radius); } end = *p1 - point; if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) { start = *p1; end = *p1; end.y -= radius; 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->Triangles[j].facenormal, &point)) { p1->y = point.y + radius; if ((animTarget == jumpdownanim || isFlip())) { if (isFlip() && (frameTarget < 5 || targetFrame().label == 7 || targetFrame().label == 4)) { RagDoll(0); } if (animTarget == jumpupanim) { jumppower = -4; animTarget = getIdle(); } target = 0; frameTarget = 0; onterrain = 1; if (id == 0) { pause_sound(whooshsound); OPENAL_SetVolume(channels[whooshsound], 0); } if ((animTarget == jumpdownanim || isFlip()) && !wasLanding() && !wasLandhard()) { if (isFlip()) { jumppower = -4; } animTarget = getLanding(); emit_sound_at(landsound, coords, 128.); if (id == 0) { addEnvSound(coords); } } } } } } if ((distance < olddistance || firstintersecting == -1) && intersecting) { olddistance = distance; firstintersecting = j; *p = point; } } } for (unsigned int j = 0; j < model->Triangles.size(); j++) { if (model->Triangles[j].facenormal.y > slopethreshold) { intersecting = 0; start = *p1; start.y -= radius / 4; XYZ& v0 = model->vertex[model->Triangles[j].vertex[0]]; XYZ& v1 = model->vertex[model->Triangles[j].vertex[1]]; XYZ& v2 = model->vertex[model->Triangles[j].vertex[2]]; distance = abs((model->Triangles[j].facenormal.x * start.x) + (model->Triangles[j].facenormal.y * start.y) + (model->Triangles[j].facenormal.z * start.z) - ((model->Triangles[j].facenormal.x * v0.x) + (model->Triangles[j].facenormal.y * v0.y) + (model->Triangles[j].facenormal.z * v0.z))); if (distance < radius * .5) { point = start - model->Triangles[j].facenormal * distance; if (PointInTriangle(&point, model->Triangles[j].facenormal, &v0, &v1, &v2)) { intersecting = 1; } if (!intersecting) { intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, p1->x, p1->y, p1->z, radius / 2); } if (!intersecting) { intersecting = sphere_line_intersection(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2); } if (!intersecting) { intersecting = sphere_line_intersection(v0.x, v0.y, v0.z, v2.x, v2.y, v2.z, p1->x, p1->y, p1->z, radius / 2); } end = *p1 - point; if (dotproduct(&model->Triangles[j].facenormal, &end) > 0 && intersecting) { if ((animTarget == jumpdownanim || animTarget == jumpupanim || isFlip())) { start = velocity; velocity -= DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0) * findLength(&velocity) * abs(normaldotproduct(velocity, DoRotation(model->Triangles[j].facenormal, 0, *rotate, 0))); //(distance-radius*.5)/multiplier; if (findLengthfast(&start) < findLengthfast(&velocity)) { velocity = start; } } *p1 += model->Triangles[j].facenormal * (distance - radius * .5); } } if ((distance < olddistance || firstintersecting == -1) && intersecting) { olddistance = distance; firstintersecting = j; *p = point; } } } } if (*rotate) { *p = DoRotation(*p, 0, *rotate, 0); } *p = *p + *move; if (*rotate) { *p1 = DoRotation(*p1, 0, *rotate, 0); } *p1 += *move; return firstintersecting; } int findPathDist(int start, int end) { int connected; int closest; unsigned int smallestcount = 1000; for (char i = 0; i < 50; i++) { unsigned int count = 0; int last = start; int last2 = -1; int last3 = -1; int last4 = -1; while (last != end && count < 30) { closest = -1; for (int j = 0; j < Game::numpathpoints; j++) { if (j != last && j != last2 && j != last3 && j != last4) { connected = 0; if (Game::numpathpointconnect[j]) { for (int k = 0; k < Game::numpathpointconnect[j]; k++) { if (Game::pathpointconnect[j][k] == last) { connected = 1; } } } if (!connected) { if (Game::numpathpointconnect[last]) { for (int k = 0; k < Game::numpathpointconnect[last]; k++) { if (Game::pathpointconnect[last][k] == j) { connected = 1; } } } } if (connected) { if (closest == -1 || Random() % 2 == 0) { closest = j; } } } } last4 = last3; last3 = last2; last2 = last; last = closest; count++; } if (count < smallestcount) { smallestcount = count; } } return smallestcount; } void Person::takeWeapon(int weaponId) { weaponactive = 0; weapons[weaponId].owner = id; if (num_weapons > 0) { weaponids[num_weapons] = weaponids[0]; } num_weapons++; weaponids[0] = weaponId; } void Person::addClothes() { if (clothes.size() > 0) { for (unsigned i = 0; i < clothes.size(); i++) { addClothes(i); } DoMipmaps(); } } bool Person::addClothes(const int& clothesId) { LOGFUNC; const std::string fileName = clothes[clothesId]; GLubyte* array = &skeleton.skinText[0]; //Load Image ImageRec texture; bool opened = load_image(Folders::getResourcePath(fileName).c_str(), texture); float alphanum; //Is it valid? if (opened) { float tintr = clothestintr[clothesId]; float tintg = clothestintg[clothesId]; float tintb = clothestintb[clothesId]; if (tintr > 1) { tintr = 1; } if (tintg > 1) { tintg = 1; } if (tintb > 1) { tintb = 1; } if (tintr < 0) { tintr = 0; } if (tintg < 0) { tintg = 0; } if (tintb < 0) { tintb = 0; } int bytesPerPixel = texture.bpp / 8; int tempnum = 0; alphanum = 255; for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) { if (bytesPerPixel == 3) { alphanum = 255; } else if ((i + 1) % 4 == 0) { alphanum = texture.data[i]; } if ((i + 1) % 4 || bytesPerPixel == 3) { if ((i % 4) == 0) { texture.data[i] *= tintr; } if ((i % 4) == 1) { texture.data[i] *= tintg; } if ((i % 4) == 2) { texture.data[i] *= tintb; } array[tempnum] = (float)array[tempnum] * (1 - alphanum / 255) + (float)texture.data[i] * (alphanum / 255); tempnum++; } } return 1; } else { return 0; } } void Person::doAI() { if (!isPlayerControlled() && !Dialog::inDialog()) { jumpclimb = 0; //disable movement in editor if (Game::editorenabled) { stunned = 1; } pause = 0; if (distsqflat(&Person::players[0]->coords, &coords) < 30 && Person::players[0]->coords.y > coords.y + 2 && !Person::players[0]->onterrain) { pause = 1; } //pathfinding if (aitype == pathfindtype) { if (finalpathfindpoint == -1) { float closestdistance; float tempdist = 0.0f; int closest; XYZ colpoint; closest = -1; closestdistance = -1; for (int j = 0; j < Game::numpathpoints; j++) { if (closest == -1 || distsq(&finalfinaltarget, &Game::pathpoint[j]) < closestdistance) { closestdistance = distsq(&finalfinaltarget, &Game::pathpoint[j]); closest = j; finaltarget = Game::pathpoint[j]; } } finalpathfindpoint = closest; for (int j = 0; j < Game::numpathpoints; j++) { for (int k = 0; k < Game::numpathpointconnect[j]; k++) { DistancePointLine(&finalfinaltarget, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint); if (sq(tempdist) < closestdistance) { if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) < findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) { closestdistance = sq(tempdist); closest = j; finaltarget = colpoint; } } } } finalpathfindpoint = closest; } if (targetpathfindpoint == -1) { float closestdistance; float tempdist = 0.0f; int closest; XYZ colpoint; closest = -1; closestdistance = -1; if (lastpathfindpoint == -1) { for (int j = 0; j < Game::numpathpoints; j++) { if (j != lastpathfindpoint) { if (closest == -1 || (distsq(&coords, &Game::pathpoint[j]) < closestdistance)) { closestdistance = distsq(&coords, &Game::pathpoint[j]); closest = j; } } } targetpathfindpoint = closest; for (int j = 0; j < Game::numpathpoints; j++) { if (j != lastpathfindpoint) { for (int k = 0; k < Game::numpathpointconnect[j]; k++) { DistancePointLine(&coords, &Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]], &tempdist, &colpoint); if (sq(tempdist) < closestdistance) { if (findDistance(&colpoint, &Game::pathpoint[j]) + findDistance(&colpoint, &Game::pathpoint[Game::pathpointconnect[j][k]]) < findDistance(&Game::pathpoint[j], &Game::pathpoint[Game::pathpointconnect[j][k]]) + .1) { closestdistance = sq(tempdist); closest = j; } } } } } targetpathfindpoint = closest; } else { for (int j = 0; j < Game::numpathpoints; j++) { if (j != lastpathfindpoint && j != lastpathfindpoint2 && j != lastpathfindpoint3 && j != lastpathfindpoint4) { bool connected = 0; if (Game::numpathpointconnect[j]) { for (int k = 0; k < Game::numpathpointconnect[j]; k++) { if (Game::pathpointconnect[j][k] == lastpathfindpoint) { connected = 1; } } } if (!connected) { if (Game::numpathpointconnect[lastpathfindpoint]) { for (int k = 0; k < Game::numpathpointconnect[lastpathfindpoint]; k++) { if (Game::pathpointconnect[lastpathfindpoint][k] == j) { connected = 1; } } } } if (connected) { tempdist = findPathDist(j, finalpathfindpoint); if (closest == -1 || tempdist < closestdistance) { closestdistance = tempdist; closest = j; } } } } targetpathfindpoint = closest; } } losupdatedelay -= multiplier; targetyaw = roughDirectionTo(coords, Game::pathpoint[targetpathfindpoint]); lookyaw = targetyaw; //reached target point if (distsqflat(&coords, &Game::pathpoint[targetpathfindpoint]) < .6) { lastpathfindpoint4 = lastpathfindpoint3; lastpathfindpoint3 = lastpathfindpoint2; lastpathfindpoint2 = lastpathfindpoint; lastpathfindpoint = targetpathfindpoint; if (lastpathfindpoint2 == -1) { lastpathfindpoint2 = lastpathfindpoint; } if (lastpathfindpoint3 == -1) { lastpathfindpoint3 = lastpathfindpoint2; } if (lastpathfindpoint4 == -1) { lastpathfindpoint4 = lastpathfindpoint3; } targetpathfindpoint = -1; } if (distsqflat(&coords, &finalfinaltarget) < distsqflat(&coords, &finaltarget) || distsqflat(&coords, &finaltarget) < .6 * sq(scale * 5) || lastpathfindpoint == finalpathfindpoint) { aitype = passivetype; } forwardkeydown = 1; leftkeydown = 0; backkeydown = 0; rightkeydown = 0; crouchkeydown = 0; attackkeydown = 0; throwkeydown = 0; if (avoidcollided > .8 && !jumpkeydown && collided < .8) { targetyaw += 90 * (whichdirection * 2 - 1); } if (collided < 1 || animTarget != jumpupanim) { jumpkeydown = 0; } if ((collided > .8 && jumppower >= 5)) { jumpkeydown = 1; } if ((!Tutorial::active || cananger) && hostile && !Person::players[0]->dead && distsq(&coords, &Person::players[0]->coords) < 400 && occluded < 25) { if (distsq(&coords, &Person::players[0]->coords) < 12 && Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled && (Person::players[0]->coords.y < coords.y + 5 || Person::players[0]->onterrain)) { aitype = attacktypecutoff; } if (distsq(&coords, &Person::players[0]->coords) < 30 && Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) { aitype = attacktypecutoff; } if (losupdatedelay < 0 && !Game::editorenabled && occluded < 2) { losupdatedelay = .2; for (unsigned j = 0; j < Person::players.size(); j++) { if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) { if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) { if (distsq(&coords, &Person::players[j]->coords) < 400) { if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) { if (Person::players[j]->coords.y < coords.y + 5 || Person::players[j]->onterrain) { if (!Person::players[j]->isWallJump() && -1 == Object::checkcollide(DoRotation(jointPos(head), 0, yaw, 0) * scale + coords, DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords) || (Person::players[j]->animTarget == hanganim && normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) { aitype = searchtype; lastchecktime = 12; lastseen = Person::players[j]->coords; lastseentime = 12; } } } } } } } } } if (aitype == attacktypecutoff && Game::musictype != 2) { if (creature != wolftype) { stunned = .6; surprised = .6; } } } if (aitype != passivetype && Game::leveltime > .5) { howactive = typeactive; } if (aitype == passivetype) { aiupdatedelay -= multiplier; losupdatedelay -= multiplier; lastseentime += multiplier; pausetime -= multiplier; if (lastseentime > 1) { lastseentime = 1; } if (aiupdatedelay < 0) { if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) { targetyaw = roughDirectionTo(coords, waypoints[waypoint]); lookyaw = targetyaw; aiupdatedelay = .05; if (distsqflat(&coords, &waypoints[waypoint]) < 1) { if (waypointtype[waypoint] == wppause) { pausetime = 4; } waypoint++; if (waypoint > numwaypoints - 1) { waypoint = 0; } } } if (numwaypoints > 1 && howactive == typeactive && pausetime <= 0) { forwardkeydown = 1; } else { forwardkeydown = 0; } leftkeydown = 0; backkeydown = 0; rightkeydown = 0; crouchkeydown = 0; attackkeydown = 0; throwkeydown = 0; if (avoidcollided > .8 && !jumpkeydown && collided < .8) { if (!avoidsomething) { targetyaw += 90 * (whichdirection * 2 - 1); } else { XYZ leftpos, rightpos; float leftdist, rightdist; leftpos = coords + DoRotation(facing, 0, 90, 0); rightpos = coords - DoRotation(facing, 0, 90, 0); leftdist = distsq(&leftpos, &avoidwhere); rightdist = distsq(&rightpos, &avoidwhere); if (leftdist < rightdist) { targetyaw += 90; } else { targetyaw -= 90; } } } } if (collided < 1 || animTarget != jumpupanim) { jumpkeydown = 0; } if ((collided > .8 && jumppower >= 5)) { jumpkeydown = 1; } //hearing sounds if (!Game::editorenabled) { if (howactive <= typesleeping) { if (numenvsounds > 0 && (!Tutorial::active || cananger) && hostile) { for (int j = 0; j < numenvsounds; j++) { float vol = howactive == typesleeping ? envsoundvol[j] - 14 : envsoundvol[j]; if (vol > 0 && distsq(&coords, &envsound[j]) < 2 * (vol + vol * (creature == rabbittype) * 3)) { aitype = attacktypecutoff; } } } } if (aitype != passivetype) { if (howactive == typesleeping) { setTargetAnimation(getupfromfrontanim); } howactive = typeactive; } } if (howactive < typesleeping && ((!Tutorial::active || cananger) && hostile) && !Person::players[0]->dead && distsq(&coords, &Person::players[0]->coords) < 400 && occluded < 25) { if (distsq(&coords, &Person::players[0]->coords) < 12 && Animation::animations[Person::players[0]->animTarget].height != lowheight && !Game::editorenabled) { aitype = attacktypecutoff; } if (distsq(&coords, &Person::players[0]->coords) < 30 && Animation::animations[Person::players[0]->animTarget].height == highheight && !Game::editorenabled) { aitype = attacktypecutoff; } //wolf smell if (creature == wolftype) { XYZ windsmell; for (unsigned j = 0; j < Person::players.size(); j++) { if (j == 0 || (Person::players[j]->dead && Person::players[j]->bloodloss > 0)) { float smelldistance = 50; if (j == 0 && Person::players[j]->num_weapons > 0) { if (weapons[Person::players[j]->weaponids[0]].bloody) { smelldistance = 100; } if (Person::players[j]->num_weapons == 2) { if (weapons[Person::players[j]->weaponids[1]].bloody) { smelldistance = 100; } } } if (j != 0) { smelldistance = 100; } windsmell = windvector; Normalise(&windsmell); windsmell = windsmell * 2 + Person::players[j]->coords; if (distsq(&coords, &windsmell) < smelldistance && !Game::editorenabled) { aitype = attacktypecutoff; } } } } if (howactive < typesleeping && losupdatedelay < 0 && !Game::editorenabled && occluded < 2) { losupdatedelay = .2; for (unsigned j = 0; j < Person::players.size(); j++) { if (j == 0 || Person::players[j]->skeleton.free || Person::players[j]->aitype != passivetype) { if (abs(Random() % 2) || Animation::animations[Person::players[j]->animTarget].height != lowheight || j != 0) { if (distsq(&coords, &Person::players[j]->coords) < 400) { if (normaldotproduct(facing, Person::players[j]->coords - coords) > 0) { if ((-1 == Object::checkcollide( DoRotation(jointPos(head), 0, yaw, 0) * scale + coords, DoRotation(Person::players[j]->jointPos(head), 0, Person::players[j]->yaw, 0) * Person::players[j]->scale + Person::players[j]->coords) && !Person::players[j]->isWallJump()) || (Person::players[j]->animTarget == hanganim && normaldotproduct(Person::players[j]->facing, coords - Person::players[j]->coords) < 0)) { lastseentime -= .2; if (j == 0 && Animation::animations[Person::players[j]->animTarget].height == lowheight) { lastseentime -= .4; } else { lastseentime -= .6; } } } } } if (lastseentime <= 0) { aitype = searchtype; lastchecktime = 12; lastseen = Person::players[j]->coords; lastseentime = 12; } } } } } //alerted surprise if (aitype == attacktypecutoff && Game::musictype != 2) { if (creature != wolftype) { stunned = .6; surprised = .6; } if (creature == wolftype) { stunned = .47; surprised = .47; } numseen++; } } //search for player int j; if (aitype == searchtype) { aiupdatedelay -= multiplier; losupdatedelay -= multiplier; if (!pause) { lastseentime -= multiplier; } lastchecktime -= multiplier; if (isRun() && !onground) { if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) { XYZ test2 = coords + facing; test2.y += 5; XYZ test = coords + facing; test.y -= 10; j = Object::checkcollide(test2, test, laststanding); if (j == -1) { j = Object::checkcollide(test2, test); } if (j == -1) { velocity = 0; setTargetAnimation(getStop()); targetyaw += 180; stunned = .5; //aitype=passivetype; aitype = pathfindtype; finalfinaltarget = waypoints[waypoint]; finalpathfindpoint = -1; targetpathfindpoint = -1; lastpathfindpoint = -1; lastpathfindpoint2 = -1; lastpathfindpoint3 = -1; lastpathfindpoint4 = -1; } else { laststanding = j; } } } //check out last seen location if (aiupdatedelay < 0) { targetyaw = roughDirectionTo(coords, lastseen); lookyaw = targetyaw; aiupdatedelay = .05; forwardkeydown = 1; if (distsqflat(&coords, &lastseen) < 1 * sq(scale * 5) || lastchecktime < 0) { forwardkeydown = 0; aiupdatedelay = 1; lastseen.x += (float(Random() % 100) - 50) / 25; lastseen.z += (float(Random() % 100) - 50) / 25; lastchecktime = 3; } leftkeydown = 0; backkeydown = 0; rightkeydown = 0; crouchkeydown = 0; attackkeydown = 0; throwkeydown = 0; if (avoidcollided > .8 && !jumpkeydown && collided < .8) { if (!avoidsomething) { targetyaw += 90 * (whichdirection * 2 - 1); } else { XYZ leftpos, rightpos; float leftdist, rightdist; leftpos = coords + DoRotation(facing, 0, 90, 0); rightpos = coords - DoRotation(facing, 0, 90, 0); leftdist = distsq(&leftpos, &avoidwhere); rightdist = distsq(&rightpos, &avoidwhere); if (leftdist < rightdist) { targetyaw += 90; } else { targetyaw -= 90; } } } } if (collided < 1 || animTarget != jumpupanim) { jumpkeydown = 0; } if ((collided > .8 && jumppower >= 5)) { jumpkeydown = 1; } if (numenvsounds > 0 && ((!Tutorial::active || cananger) && hostile)) { for (int k = 0; k < numenvsounds; k++) { if (distsq(&coords, &envsound[k]) < 2 * (envsoundvol[k] + envsoundvol[k] * (creature == rabbittype) * 3)) { aitype = attacktypecutoff; } } } if (!Person::players[0]->dead && losupdatedelay < 0 && !Game::editorenabled && occluded < 2 && ((!Tutorial::active || cananger) && hostile)) { losupdatedelay = .2; if (distsq(&coords, &Person::players[0]->coords) < 4 && Animation::animations[animTarget].height != lowheight) { aitype = attacktypecutoff; lastseentime = 1; } if (abs(Random() % 2) || Animation::animations[animTarget].height != lowheight) { //TODO: factor out canSeePlayer() if (distsq(&coords, &Person::players[0]->coords) < 400) { if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) { if ((Object::checkcollide( DoRotation(jointPos(head), 0, yaw, 0) * scale + coords, DoRotation(Person::players[0]->jointPos(head), 0, Person::players[0]->yaw, 0) * Person::players[0]->scale + Person::players[0]->coords) == -1) || (Person::players[0]->animTarget == hanganim && normaldotproduct(Person::players[0]->facing, coords - Person::players[0]->coords) < 0)) { /* //TODO: changed j to 0 on a whim, make sure this is correct (Person::players[j]->animTarget==hanganim&&normaldotproduct( Person::players[j]->facing,coords-Person::players[j]->coords)<0) */ aitype = attacktypecutoff; lastseentime = 1; } } } } } //player escaped if (lastseentime < 0) { //aitype=passivetype; numescaped++; aitype = pathfindtype; finalfinaltarget = waypoints[waypoint]; finalpathfindpoint = -1; targetpathfindpoint = -1; lastpathfindpoint = -1; lastpathfindpoint2 = -1; lastpathfindpoint3 = -1; lastpathfindpoint4 = -1; } } if (aitype != gethelptype) { runninghowlong = 0; } //get help from buddies if (aitype == gethelptype) { runninghowlong += multiplier; aiupdatedelay -= multiplier; if (aiupdatedelay < 0 || ally == 0) { aiupdatedelay = .2; //find closest ally //TODO: factor out closest search somehow if (!ally) { int closest = -1; float closestdist = -1; for (unsigned k = 0; k < Person::players.size(); k++) { if ((k != id) && (k != 0) && !Person::players[k]->dead && (Person::players[k]->howactive < typedead1) && !Person::players[k]->skeleton.free && (Person::players[k]->aitype == passivetype)) { float distance = distsq(&coords, &Person::players[k]->coords); if (closestdist == -1 || distance < closestdist) { closestdist = distance; closest = k; } } } if (closest != -1) { ally = closest; } else { ally = 0; } lastseen = Person::players[0]->coords; lastseentime = 12; } lastchecktime = 12; XYZ facing = coords; XYZ flatfacing = Person::players[ally]->coords; facing.y += jointPos(head).y * scale; flatfacing.y += Person::players[ally]->jointPos(head).y * Person::players[ally]->scale; if (-1 != Object::checkcollide(facing, flatfacing)) { lastseentime -= .1; } //no available ally, run back to player if (ally <= 0 || Person::players[ally]->skeleton.free || Person::players[ally]->aitype != passivetype || lastseentime <= 0) { aitype = searchtype; lastseentime = 12; } //seek out ally if (ally > 0) { targetyaw = roughDirectionTo(coords, Person::players[ally]->coords); lookyaw = targetyaw; aiupdatedelay = .05; forwardkeydown = 1; if (distsqflat(&coords, &Person::players[ally]->coords) < 3) { aitype = searchtype; lastseentime = 12; Person::players[ally]->aitype = searchtype; if (Person::players[ally]->lastseentime < lastseentime) { Person::players[ally]->lastseen = lastseen; Person::players[ally]->lastseentime = lastseentime; Person::players[ally]->lastchecktime = lastchecktime; } } if (avoidcollided > .8 && !jumpkeydown && collided < .8) { if (!avoidsomething) { targetyaw += 90 * (whichdirection * 2 - 1); } else { XYZ leftpos, rightpos; float leftdist, rightdist; leftpos = coords + DoRotation(facing, 0, 90, 0); rightpos = coords - DoRotation(facing, 0, 90, 0); leftdist = distsq(&leftpos, &avoidwhere); rightdist = distsq(&rightpos, &avoidwhere); if (leftdist < rightdist) { targetyaw += 90; } else { targetyaw -= 90; } } } } leftkeydown = 0; backkeydown = 0; rightkeydown = 0; crouchkeydown = 0; attackkeydown = 0; } if (collided < 1 || animTarget != jumpupanim) { jumpkeydown = 0; } if (collided > .8 && jumppower >= 5) { jumpkeydown = 1; } } //retreiving a weapon on the ground if (aitype == getweapontype) { aiupdatedelay -= multiplier; lastchecktime -= multiplier; if (aiupdatedelay < 0) { aiupdatedelay = .2; //ALLY IS WEPON if (ally < 0) { int closest = -1; float closestdist = -1; for (unsigned k = 0; k < weapons.size(); k++) { if (weapons[k].owner == -1) { float distance = distsq(&coords, &weapons[k].position); if (closestdist == -1 || distance < closestdist) { closestdist = distance; closest = k; } } } if (closest != -1) { ally = closest; } else { ally = -1; } } lastseentime = 12; if (!Person::players[0]->dead && ((!Tutorial::active || cananger) && hostile)) { if (ally < 0 || hasWeapon() || lastchecktime <= 0) { aitype = attacktypecutoff; lastseentime = 1; } } if (!Person::players[0]->dead) { if (ally >= 0) { if (weapons[ally].owner != -1 || distsq(&coords, &weapons[ally].position) > 16) { aitype = attacktypecutoff; lastseentime = 1; } //TODO: factor these out as moveToward() targetyaw = roughDirectionTo(coords, weapons[ally].position); lookyaw = targetyaw; aiupdatedelay = .05; forwardkeydown = 1; if (avoidcollided > .8 && !jumpkeydown && collided < .8) { if (!avoidsomething) { targetyaw += 90 * (whichdirection * 2 - 1); } else { XYZ leftpos, rightpos; float leftdist, rightdist; leftpos = coords + DoRotation(facing, 0, 90, 0); rightpos = coords - DoRotation(facing, 0, 90, 0); leftdist = distsq(&leftpos, &avoidwhere); rightdist = distsq(&rightpos, &avoidwhere); if (leftdist < rightdist) { targetyaw += 90; } else { targetyaw -= 90; } } } } } leftkeydown = 0; backkeydown = 0; rightkeydown = 0; attackkeydown = 0; throwkeydown = 1; crouchkeydown = 0; if (animTarget != crouchremoveknifeanim && animTarget != removeknifeanim) { throwtogglekeydown = 0; } drawkeydown = 0; } if (collided < 1 || animTarget != jumpupanim) { jumpkeydown = 0; } if ((collided > .8 && jumppower >= 5)) { jumpkeydown = 1; } } if (aitype == attacktypecutoff) { aiupdatedelay -= multiplier; //dodge or reverse rabbit kicks, knife throws, flips if (damage < damagetolerance * 2 / 3) { if ((Person::players[0]->animTarget == rabbitkickanim || Person::players[0]->animTarget == knifethrowanim || (Person::players[0]->isFlip() && normaldotproduct(Person::players[0]->facing, Person::players[0]->coords - coords) < 0)) && !Person::players[0]->skeleton.free && (aiupdatedelay < .1)) { attackkeydown = 0; if (isIdle()) { crouchkeydown = 1; } if (Person::players[0]->animTarget != rabbitkickanim && Person::players[0]->hasWeapon()) { if (weapons[Person::players[0]->weaponids[0]].getType() == knife) { if (isIdle() || isCrouch() || isRun() || isFlip()) { if (abs(Random() % 2) == 0) { setTargetAnimation(backhandspringanim); } else { setTargetAnimation(rollanim); } targetyaw += 90 * (abs(Random() % 2) * 2 - 1); wentforweapon = 0; } if (animTarget == jumpupanim || animTarget == jumpdownanim) { setTargetAnimation(flipanim); } } } forwardkeydown = 0; aiupdatedelay = .02; } } //get confused by flips if (Person::players[0]->isFlip() && !Person::players[0]->skeleton.free && Person::players[0]->animTarget != walljumprightkickanim && Person::players[0]->animTarget != walljumpleftkickanim) { if (distsq(&Person::players[0]->coords, &coords) < 25) { if ((1 - damage / damagetolerance) > .5) { stunned = 1; } } } //go for weapon on the ground if (wentforweapon < 3) { for (unsigned k = 0; k < weapons.size(); k++) { if (creature != wolftype) { if (num_weapons == 0 && weapons[k].owner == -1 && weapons[k].velocity.x == 0 && weapons[k].velocity.z == 0 && weapons[k].velocity.y == 0) { if (distsq(&coords, &weapons[k].position) < 16) { wentforweapon++; lastchecktime = 6; aitype = getweapontype; ally = -1; } } } } } //dodge/reverse walljump kicks if (damage < damagetolerance / 2) { if (Animation::animations[animTarget].height != highheight) { if (damage < damagetolerance * .5 && ((Person::players[0]->animTarget == walljumprightkickanim || Person::players[0]->animTarget == walljumpleftkickanim) && ((aiupdatedelay < .15 && difficulty == 2) || (aiupdatedelay < .08 && difficulty != 2)))) { crouchkeydown = 1; } } } //walked off a ledge (?) if (isRun() && !onground) { if (coords.y > terrain.getHeight(coords.x, coords.z) + 10) { XYZ test2 = coords + facing; test2.y += 5; XYZ test = coords + facing; test.y -= 10; j = Object::checkcollide(test2, test, laststanding); if (j == -1) { j = Object::checkcollide(test2, test); } if (j == -1) { velocity = 0; setTargetAnimation(getStop()); targetyaw += 180; stunned = .5; aitype = pathfindtype; finalfinaltarget = waypoints[waypoint]; finalpathfindpoint = -1; targetpathfindpoint = -1; lastpathfindpoint = -1; lastpathfindpoint2 = -1; lastpathfindpoint3 = -1; lastpathfindpoint4 = -1; } else { laststanding = j; } } } //lose sight of player in the air (?) if (Person::players[0]->coords.y > coords.y + 5 && Animation::animations[Person::players[0]->animTarget].height != highheight && !Person::players[0]->onterrain) { aitype = pathfindtype; finalfinaltarget = waypoints[waypoint]; finalpathfindpoint = -1; targetpathfindpoint = -1; lastpathfindpoint = -1; lastpathfindpoint2 = -1; lastpathfindpoint3 = -1; lastpathfindpoint4 = -1; } //it's time to think (?) if (aiupdatedelay < 0 && !Animation::animations[animTarget].attack && animTarget != staggerbackhighanim && animTarget != staggerbackhardanim && animTarget != backhandspringanim && animTarget != dodgebackanim) { //draw weapon if (!hasWeapon() && num_weapons > 0) { drawkeydown = Random() % 2; } else { drawkeydown = 0; } rabbitkickenabled = Random() % 2; //chase player XYZ rotatetarget = Person::players[0]->coords + Person::players[0]->velocity; XYZ targetpoint = Person::players[0]->coords; float vellength = findLength(&velocity); if (vellength != 0 && distsq(&Person::players[0]->coords, &coords) < distsq(&rotatetarget, &coords)) { targetpoint += Person::players[0]->velocity * findDistance(&Person::players[0]->coords, &coords) / vellength; } targetyaw = roughDirectionTo(coords, targetpoint); lookyaw = targetyaw; aiupdatedelay = .2 + fabs((float)(Random() % 100) / 1000); if (distsq(&coords, &Person::players[0]->coords) > 5 && (!Person::players[0]->hasWeapon() || hasWeapon())) { forwardkeydown = 1; } else if ((distsq(&coords, &Person::players[0]->coords) > 16 || distsq(&coords, &Person::players[0]->coords) < 9) && Person::players[0]->hasWeapon()) { forwardkeydown = 1; } else if (Random() % 6 == 0 || (creature == wolftype && Random() % 3 == 0)) { forwardkeydown = 1; } else { forwardkeydown = 0; } //chill out around the corpse if (Person::players[0]->dead) { forwardkeydown = 0; if (Random() % 10 == 0) { forwardkeydown = 1; } if (Random() % 100 == 0) { aitype = pathfindtype; finalfinaltarget = waypoints[waypoint]; finalpathfindpoint = -1; targetpathfindpoint = -1; lastpathfindpoint = -1; lastpathfindpoint2 = -1; lastpathfindpoint3 = -1; lastpathfindpoint4 = -1; } } leftkeydown = 0; backkeydown = 0; rightkeydown = 0; crouchkeydown = 0; throwkeydown = 0; if (avoidcollided > .8 && !jumpkeydown && collided < .8) { targetyaw += 90 * (whichdirection * 2 - 1); } //attack!!! if (Random() % 2 == 0 || hasWeapon() || creature == wolftype) { attackkeydown = 1; } else { attackkeydown = 0; } if (isRun() && Random() % 6 && distsq(&coords, &Person::players[0]->coords) > 7) { attackkeydown = 0; } //TODO: wat if (!isPlayerControlled() && (isIdle() || isCrouch() || isRun())) { int target = -2; for (unsigned j = 0; j < Person::players.size(); j++) { if (j != id && !Person::players[j]->skeleton.free && Person::players[j]->hasvictim && (Tutorial::active && reversaltrain || Random() % 2 == 0 && difficulty == 2 || Random() % 4 == 0 && difficulty == 1 || Random() % 8 == 0 && difficulty == 0 || Person::players[j]->lastattack2 == Person::players[j]->animTarget && Person::players[j]->lastattack3 == Person::players[j]->animTarget && (Random() % 2 == 0 || difficulty == 2) || (isIdle() || isRun()) && Person::players[j]->hasWeapon() || Person::players[j]->animTarget == swordslashanim && hasWeapon() || Person::players[j]->animTarget == staffhitanim || Person::players[j]->animTarget == staffspinhitanim)) { if (distsq(&Person::players[j]->coords, &Person::players[j]->victim->coords) < 4 && Person::players[j]->victim == Person::players[id] && (Person::players[j]->animTarget == sweepanim || Person::players[j]->animTarget == spinkickanim || Person::players[j]->animTarget == staffhitanim || Person::players[j]->animTarget == staffspinhitanim || Person::players[j]->animTarget == winduppunchanim || Person::players[j]->animTarget == upunchanim || Person::players[j]->animTarget == wolfslapanim || Person::players[j]->animTarget == knifeslashstartanim || Person::players[j]->animTarget == swordslashanim && (distsq(&Person::players[j]->coords, &coords) < 2 || hasWeapon()))) { if (target >= 0) { target = -1; } else { target = j; } } } } if (target >= 0) { Person::players[target]->Reverse(); } } if (collided < 1) { jumpkeydown = 0; } if (collided > .8 && jumppower >= 5 || distsq(&coords, &Person::players[0]->coords) > 400 && onterrain && creature == rabbittype) { jumpkeydown = 1; } //TODO: why are we controlling the human? if (normaldotproduct(facing, Person::players[0]->coords - coords) > 0) { Person::players[0]->jumpkeydown = 0; } if (Person::players[0]->animTarget == jumpdownanim && distsq(&Person::players[0]->coords, &coords) < 40) { crouchkeydown = 1; } if (jumpkeydown) { attackkeydown = 0; } if (Tutorial::active) { if (!canattack) { attackkeydown = 0; } } XYZ facing = coords; XYZ flatfacing = Person::players[0]->coords; facing.y += jointPos(head).y * scale; flatfacing.y += Person::players[0]->jointPos(head).y * Person::players[0]->scale; if (occluded >= 2) { if (-1 != Object::checkcollide(facing, flatfacing)) { if (!pause) { lastseentime -= .2; } if (lastseentime <= 0 && (creature != wolftype || weaponstuck == -1)) { aitype = searchtype; lastchecktime = 12; lastseen = Person::players[0]->coords; lastseentime = 12; } } else { lastseentime = 1; } } } } if (Animation::animations[Person::players[0]->animTarget].height == highheight && (aitype == attacktypecutoff || aitype == searchtype)) { if (Person::players[0]->coords.y > terrain.getHeight(Person::players[0]->coords.x, Person::players[0]->coords.z) + 10) { XYZ test = Person::players[0]->coords; test.y -= 40; if (-1 == Object::checkcollide(Person::players[0]->coords, test)) { stunned = 1; } } } //stunned if (aitype == passivetype && !(numwaypoints > 1) || stunned > 0 || pause && damage > superpermanentdamage) { if (pause) { lastseentime = 1; } targetyaw = yaw; forwardkeydown = 0; leftkeydown = 0; backkeydown = 0; rightkeydown = 0; jumpkeydown = 0; attackkeydown = 0; crouchkeydown = 0; throwkeydown = 0; } XYZ facing; facing = 0; facing.z = -1; XYZ flatfacing = DoRotation(facing, 0, yaw + 180, 0); facing = flatfacing; if (aitype == attacktypecutoff) { targetheadyaw = 180 - roughDirectionTo(coords, Person::players[0]->coords); targetheadpitch = pitchTo(coords, Person::players[0]->coords); } else if (howactive >= typesleeping) { targetheadyaw = targetyaw; targetheadpitch = 0; } else { if (interestdelay <= 0) { interestdelay = .7 + (float)(abs(Random() % 100)) / 100; headtarget = coords; headtarget.x += (float)(abs(Random() % 200) - 100) / 100; headtarget.z += (float)(abs(Random() % 200) - 100) / 100; headtarget.y += (float)(abs(Random() % 200) - 100) / 300; headtarget += facing * 1.5; } targetheadyaw = 180 - roughDirectionTo(coords, headtarget); targetheadpitch = pitchTo(coords, headtarget); } } } bool Person::catchKnife() { return ((PersonType::types[creature].knifeCatchingType == 0) && (Random() % 2 != 0) && (!hasWeapon()) && (aitype == attacktypecutoff)) || ((PersonType::types[creature].knifeCatchingType == 1) && (Random() % 3 != 0) && (!hasWeapon()) && (isIdle() || isRun() || animTarget == walkanim)); } Person::Person(Json::Value value, int /*mapvers*/, unsigned i) : Person() { id = i; whichskin = value["whichskin"].asInt(); creature = value["creature"].asInt(); coords = value["coords"]; yaw = value["yaw"].asFloat(); power = value["power"].asFloat(); speedmult = value["speedmult"].asFloat(); numwaypoints = value["waypoints"].size(); num_weapons = value["weapons"].size(); if (id == 0) { targetyaw = value["targetyaw"].asFloat(); } else { targetyaw = yaw; howactive = value["howactive"].asInt(); immobile = value["immobile"].asBool(); if (value["waypoints"].size() < 30) { for (unsigned k = 0; k < value["waypoints"].size(); k++) { waypointtype[k] = value["waypoints"][k]["type"].asInt(); waypoints[k] = value["waypoints"][k]["pos"]; } waypoint = value["waypoint"].asInt(); if (waypoint > int(value["waypoints"].size())) { waypoint = 0; } } else { // TODO output an error? //~ numwaypoints = 0; //~ waypoint = 0; //~ fpackf(tfile, "Bi Bi Bi", numwaypoints, waypoint, waypoint); } // Not sure why scale and proportion are not saved for main player scale = value.get("scale", -1).asFloat(); for (int k = 0; k < 4; k++) { proportions[k] = value["proportions"][k].asFloat(); } } if (value["weapons"].size() > 5) { throw InvalidPersonException(); } for (unsigned j = 0; j < value["weapons"].size(); j++) { weaponids[j] = weapons.size(); weapons.push_back(Weapon(value["weapons"][j].asInt(), id)); } armorhead = value["armor"]["head"].asFloat(); armorhigh = value["armor"]["high"].asFloat(); armorlow = value["armor"]["low"].asFloat(); protectionhead = value["protection"]["head"].asFloat(); protectionhigh = value["protection"]["high"].asFloat(); protectionlow = value["protection"]["low"].asFloat(); metalhead = value["metal"]["head"].asFloat(); metalhigh = value["metal"]["high"].asFloat(); metallow = value["metal"]["low"].asFloat(); for (unsigned k = 0; k < value["clothes"].size(); k++) { clothes.push_back(value["clothes"][k]["path"].asString()); clothestintr.push_back(value["clothes"][k]["tintr"].asFloat()); clothestintg.push_back(value["clothes"][k]["tintg"].asFloat()); clothestintb.push_back(value["clothes"][k]["tintb"].asFloat()); } loaded = true; damagetolerance = PersonType::types[creature].defaultDamageTolerance; if (scale < 0) { scale = PersonType::types[creature].defaultScale; } oldcoords = coords; realoldcoords = coords; } Person::operator Json::Value() { Json::Value person; person["whichskin"] = whichskin; person["creature"] = creature; person["coords"] = coords; person["yaw"] = yaw; person["power"] = power; person["speedmult"] = speedmult; if (aitype == playercontrolled) { person["targetyaw"] = targetyaw; } else { person["howactive"] = howactive; person["immobile"] = immobile; if (numwaypoints < 30) { for (int k = 0; k < numwaypoints; k++) { person["waypoints"][k]["type"] = waypointtype[k]; person["waypoints"][k]["pos"] = waypoints[k]; } person["waypoint"] = waypoint; } else { // TODO output an error? //~ numwaypoints = 0; //~ waypoint = 0; //~ fpackf(tfile, "Bi Bi Bi", numwaypoints, waypoint, waypoint); } // Not sure why scale and proportion are not saved for main player person["scale"] = scale; for (int k = 0; k < 4; k++) { person["proportions"][k] = getProportion(k); } } for (int k = 0; k < num_weapons; k++) { person["weapons"][k] = weapons[weaponids[k]].getType(); } person["armor"]["head"] = armorhead; person["armor"]["high"] = armorhigh; person["armor"]["low"] = armorlow; person["protection"]["head"] = protectionhead; person["protection"]["high"] = protectionhigh; person["protection"]["low"] = protectionlow; person["metal"]["head"] = metalhead; person["metal"]["high"] = metalhigh; person["metal"]["low"] = metallow; for (unsigned k = 0; k < clothes.size(); k++) { person["clothes"][k]["path"] = clothes[k]; person["clothes"][k]["tintr"] = clothestintr[k]; person["clothes"][k]["tintg"] = clothestintg[k]; person["clothes"][k]["tintb"] = clothestintb[k]; } return person; }