1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 09:45:36 +00:00

Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2014-08-17 12:07:44 +02:00
commit 02b7712d7c
33 changed files with 552 additions and 155 deletions

View file

@ -541,11 +541,11 @@ namespace MWClass
float moveSpeed; float moveSpeed;
if(normalizedEncumbrance >= 1.0f) if(normalizedEncumbrance >= 1.0f)
moveSpeed = 0.0f; moveSpeed = 0.0f;
else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 && else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 &&
world->isLevitationEnabled())) world->isLevitationEnabled()))
{ {
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() + float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude); mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat()); flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance; flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
flySpeed = std::max(0.0f, flySpeed); flySpeed = std::max(0.0f, flySpeed);
@ -556,7 +556,7 @@ namespace MWClass
float swimSpeed = walkSpeed; float swimSpeed = walkSpeed;
if(running) if(running)
swimSpeed = runSpeed; swimSpeed = runSpeed;
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude; swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) * swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
gmst.fSwimRunAthleticsMult->getFloat(); gmst.fSwimRunAthleticsMult->getFloat();
moveSpeed = swimSpeed; moveSpeed = swimSpeed;
@ -617,7 +617,7 @@ namespace MWClass
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
{ {
// Note this is currently unused. Creatures do not use armor mitigation. // Note this is currently unused. Creatures do not use armor mitigation.
return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude; return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude();
} }
float Creature::getCapacity (const MWWorld::Ptr& ptr) const float Creature::getCapacity (const MWWorld::Ptr& ptr) const
@ -632,9 +632,9 @@ namespace MWClass
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr); const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).mMagnitude; weight -= stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Feather)).getMagnitude();
weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).mMagnitude; weight += stats.getMagicEffects().get (MWMechanics::EffectKey (ESM::MagicEffect::Burden)).getMagnitude();
if (weight<0) if (weight<0)
weight = 0; weight = 0;

View file

@ -180,7 +180,7 @@ namespace MWClass
std::string text; std::string text;
if (!gold) if (!gold && !ref->mBase->mData.mIsKey)
{ {
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}");

View file

@ -565,7 +565,7 @@ namespace MWClass
damage = stats.getSkill(weapskill).getModified(); damage = stats.getSkill(weapskill).getModified();
damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength()); damage *= minstrike + ((maxstrike-minstrike)*stats.getAttackStrength());
healthdmg = (otherstats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0) healthdmg = (otherstats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
|| otherstats.getKnockedDown(); || otherstats.getKnockedDown();
if(stats.isWerewolf()) if(stats.isWerewolf())
{ {
@ -922,11 +922,11 @@ namespace MWClass
float moveSpeed; float moveSpeed;
if(normalizedEncumbrance >= 1.0f) if(normalizedEncumbrance >= 1.0f)
moveSpeed = 0.0f; moveSpeed = 0.0f;
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 && else if(mageffects.get(ESM::MagicEffect::Levitate).getMagnitude() > 0 &&
world->isLevitationEnabled()) world->isLevitationEnabled())
{ {
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() + float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude); mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat()); flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance; flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
flySpeed = std::max(0.0f, flySpeed); flySpeed = std::max(0.0f, flySpeed);
@ -937,7 +937,7 @@ namespace MWClass
float swimSpeed = walkSpeed; float swimSpeed = walkSpeed;
if(running) if(running)
swimSpeed = runSpeed; swimSpeed = runSpeed;
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude; swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()* swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
gmst.fSwimRunAthleticsMult->getFloat(); gmst.fSwimRunAthleticsMult->getFloat();
moveSpeed = swimSpeed; moveSpeed = swimSpeed;
@ -975,7 +975,7 @@ namespace MWClass
float x = gmst.fJumpAcrobaticsBase->getFloat() + float x = gmst.fJumpAcrobaticsBase->getFloat() +
std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->getFloat()); std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->getFloat());
x += 3.0f * b * gmst.fJumpAcroMultiplier->getFloat(); x += 3.0f * b * gmst.fJumpAcroMultiplier->getFloat();
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64; x += mageffects.get(ESM::MagicEffect::Jump).getMagnitude() * 64;
x *= encumbranceTerm; x *= encumbranceTerm;
if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run)) if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
@ -998,7 +998,7 @@ namespace MWClass
{ {
const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); const float acrobaticsSkill = ptr.getClass().getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData()); const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude; const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude();
const float fallAcroBase = store.find("fFallAcroBase")->getFloat(); const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
const float fallAcroMult = store.find("fFallAcroMult")->getFloat(); const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat(); const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
@ -1104,8 +1104,8 @@ namespace MWClass
if(!stats.isWerewolf()) if(!stats.isWerewolf())
{ {
weight = getContainerStore(ptr).getWeight(); weight = getContainerStore(ptr).getWeight();
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude; weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).getMagnitude();
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude; weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).getMagnitude();
if(weight < 0.0f) if(weight < 0.0f)
weight = 0.0f; weight = 0.0f;
} }
@ -1170,7 +1170,7 @@ namespace MWClass
} }
} }
float shield = stats.getMagicEffects().get(ESM::MagicEffect::Shield).mMagnitude; float shield = stats.getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude();
return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3f return ratings[MWWorld::InventoryStore::Slot_Cuirass] * 0.3f
+ (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet] + (ratings[MWWorld::InventoryStore::Slot_CarriedLeft] + ratings[MWWorld::InventoryStore::Slot_Helmet]

View file

@ -290,6 +290,9 @@ namespace MWDialogue
std::string title; std::string title;
if (dialogue.mType==ESM::Dialogue::Persuasion) if (dialogue.mType==ESM::Dialogue::Persuasion)
{ {
// Determine GMST from dialogue topic. GMSTs are:
// sAdmireSuccess, sAdmireFail, sIntimidateSuccess, sIntimidateFail,
// sTauntSuccess, sTauntFail, sBribeSuccess, sBribeFail
std::string modifiedTopic = "s" + topic; std::string modifiedTopic = "s" + topic;
modifiedTopic.erase (std::remove (modifiedTopic.begin(), modifiedTopic.end(), ' '), modifiedTopic.end()); modifiedTopic.erase (std::remove (modifiedTopic.begin(), modifiedTopic.end(), ' '), modifiedTopic.end());

View file

@ -492,7 +492,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_PcCorprus: case SelectWrapper::Function_PcCorprus:
return player.getClass().getCreatureStats (player). return player.getClass().getCreatureStats (player).
getMagicEffects().get (ESM::MagicEffect::Corprus).mMagnitude!=0; getMagicEffects().get (ESM::MagicEffect::Corprus).getMagnitude()!=0;
case SelectWrapper::Function_PcExpelled: case SelectWrapper::Function_PcExpelled:
{ {
@ -508,7 +508,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
case SelectWrapper::Function_PcVampire: case SelectWrapper::Function_PcVampire:
return player.getClass().getCreatureStats(player).getMagicEffects(). return player.getClass().getCreatureStats(player).getMagicEffects().
get(ESM::MagicEffect::Vampirism).mMagnitude > 0; get(ESM::MagicEffect::Vampirism).getMagnitude() > 0;
case SelectWrapper::Function_TalkedToPc: case SelectWrapper::Function_TalkedToPc:

View file

@ -229,9 +229,6 @@ namespace MWGui
else else
dragItem (NULL, count); dragItem (NULL, count);
} }
// item might have been unequipped
notifyContentChanged();
} }
void InventoryWindow::ensureSelectedItemUnequipped() void InventoryWindow::ensureSelectedItemUnequipped()
@ -269,6 +266,7 @@ namespace MWGui
{ {
ensureSelectedItemUnequipped(); ensureSelectedItemUnequipped();
mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count); mDragAndDrop->startDrag(mSelectedItem, mSortModel, mTradeModel, mItemView, count);
notifyContentChanged();
} }
void InventoryWindow::sellItem(MyGUI::Widget* sender, int count) void InventoryWindow::sellItem(MyGUI::Widget* sender, int count)
@ -292,6 +290,7 @@ namespace MWGui
} }
mItemView->update(); mItemView->update();
notifyContentChanged();
} }
void InventoryWindow::updateItemView() void InventoryWindow::updateItemView()

