diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 40b9a2146..67fd54456 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -43,7 +43,7 @@ namespace float getXAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f) { float len = (dirLen > 0.0f)? dirLen : dir.length(); - return -Ogre::Math::ASin(dir.z / len).valueRadians(); + return -Ogre::Math::ASin(dir.z / len).valueDegrees(); } @@ -185,28 +185,10 @@ namespace MWMechanics */ bool AiCombat::execute (const MWWorld::Ptr& actor, AiState& state, float duration) { + // get or create temporary storage AiCombatStorage& storage = state.get(); - // PathFinder& mPathFinder; - // ObstacleCheck& mObstacleCheck = storage.mObstacleCheck; - float& timerAttack = storage.mTimerAttack; - float& timerReact = storage.mTimerReact; - float& timerCombatMove = storage.mTimerCombatMove; - bool& readyToAttack = storage.mReadyToAttack; - bool& attack = storage.mAttack; - bool& followTarget = storage.mFollowTarget; - bool& combatMove = storage.mCombatMove; - Ogre::Vector3& lastTargetPos = storage.mLastTargetPos; - const MWWorld::CellStore*& currentCell = storage.mCell; - boost::shared_ptr& currentAction = storage.mCurrentAction; - float& actionCooldown = storage.mActionCooldown; - float& strength = storage.mStrength; - float (&minMaxAttackDuration)[3][2] = storage.mMinMaxAttackDuration; - bool& minMaxAttackDurationInitialised = storage.mMinMaxAttackDurationInitialised; - bool& forceNoShortcut = storage.mForceNoShortcut; - ESM::Position& shortcutFailPos = storage.mShortcutFailPos; - Ogre::Vector3& lastActorPos = storage.mLastActorPos; - MWMechanics::Movement& movement = storage.mMovement; + //General description if(actor.getClass().getCreatureStats(actor).isDead()) @@ -233,9 +215,16 @@ namespace MWMechanics { actorClass.getCreatureStats(actor).setAttackingOrSpell(false); return true; - } + } + + + + //Update every frame + bool& combatMove = storage.mCombatMove; + float& timerCombatMove = storage.mTimerCombatMove; + MWMechanics::Movement& movement = storage.mMovement; if(combatMove) { timerCombatMove -= duration; @@ -266,6 +255,16 @@ namespace MWMechanics ESM::Weapon::AttackType attackType; + + + + bool& attack = storage.mAttack; + bool& readyToAttack = storage.mReadyToAttack; + float& timerAttack = storage.mTimerAttack; + + bool& minMaxAttackDurationInitialised = storage.mMinMaxAttackDurationInitialised; + float (&minMaxAttackDuration)[3][2] = storage.mMinMaxAttackDuration; + if(readyToAttack) { if (!minMaxAttackDurationInitialised) @@ -287,8 +286,11 @@ namespace MWMechanics actorClass.getCreatureStats(actor).setAttackingOrSpell(attack); - actionCooldown -= duration; + float& actionCooldown = storage.mActionCooldown; + actionCooldown -= duration; + + float& timerReact = storage.mTimerReact; float tReaction = 0.25f; if(timerReact < tReaction) { @@ -299,7 +301,7 @@ namespace MWMechanics //Update with period = tReaction timerReact = 0; - + const MWWorld::CellStore*& currentCell = storage.mCell; bool cellChange = currentCell && (actor.getCell() != currentCell); if(!currentCell || cellChange) { @@ -317,6 +319,7 @@ namespace MWMechanics float rangeAttack = 0; float rangeFollow = 0; + boost::shared_ptr& currentAction = storage.mCurrentAction; if (anim->upperBodyReady()) { currentAction = prepareNextAction(actor, target); @@ -382,6 +385,8 @@ namespace MWMechanics weapRange = 150.f; } + + float& strength = storage.mStrength; // start new attack if(readyToAttack) { @@ -447,6 +452,9 @@ namespace MWMechanics Ogre::Vector3 vTargetPos(target.getRefData().getPosition().pos); Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos; float distToTarget = vDirToTarget.length(); + + Ogre::Vector3& lastActorPos = storage.mLastActorPos; + bool& followTarget = storage.mFollowTarget; bool isStuck = false; float speed = 0.0f; @@ -473,6 +481,7 @@ namespace MWMechanics // note: in getZAngleToDir if we preserve dir.z then horizontal angle can be inaccurate if (distantCombat) { + Ogre::Vector3& lastTargetPos = storage.mLastTargetPos; Ogre::Vector3 vAimDir = AimDirToMovingTarget(actor, target, lastTargetPos, tReaction, weaptype, strength); lastTargetPos = vTargetPos; movement.mRotation[0] = getXAngleToDir(vAimDir); @@ -525,6 +534,9 @@ namespace MWMechanics if (!distantCombat) inLOS = world->getLOS(actor, target); // check if shortcut is available + bool& forceNoShortcut = storage.mForceNoShortcut; + ESM::Position& shortcutFailPos = storage.mShortcutFailPos; + if(inLOS && (!isStuck || readyToAttack) && (!forceNoShortcut || (Ogre::Vector3(shortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)) { diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7826df708..a70200833 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -33,7 +33,7 @@ namespace MWMechanics { // the z rotation angle (degrees) we want to reach // used every frame when mRotate is true - float mTargetAngle; + Ogre::Radian mTargetAngle; bool mRotate; float mReaction; // update some actions infrequently @@ -166,31 +166,16 @@ namespace MWMechanics */ bool AiWander::execute (const MWWorld::Ptr& actor, AiState& state, float duration) { - // define references for readability + // get or create temporary storage AiWanderStorage& storage = state.get(); - float& targetAngle = storage.mTargetAngle; - bool& rotate = storage.mRotate; - float& lastReaction = storage.mReaction; - AiWander::GreetingState& greetingState = storage.mSaidGreeting; - int& greetingTimer = storage.mGreetingTimer; - int& cachedCellX = storage.mCellX; - int& cachedCellY = storage.mCellY; - float& cachedCellXposition = storage.mXCell; - float& cachedCellYposition = storage.mYCell; - const MWWorld::CellStore*& currentCell = storage.mCell; - bool& chooseAction = storage.mChooseAction; - bool& idleNow = storage.mIdleNow; - bool& moveNow = storage.mMoveNow; - bool& walking = storage.mWalking; - short unsigned& playedIdle = storage.mPlayedIdle; - + const MWWorld::CellStore*& currentCell = storage.mCell; MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor); if(cStats.isDead() || cStats.getHealth().getCurrent() <= 0) return true; // Don't bother with dead actors - bool cellChange = storage.mCell && (actor.getCell() != storage.mCell); + bool cellChange = currentCell && (actor.getCell() != currentCell); if(!currentCell || cellChange) { currentCell = actor.getCell(); @@ -202,7 +187,11 @@ namespace MWMechanics cStats.setMovementFlag(CreatureStats::Flag_Run, false); ESM::Position pos = actor.getRefData().getPosition(); - + + + bool& idleNow = storage.mIdleNow; + bool& moveNow = storage.mMoveNow; + bool& walking = storage.mWalking; // Check if an idle actor is too close to a door - if so start walking mDoorCheckDuration += duration; if(mDoorCheckDuration >= DOOR_CHECK_INTERVAL) @@ -220,6 +209,7 @@ namespace MWMechanics } // Are we there yet? + bool& chooseAction = storage.mChooseAction; if(walking && mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { @@ -230,6 +220,8 @@ namespace MWMechanics mHasReturnPosition = false; } + + if(walking) // have not yet reached the destination { // turn towards the next point in mPath @@ -275,16 +267,20 @@ namespace MWMechanics } //#endif } - + + + Ogre::Radian& targetAngle = storage.mTargetAngle; + bool& rotate = storage.mRotate; if (rotate) { // Reduce the turning animation glitch by using a *HUGE* value of // epsilon... TODO: a proper fix might be in either the physics or the // animation subsystem - if (zTurn(actor, Ogre::Degree(targetAngle), Ogre::Degree(5))) + if (zTurn(actor, targetAngle, Ogre::Degree(5))) rotate = false; } + float& lastReaction = storage.mReaction; lastReaction += duration; if(lastReaction < REACTION_INTERVAL) { @@ -322,6 +318,12 @@ namespace MWMechanics } } + + + int& cachedCellX = storage.mCellX; + int& cachedCellY = storage.mCellY; + float& cachedCellXposition = storage.mXCell; + float& cachedCellYposition = storage.mYCell; // Initialization to discover & store allowed node points for this actor. if(!mStoredAvailableNodes) { @@ -435,6 +437,8 @@ namespace MWMechanics } } + AiWander::GreetingState& greetingState = storage.mSaidGreeting; + short unsigned& playedIdle = storage.mPlayedIdle; if(chooseAction) { playedIdle = 0; @@ -491,6 +495,7 @@ namespace MWMechanics Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos); float playerDistSqr = playerPos.squaredDistance(actorPos); + int& greetingTimer = storage.mGreetingTimer; if (greetingState == Greet_None) { if ((playerDistSqr <= helloDistance*helloDistance) && @@ -524,10 +529,10 @@ namespace MWMechanics { Ogre::Vector3 dir = playerPos - actorPos; - float faceAngle = Ogre::Math::ATan2(dir.x,dir.y).valueDegrees(); - float actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll().valueDegrees(); + Ogre::Radian faceAngle = Ogre::Math::ATan2(dir.x,dir.y); + Ogre::Radian actorAngle = actor.getRefData().getBaseNode()->getOrientation().getRoll(); // an attempt at reducing the turning animation glitch - if(abs(abs(faceAngle) - abs(actorAngle)) >= 5) // TODO: is there a better way? + if( Ogre::Math::Abs( faceAngle - actorAngle ) >= Ogre::Degree(5) ) // TODO: is there a better way? { targetAngle = faceAngle; rotate = true;