mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-16 16:20:53 +00:00
Merge branch 'dagoth_wave' into 'master'
Remove weaponless, non-biped distinction Closes #5054 See merge request OpenMW/openmw!1517
This commit is contained in:
commit
14a9af15ab
@ -19,6 +19,7 @@
|
||||
Bug #4700: Editor: Incorrect command implementation
|
||||
Bug #4744: Invisible particles must still be processed
|
||||
Bug #4949: Incorrect particle lighting
|
||||
Bug #5054: Non-biped creatures don't use spellcast equip/unequip animations
|
||||
Bug #5088: Sky abruptly changes direction during certain weather transitions
|
||||
Bug #5100: Persuasion doesn't always clamp the resulting disposition
|
||||
Bug #5120: Scripted object spawning updates physics system
|
||||
|
@ -435,6 +435,8 @@ std::string CharacterController::getWeaponAnimation(int weaponType) const
|
||||
else if (isRealWeapon)
|
||||
weaponGroup = oneHandFallback;
|
||||
}
|
||||
else if (weaponType == ESM::Weapon::HandToHand && !mPtr.getClass().isBipedal(mPtr))
|
||||
return "attack1";
|
||||
|
||||
return weaponGroup;
|
||||
}
|
||||
@ -707,9 +709,7 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||
if (mPtr.getClass().isActor())
|
||||
refreshHitRecoilAnims(idle);
|
||||
|
||||
std::string weap;
|
||||
if (mPtr.getClass().hasInventoryStore(mPtr))
|
||||
weap = getWeaponType(mWeaponType)->mShortGroup;
|
||||
std::string weap = getWeaponType(mWeaponType)->mShortGroup;
|
||||
|
||||
refreshJumpAnims(weap, jump, idle, force);
|
||||
refreshMovementAnims(weap, movement, idle, force);
|
||||
@ -1119,97 +1119,6 @@ void CharacterController::updateIdleStormState(bool inwater)
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterController::updateCreatureState()
|
||||
{
|
||||
const MWWorld::Class &cls = mPtr.getClass();
|
||||
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
||||
|
||||
int weapType = ESM::Weapon::None;
|
||||
if(stats.getDrawState() == DrawState_Weapon)
|
||||
weapType = ESM::Weapon::HandToHand;
|
||||
else if (stats.getDrawState() == DrawState_Spell)
|
||||
weapType = ESM::Weapon::Spell;
|
||||
|
||||
if (weapType != mWeaponType)
|
||||
{
|
||||
mWeaponType = weapType;
|
||||
if (mAnimation->isPlaying(mCurrentWeapon))
|
||||
mAnimation->disable(mCurrentWeapon);
|
||||
}
|
||||
|
||||
if(getAttackingOrSpell())
|
||||
{
|
||||
if(mUpperBodyState == UpperCharState_Nothing && mHitState == CharState_None)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||
|
||||
std::string startKey = "start";
|
||||
std::string stopKey = "stop";
|
||||
if (weapType == ESM::Weapon::Spell)
|
||||
{
|
||||
const std::string spellid = stats.getSpells().getSelectedSpell();
|
||||
bool canCast = mCastingManualSpell || MWBase::Environment::get().getWorld()->startSpellCast(mPtr);
|
||||
|
||||
if (!spellid.empty() && canCast)
|
||||
{
|
||||
MWMechanics::CastSpell cast(mPtr, nullptr, false, mCastingManualSpell);
|
||||
cast.playSpellCastingEffects(spellid, false);
|
||||
|
||||
if (!mAnimation->hasAnimation("spellcast"))
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->castSpell(mPtr, mCastingManualSpell); // No "release" text key to use, so cast immediately
|
||||
mCastingManualSpell = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM::Spell *spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellid);
|
||||
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
|
||||
|
||||
switch(effectentry.mRange)
|
||||
{
|
||||
case 0: mAttackType = "self"; break;
|
||||
case 1: mAttackType = "touch"; break;
|
||||
case 2: mAttackType = "target"; break;
|
||||
}
|
||||
|
||||
startKey = mAttackType + " " + startKey;
|
||||
stopKey = mAttackType + " " + stopKey;
|
||||
mCurrentWeapon = "spellcast";
|
||||
}
|
||||
}
|
||||
else
|
||||
mCurrentWeapon = "";
|
||||
}
|
||||
|
||||
if (weapType != ESM::Weapon::Spell || !mAnimation->hasAnimation("spellcast")) // Not all creatures have a dedicated spellcast animation
|
||||
{
|
||||
mCurrentWeapon = chooseRandomAttackAnimation();
|
||||
}
|
||||
|
||||
if (!mCurrentWeapon.empty())
|
||||
{
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::BlendMask_All, true,
|
||||
1, startKey, stopKey,
|
||||
0.0f, 0);
|
||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||
|
||||
mAttackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability());
|
||||
|
||||
if (weapType == ESM::Weapon::HandToHand)
|
||||
playSwishSound(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
setAttackingOrSpell(false);
|
||||
}
|
||||
|
||||
bool animPlaying = mAnimation->getInfo(mCurrentWeapon);
|
||||
if (!animPlaying)
|
||||
mUpperBodyState = UpperCharState_Nothing;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CharacterController::updateCarriedLeftVisible(const int weaptype) const
|
||||
{
|
||||
// Shields/torches shouldn't be visible during any operation involving two hands
|
||||
@ -1218,7 +1127,7 @@ bool CharacterController::updateCarriedLeftVisible(const int weaptype) const
|
||||
return mAnimation->updateCarriedLeftVisible(weaptype);
|
||||
}
|
||||
|
||||
bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
bool CharacterController::updateState(CharacterState& idle)
|
||||
{
|
||||
const MWWorld::Class &cls = mPtr.getClass();
|
||||
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
||||
@ -1386,7 +1295,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
}
|
||||
|
||||
mWeaponType = weaptype;
|
||||
mCurrentWeapon = getWeaponAnimation(mWeaponType);
|
||||
mCurrentWeapon = weapgroup;
|
||||
|
||||
if(!upSoundId.empty() && !isStillWeapon)
|
||||
{
|
||||
@ -1456,15 +1365,13 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
ESM::WeaponType::Class weapclass = getWeaponType(mWeaponType)->mWeaponClass;
|
||||
if(getAttackingOrSpell())
|
||||
{
|
||||
MWWorld::Ptr player = getPlayer();
|
||||
|
||||
bool resetIdle = ammunition;
|
||||
if(mUpperBodyState == UpperCharState_WeapEquiped && (mHitState == CharState_None || mHitState == CharState_Block))
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||
mAttackStrength = 0;
|
||||
|
||||
// Randomize attacks for non-bipedal creatures with Weapon flag
|
||||
// Randomize attacks for non-bipedal creatures
|
||||
if (mPtr.getClass().getType() == ESM::Creature::sRecordId &&
|
||||
!mPtr.getClass().isBipedal(mPtr) &&
|
||||
(!mAnimation->hasAnimation(mCurrentWeapon) || isRandomAttackAnimation(mCurrentWeapon)))
|
||||
@ -1477,7 +1384,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
// Unset casting flag, otherwise pressing the mouse button down would
|
||||
// continue casting every frame if there is no animation
|
||||
setAttackingOrSpell(false);
|
||||
if (mPtr == player)
|
||||
if (mPtr == getPlayer())
|
||||
{
|
||||
// For the player, set the spell we want to cast
|
||||
// This has to be done at the start of the casting animation,
|
||||
@ -1650,7 +1557,14 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||
weapSpeed, startKey, stopKey,
|
||||
0.0f, 0);
|
||||
if(mAnimation->getCurrentTime(mCurrentWeapon) != -1.f)
|
||||
{
|
||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||
if (isRandomAttackAnimation(mCurrentWeapon))
|
||||
{
|
||||
mAttackStrength = std::min(1.f, 0.1f + Misc::Rng::rollClosedProbability());
|
||||
playSwishSound(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2346,11 +2260,7 @@ void CharacterController::update(float duration)
|
||||
|
||||
if (!mSkipAnim)
|
||||
{
|
||||
// bipedal means hand-to-hand could be used (which is handled in updateWeaponState). an existing InventoryStore means an actual weapon could be used.
|
||||
if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr))
|
||||
forcestateupdate = updateWeaponState(idlestate) || forcestateupdate;
|
||||
else
|
||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||
forcestateupdate = updateState(idlestate) || forcestateupdate;
|
||||
|
||||
refreshCurrentAnims(idlestate, movestate, jumpstate, forcestateupdate);
|
||||
updateIdleStormState(inwater);
|
||||
@ -2879,10 +2789,7 @@ bool CharacterController::readyToStartAttack() const
|
||||
if (mHitState != CharState_None && mHitState != CharState_Block)
|
||||
return false;
|
||||
|
||||
if (mPtr.getClass().hasInventoryStore(mPtr) || mPtr.getClass().isBipedal(mPtr))
|
||||
return mUpperBodyState == UpperCharState_WeapEquiped;
|
||||
else
|
||||
return mUpperBodyState == UpperCharState_Nothing;
|
||||
return mUpperBodyState == UpperCharState_WeapEquiped;
|
||||
}
|
||||
|
||||
float CharacterController::getAttackStrength() const
|
||||
|
@ -205,8 +205,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||
|
||||
void clearAnimQueue(bool clearPersistAnims = false);
|
||||
|
||||
bool updateWeaponState(CharacterState& idle);
|
||||
bool updateCreatureState();
|
||||
bool updateState(CharacterState& idle);
|
||||
void updateIdleStormState(bool inwater);
|
||||
|
||||
std::string chooseRandomAttackAnimation() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user