View file

@ -197,9 +197,9 @@ namespace MWGui
WindowModal::open(); WindowModal::open();
int textPadding = 10; // padding between text-widget and main-widget int textPadding = 10; // padding between text-widget and main-widget
int textButtonPadding = 20; // padding between the text-widget und the button-widget int textButtonPadding = 10; // padding between the text-widget und the button-widget
int buttonLeftPadding = 10; // padding between the buttons if horizontal int buttonLeftPadding = 10; // padding between the buttons if horizontal
int buttonTopPadding = 5; // ^-- if vertical int buttonTopPadding = 10; // ^-- if vertical
int buttonPadding = 5; // padding between button label and button itself int buttonPadding = 5; // padding between button label and button itself
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
@ -219,6 +219,7 @@ namespace MWGui
int biggestButtonWidth = 0; int biggestButtonWidth = 0;
int buttonWidth = 0; int buttonWidth = 0;
int buttonsWidth = 0; int buttonsWidth = 0;
int buttonsHeight = 0;
int buttonHeight = 0; int buttonHeight = 0;
MyGUI::IntCoord dummyCoord(0, 0, 0, 0); MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
@ -236,64 +237,120 @@ namespace MWGui
mButtons.push_back(button); mButtons.push_back(button);
buttonWidth = button->getTextSize().width + 2*buttonPadding + buttonLeftPadding; if (buttonsWidth != 0)
buttonsWidth += buttonLeftPadding;
buttonWidth = button->getTextSize().width + 2*buttonPadding;
buttonsWidth += buttonWidth; buttonsWidth += buttonWidth;
buttonHeight = button->getTextSize().height + 2*buttonPadding + buttonTopPadding;
buttonHeight = button->getTextSize().height + 2*buttonPadding;
if (buttonsHeight != 0)
buttonsHeight += buttonTopPadding;
buttonsHeight += buttonHeight;
if(buttonWidth > biggestButtonWidth) if(buttonWidth > biggestButtonWidth)
{ {
biggestButtonWidth = buttonWidth; biggestButtonWidth = buttonWidth;
} }
} }
buttonsWidth += buttonLeftPadding;
MyGUI::IntSize mainWidgetSize; MyGUI::IntSize mainWidgetSize;
// among each other if(buttonsWidth < textSize.width)
if(biggestButtonWidth > textSize.width) {
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
}
else {
mainWidgetSize.width = textSize.width + 3*textPadding;
}
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int top = textButtonPadding + buttonTopPadding + textSize.height;
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{ {
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2; // on one line
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2; mainWidgetSize.width = textSize.width + 3*textPadding;
mainWidgetSize.height = textPadding + textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
buttonCord.top = top; MyGUI::IntSize realSize = mainWidgetSize +
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/ // To account for borders
(mMainWidget->getSize() - mMainWidget->getClientWidget()->getSize());
(*button)->setCoord(buttonCord); MyGUI::IntPoint absPos;
(*button)->setSize(buttonSize); absPos.left = (gameWindowSize.width - realSize.width)/2;
absPos.top = (gameWindowSize.height - realSize.height)/2;
top += buttonSize.height + 2*buttonTopPadding; mMainWidget->setPosition(absPos);
mMainWidget->setSize(realSize);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
mMessageWidget->setCoord(messageWidgetCoord);
mMessageWidget->setSize(textSize);
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int left = (mainWidgetSize.width - buttonsWidth)/2;
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonCord.left = left;
buttonCord.top = messageWidgetCoord.top + textSize.height + textButtonPadding;
buttonSize.width = (*button)->getTextSize().width + 2*buttonPadding;
buttonSize.height = (*button)->getTextSize().height + 2*buttonPadding;
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
left += buttonSize.width + buttonLeftPadding;
}
} }
else
{
// among each other
if(biggestButtonWidth > textSize.width) {
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding*2;
}
else {
mainWidgetSize.width = textSize.width + 3*textPadding;
}
mainWidgetSize.height = top + buttonMainPadding; MyGUI::IntCoord buttonCord;
mMainWidget->setSize(mainWidgetSize); MyGUI::IntSize buttonSize(0, buttonHeight);
MyGUI::IntPoint absPos; int top = textPadding + textSize.height + textButtonPadding;
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setPosition(absPos); std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonSize.width = (*button)->getTextSize().width + buttonPadding*2;
buttonSize.height = (*button)->getTextSize().height + buttonPadding*2;
MyGUI::IntCoord messageWidgetCoord; buttonCord.top = top;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2; buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2;
messageWidgetCoord.top = textPadding;
messageWidgetCoord.width = textSize.width; (*button)->setCoord(buttonCord);
messageWidgetCoord.height = textSize.height; (*button)->setSize(buttonSize);
mMessageWidget->setCoord(messageWidgetCoord);
top += buttonSize.height + buttonTopPadding;
}
mainWidgetSize.height = textPadding + textSize.height + textButtonPadding + buttonsHeight + buttonMainPadding;
mMainWidget->setSize(mainWidgetSize +
// To account for borders
(mMainWidget->getSize() - mMainWidget->getClientWidget()->getSize()));
MyGUI::IntPoint absPos;
absPos.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absPos.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setPosition(absPos);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
messageWidgetCoord.width = textSize.width;
messageWidgetCoord.height = textSize.height;
mMessageWidget->setCoord(messageWidgetCoord);
}
// Set key focus to "Ok" button // Set key focus to "Ok" button
std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}")); std::string ok = Misc::StringUtils::lowerCase(MyGUI::LanguageManager::getInstance().replaceTags("#{sOK}"));
std::vector<MyGUI::Button*>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button) for(button = mButtons.begin(); button != mButtons.end(); ++button)
{ {
if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok)) if(Misc::StringUtils::ciEqual((*button)->getCaption(), ok))

View file

@ -146,7 +146,7 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0; bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).getMagnitude() > 0;
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
health = 0.1 * endurance; health = 0.1 * endurance;
@ -357,6 +357,7 @@ namespace MWMechanics
CreatureStats& creatureStats = creature.getClass().getCreatureStats (creature); CreatureStats& creatureStats = creature.getClass().getCreatureStats (creature);
if (creatureStats.isDead()) if (creatureStats.isDead())
return; return;
MagicEffects now = creatureStats.getSpells().getMagicEffects(); MagicEffects now = creatureStats.getSpells().getMagicEffects();
if (creature.getTypeName()==typeid (ESM::NPC).name()) if (creature.getTypeName()==typeid (ESM::NPC).name())
@ -367,11 +368,7 @@ namespace MWMechanics
now += creatureStats.getActiveSpells().getMagicEffects(); now += creatureStats.getActiveSpells().getMagicEffects();
//MagicEffects diff = MagicEffects::diff (creatureStats.getMagicEffects(), now); creatureStats.modifyMagicEffects(now);
creatureStats.setMagicEffects(now);
// TODO apply diff to other stats
} }
void Actors::calculateDynamicStats (const MWWorld::Ptr& ptr) void Actors::calculateDynamicStats (const MWWorld::Ptr& ptr)
@ -385,7 +382,7 @@ namespace MWMechanics
int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getModified(); int endurance = creatureStats.getAttribute(ESM::Attribute::Endurance).getModified();
double magickaFactor = double magickaFactor =
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude * 0.1 + 1; creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1 + 1;
DynamicStat<float> magicka = creatureStats.getMagicka(); DynamicStat<float> magicka = creatureStats.getMagicka();
float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase(); float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase();
@ -473,9 +470,9 @@ namespace MWMechanics
for(int i = 0;i < ESM::Attribute::Length;++i) for(int i = 0;i < ESM::Attribute::Length;++i)
{ {
AttributeValue stat = creatureStats.getAttribute(i); AttributeValue stat = creatureStats.getAttribute(i);
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude - stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).getMagnitude() -
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude - effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).getMagnitude() -
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude); effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).getMagnitude());
creatureStats.setAttribute(i, stat); creatureStats.setAttribute(i, stat);
} }
@ -484,13 +481,13 @@ namespace MWMechanics
for(int i = 0;i < 3;++i) for(int i = 0;i < 3;++i)
{ {
DynamicStat<float> stat = creatureStats.getDynamic(i); DynamicStat<float> stat = creatureStats.getDynamic(i);
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).mMagnitude - stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).getMagnitude() -
effects.get(ESM::MagicEffect::DrainHealth+i).mMagnitude); effects.get(ESM::MagicEffect::DrainHealth+i).getMagnitude());
float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).mMagnitude float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).getMagnitude()
- creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).mMagnitude - creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).getMagnitude()
- creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).mMagnitude; - creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).getMagnitude();
stat.setCurrent(stat.getCurrent() + currentDiff * duration, i == 2); stat.setCurrent(stat.getCurrent() + currentDiff * duration, i == 2);
creatureStats.setDynamic(i, stat); creatureStats.setDynamic(i, stat);
@ -504,27 +501,27 @@ namespace MWMechanics
if (!creature || ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Creatures) if (!creature || ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Creatures)
{ {
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Fight); Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Fight);
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid+creature).mMagnitude stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::FrenzyHumanoid+creature).getMagnitude()
- creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).mMagnitude); - creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid+creature).getMagnitude());
creatureStats.setAiSetting(CreatureStats::AI_Fight, stat); creatureStats.setAiSetting(CreatureStats::AI_Fight, stat);
stat = creatureStats.getAiSetting(CreatureStats::AI_Flee); stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid+creature).mMagnitude stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::DemoralizeHumanoid+creature).getMagnitude()
- creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).mMagnitude); - creatureStats.getMagicEffects().get(ESM::MagicEffect::RallyHumanoid+creature).getMagnitude());
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat); creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
} }
if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Undead) if (creature && ptr.get<ESM::Creature>()->mBase->mData.mType == ESM::Creature::Undead)
{ {
Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Flee); Stat<int> stat = creatureStats.getAiSetting(CreatureStats::AI_Flee);
stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).mMagnitude); stat.setModifier(creatureStats.getMagicEffects().get(ESM::MagicEffect::TurnUndead).getMagnitude());
creatureStats.setAiSetting(CreatureStats::AI_Flee, stat); creatureStats.setAiSetting(CreatureStats::AI_Flee, stat);
} }
// Apply disintegration (reduces item health) // Apply disintegration (reduces item health)
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude; float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).getMagnitude();
if (disintegrateWeapon > 0) if (disintegrateWeapon > 0)
disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration); disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration);
float disintegrateArmor = effects.get(ESM::MagicEffect::DisintegrateArmor).mMagnitude; float disintegrateArmor = effects.get(ESM::MagicEffect::DisintegrateArmor).getMagnitude();
if (disintegrateArmor > 0) if (disintegrateArmor > 0)
{ {
// According to UESP // According to UESP
@ -556,7 +553,7 @@ namespace MWMechanics
DynamicStat<float> health = creatureStats.getHealth(); DynamicStat<float> health = creatureStats.getHealth();
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i) for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
{ {
float magnitude = creatureStats.getMagicEffects().get(damageEffects[i]).mMagnitude; float magnitude = creatureStats.getMagicEffects().get(damageEffects[i]).getMagnitude();
if (damageEffects[i] == ESM::MagicEffect::SunDamage) if (damageEffects[i] == ESM::MagicEffect::SunDamage)
{ {
@ -647,7 +644,7 @@ namespace MWMechanics
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it) for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
{ {
bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end(); bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end();
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude; int magnitude = creatureStats.getMagicEffects().get(it->first).getMagnitude();
if (found != (magnitude > 0)) if (found != (magnitude > 0))
{ {
std::string itemGmst = it->second; std::string itemGmst = it->second;
@ -704,7 +701,7 @@ namespace MWMechanics
for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it) for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it)
{ {
bool found = creatureMap.find(it->first) != creatureMap.end(); bool found = creatureMap.find(it->first) != creatureMap.end();
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude; int magnitude = creatureStats.getMagicEffects().get(it->first).getMagnitude();
if (found != (magnitude > 0)) if (found != (magnitude > 0))
{ {
if (magnitude > 0) if (magnitude > 0)
@ -808,9 +805,9 @@ namespace MWMechanics
for(int i = 0;i < ESM::Skill::Length;++i) for(int i = 0;i < ESM::Skill::Length;++i)
{ {
SkillValue& skill = npcStats.getSkill(i); SkillValue& skill = npcStats.getSkill(i);
skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).mMagnitude - skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).getMagnitude() -
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).mMagnitude - effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).getMagnitude() -
effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).mMagnitude); effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).getMagnitude());
} }
} }
@ -819,7 +816,7 @@ namespace MWMechanics
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
NpcStats &stats = ptr.getClass().getNpcStats(ptr); NpcStats &stats = ptr.getClass().getNpcStats(ptr);
if(world->isSubmerged(ptr) && if(world->isSubmerged(ptr) &&
stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).mMagnitude == 0) stats.getMagicEffects().get(ESM::MagicEffect::WaterBreathing).getMagnitude() == 0)
{ {
float timeLeft = 0.0f; float timeLeft = 0.0f;
if(stats.getFatigue().getCurrent() == 0) if(stats.getFatigue().getCurrent() == 0)
@ -1128,7 +1125,7 @@ namespace MWMechanics
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{ {
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).mMagnitude > 0) ESM::MagicEffect::Paralyze).getMagnitude() > 0)
iter->second->skipAnim(); iter->second->skipAnim();
iter->second->update(duration); iter->second->update(duration);
} }
@ -1297,7 +1294,7 @@ namespace MWMechanics
// Reset magic effects and recalculate derived effects // Reset magic effects and recalculate derived effects
// One case where we need this is to make sure bound items are removed upon death // One case where we need this is to make sure bound items are removed upon death
stats.setMagicEffects(MWMechanics::MagicEffects()); stats.modifyMagicEffects(MWMechanics::MagicEffects());
stats.getActiveSpells().clear(); stats.getActiveSpells().clear();
calculateCreatureStatModifiers(iter->first, 0); calculateCreatureStatModifiers(iter->first, 0);
@ -1463,5 +1460,7 @@ namespace MWMechanics
{ {
adjustMagicEffects(ptr); adjustMagicEffects(ptr);
calculateCreatureStatModifiers(ptr, 0.f); calculateCreatureStatModifiers(ptr, 0.f);
if (ptr.getClass().isNpc())
calculateNpcStatModifiers(ptr);
} }
} }

View file

@ -1639,7 +1639,7 @@ void CharacterController::updateContinuousVfx()
for (std::vector<int>::iterator it = effects.begin(); it != effects.end(); ++it) for (std::vector<int>::iterator it = effects.begin(); it != effects.end(); ++it)
{ {
if (mPtr.getClass().getCreatureStats(mPtr).isDead() if (mPtr.getClass().getCreatureStats(mPtr).isDead()
|| mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(MWMechanics::EffectKey(*it)).mMagnitude <= 0) || mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(MWMechanics::EffectKey(*it)).getMagnitude() <= 0)
mAnimation->removeEffect(*it); mAnimation->removeEffect(*it);
} }
} }
@ -1649,14 +1649,14 @@ void CharacterController::updateVisibility()
if (!mPtr.getClass().isActor()) if (!mPtr.getClass().isActor())
return; return;
float alpha = 1.f; float alpha = 1.f;
if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude) if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude())
{ {
if (mPtr.getRefData().getHandle() == "player") if (mPtr.getRefData().getHandle() == "player")
alpha = 0.4f; alpha = 0.4f;
else else
alpha = 0.f; alpha = 0.f;
} }
float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude; float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude();
if (chameleon) if (chameleon)
{ {
alpha *= std::max(0.2f, (100.f - chameleon)/100.f); alpha *= std::max(0.2f, (100.f - chameleon)/100.f);

View file

@ -59,7 +59,7 @@ namespace MWMechanics
if (blockerStats.getKnockedDown() // Used for both knockout or knockdown if (blockerStats.getKnockedDown() // Used for both knockout or knockdown
|| blockerStats.getHitRecovery() || blockerStats.getHitRecovery()
|| blockerStats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0) || blockerStats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
return false; return false;
// Don't block when in spellcasting state (shield is equipped, but not visible) // Don't block when in spellcasting state (shield is equipped, but not visible)
@ -144,8 +144,8 @@ namespace MWMechanics
void resistNormalWeapon(const MWWorld::Ptr &actor, const MWWorld::Ptr& attacker, const MWWorld::Ptr &weapon, float &damage) void resistNormalWeapon(const MWWorld::Ptr &actor, const MWWorld::Ptr& attacker, const MWWorld::Ptr &weapon, float &damage)
{ {
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
float resistance = std::min(100.f, stats.getMagicEffects().get(ESM::MagicEffect::ResistNormalWeapons).mMagnitude float resistance = std::min(100.f, stats.getMagicEffects().get(ESM::MagicEffect::ResistNormalWeapons).getMagnitude()
- stats.getMagicEffects().get(ESM::MagicEffect::WeaknessToNormalWeapons).mMagnitude); - stats.getMagicEffects().get(ESM::MagicEffect::WeaknessToNormalWeapons).getMagnitude());
float multiplier = 1.f - resistance / 100.f; float multiplier = 1.f - resistance / 100.f;
@ -246,8 +246,8 @@ namespace MWMechanics
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) + (stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f); (stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
hitchance *= stats.getFatigueTerm(); hitchance *= stats.getFatigueTerm();
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude - hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).getMagnitude() -
mageffects.get(ESM::MagicEffect::Blind).mMagnitude; mageffects.get(ESM::MagicEffect::Blind).getMagnitude();
hitchance -= victim.getClass().getCreatureStats(victim).getEvasion(); hitchance -= victim.getClass().getCreatureStats(victim).getEvasion();
return hitchance; return hitchance;
} }
@ -256,7 +256,7 @@ namespace MWMechanics
{ {
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
{ {
float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).mMagnitude; float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).getMagnitude();
if (!magnitude) if (!magnitude)
continue; continue;

View file

@ -211,13 +211,13 @@ namespace MWMechanics
mActiveSpells = active; mActiveSpells = active;
} }
void CreatureStats::setMagicEffects(const MagicEffects &effects) void CreatureStats::modifyMagicEffects(const MagicEffects &effects)
{ {
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude) != mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier())
mRecalcDynamicStats = true; mRecalcDynamicStats = true;
mMagicEffects = effects; mMagicEffects.setModifiers(effects);
} }
void CreatureStats::setAttackingOrSpell(bool attackingOrSpell) void CreatureStats::setAttackingOrSpell(bool attackingOrSpell)
@ -346,7 +346,7 @@ namespace MWMechanics
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) + float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f); (getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
evasion *= getFatigueTerm(); evasion *= getFatigueTerm();
evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).mMagnitude; evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).getMagnitude();
return evasion; return evasion;
} }
@ -516,6 +516,7 @@ namespace MWMechanics
mSpells.writeState(state.mSpells); mSpells.writeState(state.mSpells);
mActiveSpells.writeState(state.mActiveSpells); mActiveSpells.writeState(state.mActiveSpells);
mAiSequence.writeState(state.mAiSequence); mAiSequence.writeState(state.mAiSequence);
mMagicEffects.writeState(state.mMagicEffects);
state.mSummonedCreatureMap = mSummonedCreatures; state.mSummonedCreatureMap = mSummonedCreatures;
state.mSummonGraveyard = mSummonGraveyard; state.mSummonGraveyard = mSummonGraveyard;
@ -564,6 +565,7 @@ namespace MWMechanics
mSpells.readState(state.mSpells); mSpells.readState(state.mSpells);
mActiveSpells.readState(state.mActiveSpells); mActiveSpells.readState(state.mActiveSpells);
mAiSequence.readState(state.mAiSequence); mAiSequence.readState(state.mAiSequence);
mMagicEffects.readState(state.mMagicEffects);
mSummonedCreatures = state.mSummonedCreatureMap; mSummonedCreatures = state.mSummonedCreatureMap;
mSummonGraveyard = state.mSummonGraveyard; mSummonGraveyard = state.mSummonGraveyard;

View file

@ -141,7 +141,8 @@ namespace MWMechanics
void setActiveSpells(const ActiveSpells &active); void setActiveSpells(const ActiveSpells &active);
void setMagicEffects(const MagicEffects &effects); /// Set Modifier for each magic effect according to \a effects. Does not touch Base values.
void modifyMagicEffects(const MagicEffects &effects);
void setAttackingOrSpell(bool attackingOrSpell); void setAttackingOrSpell(bool attackingOrSpell);

View file

@ -45,14 +45,14 @@ namespace MWMechanics
float resist = 0.f; float resist = 0.f;
if (hasCorprusEffect) if (hasCorprusEffect)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCorprusDisease).mMagnitude resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCorprusDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCorprusDisease).mMagnitude); - actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCorprusDisease).getMagnitude());
else if (spell->mData.mType == ESM::Spell::ST_Disease) else if (spell->mData.mType == ESM::Spell::ST_Disease)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).mMagnitude resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCommonDisease).mMagnitude); - actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToCommonDisease).getMagnitude());
else if (spell->mData.mType == ESM::Spell::ST_Blight) else if (spell->mData.mType == ESM::Spell::ST_Blight)
resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).mMagnitude resist = 1.f - 0.01 * (actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).getMagnitude()
- actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToBlightDisease).mMagnitude); - actor.getClass().getCreatureStats(actor).getMagicEffects().get(ESM::MagicEffect::WeaknessToBlightDisease).getMagnitude());
else else
continue; continue;

View file

@ -6,6 +6,7 @@
#include <stdexcept> #include <stdexcept>
#include <components/esm/effectlist.hpp> #include <components/esm/effectlist.hpp>
#include <components/esm/magiceffects.hpp>
namespace MWMechanics namespace MWMechanics
{ {
@ -40,20 +41,57 @@ namespace MWMechanics
return left.mArg<right.mArg; return left.mArg<right.mArg;
} }
EffectParam::EffectParam() : mMagnitude (0) {} float EffectParam::getMagnitude() const
{
return mBase + mModifier;
}
void EffectParam::modifyBase(int diff)
{
mBase += diff;
}
int EffectParam::getBase() const
{
return mBase;
}
void EffectParam::setBase(int base)
{
mBase = base;
}
void EffectParam::setModifier(float mod)
{
mModifier = mod;
}
float EffectParam::getModifier() const
{
return mModifier;
}
EffectParam::EffectParam() : mModifier (0), mBase(0) {}
EffectParam& EffectParam::operator+= (const EffectParam& param) EffectParam& EffectParam::operator+= (const EffectParam& param)
{ {
mMagnitude += param.mMagnitude; mModifier += param.mModifier;
mBase += param.mBase;
return *this; return *this;
} }
EffectParam& EffectParam::operator-= (const EffectParam& param) EffectParam& EffectParam::operator-= (const EffectParam& param)
{ {
mMagnitude -= param.mMagnitude; mModifier -= param.mModifier;
mBase -= param.mBase;
return *this; return *this;
} }
void MagicEffects::remove(const EffectKey &key)
{
mCollection.erase(key);
}
void MagicEffects::add (const EffectKey& key, const EffectParam& param) void MagicEffects::add (const EffectKey& key, const EffectParam& param)
{ {
Collection::iterator iter = mCollection.find (key); Collection::iterator iter = mCollection.find (key);
@ -68,6 +106,24 @@ namespace MWMechanics
} }
} }
void MagicEffects::modifyBase(const EffectKey &key, int diff)
{
mCollection[key].modifyBase(diff);
}
void MagicEffects::setModifiers(const MagicEffects &effects)
{
for (Collection::iterator it = mCollection.begin(); it != mCollection.end(); ++it)
{
it->second.setModifier(effects.get(it->first).getModifier());
}
for (Collection::const_iterator it = effects.begin(); it != effects.end(); ++it)
{
mCollection[it->first].setModifier(it->second.getModifier());
}
}
MagicEffects& MagicEffects::operator+= (const MagicEffects& effects) MagicEffects& MagicEffects::operator+= (const MagicEffects& effects)
{ {
if (this==&effects) if (this==&effects)
@ -137,4 +193,25 @@ namespace MWMechanics
return result; return result;
} }
void MagicEffects::writeState(ESM::MagicEffects &state) const
{
// Don't need to save Modifiers, they are recalculated every frame anyway.
for (Collection::const_iterator iter (begin()); iter!=end(); ++iter)
{
if (iter->second.getBase() != 0)
{
// Don't worry about mArg, never used by magic effect script instructions
state.mEffects.insert(std::make_pair(iter->first.mId, iter->second.getBase()));
}
}
}
void MagicEffects::readState(const ESM::MagicEffects &state)
{
for (std::map<int, int>::const_iterator it = state.mEffects.begin(); it != state.mEffects.end(); ++it)
{
mCollection[EffectKey(it->first)].setBase(it->second);
}
}
} }

View file

@ -8,6 +8,8 @@ namespace ESM
{ {
struct ENAMstruct; struct ENAMstruct;
struct EffectList; struct EffectList;
struct MagicEffects;
} }
namespace MWMechanics namespace MWMechanics
@ -28,12 +30,27 @@ namespace MWMechanics
struct EffectParam struct EffectParam
{ {
// Note usually this would be int, but applying partial resistance might introduce decimal point. private:
float mMagnitude; // Note usually this would be int, but applying partial resistance might introduce a decimal point.
float mModifier;
int mBase;
public:
/// Get the total magnitude including base and modifier.
float getMagnitude() const;
void setModifier(float mod);
float getModifier() const;
/// Change mBase by \a diff
void modifyBase(int diff);
void setBase(int base);
int getBase() const;
EffectParam(); EffectParam();
EffectParam(float magnitude) : mMagnitude(magnitude) {} EffectParam(float magnitude) : mModifier(magnitude), mBase(0) {}
EffectParam& operator+= (const EffectParam& param); EffectParam& operator+= (const EffectParam& param);
@ -77,7 +94,16 @@ namespace MWMechanics
Collection::const_iterator end() const { return mCollection.end(); } Collection::const_iterator end() const { return mCollection.end(); }
void readState (const ESM::MagicEffects& state);
void writeState (ESM::MagicEffects& state) const;
void add (const EffectKey& key, const EffectParam& param); void add (const EffectKey& key, const EffectParam& param);
void remove (const EffectKey& key);
void modifyBase (const EffectKey& key, int diff);
/// Copy Modifier values from \a effects, but keep original mBase values.
void setModifiers(const MagicEffects& effects);
MagicEffects& operator+= (const MagicEffects& effects); MagicEffects& operator+= (const MagicEffects& effects);

View file

@ -68,7 +68,7 @@ namespace MWMechanics
// reset // reset
creatureStats.setLevel(player->mNpdt52.mLevel); creatureStats.setLevel(player->mNpdt52.mLevel);
creatureStats.getSpells().clear(); creatureStats.getSpells().clear();
creatureStats.setMagicEffects(MagicEffects()); creatureStats.modifyMagicEffects(MagicEffects());
for (int i=0; i<27; ++i) for (int i=0; i<27; ++i)
npcStats.getSkill (i).setBase (player->mNpdt52.mSkills[i]); npcStats.getSkill (i).setBase (player->mNpdt52.mSkills[i]);
@ -613,7 +613,7 @@ namespace MWMechanics
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon) if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat(); x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat();
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).mMagnitude; x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude();
int effective_disposition = std::max(0,std::min(int(x),100));//, normally clamped to [0..100] when used int effective_disposition = std::max(0,std::min(int(x),100));//, normally clamped to [0..100] when used
return effective_disposition; return effective_disposition;
@ -1144,7 +1144,7 @@ namespace MWMechanics
CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
float invisibility = stats.getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude; float invisibility = stats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude();
if (invisibility > 0) if (invisibility > 0)
return false; return false;
@ -1176,13 +1176,13 @@ namespace MWMechanics
Ogre::Vector3 pos2 (observer.getRefData().getPosition().pos); Ogre::Vector3 pos2 (observer.getRefData().getPosition().pos);
float distTerm = fSneakDistBase + fSneakDistMult * pos1.distance(pos2); float distTerm = fSneakDistBase + fSneakDistMult * pos1.distance(pos2);
float chameleon = stats.getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude; float chameleon = stats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude();
float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon + invisibility; float x = sneakTerm * distTerm * stats.getFatigueTerm() + chameleon + invisibility;
CreatureStats& observerStats = observer.getClass().getCreatureStats(observer); CreatureStats& observerStats = observer.getClass().getCreatureStats(observer);
int obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified(); int obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified();
int obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified(); int obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified();
float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude();
int obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak); int obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak);
float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind; float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind;

View file

