mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 16:53:55 +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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace
|
|||
return -1.0;
|
||||
}
|
||||
|
||||
void determineAttackType(const MWWorld::Ptr& actor, MWMechanics::Movement &movement);
|
||||
//chooses an attack depending on probability to avoid uniformity
|
||||
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement);
|
||||
}
|
||||
|
@ -57,9 +56,6 @@ namespace MWMechanics
|
|||
return true;
|
||||
|
||||
//Update every frame
|
||||
if(mReadyToAttack)
|
||||
determineAttackType(actor, mMovement);
|
||||
|
||||
if(mCombatMove)
|
||||
{
|
||||
mTimerCombatMove -= duration;
|
||||
|
@ -155,7 +151,7 @@ namespace MWMechanics
|
|||
else //is creature
|
||||
{
|
||||
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);
|
||||
|
@ -167,7 +163,9 @@ namespace MWMechanics
|
|||
float rangeMelee;
|
||||
float rangeCloseUp;
|
||||
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
|
||||
rangeCloseUp = 0; //doesn't needed when attacking from distance
|
||||
|
@ -251,7 +249,11 @@ namespace MWMechanics
|
|||
//delete visited path node
|
||||
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
|
||||
MWBase::Environment::get().getWorld()->rotateObject(actor, 0, 0, zAngle, false);
|
||||
|
@ -375,24 +377,12 @@ namespace MWMechanics
|
|||
|
||||
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)
|
||||
{
|
||||
//the more damage attackType deals the more probability it has
|
||||
|
||||
if (weapon == NULL)
|
||||
{
|
||||
//hand-to-hand and creatures' attacks handled here
|
||||
//hand-to-hand deals equal damage
|
||||
//hand-to-hand and creatures' attacks deal equal damage for each type
|
||||
float roll = static_cast<float>(rand())/RAND_MAX;
|
||||
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
|
||||
movement.mPosition[1] = 1;
|
||||
else
|
||||
{
|
||||
movement.mPosition[1] = movement.mPosition[0] = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//the more damage attackType deals the more probability it has
|
||||
int slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1])/2;
|
||||
int chop = (weapon->mData.mChop[0] + weapon->mData.mChop[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)
|
||||
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);
|
||||
|
||||
switch (stats.getAttackType())
|
||||
{
|
||||
case CreatureStats::AT_Chop:
|
||||
mCurrentWeapon = "attack1";
|
||||
break;
|
||||
case CreatureStats::AT_Slash:
|
||||
mCurrentWeapon = "attack2";
|
||||
break;
|
||||
case CreatureStats::AT_Thrust:
|
||||
mCurrentWeapon = "attack3";
|
||||
break;
|
||||
}
|
||||
determineAttackType();
|
||||
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_All, true,
|
||||
|
@ -517,7 +506,7 @@ bool CharacterController::updateCreatureState()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
||||
bool CharacterController::updateNpcState()
|
||||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
NpcStats &stats = cls.getNpcStats(mPtr);
|
||||
|
@ -586,7 +575,9 @@ bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
|||
if(isWerewolf)
|
||||
{
|
||||
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"))
|
||||
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, "Right Hand", effect->mParticle);
|
||||
|
||||
switch(effectentry.mRange)
|
||||
{
|
||||
case 0: mAttackType = "self"; break;
|
||||
case 1: mAttackType = "touch"; break;
|
||||
case 2: mAttackType = "target"; break;
|
||||
}
|
||||
determineAttackType(effectentry.mRange);
|
||||
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, true,
|
||||
|
@ -715,13 +701,8 @@ bool CharacterController::updateNpcState(bool inwater, bool isrunning)
|
|||
int attackType = stats.getAttackType();
|
||||
if(isWeapon && Settings::Manager::getBool("best attack", "Game"))
|
||||
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
|
||||
mAttackType = "thrust";
|
||||
determineAttackType();
|
||||
}
|
||||
|
||||
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 sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
|
||||
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();
|
||||
if(mHitState != CharState_None && mJumpState == JumpState_None)
|
||||
vec = Ogre::Vector3(0.0f);
|
||||
|
@ -1129,7 +1111,7 @@ void CharacterController::update(float duration)
|
|||
}
|
||||
|
||||
if(cls.isNpc())
|
||||
forcestateupdate = updateNpcState(inwater, isrunning) || forcestateupdate;
|
||||
forcestateupdate = updateNpcState() || forcestateupdate;
|
||||
else
|
||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||
|
||||
|
@ -1149,6 +1131,7 @@ void CharacterController::update(float duration)
|
|||
}
|
||||
|
||||
movement = vec;
|
||||
cls.getMovementSettings(mPtr).mPosition[0] = cls.getMovementSettings(mPtr).mPosition[1] = cls.getMovementSettings(mPtr).mPosition[2] = 0;
|
||||
}
|
||||
else if(cls.getCreatureStats(mPtr).isDead())
|
||||
{
|
||||
|
@ -1319,4 +1302,57 @@ void CharacterController::updateVisibility()
|
|||
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;
|
||||
|
||||
std::string mAttackType; // slash, chop or thrust
|
||||
void determineAttackType(int spellRange = -1);
|
||||
|
||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
||||
|
||||
void clearAnimQueue();
|
||||
|
||||
bool updateNpcState(bool inwater, bool isrunning);
|
||||
bool updateNpcState();
|
||||
bool updateCreatureState();
|
||||
|
||||
void updateVisibility();
|
||||
|
|
|
@ -118,7 +118,11 @@ namespace MWMechanics
|
|||
{
|
||||
AT_Chop,
|
||||
AT_Slash,
|
||||
AT_Thrust
|
||||
AT_Thrust,
|
||||
|
||||
AT_Self,
|
||||
AT_Touch,
|
||||
AT_Target,
|
||||
};
|
||||
void setAttackType(int attackType) { mAttackType = attackType; }
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(mPath.empty())
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace MWMechanics
|
|||
///< \Returns true if a way point was reached
|
||||
float getZAngleToNext(float x, float y) const;
|
||||
|
||||
float getDistToNext(float x, float y, float z);
|
||||
|
||||
bool isPathConstructed() const
|
||||
{
|
||||
return mIsPathConstructed;
|
||||
|
|
Loading…
Reference in a new issue