mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +00:00
Implement difficulty scaling (Fixes #1505)
This commit is contained in:
parent
5bbf07976f
commit
28a0899d2b
10 changed files with 159 additions and 63 deletions
|
@ -69,7 +69,7 @@ add_openmw_dir (mwmechanics
|
|||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
||||
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
||||
disease pickpocket levelledlist combat steering obstacle autocalcspell
|
||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling
|
||||
)
|
||||
|
||||
add_openmw_dir (mwstate
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "../mwmechanics/movement.hpp"
|
||||
#include "../mwmechanics/disease.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
#include "../mwmechanics/difficultyscaling.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
@ -412,6 +413,9 @@ namespace MWClass
|
|||
|
||||
if(ishealth)
|
||||
{
|
||||
if (!attacker.isEmpty())
|
||||
damage = scaleDamage(damage, attacker, ptr);
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
|
||||
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
|
||||
setActorHealth(ptr, health, attacker);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "../mwmechanics/disease.hpp"
|
||||
#include "../mwmechanics/combat.hpp"
|
||||
#include "../mwmechanics/autocalcspell.hpp"
|
||||
#include "../mwmechanics/difficultyscaling.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
|
@ -788,6 +789,9 @@ namespace MWClass
|
|||
|
||||
if(ishealth)
|
||||
{
|
||||
if (!attacker.isEmpty())
|
||||
damage = scaleDamage(damage, attacker, ptr);
|
||||
|
||||
if(damage > 0.0f)
|
||||
sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f);
|
||||
float health = getCreatureStats(ptr).getHealth().getCurrent() - damage;
|
||||
|
|
|
@ -157,6 +157,8 @@ namespace MWGui
|
|||
{
|
||||
configureWidgets(mMainWidget);
|
||||
|
||||
setTitle("#{sOptions}");
|
||||
|
||||
getWidget(mOkButton, "OkButton");
|
||||
getWidget(mResolutionList, "ResolutionList");
|
||||
getWidget(mFullscreenButton, "FullscreenButton");
|
||||
|
@ -174,6 +176,7 @@ namespace MWGui
|
|||
getWidget(mControlsBox, "ControlsBox");
|
||||
getWidget(mResetControlsButton, "ResetControlsButton");
|
||||
getWidget(mRefractionButton, "RefractionButton");
|
||||
getWidget(mDifficultySlider, "DifficultySlider");
|
||||
|
||||
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
|
||||
mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled);
|
||||
|
@ -227,6 +230,10 @@ namespace MWGui
|
|||
MyGUI::TextBox* fovText;
|
||||
getWidget(fovText, "FovText");
|
||||
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getInt("field of view", "General"))) + ")");
|
||||
|
||||
MyGUI::TextBox* diffText;
|
||||
getWidget(diffText, "DifficultyText");
|
||||
diffText->setCaptionWithReplacing("#{sDifficulty} (" + boost::lexical_cast<std::string>(int(Settings::Manager::getInt("difficulty", "Game"))) + ")");
|
||||
}
|
||||
|
||||
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
|
||||
|
@ -406,6 +413,12 @@ namespace MWGui
|
|||
getWidget(fovText, "FovText");
|
||||
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(value)) + ")");
|
||||
}
|
||||
if (scroller == mDifficultySlider)
|
||||
{
|
||||
MyGUI::TextBox* diffText;
|
||||
getWidget(diffText, "DifficultyText");
|
||||
diffText->setCaptionWithReplacing("#{sDifficulty} (" + boost::lexical_cast<std::string>(int(value)) + ")");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace MWGui
|
|||
MyGUI::Button* mVSyncButton;
|
||||
MyGUI::Button* mFPSButton;
|
||||
MyGUI::ScrollBar* mFOVSlider;
|
||||
MyGUI::ScrollBar* mDifficultySlider;
|
||||
MyGUI::ScrollBar* mAnisotropySlider;
|
||||
MyGUI::ComboBox* mTextureFilteringButton;
|
||||
MyGUI::TextBox* mAnisotropyLabel;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwmechanics/movement.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
#include "../mwmechanics/difficultyscaling.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
@ -292,6 +293,10 @@ namespace MWMechanics
|
|||
|
||||
static const float fElementalShieldMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fElementalShieldMult")->getFloat();
|
||||
x = fElementalShieldMult * magnitude * (1.f - 0.01f * x);
|
||||
|
||||
// Note swapped victim and attacker, since the attacker takes the damage here.
|
||||
x = scaleDamage(x, victim, attacker);
|
||||
|
||||
MWMechanics::DynamicStat<float> health = attackerStats.getHealth();
|
||||
health.setCurrent(health.getCurrent() - x);
|
||||
attackerStats.setHealth(health);
|
||||
|
|
38
apps/openmw/mwmechanics/difficultyscaling.cpp
Normal file
38
apps/openmw/mwmechanics/difficultyscaling.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "difficultyscaling.hpp"
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
float scaleDamage(float damage, const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim)
|
||||
{
|
||||
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
|
||||
// [-100, 100]
|
||||
int difficultySetting = Settings::Manager::getInt("difficulty", "Game");
|
||||
|
||||
static const float fDifficultyMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDifficultyMult")->getFloat();
|
||||
|
||||
float difficultyTerm = 0.01f * difficultySetting;
|
||||
|
||||
float x = 0;
|
||||
if (victim == player)
|
||||
{
|
||||
if (difficultyTerm > 0)
|
||||
x = fDifficultyMult * difficultyTerm;
|
||||
else
|
||||
x = difficultyTerm / fDifficultyMult;
|
||||
}
|
||||
else if (attacker == player)
|
||||
{
|
||||
if (difficultyTerm > 0)
|
||||
x = -difficultyTerm / fDifficultyMult;
|
||||
else
|
||||
x = fDifficultyMult * (-difficultyTerm);
|
||||
}
|
||||
|
||||
damage *= 1 + x;
|
||||
return damage;
|
||||
}
|
12
apps/openmw/mwmechanics/difficultyscaling.hpp
Normal file
12
apps/openmw/mwmechanics/difficultyscaling.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef OPENMW_MWMECHANICS_DIFFICULTYSCALING_H
|
||||
#define OPENMW_MWMECHANICS_DIFFICULTYSCALING_H
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Ptr;
|
||||
}
|
||||
|
||||
/// Scales damage dealt to an actor based on difficulty setting
|
||||
float scaleDamage(float damage, const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim);
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<MyGUI type="Layout">
|
||||
<Widget type="Window" skin="MW_Window_NoCaption" layer="Windows" position="0 0 400 426" name="_Main">
|
||||
<Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 400 426" name="_Main">
|
||||
|
||||
<Property key="MinSize" value="400 446"/>
|
||||
<Property key="MaxSize" value="400 446"/>
|
||||
|
@ -12,47 +12,86 @@
|
|||
<Widget type="TabItem" skin="" position="4 28 360 312">
|
||||
<Property key="Caption" value=" #{sPrefs} "/>
|
||||
|
||||
<Widget type="TextBox" skin="NormalText" position="4 4 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sTransparency_Menu}"/>
|
||||
</Widget>
|
||||
<Widget type="MWScrollBar" skin="MW_HScroll" position="4 28 352 18" align="Left Top" name="MenuTransparencySlider">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="GUI"/>
|
||||
<UserString key="SettingName" value="menu transparency"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="4 52 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sFull}"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="4 52 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sNone}"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
<Widget type="Widget" position="4 4 352 54" align="Left Top">
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sTransparency_Menu}"/>
|
||||
</Widget>
|
||||
<Widget type="MWScrollBar" skin="MW_HScroll" position="0 20 352 14" align="Left Top" name="MenuTransparencySlider">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="GUI"/>
|
||||
<UserString key="SettingName" value="menu transparency"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sFull}"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sNone}"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="TextBox" skin="NormalText" position="4 78 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sMenu_Help_Delay}"/>
|
||||
</Widget>
|
||||
<Widget type="MWScrollBar" skin="MW_HScroll" position="4 102 352 18" align="Left Top" name="ToolTipDelaySlider">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="GUI"/>
|
||||
<UserString key="SettingName" value="tooltip delay"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="4 126 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sFast}"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="4 126 352 18" align="Left Top">
|
||||
<Property key="Caption" value="#{sSlow}"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
<Widget type="Widget" position="4 64 352 54" align="Left Top">
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sMenu_Help_Delay}"/>
|
||||
</Widget>
|
||||
<Widget type="MWScrollBar" skin="MW_HScroll" position="0 20 352 14" align="Left Top" name="ToolTipDelaySlider">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="GUI"/>
|
||||
<UserString key="SettingName" value="tooltip delay"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sFast}"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sSlow}"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 170 260 24">
|
||||
<Widget type="Widget" position="4 124 352 54" align="Left Top">
|
||||
<Widget type="TextBox" skin="NormalText" position="0 0 352 16" align="Left Top" name="DifficultyText">
|
||||
<Property key="Caption" value="#{sDifficulty}"/>
|
||||
</Widget>
|
||||
<Widget type="MWScrollBar" skin="MW_HScroll" position="0 20 352 14" align="Left Top" name="DifficultySlider">
|
||||
<Property key="Range" value="10000"/>
|
||||
<Property key="Page" value="300"/>
|
||||
<UserString key="SettingType" value="Slider"/>
|
||||
<UserString key="SettingCategory" value="Game"/>
|
||||
<UserString key="SettingName" value="difficulty"/>
|
||||
<UserString key="SettingValueType" value="Float"/>
|
||||
<UserString key="SettingMin" value="-100"/>
|
||||
<UserString key="SettingMax" value="100"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sEasy}"/>
|
||||
<Property key="TextAlign" value="Left"/>
|
||||
</Widget>
|
||||
<Widget type="TextBox" skin="SandText" position="0 38 352 16" align="Left Top">
|
||||
<Property key="Caption" value="#{sHard}"/>
|
||||
<Property key="TextAlign" value="Right"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 200 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="AutosaveButton">
|
||||
<UserString key="SettingCategory" value="Saves"/>
|
||||
<UserString key="SettingName" value="autosave"/>
|
||||
<UserString key="SettingType" value="CheckButton"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" align="Left Top">
|
||||
<Property key="Caption" value="#{sQuick_Save}"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 230 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="BestAttackButton">
|
||||
<UserString key="SettingCategory" value="Game"/>
|
||||
<UserString key="SettingName" value="best attack"/>
|
||||
|
@ -63,7 +102,7 @@
|
|||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 200 260 24">
|
||||
<Widget type="HBox" skin="" position="4 260 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="SubtitlesButton">
|
||||
<UserString key="SettingCategory" value="GUI"/>
|
||||
<UserString key="SettingName" value="subtitles"/>
|
||||
|
@ -74,7 +113,7 @@
|
|||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 230 260 24">
|
||||
<Widget type="HBox" skin="" position="4 290 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="CrosshairButton">
|
||||
<UserString key="SettingCategory" value="HUD"/>
|
||||
<UserString key="SettingName" value="crosshair"/>
|
||||
|
@ -85,28 +124,6 @@
|
|||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 260 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="GrabCursorButton">
|
||||
<UserString key="SettingCategory" value="Input"/>
|
||||
<UserString key="SettingName" value="grab cursor"/>
|
||||
<UserString key="SettingType" value="CheckButton"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" align="Left Top">
|
||||
<Property key="Caption" value="Grab cursor"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
<Widget type="HBox" skin="" position="4 290 260 24">
|
||||
<Widget type="AutoSizedButton" skin="MW_Button" align="Left Top" name="AutosaveButton">
|
||||
<UserString key="SettingCategory" value="Saves"/>
|
||||
<UserString key="SettingName" value="autosave"/>
|
||||
<UserString key="SettingType" value="CheckButton"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" align="Left Top">
|
||||
<Property key="Caption" value="#{sQuick_Save}"/>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
</Widget>
|
||||
<Widget type="TabItem" skin="" position="4 28 360 312">
|
||||
<Property key="Caption" value=" #{sAudio} "/>
|
||||
|
|
|
@ -170,6 +170,8 @@ always run = false
|
|||
# Always use the most powerful attack when striking with a weapon (chop, slash or thrust)
|
||||
best attack = false
|
||||
|
||||
difficulty = 0
|
||||
|
||||
[Saves]
|
||||
character =
|
||||
# Save when resting
|
||||
|
|
Loading…
Reference in a new issue