@ -76,7 +76,7 @@ namespace MWMechanics
{ {
CreatureStats& stats = actor.getClass().getCreatureStats(actor); CreatureStats& stats = actor.getClass().getCreatureStats(actor);
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).mMagnitude) if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude())
return 0; return 0;
float y = FLT_MAX; float y = FLT_MAX;
@ -114,7 +114,7 @@ namespace MWMechanics
if (spell->mData.mFlags & ESM::Spell::F_Always) if (spell->mData.mFlags & ESM::Spell::F_Always)
return 100; return 100;
int castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).mMagnitude; int castBonus = -stats.getMagicEffects().get(ESM::MagicEffect::Sound).getMagnitude();
int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); int actorWillpower = stats.getAttribute(ESM::Attribute::Willpower).getModified();
int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified(); int actorLuck = stats.getAttribute(ESM::Attribute::Luck).getModified();
@ -158,16 +158,16 @@ namespace MWMechanics
float resistance = 0; float resistance = 0;
if (resistanceEffect != -1) if (resistanceEffect != -1)
resistance += actorEffects->get(resistanceEffect).mMagnitude; resistance += actorEffects->get(resistanceEffect).getMagnitude();
if (weaknessEffect != -1) if (weaknessEffect != -1)
resistance -= actorEffects->get(weaknessEffect).mMagnitude; resistance -= actorEffects->get(weaknessEffect).getMagnitude();
if (effectId == ESM::MagicEffect::FireDamage) if (effectId == ESM::MagicEffect::FireDamage)
resistance += actorEffects->get(ESM::MagicEffect::FireShield).mMagnitude; resistance += actorEffects->get(ESM::MagicEffect::FireShield).getMagnitude();
if (effectId == ESM::MagicEffect::ShockDamage) if (effectId == ESM::MagicEffect::ShockDamage)
resistance += actorEffects->get(ESM::MagicEffect::LightningShield).mMagnitude; resistance += actorEffects->get(ESM::MagicEffect::LightningShield).getMagnitude();
if (effectId == ESM::MagicEffect::FrostDamage) if (effectId == ESM::MagicEffect::FrostDamage)
resistance += actorEffects->get(ESM::MagicEffect::FrostShield).mMagnitude; resistance += actorEffects->get(ESM::MagicEffect::FrostShield).getMagnitude();
return resistance; return resistance;
} }
@ -306,8 +306,8 @@ namespace MWMechanics
if (spell && (spell->mData.mType == ESM::Spell::ST_Disease || spell->mData.mType == ESM::Spell::ST_Blight)) if (spell && (spell->mData.mType == ESM::Spell::ST_Disease || spell->mData.mType == ESM::Spell::ST_Blight))
{ {
float x = (spell->mData.mType == ESM::Spell::ST_Disease) ? float x = (spell->mData.mType == ESM::Spell::ST_Disease) ?
target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).mMagnitude target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistCommonDisease).getMagnitude()
: target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).mMagnitude; : target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::ResistBlightDisease).getMagnitude();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
if (roll <= x) if (roll <= x)
@ -339,7 +339,7 @@ namespace MWMechanics
bool absorbed = false; bool absorbed = false;
if (spell && caster != target && target.getClass().isActor()) if (spell && caster != target && target.getClass().isActor())
{ {
int absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).mMagnitude; int absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).getMagnitude();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
absorbed = (roll < absorb); absorbed = (roll < absorb);
if (absorbed) if (absorbed)
@ -388,7 +388,7 @@ namespace MWMechanics
// Try reflecting // Try reflecting
if (!reflected && magnitudeMult > 0 && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable)) if (!reflected && magnitudeMult > 0 && !caster.isEmpty() && caster != target && !(magicEffect->mData.mFlags & ESM::MagicEffect::Unreflectable))
{ {
int reflect = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::Reflect).mMagnitude; int reflect = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::Reflect).getMagnitude();
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
bool isReflected = (roll < reflect); bool isReflected = (roll < reflect);
if (isReflected) if (isReflected)

View file

@ -300,7 +300,7 @@ void NpcAnimation::updateParts()
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
NpcType curType = Type_Normal; NpcType curType = Type_Normal;
if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).mMagnitude > 0) if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0)
curType = Type_Vampire; curType = Type_Vampire;
if (cls.getNpcStats(mPtr).isWerewolf()) if (cls.getNpcStats(mPtr).isWerewolf())
curType = Type_Werewolf; curType = Type_Werewolf;

View file

@ -339,7 +339,7 @@ void RenderingManager::update (float duration, bool paused)
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude();
MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f))); MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f)));
setAmbientMode(); setAmbientMode();
@ -611,7 +611,7 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
mAmbientColor = colour; mAmbientColor = colour;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
int nightEye = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).mMagnitude; int nightEye = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude();
Ogre::ColourValue final = colour; Ogre::ColourValue final = colour;
final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f)); final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f));

View file

@ -421,5 +421,15 @@ op 0x200025c: ClearForceMoveJump
op 0x200025d: ClearForceMoveJump, explicit reference op 0x200025d: ClearForceMoveJump, explicit reference
op 0x200025e: ForceMoveJump op 0x200025e: ForceMoveJump
op 0x200025f: ForceMoveJump, explicit reference op 0x200025f: ForceMoveJump, explicit reference
op 0x2000260: GetForceJump
op 0x2000261: GetForceJump, explicit reference
op 0x2000262: GetForceMoveJump
op 0x2000263: GetForceMoveJump, explicit reference
op 0x2000264-0x200027b: GetMagicEffect
op 0x200027c-0x2000293: GetMagicEffect, explicit
op 0x2000294-0x20002ab: SetMagicEffect
op 0x20002ac-0x20002c3: SetMagicEffect, explicit
op 0x20002c4-0x20002db: ModMagicEffect
op 0x20002dc-0x20002f3: ModMagicEffect, explicit
opcodes 0x2000260-0x3ffffff unused opcodes 0x20002f4-0x3ffffff unused

View file

@ -356,7 +356,7 @@ namespace MWScript
key = ESM::MagicEffect::effectStringToId(effect); key = ESM::MagicEffect::effectStringToId(effect);
runtime.push(ptr.getClass().getCreatureStats(ptr).getMagicEffects().get( runtime.push(ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(
MWMechanics::EffectKey(key)).mMagnitude > 0); MWMechanics::EffectKey(key)).getMagnitude() > 0);
} }
}; };

View file

@ -1176,6 +1176,91 @@ namespace MWScript
} }
}; };
template <class R>
class OpGetMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpGetMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
float currentValue = stats.getMagicEffects().get(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
currentValue -= stats.getMagicEffects().get(mNegativeEffect).getMagnitude();
int ret = static_cast<int>(currentValue);
runtime.push(ret);
}
};
template <class R>
class OpSetMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpSetMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
float currentValue = stats.getMagicEffects().get(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
currentValue -= stats.getMagicEffects().get(mNegativeEffect).getMagnitude();
currentValue = int(currentValue);
int arg = runtime[0].mInteger;
runtime.pop();
stats.getMagicEffects().modifyBase(mPositiveEffect, (arg - currentValue));
}
};
template <class R>
class OpModMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpModMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
int arg = runtime[0].mInteger;
runtime.pop();
stats.getMagicEffects().modifyBase(mPositiveEffect, arg);
}
};
struct MagicEffect
{
int mPositiveEffect;
int mNegativeEffect;
};
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
{ {
for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i) for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i)
@ -1320,6 +1405,48 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics<ExplicitRef>); interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetStat, new OpGetStat<ImplicitRef>); interpreter.installSegment5 (Compiler::Stats::opcodeGetStat, new OpGetStat<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetStatExplicit, new OpGetStat<ExplicitRef>); interpreter.installSegment5 (Compiler::Stats::opcodeGetStatExplicit, new OpGetStat<ExplicitRef>);
static const MagicEffect sMagicEffects[] = {
{ ESM::MagicEffect::ResistMagicka, ESM::MagicEffect::WeaknessToMagicka },
{ ESM::MagicEffect::ResistFire, ESM::MagicEffect::WeaknessToFire },
{ ESM::MagicEffect::ResistFrost, ESM::MagicEffect::WeaknessToFrost },
{ ESM::MagicEffect::ResistShock, ESM::MagicEffect::WeaknessToShock },
{ ESM::MagicEffect::ResistCommonDisease, ESM::MagicEffect::WeaknessToCommonDisease },
{ ESM::MagicEffect::ResistBlightDisease, ESM::MagicEffect::WeaknessToBlightDisease },
{ ESM::MagicEffect::ResistCorprusDisease, ESM::MagicEffect::WeaknessToCorprusDisease },
{ ESM::MagicEffect::ResistPoison, ESM::MagicEffect::WeaknessToPoison },
{ ESM::MagicEffect::ResistParalysis, -1 },
{ ESM::MagicEffect::ResistNormalWeapons, ESM::MagicEffect::WeaknessToNormalWeapons },
{ ESM::MagicEffect::WaterBreathing, -1 },
{ ESM::MagicEffect::Chameleon, -1 },
{ ESM::MagicEffect::WaterWalking, -1 },
{ ESM::MagicEffect::SwiftSwim, -1 },
{ ESM::MagicEffect::Jump, -1 },
{ ESM::MagicEffect::Levitate, -1 },
{ ESM::MagicEffect::Shield, -1 },
{ ESM::MagicEffect::Sound, -1 },
{ ESM::MagicEffect::Silence, -1 },
{ ESM::MagicEffect::Blind, -1 },
{ ESM::MagicEffect::Paralyze, -1 },
{ ESM::MagicEffect::Invisibility, -1 },
{ ESM::MagicEffect::FortifyAttack, -1 },
{ ESM::MagicEffect::Sanctuary, -1 },
};
for (int i=0; i<24; ++i)
{
int positive = sMagicEffects[i].mPositiveEffect;
int negative = sMagicEffects[i].mNegativeEffect;
interpreter.installSegment5 (Compiler::Stats::opcodeGetMagicEffect+i, new OpGetMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeGetMagicEffectExplicit+i, new OpGetMagicEffect<ExplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeSetMagicEffect+i, new OpSetMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeSetMagicEffectExplicit+i, new OpSetMagicEffect<ExplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeModMagicEffect+i, new OpModMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeModMagicEffectExplicit+i, new OpModMagicEffect<ExplicitRef> (positive, negative));
}
} }
} }
} }

