1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-01 21:45:38 +00:00

Merge remote-tracking branch 'glorf/enchanting'

This commit is contained in:
Marc Zinnschlag 2013-04-01 17:35:04 +02:00
commit 751c679255
13 changed files with 135 additions and 58 deletions

View file

@ -274,7 +274,7 @@ namespace MWClass
return ref->mBase->mEnchant; return ref->mBase->mEnchant;
} }
std::string Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const void Armor::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{ {
MWWorld::LiveCellRef<ESM::Armor> *ref = MWWorld::LiveCellRef<ESM::Armor> *ref =
ptr.get<ESM::Armor>(); ptr.get<ESM::Armor>();
@ -285,7 +285,7 @@ namespace MWClass
newItem.mData.mEnchant=enchCharge; newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId; newItem.mEnchant=enchId;
const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem); const ESM::Armor *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId; ref->mBase = record;
} }
boost::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const boost::shared_ptr<MWWorld::Action> Armor::use (const MWWorld::Ptr& ptr) const

View file

@ -65,7 +65,7 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string ///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const; const;

View file

@ -147,7 +147,7 @@ namespace MWClass
return ref->mBase->mEnchant; return ref->mBase->mEnchant;
} }
std::string Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const void Book::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{ {
MWWorld::LiveCellRef<ESM::Book> *ref = MWWorld::LiveCellRef<ESM::Book> *ref =
ptr.get<ESM::Book>(); ptr.get<ESM::Book>();
@ -159,7 +159,7 @@ namespace MWClass
newItem.mData.mEnchant=enchCharge; newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId; newItem.mEnchant=enchId;
const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem); const ESM::Book *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId; ref->mBase = record;
} }
boost::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr) const boost::shared_ptr<MWWorld::Action> Book::use (const MWWorld::Ptr& ptr) const

View file

@ -51,7 +51,7 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string ///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) const; virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) const;
///< Generate action for using via inventory menu ///< Generate action for using via inventory menu

View file

@ -221,7 +221,7 @@ namespace MWClass
return ref->mBase->mEnchant; return ref->mBase->mEnchant;
} }
std::string Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const void Clothing::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{ {
MWWorld::LiveCellRef<ESM::Clothing> *ref = MWWorld::LiveCellRef<ESM::Clothing> *ref =
ptr.get<ESM::Clothing>(); ptr.get<ESM::Clothing>();
@ -232,7 +232,7 @@ namespace MWClass
newItem.mData.mEnchant=enchCharge; newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId; newItem.mEnchant=enchId;
const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem); const ESM::Clothing *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId; ref->mBase = record;
} }
boost::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const boost::shared_ptr<MWWorld::Action> Clothing::use (const MWWorld::Ptr& ptr) const

View file

@ -59,7 +59,7 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string ///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const; const;

View file

@ -367,7 +367,7 @@ namespace MWClass
return ref->mBase->mEnchant; return ref->mBase->mEnchant;
} }
std::string Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const void Weapon::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{ {
MWWorld::LiveCellRef<ESM::Weapon> *ref = MWWorld::LiveCellRef<ESM::Weapon> *ref =
ptr.get<ESM::Weapon>(); ptr.get<ESM::Weapon>();
@ -378,7 +378,7 @@ namespace MWClass
newItem.mData.mEnchant=enchCharge; newItem.mData.mEnchant=enchCharge;
newItem.mEnchant=enchId; newItem.mEnchant=enchId;
const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem); const ESM::Weapon *record = MWBase::Environment::get().getWorld()->createRecord (newItem);
return record->mId; ref->mBase = record;
} }
boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const boost::shared_ptr<MWWorld::Action> Weapon::use (const MWWorld::Ptr& ptr) const

View file

@ -65,7 +65,7 @@ namespace MWClass
virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const; virtual std::string getEnchantment (const MWWorld::Ptr& ptr) const;
///< @return the enchantment ID if the object is enchanted, otherwise an empty string ///< @return the enchantment ID if the object is enchanted, otherwise an empty string
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr) virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const; const;

View file

