mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 12:58:00 +03:00
Merge branch 'lua-jail-skills' into 'master'
Some checks are pending
Build and test / Ubuntu (push) Waiting to run
Build and test / MacOS (push) Waiting to run
Build and test / Read .env file and expose it as output (push) Waiting to run
Build and test / Windows (2019) (push) Blocked by required conditions
Build and test / Windows (2022) (push) Blocked by required conditions
Some checks are pending
Build and test / Ubuntu (push) Waiting to run
Build and test / MacOS (push) Waiting to run
Build and test / Read .env file and expose it as output (push) Waiting to run
Build and test / Windows (2019) (push) Blocked by required conditions
Build and test / Windows (2022) (push) Blocked by required conditions
Bring jail time skill changes over to lua Closes #8399 See merge request OpenMW/openmw!4593
This commit is contained in:
commit
c9b702041d
12 changed files with 120 additions and 67 deletions
|
@ -68,6 +68,7 @@ namespace MWBase
|
|||
const MWRender::AnimPriority& priority, int blendMask, bool autodisable, float speedmult,
|
||||
std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback)
|
||||
= 0;
|
||||
virtual void jailTimeServed(const MWWorld::Ptr& actor, int days) = 0;
|
||||
virtual void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) = 0;
|
||||
virtual void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) = 0;
|
||||
virtual void exteriorCreated(MWWorld::CellStore& cell) = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <components/misc/strings/format.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -87,46 +88,6 @@ namespace MWGui
|
|||
|
||||
// We should not worsen corprus when in prison
|
||||
player.getClass().getCreatureStats(player).getActiveSpells().skipWorsenings(mDays * 24);
|
||||
|
||||
const auto& skillStore = MWBase::Environment::get().getESMStore()->get<ESM::Skill>();
|
||||
std::set<const ESM::Skill*> skills;
|
||||
for (int day = 0; day < mDays; ++day)
|
||||
{
|
||||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||
const ESM::Skill* skill = skillStore.searchRandom({}, prng);
|
||||
skills.insert(skill);
|
||||
|
||||
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill->mId);
|
||||
if (skill->mId == ESM::Skill::Security || skill->mId == ESM::Skill::Sneak)
|
||||
value.setBase(std::min(100.f, value.getBase() + 1));
|
||||
else
|
||||
value.setBase(std::max(0.f, value.getBase() - 1));
|
||||
}
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
||||
|
||||
std::string message;
|
||||
if (mDays == 1)
|
||||
message = gmst.find("sNotifyMessage42")->mValue.getString();
|
||||
else
|
||||
message = gmst.find("sNotifyMessage43")->mValue.getString();
|
||||
|
||||
message = Misc::StringUtils::format(message, mDays);
|
||||
|
||||
for (const ESM::Skill* skill : skills)
|
||||
{
|
||||
int skillValue = player.getClass().getNpcStats(player).getSkill(skill->mId).getBase();
|
||||
std::string skillMsg = gmst.find("sNotifyMessage44")->mValue.getString();
|
||||
if (skill->mId == ESM::Skill::Sneak || skill->mId == ESM::Skill::Security)
|
||||
skillMsg = gmst.find("sNotifyMessage39")->mValue.getString();
|
||||
|
||||
skillMsg = Misc::StringUtils::format(skillMsg, skill->mName, skillValue);
|
||||
message += "\n" + skillMsg;
|
||||
}
|
||||
|
||||
std::vector<std::string> buttons;
|
||||
buttons.emplace_back("#{Interface:OK}");
|
||||
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons);
|
||||
MWBase::Environment::get().getLuaManager()->jailTimeServed(player, mDays);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,15 @@ namespace MWLua
|
|||
scripts->onSkillLevelUp(event.mSkill, event.mSource);
|
||||
}
|
||||
|
||||
void operator()(const OnJailTimeServed& event) const
|
||||
{
|
||||
MWWorld::Ptr actor = getPtr(event.mActor);
|
||||
if (actor.isEmpty())
|
||||
return;
|
||||
if (auto* scripts = getLocalScripts(actor))
|
||||
scripts->onJailTimeServed(event.mDays);
|
||||
}
|
||||
|
||||
private:
|
||||
MWWorld::Ptr getPtr(ESM::RefNum id) const
|
||||
{
|
||||
|
|
|
@ -70,8 +70,13 @@ namespace MWLua
|
|||
std::string mSkill;
|
||||
std::string mSource;
|
||||
};
|
||||
struct OnJailTimeServed
|
||||
{
|
||||
ESM::RefNum mActor;
|
||||
int mDays;
|
||||
};
|
||||
using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnUseItem, OnNewExterior, OnTeleported,
|
||||
OnAnimationTextKey, OnSkillUse, OnSkillLevelUp>;
|
||||
OnAnimationTextKey, OnSkillUse, OnSkillLevelUp, OnJailTimeServed>;
|
||||
|
||||
void clear() { mQueue.clear(); }
|
||||
void addToQueue(Event e) { mQueue.push_back(std::move(e)); }
|
||||
|
|
|
@ -232,7 +232,7 @@ namespace MWLua
|
|||
[&](LuaUtil::LuaView& view) { addPackage("openmw.self", sol::make_object(view.sol(), &mData)); });
|
||||
registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers,
|
||||
&mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse,
|
||||
&mOnSkillLevelUp });
|
||||
&mOnSkillLevelUp, &mOnJailTimeServed });
|
||||
}
|
||||
|
||||
void LocalScripts::setActive(bool active)
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace MWLua
|
|||
{
|
||||
callEngineHandlers(mOnSkillLevelUp, skillId, source);
|
||||
}
|
||||
void onJailTimeServed(int days) { callEngineHandlers(mOnJailTimeServed, days); }
|
||||
|
||||
void applyStatsCache();
|
||||
|
||||
|
@ -104,6 +105,7 @@ namespace MWLua
|
|||
EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" };
|
||||
EngineHandlerList mOnSkillUse{ "_onSkillUse" };
|
||||
EngineHandlerList mOnSkillLevelUp{ "_onSkillLevelUp" };
|
||||
EngineHandlerList mOnJailTimeServed{ "_onJailTimeServed" };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -482,6 +482,11 @@ namespace MWLua
|
|||
EngineEvents::OnSkillLevelUp{ getId(actor), skillId.serializeText(), std::string(source) });
|
||||
}
|
||||
|
||||
void LuaManager::jailTimeServed(const MWWorld::Ptr& actor, int days)
|
||||
{
|
||||
mEngineEvents.addToQueue(EngineEvents::OnJailTimeServed{ getId(actor), days });
|
||||
}
|
||||
|
||||
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mObjectLists.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace MWLua
|
|||
bool loopfallback) override;
|
||||
void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) override;
|
||||
void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) override;
|
||||
void jailTimeServed(const MWWorld::Ptr& actor, int days) override;
|
||||
void exteriorCreated(MWWorld::CellStore& cell) override
|
||||
{
|
||||
mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell });
|
||||
|
|
|
@ -108,6 +108,10 @@ namespace MWLua
|
|||
}
|
||||
luaManager->addUIMessage(message, mode);
|
||||
};
|
||||
|
||||
api["_showInteractiveMessage"] = [windowManager](std::string_view message, sol::optional<sol::table>) {
|
||||
windowManager->interactiveMessageBox(message, { "#{Interface:OK}" });
|
||||
};
|
||||
api["CONSOLE_COLOR"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs<std::string, Misc::Color>(lua,
|
||||
{
|
||||
{ "Default", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Default.substr(1)) },
|
||||
|
|
|
@ -39,7 +39,8 @@ end
|
|||
|
||||
local function skillLevelUpHandler(skillid, source, params)
|
||||
local skillStat = NPC.stats.skills[skillid](self)
|
||||
if skillStat.base >= 100 then
|
||||
if (skillStat.base >= 100 and params.skillIncreaseValue > 0) or
|
||||
(skillStat.base <= 0 and params.skillIncreaseValue < 0) then
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -62,25 +63,67 @@ local function skillLevelUpHandler(skillid, source, params)
|
|||
= levelStat.skillIncreasesForSpecialization[params.levelUpSpecialization] + params.levelUpSpecializationIncreaseValue;
|
||||
end
|
||||
|
||||
local skillRecord = Skill.record(skillid)
|
||||
local npcRecord = NPC.record(self)
|
||||
local class = NPC.classes.record(npcRecord.class)
|
||||
if source ~= 'jail' then
|
||||
local skillRecord = Skill.record(skillid)
|
||||
local npcRecord = NPC.record(self)
|
||||
local class = NPC.classes.record(npcRecord.class)
|
||||
|
||||
ambient.playSound("skillraise")
|
||||
ambient.playSound("skillraise")
|
||||
|
||||
local message = string.format(core.getGMST('sNotifyMessage39'),skillRecord.name,skillStat.base)
|
||||
local message = string.format(core.getGMST('sNotifyMessage39'),skillRecord.name,skillStat.base)
|
||||
|
||||
if source == I.SkillProgression.SKILL_INCREASE_SOURCES.Book then
|
||||
message = '#{sBookSkillMessage}\n'..message
|
||||
if source == I.SkillProgression.SKILL_INCREASE_SOURCES.Book then
|
||||
message = '#{sBookSkillMessage}\n'..message
|
||||
end
|
||||
|
||||
ui.showMessage(message, { showInDialogue = false })
|
||||
|
||||
if levelStat.progress >= core.getGMST('iLevelUpTotal') then
|
||||
ui.showMessage('#{sLevelUpMsg}', { showInDialogue = false })
|
||||
end
|
||||
|
||||
if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end
|
||||
end
|
||||
end
|
||||
|
||||
ui.showMessage(message, { showInDialogue = false })
|
||||
local function jailTimeServed(days)
|
||||
if not days or days <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if levelStat.progress >= core.getGMST('iLevelUpTotal') then
|
||||
ui.showMessage('#{sLevelUpMsg}', { showInDialogue = false })
|
||||
local oldSkillLevels = {}
|
||||
local skillByNumber = {}
|
||||
for skillid, skillStat in pairs(NPC.stats.skills) do
|
||||
oldSkillLevels[skillid] = skillStat(self).base
|
||||
skillByNumber[#skillByNumber+1] = skillid
|
||||
end
|
||||
|
||||
math.randomseed(core.getSimulationTime())
|
||||
for day=1,days do
|
||||
local skillid = skillByNumber[math.random(#skillByNumber)]
|
||||
-- skillLevelUp() handles skill-based increase/decrease
|
||||
I.SkillProgression.skillLevelUp(skillid, I.SkillProgression.SKILL_INCREASE_SOURCES.Jail)
|
||||
end
|
||||
|
||||
if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end
|
||||
local message = ''
|
||||
if days == 1 then
|
||||
message = string.format(core.getGMST('sNotifyMessage42'), days)
|
||||
else
|
||||
message = string.format(core.getGMST('sNotifyMessage43'), days)
|
||||
end
|
||||
for skillid, skillStat in pairs(NPC.stats.skills) do
|
||||
local diff = skillStat(self).base - oldSkillLevels[skillid]
|
||||
if diff ~= 0 then
|
||||
local skillMsg = core.getGMST('sNotifyMessage39')
|
||||
if diff < 0 then
|
||||
skillMsg = core.getGMST('sNotifyMessage44')
|
||||
end
|
||||
local skillRecord = Skill.record(skillid)
|
||||
message = message..'\n'..string.format(skillMsg, skillRecord.name, skillStat(self).base)
|
||||
end
|
||||
end
|
||||
|
||||
I.UI.showInteractiveMessage(message)
|
||||
end
|
||||
|
||||
local function skillUsedHandler(skillid, params)
|
||||
|
@ -102,6 +145,9 @@ local function onUpdate()
|
|||
onCellChange()
|
||||
end
|
||||
processAutomaticDoors()
|
||||
if jailReport then
|
||||
doJailReport()
|
||||
end
|
||||
end
|
||||
|
||||
I.SkillProgression.addSkillUsedHandler(skillUsedHandler)
|
||||
|
@ -110,5 +156,6 @@ I.SkillProgression.addSkillLevelUpHandler(skillLevelUpHandler)
|
|||
return {
|
||||
engineHandlers = {
|
||||
onUpdate = onUpdate,
|
||||
_onJailTimeServed = jailTimeServed,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ local Skill = core.stats.Skill
|
|||
-- Table of all existing sources for skill increases. Any sources not listed below will be treated as equal to Trainer.
|
||||
-- @type SkillLevelUpSource
|
||||
-- @field #string Book book
|
||||
-- @field #string Jail jail
|
||||
-- @field #string Trainer trainer
|
||||
-- @field #string Usage usage
|
||||
|
||||
|
@ -131,15 +132,17 @@ local function skillLevelUp(skillid, source)
|
|||
levelUpAttributeIncreaseValue = core.getGMST('iLevelUpMajorMultAttribute')
|
||||
end
|
||||
|
||||
local options =
|
||||
{
|
||||
skillIncreaseValue = 1,
|
||||
levelUpProgress = levelUpProgress,
|
||||
levelUpAttribute = skillRecord.attribute,
|
||||
levelUpAttributeIncreaseValue = levelUpAttributeIncreaseValue,
|
||||
levelUpSpecialization = skillRecord.specialization,
|
||||
levelUpSpecializationIncreaseValue = core.getGMST('iLevelupSpecialization'),
|
||||
}
|
||||
local options = {}
|
||||
if source == 'jail' and not (skillid == 'security' or skillid == 'sneak') then
|
||||
options.skillIncreaseValue = -1
|
||||
else
|
||||
options.skillIncreaseValue = 1
|
||||
options.levelUpProgress = levelUpProgress
|
||||
options.levelUpAttribute = skillRecord.attribute
|
||||
options.levelUpAttributeIncreaseValue = levelUpAttributeIncreaseValue
|
||||
options.levelUpSpecialization = skillRecord.specialization
|
||||
options.levelUpSpecializationIncreaseValue = core.getGMST('iLevelupSpecialization')
|
||||
end
|
||||
|
||||
for i = #skillLevelUpHandlers, 1, -1 do
|
||||
if skillLevelUpHandlers[i](skillid, source, options) == false then
|
||||
|
@ -155,8 +158,15 @@ return {
|
|||
-- @module SkillProgression
|
||||
-- @usage local I = require('openmw.interfaces')
|
||||
--
|
||||
-- -- Make jail time hurt sneak skill instead of benefitting it
|
||||
-- I.SkillProgression.addSkillLevelUpHandler(function(skillid, source, options)
|
||||
-- if skillid == 'sneak' and source == 'jail' and options.skillIncreaseValue > 0 then
|
||||
-- options.skillIncreaseValue = -options.skillIncreaseValue
|
||||
-- end
|
||||
-- end)
|
||||
--
|
||||
-- -- Forbid increasing destruction skill past 50
|
||||
-- I.SkillProgression.addSkillLevelUpHandler(function(skillid, options)
|
||||
-- I.SkillProgression.addSkillLevelUpHandler(function(skillid, source, options)
|
||||
-- if skillid == 'destruction' and types.NPC.stats.skills.destruction(self).base >= 50 then
|
||||
-- return false
|
||||
-- end
|
||||
|
@ -186,7 +196,7 @@ return {
|
|||
-- a modifiable table of skill level up values, and can be modified to change the behavior of later handlers.
|
||||
-- These values are calculated based on vanilla mechanics. Setting any value to nil will cause that mechanic to be skipped. By default contains these values:
|
||||
--
|
||||
-- * `skillIncreaseValue` - The numeric amount of skill levels gained.
|
||||
-- * `skillIncreaseValue` - The numeric amount of skill levels gained. By default this is 1, except when the source is jail in which case it will instead be -1 for all skills except sneak and security.
|
||||
-- * `levelUpProgress` - The numeric amount of level up progress gained.
|
||||
-- * `levelUpAttribute` - The string identifying the attribute that should receive points from this skill level up.
|
||||
-- * `levelUpAttributeIncreaseValue` - The numeric amount of attribute increase points received. This contributes to the amount of each attribute the character receives during a vanilla level up.
|
||||
|
@ -262,7 +272,7 @@ return {
|
|||
--- Trigger a skill level up, activating relevant handlers
|
||||
-- @function [parent=#SkillProgression] skillLevelUp
|
||||
-- @param #string skillid The id of the skill to level up.
|
||||
-- @param #SkillLevelUpSource source The source of the skill increase.
|
||||
-- @param #SkillLevelUpSource source The source of the skill increase. Note that passing a value of @{#SkillLevelUpSource.Jail} will cause a skill decrease for all skills except sneak and security.
|
||||
skillLevelUp = skillLevelUp,
|
||||
|
||||
--- @{#SkillLevelUpSource}
|
||||
|
@ -271,6 +281,7 @@ return {
|
|||
Book = 'book',
|
||||
Usage = 'usage',
|
||||
Trainer = 'trainer',
|
||||
Jail = 'jail',
|
||||
},
|
||||
|
||||
--- Compute the total skill gain required to level up a skill based on its current level, and other modifying factors such as major skills and specialization.
|
||||
|
|
|
@ -239,6 +239,13 @@ return {
|
|||
-- @return #boolean
|
||||
isHudVisible = function() return ui._isHudVisible() end,
|
||||
|
||||
---
|
||||
-- Shows a message as an interactive message box pausing the game, with a single button with the localized text OK.
|
||||
-- @function [parent=#UI] showInteractiveMessage
|
||||
-- @param #string message Message to display
|
||||
-- @param #table options Options (none yet)
|
||||
showInteractiveMessage = ui._showInteractiveMessage
|
||||
|
||||
-- TODO
|
||||
-- registerHudElement = function(name, showFn, hideFn) end,
|
||||
-- showHudElement = function(name, bool) end,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue