Better formula for enchantment cost and code refactorization.

actorid
Miroslav Puda 12 years ago
parent 56edc1b213
commit 4788b5e226

@ -70,7 +70,7 @@ namespace MWGui
mPrice->setCaption(boost::lexical_cast<std::string>(mEnchanting.getEnchantPrice()));
switch(mEnchanting.getEnchantType())
switch(mEnchanting.getCastStyle())
{
case 0:
mTypeButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sItemCastOnce","Cast Once"));
@ -169,7 +169,7 @@ namespace MWGui
image->eventMouseButtonClick += MyGUI::newDelegate(this, &EnchantingDialog::onRemoveItem);
mEnchanting.setOldItem(item);
mEnchanting.nextEnchantType();
mEnchanting.nextCastStyle();
updateLabels();
}
@ -248,7 +248,7 @@ namespace MWGui
void EnchantingDialog::onTypeButtonClicked(MyGUI::Widget* sender)
{
mEnchanting.nextEnchantType();
mEnchanting.nextCastStyle();
updateLabels();
}

@ -12,7 +12,7 @@
namespace MWMechanics
{
Enchanting::Enchanting():
mEnchantType(0)
mCastStyle(ESM::CS_CastOnce)
{}
void Enchanting::setOldItem(MWWorld::Ptr oldItem)
@ -41,9 +41,9 @@ namespace MWMechanics
mEffectList=effectList;
}
int Enchanting::getEnchantType() const
int Enchanting::getCastStyle() const
{
return mEnchantType;
return mCastStyle;
}
void Enchanting::setSoulGem(MWWorld::Ptr soulGem)
@ -74,11 +74,11 @@ namespace MWMechanics
MWWorld::Class::get (mEnchanter).skillUsageSucceeded (mEnchanter, ESM::Skill::Enchant, 1);
}
if(mEnchantType==3)
if(mCastStyle==3)
{
enchantment.mData.mCharge=0;
}
enchantment.mData.mType = mEnchantType;
enchantment.mData.mType = mCastStyle;
enchantment.mData.mCost = getEnchantCost();
enchantment.mEffects = mEffectList;
@ -98,78 +98,97 @@ namespace MWMechanics
return true;
}
void Enchanting::nextEnchantType()
void Enchanting::nextCastStyle()
{
mEnchantType++;
mCastStyle++;
if (itemEmpty())
{
mEnchantType = 0;
mCastStyle = 0;
return;
}
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(mCastStyle)
{
case 1:
mEnchantType = 2;
mCastStyle = 2;
case 3:
if(getGemCharge()<soulConstAmount)
mEnchantType=2;
mCastStyle=2;
case 4:
mEnchantType = 2;
mCastStyle = 2;
}
}
else if(mObjectType == typeid(ESM::Weapon).name())
{
switch(mEnchantType)
switch(mCastStyle)
{
case 3:
mEnchantType = 1;
mCastStyle = 1;
}
}
else if(mObjectType == typeid(ESM::Book).name())
{
mEnchantType=0;
mCastStyle=0;
}
}
/*
* Vanilla enchant cost formula:
*
* Touch/Self: (min + max) * baseCost * 0.025 * duration + area * baseCost * 0.025
* Target: 1.5 * ((min + max) * baseCost * 0.025 * duration + area * baseCost * 0.025)
* Constant eff: (min + max) * baseCost * 2.5 + area * baseCost * 0.025
*
* For multiple effects - cost of each effect is multiplied by number of effects that follows +1.
*
* Note: Minimal value inside formula for 'min' and 'max' is 1. So in vanilla:
* (0 + 0) == (1 + 0) == (1 + 1) => 2 or (2 + 0) == (1 + 2) => 3
*
* Formula on UESPWiki is not entirely correct.
*/
float Enchanting::getEnchantCost() const
{
if (mEffectList.mList.empty())
// No effects added, cost = 0
return 0;
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
float cost = 0;
std::vector<ESM::ENAMstruct> mEffects = mEffectList.mList;
int i=mEffects.size();
if(i<=0)
return 0;
/*
Formula from http://www.uesp.net/wiki/Morrowind:Enchant
*/
float enchantmentCost = 0;
int effectsLeftCnt = mEffects.size();
float baseCost, magnitudeCost, areaCost;
int magMin, magMax, area;
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);
baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost;
// To reflect vanilla behavior
magMin = (it->mMagnMin == 0) ? 1 : it->mMagnMin;
magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax;
area = (it->mArea == 0) ? 1 : it->mArea;
float cost1 = ((it->mMagnMin + it->mMagnMax)*it->mDuration*effect->mData.mBaseCost*0.025);
float cost2 = (std::max(1, it->mArea)*0.125*effect->mData.mBaseCost);
if(mEnchantType==3)
if (mCastStyle == ESM::CS_ConstantEffect)
{
int constDurationMultipler = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentConstantDurationMult")->getFloat();
cost1 *= constDurationMultipler;
cost2 *= 2;
magnitudeCost = (magMin + magMax) * baseCost * 2.5;
}
else
{
magnitudeCost = (magMin + magMax) * it->mDuration * baseCost * 0.025;
if(it->mRange == ESM::RT_Target)
magnitudeCost *= 1.5;
}
if(it->mRange == ESM::RT_Target)
cost1 *= 1.5;
float fullcost = cost1+cost2;
fullcost*= i;
i--;
areaCost = area * 0.025 * baseCost;
if (it->mRange == ESM::RT_Target)
areaCost *= 1.5;
cost+=fullcost;
enchantmentCost += (magnitudeCost + areaCost) * effectsLeftCnt;
--effectsLeftCnt;
}
return cost;
return enchantmentCost;
}
int Enchanting::getEnchantPrice() const
@ -236,7 +255,7 @@ namespace MWMechanics
+ (0.125 * creatureStats.getAttribute (ESM::Attribute::Luck).getModified()));
float chance2 = 2.5 * getEnchantCost();
if(mEnchantType==3)
if(mCastStyle==3)
{
float constantChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentConstantChanceMult")->getFloat();
chance2 /= constantChance;

@ -14,7 +14,7 @@ namespace MWMechanics
MWWorld::Ptr mSoulGemPtr;
MWWorld::Ptr mEnchanter;
int mEnchantType;
int mCastStyle;
bool mSelfEnchanting;
@ -34,8 +34,8 @@ namespace MWMechanics
void setEffect(ESM::EffectList effectList);
void setSoulGem(MWWorld::Ptr soulGem);
bool create(); //Return true if created, false if failed.
void nextEnchantType(); //Set enchant type to next possible type (for mOldItemPtr object)
int getEnchantType() const;
void nextCastStyle(); //Set enchant type to next possible type (for mOldItemPtr object)
int getCastStyle() const;
float getEnchantCost() const;
int getEnchantPrice() const;
float getMaxEnchantValue() const;

@ -23,6 +23,15 @@ enum RangeType
RT_Target = 2
};
// Casting style (in enchanting)
enum Type
{
CS_CastOnce = 0,
CS_WhenStrikes = 1,
CS_WhenUsed = 2,
CS_ConstantEffect = 3
};
#pragma pack(push)
#pragma pack(1)

Loading…
Cancel
Save