Merge branch 'skill-used-rework' into 'master'

Rewrite SkillProgression.skillUsed to allow directly adding xp

See merge request OpenMW/openmw!3927
fix-osga-rotate-wildly
psi29a 10 months ago
commit 0557a649ce

@ -12,6 +12,7 @@ GLOBAL: scripts/omw/cellhandlers.lua
GLOBAL: scripts/omw/usehandlers.lua GLOBAL: scripts/omw/usehandlers.lua
GLOBAL: scripts/omw/worldeventhandlers.lua GLOBAL: scripts/omw/worldeventhandlers.lua
CREATURE, NPC, PLAYER: scripts/omw/mechanics/animationcontroller.lua CREATURE, NPC, PLAYER: scripts/omw/mechanics/animationcontroller.lua
PLAYER: scripts/omw/skillhandlers.lua
PLAYER: scripts/omw/mechanics/playercontroller.lua PLAYER: scripts/omw/mechanics/playercontroller.lua
MENU: scripts/omw/camera/settings.lua MENU: scripts/omw/camera/settings.lua
MENU: scripts/omw/input/settings.lua MENU: scripts/omw/input/settings.lua
@ -19,7 +20,6 @@ PLAYER: scripts/omw/input/playercontrols.lua
PLAYER: scripts/omw/camera/camera.lua PLAYER: scripts/omw/camera/camera.lua
PLAYER: scripts/omw/input/actionbindings.lua PLAYER: scripts/omw/input/actionbindings.lua
PLAYER: scripts/omw/input/smoothmovement.lua PLAYER: scripts/omw/input/smoothmovement.lua
PLAYER: scripts/omw/skillhandlers.lua
NPC,CREATURE: scripts/omw/ai.lua NPC,CREATURE: scripts/omw/ai.lua
# User interface # User interface

@ -83,19 +83,17 @@ local function skillLevelUpHandler(skillid, source, params)
if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end if not source or source == I.SkillProgression.SKILL_INCREASE_SOURCES.Usage then skillStat.progress = 0 end
end end
local function skillUsedHandler(skillid, useType, params) local function skillUsedHandler(skillid, params)
if NPC.isWerewolf(self) then if NPC.isWerewolf(self) then
return false return false
end end
if params.skillGain then
local skillStat = NPC.stats.skills[skillid](self) local skillStat = NPC.stats.skills[skillid](self)
skillStat.progress = skillStat.progress + params.skillGain skillStat.progress = skillStat.progress + params.skillGain / I.SkillProgression.getSkillProgressRequirement(skillid)
if skillStat.progress >= 1 then if skillStat.progress >= 1 then
I.SkillProgression.skillLevelUp(skillid, I.SkillProgression.SKILL_INCREASE_SOURCES.Usage) I.SkillProgression.skillLevelUp(skillid, I.SkillProgression.SKILL_INCREASE_SOURCES.Usage)
end end
end
end end
local function onUpdate() local function onUpdate()
@ -106,14 +104,11 @@ local function onUpdate()
processAutomaticDoors() processAutomaticDoors()
end end
local function onActive() I.SkillProgression.addSkillUsedHandler(skillUsedHandler)
I.SkillProgression.addSkillUsedHandler(skillUsedHandler) I.SkillProgression.addSkillLevelUpHandler(skillLevelUpHandler)
I.SkillProgression.addSkillLevelUpHandler(skillLevelUpHandler)
end
return { return {
engineHandlers = { engineHandlers = {
onUpdate = onUpdate, onUpdate = onUpdate,
onActive = onActive,
}, },
} }