@ -19,7 +19,6 @@ namespace MWGui
: WindowBase("openmw_enchanting_dialog.layout", parWindowManager) : WindowBase("openmw_enchanting_dialog.layout", parWindowManager)
, EffectEditorBase(parWindowManager) , EffectEditorBase(parWindowManager)
, mItemSelectionDialog(NULL) , mItemSelectionDialog(NULL)
, mEnchanting(MWBase::Environment::get().getWorld()->getPlayer().getPlayer())
{ {
getWidget(mName, "NameEdit"); getWidget(mName, "NameEdit");
getWidget(mCancelButton, "CancelButton"); getWidget(mCancelButton, "CancelButton");
@ -87,14 +86,30 @@ namespace MWGui
void EnchantingDialog::startEnchanting (MWWorld::Ptr actor) void EnchantingDialog::startEnchanting (MWWorld::Ptr actor)
{ {
mPtr = actor;
/*Now there's no need to use other enchanters, player is the enchanter here,
even if the enchanted object is created by NPC. Could be changed later, probably
with some price formulas */
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
mEnchanting.setSelfEnchanting(false);
mEnchanting.setEnchanter(player);
mPtr = player;
startEditing (); startEditing ();
} }
void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem) void EnchantingDialog::startSelfEnchanting(MWWorld::Ptr soulgem)
{ {
/// \todo MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
mEnchanting.setSelfEnchanting(true);
mEnchanting.setEnchanter(player);
mPtr = player;
startEditing();
} }
void EnchantingDialog::onReferenceUnavailable () void EnchantingDialog::onReferenceUnavailable ()
@ -264,8 +279,13 @@ namespace MWGui
mEnchanting.setNewItemName(mName->getCaption()); mEnchanting.setNewItemName(mName->getCaption());
mEnchanting.setEffect(mEffectList); mEnchanting.setEffect(mEffectList);
mEnchanting.create(); int result = mEnchanting.create();
if(result==1)
mWindowManager.messageBox ("#{sEnchantmentMenu12}"); mWindowManager.messageBox ("#{sEnchantmentMenu12}");
else
mWindowManager.messageBox ("#{sNotifyMessage34}");
mWindowManager.removeGuiMode (GM_Enchanting); mWindowManager.removeGuiMode (GM_Enchanting);
} }
} }

View file

@ -3,10 +3,13 @@
#include "../mwworld/manualref.hpp" #include "../mwworld/manualref.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp" #include "../mwworld/containerstore.hpp"
#include "creaturestats.hpp"
#include "npcstats.hpp"
namespace MWMechanics namespace MWMechanics
{ {
Enchanting::Enchanting(MWWorld::Ptr enchanter): Enchanting::Enchanting():
mEnchanter(enchanter),
mEnchantType(0) mEnchantType(0)
{} {}
@ -17,6 +20,7 @@ namespace MWMechanics
{ {
mObjectType = mOldItemPtr.getTypeName(); mObjectType = mOldItemPtr.getTypeName();
mOldItemId = mOldItemPtr.getCellRef().mRefID; mOldItemId = mOldItemPtr.getCellRef().mRefID;
mOldItemCount = mOldItemPtr.getRefData().getCount();
} }
else else
{ {
@ -25,7 +29,7 @@ namespace MWMechanics
} }
} }
void Enchanting::setNewItemName(std::string s) void Enchanting::setNewItemName(const std::string& s)
{ {
mNewItemName=s; mNewItemName=s;
} }
@ -35,7 +39,7 @@ namespace MWMechanics
mEffectList=effectList; mEffectList=effectList;
} }
int Enchanting::getEnchantType() int Enchanting::getEnchantType() const
{ {
return mEnchantType; return mEnchantType;
} }
@ -45,28 +49,39 @@ namespace MWMechanics
mSoulGemPtr=soulGem; mSoulGemPtr=soulGem;
} }
void Enchanting::create() bool Enchanting::create()
{ {
mOldItemPtr.getRefData().setCount(mOldItemPtr.getRefData().getCount()-1); ESM::Enchantment enchantment;
mSoulGemPtr.getRefData().setCount(mSoulGemPtr.getRefData().getCount()-1); enchantment.mData.mCharge = getGemCharge();
mSoulGemPtr.getRefData().setCount (mSoulGemPtr.getRefData().getCount()-1);
if(mSelfEnchanting)
{
if(getEnchantChance()<std::rand()/static_cast<double> (RAND_MAX)*100)
return false;
MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 1);
}
mEnchantment.mData.mCharge = getGemCharge();
if(mEnchantType==3) if(mEnchantType==3)
{ {
mEnchantment.mData.mCharge=0; enchantment.mData.mCharge=0;
} }
mEnchantment.mData.mType = mEnchantType; enchantment.mData.mType = mEnchantType;
mEnchantment.mData.mCost = getEnchantCost(); enchantment.mData.mCost = getEnchantCost();
mEnchantment.mEffects = mEffectList; enchantment.mEffects = mEffectList;
const ESM::Enchantment *enchantment = MWBase::Environment::get().getWorld()->createRecord (mEnchantment);
std::string newobjId = MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantment->mId, getGemCharge(), mNewItemName); const ESM::Enchantment *enchantmentPtr = MWBase::Environment::get().getWorld()->createRecord (enchantment);
MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), newobjId); MWWorld::Class::get(mOldItemPtr).applyEnchantment(mOldItemPtr, enchantmentPtr->mId, getGemCharge(), mNewItemName);
MWWorld::Ptr newobjPtr = ref.getPtr();
MWWorld::Ptr result = mOldItemPtr; mOldItemPtr.getRefData().setCount(1);
result.mPtr = newobjPtr.mPtr;
MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (result); MWWorld::ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), mOldItemId);
ref.getPtr().getRefData().setCount (mOldItemCount-1);
MWWorld::Class::get (mEnchanter).getContainerStore (mEnchanter).add (ref.getPtr());
return true;
} }
void Enchanting::nextEnchantType() void Enchanting::nextEnchantType()
@ -79,12 +94,13 @@ namespace MWMechanics
} }
if ((mObjectType == typeid(ESM::Armor).name())||(mObjectType == typeid(ESM::Clothing).name())) if ((mObjectType == typeid(ESM::Armor).name())||(mObjectType == typeid(ESM::Clothing).name()))
{ {
int soulConstAmount = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("iSoulAmountForConstantEffect")->getInt();
switch(mEnchantType) switch(mEnchantType)
{ {
case 1: case 1:
mEnchantType = 2; mEnchantType = 2;
case 3: case 3:
if(getGemCharge()<400) if(getGemCharge()<soulConstAmount)
mEnchantType=2; mEnchantType=2;
case 4: case 4:
mEnchantType = 2; mEnchantType = 2;
@ -104,12 +120,16 @@ namespace MWMechanics
} }
} }
int Enchanting::getEnchantCost() int Enchanting::getEnchantCost() const
{ {
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
float cost = 0; float cost = 0;
std::vector<ESM::ENAMstruct> mEffects = mEffectList.mList; std::vector<ESM::ENAMstruct> mEffects = mEffectList.mList;
int i=mEffects.size(); int i=mEffects.size();
/*
Formula from http://www.uesp.net/wiki/Morrowind:Enchant
*/
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{ {
const ESM::MagicEffect* effect = store.get<ESM::MagicEffect>().find(it->mEffectID); const ESM::MagicEffect* effect = store.get<ESM::MagicEffect>().find(it->mEffectID);
@ -120,7 +140,8 @@ namespace MWMechanics
if(mEnchantType==3) if(mEnchantType==3)
{ {
cost1 *= 100; int constDurationMultipler = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentConstantDurationMult")->getFloat();
cost1 *= constDurationMultipler;
cost2 *= 2; cost2 *= 2;
} }
if(effect->mData.mFlags & ESM::MagicEffect::CastTarget) if(effect->mData.mFlags & ESM::MagicEffect::CastTarget)
@ -134,7 +155,7 @@ namespace MWMechanics
} }
return cost; return cost;
} }
int Enchanting::getGemCharge() int Enchanting::getGemCharge() const
{ {
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
if(soulEmpty()) if(soulEmpty())
@ -145,23 +166,54 @@ namespace MWMechanics
return soul->mData.mSoul; return soul->mData.mSoul;
} }
int Enchanting::getMaxEnchantValue() int Enchanting::getMaxEnchantValue() const
{ {
if (itemEmpty()) if (itemEmpty())
return 0; return 0;
return MWWorld::Class::get(mOldItemPtr).getEnchantmentPoints(mOldItemPtr); return MWWorld::Class::get(mOldItemPtr).getEnchantmentPoints(mOldItemPtr);
} }
bool Enchanting::soulEmpty() bool Enchanting::soulEmpty() const
{ {
if (mSoulGemPtr.isEmpty()) if (mSoulGemPtr.isEmpty())
return true; return true;
return false; return false;
} }
bool Enchanting::itemEmpty() bool Enchanting::itemEmpty() const
{ {
if(mOldItemPtr.isEmpty()) if(mOldItemPtr.isEmpty())
return true; return true;
return false; return false;
} }
void Enchanting::setSelfEnchanting(bool selfEnchanting)
{
mSelfEnchanting = selfEnchanting;
}
void Enchanting::setEnchanter(MWWorld::Ptr enchanter)
{
mEnchanter = enchanter;
}
float Enchanting::getEnchantChance() const
{
/*
Formula from http://www.uesp.net/wiki/Morrowind:Enchant
*/
const CreatureStats& creatureStats = MWWorld::Class::get (mEnchanter).getCreatureStats (mEnchanter);
const NpcStats& npcStats = MWWorld::Class::get (mEnchanter).getNpcStats (mEnchanter);
float chance1 = (npcStats.getSkill (ESM::Skill::Enchant).getModified() +
(0.25 * creatureStats.getAttribute (ESM::Attribute::Intelligence).getModified())
+ (0.125 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()));
float chance2 = 2.5 * getEnchantCost();
if(mEnchantType==3)
{
float constantChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentConstantChanceMult")->getFloat();
chance2 /= constantChance;
}
return (chance1-chance2);
}
} }

