From 234716daa6fca5d0f92069fdf19a03e67cd2b9a9 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 23 Oct 2012 11:42:38 +0200 Subject: [PATCH] finished spell creation --- apps/openmw/mwgui/spellcreationdialog.cpp | 77 +++++++++++++++++-- apps/openmw/mwgui/spellcreationdialog.hpp | 4 + apps/openmw/mwmechanics/spellsuccess.hpp | 26 +++++-- .../mygui/openmw_spellcreation_dialog.layout | 3 - 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index bb066e8ff..4ce056010 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -15,10 +15,14 @@ #include "../mwmechanics/spells.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/spellsuccess.hpp" + #include "tooltips.hpp" #include "widgets.hpp" #include "class.hpp" +#include "inventorywindow.hpp" +#include "tradewindow.hpp" namespace { @@ -310,14 +314,25 @@ namespace MWGui return; } - ESM::Spell newSpell; - ESM::EffectList effectList; - effectList.mList = mEffects; - newSpell.mEffects = effectList; - newSpell.mName = mNameEdit->getCaption(); - newSpell.mData.mType = ESM::Spell::ST_Spell; + if (mMagickaCost->getCaption() == "0") + { + mWindowManager.messageBox ("#{sEnchantmentMenu8}", std::vector()); + return; + } + + if (boost::lexical_cast(mPriceLabel->getCaption()) > mWindowManager.getInventoryWindow()->getPlayerGold()) + { + mWindowManager.messageBox ("#{sNotifyMessage18}", std::vector()); + return; + } - std::pair result = MWBase::Environment::get().getWorld()->createRecord(newSpell); + mSpell.mName = mNameEdit->getCaption(); + + mWindowManager.getTradeWindow()->addOrRemoveGold(-boost::lexical_cast(mPriceLabel->getCaption())); + + MWBase::Environment::get().getSoundManager()->playSound ("Item Gold Up", 1.0, 1.0); + + std::pair result = MWBase::Environment::get().getWorld()->createRecord(mSpell); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); @@ -340,6 +355,47 @@ namespace MWGui mWindowManager.removeGuiMode (GM_SpellCreation); } + void SpellCreationDialog::notifyEffectsChanged () + { + float y = 0; + + for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) + { + float x = 0.5 * it->mMagnMin + it->mMagnMax; + + const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().magicEffects.find(it->mEffectID); + x *= 0.1 * effect->mData.mBaseCost; + x *= 1 + it->mDuration; + x += 0.05 * std::max(1, it->mArea) * effect->mData.mBaseCost; + + float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fEffectCostMult")->getFloat(); + y += x * fEffectCostMult; + y = std::max(1.f,y); + + if (effect->mData.mFlags & ESM::MagicEffect::CastTarget) + y *= 1.5; + } + + mSpell.mData.mCost = int(y); + + ESM::EffectList effectList; + effectList.mList = mEffects; + mSpell.mEffects = effectList; + mSpell.mData.mType = ESM::Spell::ST_Spell; + + mMagickaCost->setCaption(boost::lexical_cast(int(y))); + + float fSpellMakingValueMult = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fSpellMakingValueMult")->getFloat(); + + /// \todo mercantile + int price = int(y) * fSpellMakingValueMult; + + mPriceLabel->setCaption(boost::lexical_cast(int(price))); + + float chance = MWMechanics::getSpellSuccessChance(&mSpell, MWBase::Environment::get().getWorld()->getPlayer().getPlayer()); + mSuccessChance->setCaption(boost::lexical_cast(int(chance))); + } + // ------------------------------------------------------------------------------------------------ @@ -443,6 +499,11 @@ namespace MWGui void EffectEditorBase::onAvailableEffectClicked (MyGUI::Widget* sender) { + if (mEffects.size() >= 8) + { + MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage28}", std::vector()); + return; + } short effectId = *sender->getUserData(); @@ -534,6 +595,8 @@ namespace MWGui } mUsedEffectsView->setCanvasSize(size); + + notifyEffectsChanged(); } void EffectEditorBase::onEffectAdded (ESM::ENAMstruct effect) diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index 255b04cf6..4d27ec1c6 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -116,6 +116,7 @@ namespace MWGui void startEditing(); void setWidgets (Widgets::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView); + virtual void notifyEffectsChanged () {} }; class SpellCreationDialog : public WindowBase, public ReferenceInterface, public EffectEditorBase @@ -133,6 +134,7 @@ namespace MWGui void onCancelButtonClicked (MyGUI::Widget* sender); void onBuyButtonClicked (MyGUI::Widget* sender); + virtual void notifyEffectsChanged (); MyGUI::EditBox* mNameEdit; MyGUI::TextBox* mMagickaCost; @@ -143,6 +145,8 @@ namespace MWGui Widgets::MWEffectList* mUsedEffectsList; + ESM::Spell mSpell; + }; } diff --git a/apps/openmw/mwmechanics/spellsuccess.hpp b/apps/openmw/mwmechanics/spellsuccess.hpp index 43db42aab..a46667cdc 100644 --- a/apps/openmw/mwmechanics/spellsuccess.hpp +++ b/apps/openmw/mwmechanics/spellsuccess.hpp @@ -27,9 +27,8 @@ namespace MWMechanics return schoolSkillMap[school]; } - inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + inline int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); // determine the spell's school @@ -60,27 +59,34 @@ namespace MWMechanics return school; } + inline int getSpellSchool(const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + return getSpellSchool(spell, actor); + } + // UESP wiki / Morrowind/Spells: // Chance of success is (Spell's skill * 2 + Willpower / 5 + Luck / 10 - Spell cost - Sound magnitude) * (Current fatigue + Maximum Fatigue * 1.5) / Maximum fatigue * 2 /** - * @param spellId ID of spell + * @param spell spell to cast * @param actor calculate spell success chance for this actor (depends on actor's skills) * @attention actor has to be an NPC and not a creature! * @return success chance from 0 to 100 (in percent) */ - inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + inline float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor) { - const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); - if (spell->mData.mFlags & ESM::Spell::F_Always // spells with this flag always succeed (usually birthsign spells) || spell->mData.mType == ESM::Spell::ST_Power) // powers always succeed, but can be cast only once per day return 100.0; + if (spell->mEffects.mList.size() == 0) + return 0.0; + NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); - int skillLevel = stats.getSkill (getSpellSchool(spellId, actor)).getModified(); + int skillLevel = stats.getSkill (getSpellSchool(spell, actor)).getModified(); // Sound magic effect (reduces spell casting chance) int soundMagnitude = creatureStats.getMagicEffects().get (MWMechanics::EffectKey (48)).mMagnitude; @@ -98,6 +104,12 @@ namespace MWMechanics return chance; } + + inline float getSpellSuccessChance (const std::string& spellId, const MWWorld::Ptr& actor) + { + const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().spells.find(spellId); + return getSpellSuccessChance(spell, actor); + } } #endif diff --git a/files/mygui/openmw_spellcreation_dialog.layout b/files/mygui/openmw_spellcreation_dialog.layout index 499224362..78d3f3de7 100644 --- a/files/mygui/openmw_spellcreation_dialog.layout +++ b/files/mygui/openmw_spellcreation_dialog.layout @@ -22,7 +22,6 @@ - @@ -31,7 +30,6 @@ - @@ -64,7 +62,6 @@ -