View file

@ -640,7 +640,7 @@ void MWWorld::InventoryStore::rechargeItems(float duration)
void MWWorld::InventoryStore::purgeEffect(short effectId) void MWWorld::InventoryStore::purgeEffect(short effectId)
{ {
mMagicEffects.add(MWMechanics::EffectKey(effectId), -mMagicEffects.get(MWMechanics::EffectKey(effectId)).mMagnitude); mMagicEffects.remove(MWMechanics::EffectKey(effectId));
} }
void MWWorld::InventoryStore::clear() void MWWorld::InventoryStore::clear()

View file

@ -816,7 +816,7 @@ namespace MWWorld
const MWMechanics::MagicEffects& effects = iter->first.getClass().getCreatureStats(iter->first).getMagicEffects(); const MWMechanics::MagicEffects& effects = iter->first.getClass().getCreatureStats(iter->first).getMagicEffects();
bool waterCollision = false; bool waterCollision = false;
if (effects.get(ESM::MagicEffect::WaterWalking).mMagnitude if (effects.get(ESM::MagicEffect::WaterWalking).getMagnitude()
&& cell->hasWater() && cell->hasWater()
&& !world->isUnderwater(iter->first.getCell(), && !world->isUnderwater(iter->first.getCell(),
Ogre::Vector3(iter->first.getRefData().getPosition().pos))) Ogre::Vector3(iter->first.getRefData().getPosition().pos)))
@ -832,7 +832,7 @@ namespace MWWorld
0xff, OEngine::Physic::CollisionType_Actor); 0xff, OEngine::Physic::CollisionType_Actor);
// 100 points of slowfall reduce gravity by 90% (this is just a guess) // 100 points of slowfall reduce gravity by 90% (this is just a guess)
float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).mMagnitude / 100.f) * 0.9f), 0.9f); float slowFall = 1-std::min(std::max(0.f, (effects.get(ESM::MagicEffect::SlowFall).getMagnitude() / 100.f) * 0.9f), 0.9f);
Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum, Ogre::Vector3 newpos = MovementSolver::move(iter->first, iter->second, mTimeAccum,
world->isFlying(iter->first), world->isFlying(iter->first),

View file

@ -372,6 +372,14 @@ namespace MWWorld
gmst["sHard"] = ESM::Variant("Hard"); gmst["sHard"] = ESM::Variant("Hard");
gmst["sDeleteNote"] = ESM::Variant("Delete Note"); gmst["sDeleteNote"] = ESM::Variant("Delete Note");
gmst["sEditNote"] = ESM::Variant("Edit Note"); gmst["sEditNote"] = ESM::Variant("Edit Note");
gmst["sAdmireSuccess"] = ESM::Variant("Admire Success");
gmst["sAdmireFail"] = ESM::Variant("Admire Fail");
gmst["sIntimidateSuccess"] = ESM::Variant("Intimidate Success");
gmst["sIntimidateFail"] = ESM::Variant("Intimidate Fail");
gmst["sTauntSuccess"] = ESM::Variant("Taunt Success");
gmst["sTauntFail"] = ESM::Variant("Taunt Fail");
gmst["sBribeSuccess"] = ESM::Variant("Bribe Success");
gmst["sBribeFail"] = ESM::Variant("Bribe Fail");
// Werewolf (BM) // Werewolf (BM)
gmst["fWereWolfRunMult"] = ESM::Variant(1.f); gmst["fWereWolfRunMult"] = ESM::Variant(1.f);
@ -1536,7 +1544,7 @@ namespace MWWorld
{ {
float telekinesisRangeBonus = float telekinesisRangeBonus =
mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects() mPlayer->getPlayer().getClass().getCreatureStats(mPlayer->getPlayer()).getMagicEffects()
.get(ESM::MagicEffect::Telekinesis).mMagnitude; .get(ESM::MagicEffect::Telekinesis).getMagnitude();
telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus); telekinesisRangeBonus = feetToGameUnits(telekinesisRangeBonus);
float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus; float activationDistance = getMaxActivationDistance() + telekinesisRangeBonus;
@ -1803,7 +1811,7 @@ namespace MWWorld
World::isFlying(const MWWorld::Ptr &ptr) const World::isFlying(const MWWorld::Ptr &ptr) const
{ {
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
bool isParalyzed = (stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).mMagnitude > 0); bool isParalyzed = (stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0);
if(!ptr.getClass().isActor()) if(!ptr.getClass().isActor())
return false; return false;
@ -1814,7 +1822,7 @@ namespace MWWorld
if (ptr.getClass().canFly(ptr)) if (ptr.getClass().canFly(ptr))
return !isParalyzed; return !isParalyzed;
if(stats.getMagicEffects().get(ESM::MagicEffect::Levitate).mMagnitude > 0 if(stats.getMagicEffects().get(ESM::MagicEffect::Levitate).getMagnitude() > 0
&& isLevitationEnabled()) && isLevitationEnabled())
return true; return true;
@ -1832,7 +1840,7 @@ namespace MWWorld
return false; return false;
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr); const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
if(stats.getMagicEffects().get(ESM::MagicEffect::SlowFall).mMagnitude > 0) if(stats.getMagicEffects().get(ESM::MagicEffect::SlowFall).getMagnitude() > 0)
return true; return true;
return false; return false;
@ -2653,11 +2661,11 @@ namespace MWWorld
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects(); const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
float dist=0; float dist=0;
if (type == World::Detect_Creature) if (type == World::Detect_Creature)
dist = effects.get(ESM::MagicEffect::DetectAnimal).mMagnitude; dist = effects.get(ESM::MagicEffect::DetectAnimal).getMagnitude();
else if (type == World::Detect_Key) else if (type == World::Detect_Key)
dist = effects.get(ESM::MagicEffect::DetectKey).mMagnitude; dist = effects.get(ESM::MagicEffect::DetectKey).getMagnitude();
else if (type == World::Detect_Enchantment) else if (type == World::Detect_Enchantment)
dist = effects.get(ESM::MagicEffect::DetectEnchantment).mMagnitude; dist = effects.get(ESM::MagicEffect::DetectEnchantment).getMagnitude();
if (!dist) if (!dist)
return; return;

View file

@ -42,7 +42,7 @@ add_component_dir (esm
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate
aisequence aisequence magiceffects
) )
add_component_dir (esmterrain add_component_dir (esmterrain

View file

@ -370,6 +370,16 @@ namespace Compiler
"mercantile", "speechcraft", "handtohand" "mercantile", "speechcraft", "handtohand"
}; };
static const char *magicEffects[numberOfMagicEffects] =
{
"resistmagicka", "resistfire", "resistfrost", "resistshock",
"resistdisease", "resistblight", "resistcorprus", "resistpoison",
"resistparalysis", "resistnormalweapons", "waterbreathing", "chameleon",
"waterwalking", "swimspeed", "superjump", "flying",
"armorbonus", "castpenalty", "silence", "blindness",
"paralysis", "invisible", "attackbonus", "defendbonus"
};
std::string get ("get"); std::string get ("get");
std::string set ("set"); std::string set ("set");
std::string mod ("mod"); std::string mod ("mod");
@ -418,6 +428,18 @@ namespace Compiler
opcodeModSkill+i, opcodeModSkillExplicit+i); opcodeModSkill+i, opcodeModSkillExplicit+i);
} }
for (int i=0; i<numberOfMagicEffects; ++i)
{
extensions.registerFunction (get + magicEffects[i], 'l', "",
opcodeGetMagicEffect+i, opcodeGetMagicEffectExplicit+i);
extensions.registerInstruction (set + magicEffects[i], "l",
opcodeSetMagicEffect+i, opcodeSetMagicEffectExplicit+i);
extensions.registerInstruction(mod + magicEffects[i], "l",
opcodeModMagicEffect+i, opcodeModMagicEffectExplicit+i);
}
extensions.registerFunction ("getpccrimelevel", 'f', "", opcodeGetPCCrimeLevel); extensions.registerFunction ("getpccrimelevel", 'f', "", opcodeGetPCCrimeLevel);
extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel); extensions.registerInstruction ("setpccrimelevel", "f", opcodeSetPCCrimeLevel);
extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel); extensions.registerInstruction ("modpccrimelevel", "f", opcodeModPCCrimeLevel);

View file

@ -322,6 +322,8 @@ namespace Compiler
const int numberOfDynamics = 3; const int numberOfDynamics = 3;
const int numberOfSkills = 27; const int numberOfSkills = 27;
const int numberOfMagicEffects = 24;
const int opcodeGetAttribute = 0x2000027; const int opcodeGetAttribute = 0x2000027;
const int opcodeGetAttributeExplicit = 0x200002f; const int opcodeGetAttributeExplicit = 0x200002f;
const int opcodeSetAttribute = 0x2000037; const int opcodeSetAttribute = 0x2000037;
@ -347,6 +349,13 @@ namespace Compiler
const int opcodeModSkill = 0x20000fa; const int opcodeModSkill = 0x20000fa;
const int opcodeModSkillExplicit = 0x2000115; const int opcodeModSkillExplicit = 0x2000115;
const int opcodeGetMagicEffect = 0x2000264;
const int opcodeGetMagicEffectExplicit = 0x200027c;
const int opcodeSetMagicEffect = 0x2000294;
const int opcodeSetMagicEffectExplicit = 0x20002ac;
const int opcodeModMagicEffect = 0x20002c4;
const int opcodeModMagicEffectExplicit = 0x20002dc;
const int opcodeGetPCCrimeLevel = 0x20001ec; const int opcodeGetPCCrimeLevel = 0x20001ec;
const int opcodeSetPCCrimeLevel = 0x20001ed; const int opcodeSetPCCrimeLevel = 0x20001ed;
const int opcodeModPCCrimeLevel = 0x20001ee; const int opcodeModPCCrimeLevel = 0x20001ee;

View file

@ -86,6 +86,7 @@ void ESM::CreatureStats::load (ESMReader &esm)
mSpells.load(esm); mSpells.load(esm);
mActiveSpells.load(esm); mActiveSpells.load(esm);
mAiSequence.load(esm); mAiSequence.load(esm);
mMagicEffects.load(esm);
while (esm.isNextSub("SUMM")) while (esm.isNextSub("SUMM"))
{ {
@ -196,6 +197,7 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
mSpells.save(esm); mSpells.save(esm);
mActiveSpells.save(esm); mActiveSpells.save(esm);
mAiSequence.save(esm); mAiSequence.save(esm);
mMagicEffects.save(esm);
for (std::map<int, int>::const_iterator it = mSummonedCreatureMap.begin(); it != mSummonedCreatureMap.end(); ++it) for (std::map<int, int>::const_iterator it = mSummonedCreatureMap.begin(); it != mSummonedCreatureMap.end(); ++it)
{ {

View file

@ -11,6 +11,7 @@
#include "spellstate.hpp" #include "spellstate.hpp"
#include "activespells.hpp" #include "activespells.hpp"
#include "magiceffects.hpp"
#include "aisequence.hpp" #include "aisequence.hpp"
namespace ESM namespace ESM
@ -24,6 +25,8 @@ namespace ESM
StatState<int> mAttributes[8]; StatState<int> mAttributes[8];
StatState<float> mDynamic[3]; StatState<float> mDynamic[3];
MagicEffects mMagicEffects;
AiSequence::AiSequence mAiSequence; AiSequence::AiSequence mAiSequence;
bool mHasAiSettings; bool mHasAiSettings;

View file

@ -0,0 +1,29 @@
#include "magiceffects.hpp"
#include "esmwriter.hpp"
#include "esmreader.hpp"
namespace ESM
{
void MagicEffects::save(ESMWriter &esm) const
{
for (std::map<int, int>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{
esm.writeHNT("EFID", it->first);
esm.writeHNT("BASE", it->second);
}
}
void MagicEffects::load(ESMReader &esm)
{
while (esm.isNextSub("EFID"))
{
int id, base;
esm.getHT(id);
esm.getHNT(base, "BASE");
mEffects.insert(std::make_pair(id, base));
}
}
}

View file

@ -0,0 +1,23 @@
#ifndef COMPONENTS_ESM_MAGICEFFECTS_H
#define COMPONENTS_ESM_MAGICEFFECTS_H
#include <map>
namespace ESM
{
class ESMReader;
class ESMWriter;
// format 0, saved games only
struct MagicEffects
{
// <Effect Id, Base value>
std::map<int, int> mEffects;
void load (ESMReader &esm);
void save (ESMWriter &esm) const;
};
}
#endif

View file

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout"> <MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 600 125" name="_Main"> <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 600 128" name="_Main">
<Property key="Visible" value="false"/> <Property key="Visible" value="false"/>
<Widget type="TextBox" skin="SandText" position="4 0 592 24" name="LabelText" align="Left Top HStretch"> <Widget type="TextBox" skin="SandText" position="4 4 592 24" name="LabelText" align="Left Top HStretch">
<Property key="TextAlign" value="Center"/> <Property key="TextAlign" value="Center"/>
</Widget> </Widget>
<Widget type="TextBox" skin="SandText" position="4 30 532 24" name="ItemText" align="Left Top HStretch"> <Widget type="TextBox" skin="SandText" position="4 30 507 24" name="ItemText" align="Left Top HStretch">
<Property key="TextAlign" value="Right"/> <Property key="TextAlign" value="Right"/>
</Widget> </Widget>
<Widget type="EditBox" skin="MW_TextEdit" position="540 30 32 24" name="ItemEdit" align="Right Top"> <Widget type="EditBox" skin="MW_TextEdit" position="520 30 52 24" name="ItemEdit" align="Right Top">
<Property key="TextAlign" value="Center"/> <Property key="TextAlign" value="Center"/>
</Widget> </Widget>
@ -21,7 +21,7 @@
</Widget> </Widget>
<Widget type="HBox" position="0 90 572 24" align="Right Bottom"> <Widget type="HBox" position="0 86 572 24" align="Right Bottom">
<Widget type="Widget"> <Widget type="Widget">
<UserString key="HStretch" value="true"/> <UserString key="HStretch" value="true"/>
</Widget> </Widget>