View file

@ -9,33 +9,38 @@ namespace MWMechanics
{ {
class Enchanting class Enchanting
{ {
MWWorld::Ptr mOldItemPtr; MWWorld::Ptr mOldItemPtr;
MWWorld::Ptr mSoulGemPtr; MWWorld::Ptr mSoulGemPtr;
MWWorld::Ptr mEnchanter; MWWorld::Ptr mEnchanter;
const MWWorld::Ptr *mNewItemPtr;
int mEnchantType; int mEnchantType;
bool mSelfEnchanting;
ESM::EffectList mEffectList; ESM::EffectList mEffectList;
ESM::Enchantment mEnchantment;
std::string mNewItemName; std::string mNewItemName;
std::string mObjectType; std::string mObjectType;
std::string mOldItemId; std::string mOldItemId;
int mOldItemCount;
public: public:
Enchanting(MWWorld::Ptr enchanter); Enchanting();
void setEnchanter(MWWorld::Ptr enchanter);
void setSelfEnchanting(bool selfEnchanting);
void setOldItem(MWWorld::Ptr oldItem); void setOldItem(MWWorld::Ptr oldItem);
void setNewItemName(std::string s); void setNewItemName(const std::string& s);
void setEffect(ESM::EffectList effectList); void setEffect(ESM::EffectList effectList);
void setSoulGem(MWWorld::Ptr soulGem); void setSoulGem(MWWorld::Ptr soulGem);
void create(); bool create(); //Return true if created, false if failed.
void nextEnchantType(); void nextEnchantType(); //Set enchant type to next possible type (for mOldItemPtr object)
int getEnchantType(); int getEnchantType() const;
int getEnchantCost(); int getEnchantCost() const;
int getMaxEnchantValue(); int getMaxEnchantValue() const;
int getGemCharge(); int getGemCharge() const;
bool soulEmpty(); float getEnchantChance() const;
bool itemEmpty(); bool soulEmpty() const; //Return true if empty
bool itemEmpty() const; //Return true if empty
}; };
} }
#endif #endif

View file

@ -254,7 +254,7 @@ namespace MWWorld
return ""; return "";
} }
std::string Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const void Class::applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const
{ {
throw std::runtime_error ("class can't be enchanted"); throw std::runtime_error ("class can't be enchanted");
} }

View file

@ -237,7 +237,7 @@ namespace MWWorld
virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual std::string applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const; virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;
virtual Ptr virtual Ptr
copyToCell(const Ptr &ptr, CellStore &cell) const; copyToCell(const Ptr &ptr, CellStore &cell) const;