mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 20:23:54 +00:00
refactoring of setting an attack type
This commit is contained in:
parent
339399f8b1
commit
87e83a92f8
7 changed files with 96 additions and 65 deletions
|
@ -159,20 +159,6 @@ namespace MWInput
|
||||||
if (action == A_Use)
|
if (action == A_Use)
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
|
MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackingOrSpell(currentValue);
|
||||||
if (currentValue == 1)
|
|
||||||
{
|
|
||||||
int type = MWMechanics::CreatureStats::AT_Chop;
|
|
||||||
bool forward = (mInputBinder->getChannel(A_MoveForward)->getValue() > 0
|
|
||||||
|| mInputBinder->getChannel(A_MoveBackward)->getValue() > 0);
|
|
||||||
bool side = (mInputBinder->getChannel(A_MoveLeft)->getValue() > 0
|
|
||||||
|| mInputBinder->getChannel(A_MoveRight)->getValue() > 0);
|
|
||||||
if (side && !forward)
|
|
||||||
type = MWMechanics::CreatureStats::AT_Slash;
|
|
||||||
if (forward && !side)
|
|
||||||
type = MWMechanics::CreatureStats::AT_Thrust;
|
|
||||||
|
|
||||||
MWWorld::Class::get(mPlayer->getPlayer()).getCreatureStats(mPlayer->getPlayer()).setAttackType(type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentValue == 1)
|
if (currentValue == 1)
|
||||||
|
|
|
@ -28,7 +28,6 @@ namespace
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void determineAttackType(const MWWorld::Ptr& actor, MWMechanics::Movement &movement);
|
|
||||||
//chooses an attack depending on probability to avoid uniformity
|
//chooses an attack depending on probability to avoid uniformity
|
||||||
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement);
|
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement);
|
||||||
}
|
}
|
||||||
|
@ -57,9 +56,6 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
//Update every frame
|
//Update every frame
|
||||||
if(mReadyToAttack)
|
|
||||||
determineAttackType(actor, mMovement);
|
|
||||||
|
|
||||||
if(mCombatMove)
|
if(mCombatMove)
|
||||||
{
|
{
|
||||||
mTimerCombatMove -= duration;
|
mTimerCombatMove -= duration;
|
||||||
|
@ -155,7 +151,7 @@ namespace MWMechanics
|
||||||
else //is creature
|
else //is creature
|
||||||
{
|
{
|
||||||
weaptype = WeapType_HandToHand; //doesn't matter, should only reflect if it is melee or distant weapon
|
weaptype = WeapType_HandToHand; //doesn't matter, should only reflect if it is melee or distant weapon
|
||||||
weapRange = 100; //TODO: use true attack range (the same problem in Creature::hit)
|
weapRange = 150; //TODO: use true attack range (the same problem in Creature::hit)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false);
|
//MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(false);
|
||||||
|
@ -167,7 +163,9 @@ namespace MWMechanics
|
||||||
float rangeMelee;
|
float rangeMelee;
|
||||||
float rangeCloseUp;
|
float rangeCloseUp;
|
||||||
bool distantCombat = false;
|
bool distantCombat = false;
|
||||||
if (weaptype==WeapType_BowAndArrow || weaptype==WeapType_Crossbow || weaptype==WeapType_ThowWeapon) // || WeapType_Spell_OnTarget
|
int attackType = actor.getClass().getCreatureStats(actor).getAttackType();
|
||||||
|
if (weaptype==WeapType_BowAndArrow || weaptype==WeapType_Crossbow || weaptype==WeapType_ThowWeapon
|
||||||
|
|| attackType==MWMechanics::CreatureStats::AT_Target )
|
||||||
{
|
{
|
||||||
rangeMelee = 1000; // TODO: should depend on archer skill
|
rangeMelee = 1000; // TODO: should depend on archer skill
|
||||||
rangeCloseUp = 0; //doesn't needed when attacking from distance
|
rangeCloseUp = 0; //doesn't needed when attacking from distance
|
||||||
|
@ -251,7 +249,11 @@ namespace MWMechanics
|
||||||
//delete visited path node
|
//delete visited path node
|
||||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||||
|
|
||||||
zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
//try shortcut
|
||||||
|
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
|
||||||
|
zAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
|
||||||
|
else
|
||||||
|
zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
|
|
||||||
// TODO: use movement settings instead of rotating directly
|
// TODO: use movement settings instead of rotating directly
|
||||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||||
|
@ -375,24 +377,12 @@ namespace MWMechanics
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void determineAttackType(const MWWorld::Ptr& actor, MWMechanics::Movement &movement)
|
|
||||||
{
|
|
||||||
if (movement.mPosition[0] && !movement.mPosition[1]) //sideway
|
|
||||||
actor.getClass().getCreatureStats(actor).setAttackType(MWMechanics::CreatureStats::AT_Slash);
|
|
||||||
else if (movement.mPosition[1]) //forward
|
|
||||||
actor.getClass().getCreatureStats(actor).setAttackType(MWMechanics::CreatureStats::AT_Thrust);
|
|
||||||
else
|
|
||||||
actor.getClass().getCreatureStats(actor).setAttackType(MWMechanics::CreatureStats::AT_Chop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement)
|
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement)
|
||||||
{
|
{
|
||||||
//the more damage attackType deals the more probability it has
|
|
||||||
|
|
||||||
if (weapon == NULL)
|
if (weapon == NULL)
|
||||||
{
|
{
|
||||||
//hand-to-hand and creatures' attacks handled here
|
//hand-to-hand and creatures' attacks deal equal damage for each type
|
||||||
//hand-to-hand deals equal damage
|
|
||||||
float roll = static_cast<float>(rand())/RAND_MAX;
|
float roll = static_cast<float>(rand())/RAND_MAX;
|
||||||
if(roll <= 0.333f) //side punch
|
if(roll <= 0.333f) //side punch
|
||||||
{
|
{
|
||||||
|
@ -401,10 +391,15 @@ void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement
|
||||||
}
|
}
|
||||||
else if(roll <= 0.666f) //forward punch
|
else if(roll <= 0.666f) //forward punch
|
||||||
movement.mPosition[1] = 1;
|
movement.mPosition[1] = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movement.mPosition[1] = movement.mPosition[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//the more damage attackType deals the more probability it has
|
||||||
int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2;
|
int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2;
|
||||||
int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1])/2;
|
int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1])/2;
|
||||||
int thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1])/2;
|
int thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1])/2;
|
||||||
|
@ -419,7 +414,8 @@ void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement
|
||||||
}
|
}
|
||||||
else if(roll <= (static_cast<float>(slash) + static_cast<float>(thrust))/total)
|
else if(roll <= (static_cast<float>(slash) + static_cast<float>(thrust))/total)
|
||||||
movement.mPosition[1] = 1;
|
movement.mPosition[1] = 1;
|
||||||
//else chop
|
else
|
||||||
|
movement.mPosition[1] = movement.mPosition[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -490,18 +490,7 @@ bool CharacterController::updateCreatureState()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||||
|
|
||||||
switch (stats.getAttackType())
|
determineAttackType();
|
||||||
{
|
|
||||||
case CreatureStats::AT_Chop:
|
|
||||||
mCurrentWeapon = "attack1";
|
|
||||||
break;
|
|
||||||
case CreatureStats::AT_Slash:
|
|
||||||
mCurrentWeapon = "attack2";
|
|
||||||
break;
|
|
||||||
case CreatureStats::AT_Thrust:
|
|
||||||
mCurrentWeapon = "attack3";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
MWRender::Animation::Group_All, true,
|
MWRender::Animation::Group_All, true,
|
||||||
|
@ -517,7 +506,7 @@ bool CharacterController::updateCreatureState()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
bool CharacterController::updateNpcState()
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||||
NpcStats &stats = cls.getNpcStats(mPtr);
|
NpcStats &stats = cls.getNpcStats(mPtr);
|
||||||
|
@ -586,7 +575,9 @@ bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
||||||
if(isWerewolf)
|
if(isWerewolf)
|
||||||
{
|
{
|
||||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||||
if(isrunning && !inwater && mWeaponType == WeapType_None)
|
if(cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run)
|
||||||
|
&& !MWBase::Environment::get().getWorld()->isSwimming(mPtr)
|
||||||
|
&& mWeaponType == WeapType_None)
|
||||||
{
|
{
|
||||||
if(!sndMgr->getSoundPlaying(mPtr, "WolfRun"))
|
if(!sndMgr->getSoundPlaying(mPtr, "WolfRun"))
|
||||||
sndMgr->playSound3D(mPtr, "WolfRun", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx,
|
sndMgr->playSound3D(mPtr, "WolfRun", 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx,
|
||||||
|
@ -653,12 +644,7 @@ bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
||||||
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Left Hand", effect->mParticle);
|
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Left Hand", effect->mParticle);
|
||||||
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Right Hand", effect->mParticle);
|
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Right Hand", effect->mParticle);
|
||||||
|
|
||||||
switch(effectentry.mRange)
|
determineAttackType(effectentry.mRange);
|
||||||
{
|
|
||||||
case 0: mAttackType = "self"; break;
|
|
||||||
case 1: mAttackType = "touch"; break;
|
|
||||||
case 2: mAttackType = "target"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
MWRender::Animation::Group_UpperBody, true,
|
MWRender::Animation::Group_UpperBody, true,
|
||||||
|
@ -715,13 +701,8 @@ bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
||||||
int attackType = stats.getAttackType();
|
int attackType = stats.getAttackType();
|
||||||
if(isWeapon && Settings::Manager::getBool("best attack", "Game"))
|
if(isWeapon && Settings::Manager::getBool("best attack", "Game"))
|
||||||
attackType = getBestAttack(weapon->get<ESM::Weapon>()->mBase);
|
attackType = getBestAttack(weapon->get<ESM::Weapon>()->mBase);
|
||||||
|
|
||||||
if (attackType == MWMechanics::CreatureStats::AT_Chop)
|
|
||||||
mAttackType = "chop";
|
|
||||||
else if (attackType == MWMechanics::CreatureStats::AT_Slash)
|
|
||||||
mAttackType = "slash";
|
|
||||||
else
|
else
|
||||||
mAttackType = "thrust";
|
determineAttackType();
|
||||||
}
|
}
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
|
@ -902,7 +883,8 @@ void CharacterController::update(float duration)
|
||||||
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run);
|
||||||
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
||||||
bool flying = world->isFlying(mPtr);
|
bool flying = world->isFlying(mPtr);
|
||||||
Ogre::Vector3 vec = cls.getMovementVector(mPtr);
|
//Ogre::Vector3 vec = cls.getMovementVector(mPtr);
|
||||||
|
Ogre::Vector3 vec(cls.getMovementSettings(mPtr).mPosition);
|
||||||
vec.normalise();
|
vec.normalise();
|
||||||
if(mHitState != CharState_None && mJumpState == JumpState_None)
|
if(mHitState != CharState_None && mJumpState == JumpState_None)
|
||||||
vec = Ogre::Vector3(0.0f);
|
vec = Ogre::Vector3(0.0f);
|
||||||
|
@ -1129,7 +1111,7 @@ void CharacterController::update(float duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cls.isNpc())
|
if(cls.isNpc())
|
||||||
forcestateupdate = updateNpcState(inwater, isrunning) || forcestateupdate;
|
forcestateupdate = updateNpcState() || forcestateupdate;
|
||||||
else
|
else
|
||||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||||
|
|
||||||
|
@ -1149,6 +1131,7 @@ void CharacterController::update(float duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
movement = vec;
|
movement = vec;
|
||||||
|
cls.getMovementSettings(mPtr).mPosition[0] = cls.getMovementSettings(mPtr).mPosition[1] = cls.getMovementSettings(mPtr).mPosition[2] = 0;
|
||||||
}
|
}
|
||||||
else if(cls.getCreatureStats(mPtr).isDead())
|
else if(cls.getCreatureStats(mPtr).isDead())
|
||||||
{
|
{
|
||||||
|
@ -1319,4 +1302,57 @@ void CharacterController::updateVisibility()
|
||||||
mAnimation->setAlpha(alpha);
|
mAnimation->setAlpha(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CharacterController::determineAttackType(int spellRange)
|
||||||
|
{
|
||||||
|
if(spellRange == -1)
|
||||||
|
{
|
||||||
|
float * move = mPtr.getClass().getMovementSettings(mPtr).mPosition;
|
||||||
|
|
||||||
|
if (move[0] && !move[1]) //sideway
|
||||||
|
{
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Slash);
|
||||||
|
if(mPtr.getClass().isNpc())
|
||||||
|
mAttackType = "slash";
|
||||||
|
else
|
||||||
|
mCurrentWeapon = "attack2";
|
||||||
|
}
|
||||||
|
else if (move[1]) //forward
|
||||||
|
{
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Thrust);
|
||||||
|
if(mPtr.getClass().isNpc())
|
||||||
|
mAttackType = "thrust";
|
||||||
|
else
|
||||||
|
mCurrentWeapon = "attack3";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Chop);
|
||||||
|
if(mPtr.getClass().isNpc())
|
||||||
|
mAttackType = "chop";
|
||||||
|
else
|
||||||
|
mCurrentWeapon = "attack1";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(spellRange)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
mAttackType = "self";
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Self);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mAttackType = "touch";
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Touch);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mAttackType = "target";
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setAttackType(MWMechanics::CreatureStats::AT_Target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -165,12 +165,13 @@ class CharacterController
|
||||||
float mSecondsOfRunning;
|
float mSecondsOfRunning;
|
||||||
|
|
||||||
std::string mAttackType; // slash, chop or thrust
|
std::string mAttackType; // slash, chop or thrust
|
||||||
|
void determineAttackType(int spellRange = -1);
|
||||||
|
|
||||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
||||||
|
|
||||||
void clearAnimQueue();
|
void clearAnimQueue();
|
||||||
|
|
||||||
bool updateNpcState(bool inwater, bool isrunning);
|
bool updateNpcState();
|
||||||
bool updateCreatureState();
|
bool updateCreatureState();
|
||||||
|
|
||||||
void updateVisibility();
|
void updateVisibility();
|
||||||
|
|
|
@ -118,7 +118,11 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
AT_Chop,
|
AT_Chop,
|
||||||
AT_Slash,
|
AT_Slash,
|
||||||
AT_Thrust
|
AT_Thrust,
|
||||||
|
|
||||||
|
AT_Self,
|
||||||
|
AT_Touch,
|
||||||
|
AT_Target,
|
||||||
};
|
};
|
||||||
void setAttackType(int attackType) { mAttackType = attackType; }
|
void setAttackType(int attackType) { mAttackType = attackType; }
|
||||||
int getAttackType() { return mAttackType; }
|
int getAttackType() { return mAttackType; }
|
||||||
|
|
|
@ -201,6 +201,12 @@ namespace MWMechanics
|
||||||
return Ogre::Radian(Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult))).valueDegrees();
|
return Ogre::Radian(Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult))).valueDegrees();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float PathFinder::getDistToNext(float x, float y, float z)
|
||||||
|
{
|
||||||
|
ESM::Pathgrid::Point nextPoint = *mPath.begin();
|
||||||
|
return distance(nextPoint, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
bool PathFinder::checkWaypoint(float x, float y, float z)
|
bool PathFinder::checkWaypoint(float x, float y, float z)
|
||||||
{
|
{
|
||||||
if(mPath.empty())
|
if(mPath.empty())
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace MWMechanics
|
||||||
///< \Returns true if a way point was reached
|
///< \Returns true if a way point was reached
|
||||||
float getZAngleToNext(float x, float y) const;
|
float getZAngleToNext(float x, float y) const;
|
||||||
|
|
||||||
|
float getDistToNext(float x, float y, float z);
|
||||||
|
|
||||||
bool isPathConstructed() const
|
bool isPathConstructed() const
|
||||||
{
|
{
|
||||||
return mIsPathConstructed;
|
return mIsPathConstructed;
|
||||||
|
|
Loading…
Reference in a new issue