@ -8,7 +8,7 @@ local Skill = core.stats.Skill
--- ---
-- Table of skill use types defined by morrowind. -- Table of skill use types defined by morrowind.
-- Each entry corresponds to an index into the available skill gain values -- Each entry corresponds to an index into the available skill gain values
-- of a @{openmw.types#SkillRecord} -- of a @{openmw.core#SkillRecord}
-- @type SkillUseType -- @type SkillUseType
-- @field #number Armor_HitByOpponent 0 -- @field #number Armor_HitByOpponent 0
-- @field #number Block_Success 0 -- @field #number Block_Success 0
@ -35,7 +35,7 @@ local Skill = core.stats.Skill
-- @field #number Athletics_SwimOneSecond 1 -- @field #number Athletics_SwimOneSecond 1
--- ---
-- Table of valid sources for skill increases -- Table of all existing sources for skill increases. Any sources not listed below will be treated as equal to Trainer.
-- @type SkillLevelUpSource -- @type SkillLevelUpSource
-- @field #string Book book -- @field #string Book book
-- @field #string Trainer trainer -- @field #string Trainer trainer
@ -52,10 +52,16 @@ local function tableHasValue(table, value)
return false return false
end end
local function getSkillProgressRequirementUnorm(npc, skillid) local function shallowCopy(t1)
local npcRecord = NPC.record(npc) local t2 = {}
for key, value in pairs(t1) do t2[key] = value end
return t2
end
local function getSkillProgressRequirement(skillid)
local npcRecord = NPC.record(self)
local class = NPC.classes.record(npcRecord.class) local class = NPC.classes.record(npcRecord.class)
local skillStat = NPC.stats.skills[skillid](npc) local skillStat = NPC.stats.skills[skillid](self)
local skillRecord = Skill.record(skillid) local skillRecord = Skill.record(skillid)
local factor = core.getGMST('fMiscSkillBonus') local factor = core.getGMST('fMiscSkillBonus')
@ -72,32 +78,33 @@ local function getSkillProgressRequirementUnorm(npc, skillid)
return (skillStat.base + 1) * factor return (skillStat.base + 1) * factor
end end
local function skillUsed(skillid, useType, scale)
local function skillUsed(skillid, options)
if #skillUsedHandlers == 0 then if #skillUsedHandlers == 0 then
-- If there are no handlers, then there won't be any effect, so skip calculations -- If there are no handlers, then there won't be any effect, so skip calculations
return return
end end
if useType > 3 or useType < 0 then -- Make a copy so we don't change the caller's table
print('Error: Unknown useType: '..tostring(useType)) options = shallowCopy(options)
-- Compute use value if it was not supplied directly
if not options.skillGain then
if not options.useType or options.useType > 3 or options.useType < 0 then
print('Error: Unknown useType: '..tostring(options.useType))
return return
end end
-- Compute skill gain
local skillStat = NPC.stats.skills[skillid](self) local skillStat = NPC.stats.skills[skillid](self)
local skillRecord = Skill.record(skillid) local skillRecord = Skill.record(skillid)
local skillGainUnorm = skillRecord.skillGain[useType + 1] options.skillGain = skillRecord.skillGain[options.useType + 1]
if scale then skillGainUnorm = skillGainUnorm * scale end
local skillProgressRequirementUnorm = getSkillProgressRequirementUnorm(self, skillid)
local skillGain = skillGainUnorm / skillProgressRequirementUnorm
-- Put skill gain in a table so that handlers can modify it if options.scale then
local options = { options.skillGain = options.skillGain * options.scale
skillGain = skillGain, end
} end
for i = #skillUsedHandlers, 1, -1 do for i = #skillUsedHandlers, 1, -1 do
if skillUsedHandlers[i](skillid, useType, options) == false then if skillUsedHandlers[i](skillid, options) == false then
return return
end end
end end
@ -156,8 +163,8 @@ return {
-- end) -- end)
-- --
-- -- Scale sneak skill progression based on active invisibility effects -- -- Scale sneak skill progression based on active invisibility effects
-- I.SkillProgression.addSkillUsedHandler(function(skillid, useType, params) -- I.SkillProgression.addSkillUsedHandler(function(skillid, params)
-- if skillid == 'sneak' and useType == I.SkillProgression.SKILL_USE_TYPES.Sneak_AvoidNotice then -- if skillid == 'sneak' and params.useType == I.SkillProgression.SKILL_USE_TYPES.Sneak_AvoidNotice then
-- local activeEffects = Actor.activeEffects(self) -- local activeEffects = Actor.activeEffects(self)
-- local visibility = activeEffects:getEffect(core.magic.EFFECT_TYPE.Chameleon).magnitude / 100 -- local visibility = activeEffects:getEffect(core.magic.EFFECT_TYPE.Chameleon).magnitude / 100
-- visibility = visibility + activeEffects:getEffect(core.magic.EFFECT_TYPE.Invisibility).magnitude -- visibility = visibility + activeEffects:getEffect(core.magic.EFFECT_TYPE.Invisibility).magnitude
@ -170,11 +177,12 @@ return {
interface = { interface = {
--- Interface version --- Interface version
-- @field [parent=#SkillProgression] #number version -- @field [parent=#SkillProgression] #number version
version = 0, version = 1,
--- Add new skill level up handler for this actor --- Add new skill level up handler for this actor.
-- For load order consistency, handlers should be added in the body if your script.
-- If `handler(skillid, source, options)` returns false, other handlers (including the default skill level up handler) -- If `handler(skillid, source, options)` returns false, other handlers (including the default skill level up handler)
-- will be skipped. Where skillid and source are the parameters passed to @{SkillProgression#skillLevelUp}, and options is -- will be skipped. Where skillid and source are the parameters passed to @{#SkillProgression.skillLevelUp}, and options is
-- a modifiable table of skill level up values, and can be modified to change the behavior of later handlers. -- 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: -- 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:
-- --
@ -191,14 +199,11 @@ return {
skillLevelUpHandlers[#skillLevelUpHandlers + 1] = handler skillLevelUpHandlers[#skillLevelUpHandlers + 1] = handler
end, end,
--- Add new skillUsed handler for this actor --- Add new skillUsed handler for this actor.
-- If `handler(skillid, useType, options)` returns false, other handlers (including the default skill progress handler) -- For load order consistency, handlers should be added in the body of your script.
-- will be skipped. Where skillid and useType are the parameters passed to @{SkillProgression#skillUsed}, -- If `handler(skillid, options)` returns false, other handlers (including the default skill progress handler)
-- and options is a modifiable table of skill progression values, and can be modified to change the behavior of later handlers. -- will be skipped. Where options is a modifiable table of skill progression values, and can be modified to change the behavior of later handlers.
-- By default contains the single value: -- Contains a `skillGain` value as well as a shallow copy of the options passed to @{#SkillProgression.skillUsed}.
--
-- * `skillGain` - The numeric amount of skill progress gained, normalized to the range 0 to 1, where 1 is a full level.
--
-- @function [parent=#SkillProgression] addSkillUsedHandler -- @function [parent=#SkillProgression] addSkillUsedHandler
-- @param #function handler The handler. -- @param #function handler The handler.
addSkillUsedHandler = function(handler) addSkillUsedHandler = function(handler)
@ -208,8 +213,19 @@ return {
--- Trigger a skill use, activating relevant handlers --- Trigger a skill use, activating relevant handlers
-- @function [parent=#SkillProgression] skillUsed -- @function [parent=#SkillProgression] skillUsed
-- @param #string skillid The if of the skill that was used -- @param #string skillid The if of the skill that was used
-- @param #SkillUseType useType A number from 0 to 3 (inclusive) representing the way the skill was used, with each use type having a different skill progression rate. Available use types and its effect is skill specific. See @{SkillProgression#skillUseType} -- @param options A table of parameters. Must contain one of `skillGain` or `useType`. It's best to always include `useType` if applicable, even if you set `skillGain`, as it may be used
-- @param #number scale A number that linearly scales the skill progress received from this use. Defaults to 1. -- by handlers to make decisions. See the addSkillUsedHandler example at the top of this page.
--
-- * `skillGain` - The numeric amount of skill to be gained.
-- * `useType` - #SkillUseType, A number from 0 to 3 (inclusive) representing the way the skill was used, with each use type having a different skill progression rate. Available use types and its effect is skill specific. See @{#SkillUseType}
--
-- And may contain the following optional parameter:
--
-- * `scale` - A numeric value used to scale the skill gain. Ignored if the `skillGain` parameter is set.
--
-- Note that a copy of this table is passed to skill used handlers, so any parameters passed to this method will also be passed to the handlers. This can be used to provide additional information to
-- custom handlers when making custom skill progressions.
--
skillUsed = skillUsed, skillUsed = skillUsed,
--- @{#SkillUseType} --- @{#SkillUseType}
@ -256,11 +272,16 @@ return {
Usage = 'usage', Usage = 'usage',
Trainer = 'trainer', Trainer = 'trainer',
}, },
--- 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.
-- @function [parent=#SkillProgression] getSkillProgressRequirement
-- @param #string skillid The id of the skill to compute skill progress requirement for
getSkillProgressRequirement = getSkillProgressRequirement
}, },
engineHandlers = { engineHandlers = {
-- Use the interface in these handlers so any overrides will receive the calls. -- Use the interface in these handlers so any overrides will receive the calls.
_onSkillUse = function (skillid, useType, scale) _onSkillUse = function (skillid, useType, scale)
I.SkillProgression.skillUsed(skillid, useType, scale) I.SkillProgression.skillUsed(skillid, {useType = useType, scale = scale})
end, end,
_onSkillLevelUp = function (skillid, source) _onSkillLevelUp = function (skillid, source)
I.SkillProgression.skillLevelUp(skillid, source) I.SkillProgression.skillLevelUp(skillid, source)

Loading…
Cancel
Save