Handle spellcasting for creatures with no casting animation (Fixes #1856)

This commit is contained in:
scrawl 2014-09-15 00:29:21 +02:00
parent 3d8216ee17
commit 157c53bed4
5 changed files with 65 additions and 21 deletions

View File

@ -209,6 +209,9 @@ namespace MWClass
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::CreatureStats &stats = getCreatureStats(ptr); MWMechanics::CreatureStats &stats = getCreatureStats(ptr);
if (stats.getDrawState() != MWMechanics::DrawState_Weapon)
return;
// Get the weapon used (if hand-to-hand, weapon = inv.end()) // Get the weapon used (if hand-to-hand, weapon = inv.end())
MWWorld::Ptr weapon; MWWorld::Ptr weapon;
if (ptr.getClass().hasInventoryStore(ptr)) if (ptr.getClass().hasInventoryStore(ptr))

View File

@ -292,6 +292,9 @@ namespace MWMechanics
case ESM::MagicEffect::CurePoison: case ESM::MagicEffect::CurePoison:
return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Poison); return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Poison);
case ESM::MagicEffect::DisintegrateArmor: // TODO: check if actor is wearing armor
case ESM::MagicEffect::DisintegrateWeapon: // TODO: check if actor is wearing weapon
default: default:
break; break;
} }

View File

@ -690,11 +690,52 @@ void CharacterController::updateIdleStormState()
} }
} }
void CharacterController::castSpell(const std::string &spellid)
{
static const std::string schools[] = {
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
};
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
const ESM::MagicEffect *effect;
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
const ESM::Static* castStatic;
if (!effect->mCasting.empty())
castStatic = store.get<ESM::Static>().find (effect->mCasting);
else
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
mAnimation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!effect->mCastSound.empty())
sndMgr->playSound3D(mPtr, effect->mCastSound, 1.0f, 1.0f);
else
sndMgr->playSound3D(mPtr, schools[effect->mData.mSchool]+" cast", 1.0f, 1.0f);
}
bool CharacterController::updateCreatureState() bool CharacterController::updateCreatureState()
{ {
const MWWorld::Class &cls = mPtr.getClass(); const MWWorld::Class &cls = mPtr.getClass();
CreatureStats &stats = cls.getCreatureStats(mPtr); CreatureStats &stats = cls.getCreatureStats(mPtr);
WeaponType weapType = WeapType_None;
if(stats.getDrawState() == DrawState_Weapon)
weapType = WeapType_HandToHand;
else if (stats.getDrawState() == DrawState_Spell)
weapType = WeapType_Spell;
if (weapType != mWeaponType)
{
mWeaponType = weapType;
if (mAnimation->isPlaying(mCurrentWeapon))
mAnimation->disable(mCurrentWeapon);
}
if(stats.getAttackingOrSpell()) if(stats.getAttackingOrSpell())
{ {
if(mUpperBodyState == UpperCharState_Nothing && mHitState == CharState_None) if(mUpperBodyState == UpperCharState_Nothing && mHitState == CharState_None)
@ -715,7 +756,18 @@ bool CharacterController::updateCreatureState()
1, "start", "stop", 1, "start", "stop",
0.0f, 0); 0.0f, 0);
mUpperBodyState = UpperCharState_StartToMinAttack; mUpperBodyState = UpperCharState_StartToMinAttack;
if (weapType == WeapType_Spell)
{
const std::string spellid = stats.getSpells().getSelectedSpell();
if (!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
{
castSpell(spellid);
MWBase::Environment::get().getWorld()->castSpell(mPtr);
}
}
} }
stats.setAttackingOrSpell(false); stats.setAttackingOrSpell(false);
} }
@ -854,9 +906,7 @@ bool CharacterController::updateWeaponState()
if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr)) if(!spellid.empty() && MWBase::Environment::get().getWorld()->startSpellCast(mPtr))
{ {
static const std::string schools[] = { castSpell(spellid);
"alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration"
};
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid); const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0); const ESM::ENAMstruct &effectentry = spell->mEffects.mList.at(0);
@ -864,15 +914,7 @@ bool CharacterController::updateWeaponState()
const ESM::MagicEffect *effect; const ESM::MagicEffect *effect;
effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID); effect = store.get<ESM::MagicEffect>().find(effectentry.mEffectID);
const ESM::Static* castStatic; const ESM::Static* castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Hands");
if (!effect->mCasting.empty())
castStatic = store.get<ESM::Static>().find (effect->mCasting);
else
castStatic = store.get<ESM::Static>().find ("VFX_DefaultCast");
mAnimation->addEffect("meshes\\" + castStatic->mModel, effect->mIndex);
castStatic = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>().find ("VFX_Hands");
if (mAnimation->getNode("Left Hand")) if (mAnimation->getNode("Left Hand"))
{ {
mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Left Hand", effect->mParticle); mAnimation->addEffect("meshes\\" + castStatic->mModel, -1, false, "Left Hand", effect->mParticle);
@ -896,12 +938,6 @@ bool CharacterController::updateWeaponState()
weapSpeed, mAttackType+" start", mAttackType+" stop", weapSpeed, mAttackType+" start", mAttackType+" stop",
0.0f, 0); 0.0f, 0);
mUpperBodyState = UpperCharState_CastingSpell; mUpperBodyState = UpperCharState_CastingSpell;
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(!effect->mCastSound.empty())
sndMgr->playSound3D(mPtr, effect->mCastSound, 1.0f, 1.0f);
else
sndMgr->playSound3D(mPtr, schools[effect->mData.mSchool]+" cast", 1.0f, 1.0f);
} }
if (inv.getSelectedEnchantItem() != inv.end()) if (inv.getSelectedEnchantItem() != inv.end())
{ {

View File

@ -181,6 +181,8 @@ class CharacterController
bool updateCreatureState(); bool updateCreatureState();
void updateIdleStormState(); void updateIdleStormState();
void castSpell(const std::string& spellid);
void updateVisibility(); void updateVisibility();
void playDeath(float startpoint, CharacterState death); void playDeath(float startpoint, CharacterState death);

View File

@ -2502,9 +2502,9 @@ namespace MWWorld
{ {
const ESM::Spell* spell = getStore().get<ESM::Spell>().search(selectedSpell); const ESM::Spell* spell = getStore().get<ESM::Spell>().search(selectedSpell);
// A power can be used once per 24h // A power can be used once per 24h
if (spell->mData.mType == ESM::Spell::ST_Power) if (spell->mData.mType == ESM::Spell::ST_Power)
stats.getSpells().usePower(spell->mId); stats.getSpells().usePower(spell->mId);
cast.cast(spell); cast.cast(spell);
} }