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/worldeventhandlers.lua
CREATURE, NPC, PLAYER: scripts/omw/mechanics/animationcontroller.lua
PLAYER: scripts/omw/skillhandlers.lua
PLAYER: scripts/omw/mechanics/playercontroller.lua
MENU: scripts/omw/camera/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/input/actionbindings.lua
PLAYER: scripts/omw/input/smoothmovement.lua
PLAYER: scripts/omw/skillhandlers.lua
NPC,CREATURE: scripts/omw/ai.lua
# User interface

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

@ -7,8 +7,8 @@ local Skill = core.stats.Skill
---
-- Table of skill use types defined by morrowind.
-- Each entry corresponds to an index into the available skill gain values
-- of a @{openmw.types#SkillRecord}
-- Each entry corresponds to an index into the available skill gain values
-- of a @{openmw.core#SkillRecord}
-- @type SkillUseType
-- @field #number Armor_HitByOpponent 0
-- @field #number Block_Success 0
@ -35,7 +35,7 @@ local Skill = core.stats.Skill
-- @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
-- @field #string Book book
-- @field #string Trainer trainer
@ -52,10 +52,16 @@ local function tableHasValue(table, value)
return false
end
local function getSkillProgressRequirementUnorm(npc, skillid)
local npcRecord = NPC.record(npc)
local function shallowCopy(t1)
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 skillStat = NPC.stats.skills[skillid](npc)
local skillStat = NPC.stats.skills[skillid](self)
local skillRecord = Skill.record(skillid)
local factor = core.getGMST('fMiscSkillBonus')
@ -72,32 +78,33 @@ local function getSkillProgressRequirementUnorm(npc, skillid)
return (skillStat.base + 1) * factor
end
local function skillUsed(skillid, useType, scale)
local function skillUsed(skillid, options)
if #skillUsedHandlers == 0 then
-- If there are no handlers, then there won't be any effect, so skip calculations
return
end
-- Make a copy so we don't change the caller's table
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
end
local skillStat = NPC.stats.skills[skillid](self)
local skillRecord = Skill.record(skillid)
options.skillGain = skillRecord.skillGain[options.useType + 1]
if useType > 3 or useType < 0 then
print('Error: Unknown useType: '..tostring(useType))
return
if options.scale then
options.skillGain = options.skillGain * options.scale
end
end
-- Compute skill gain
local skillStat = NPC.stats.skills[skillid](self)
local skillRecord = Skill.record(skillid)
local skillGainUnorm = skillRecord.skillGain[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
local options = {
skillGain = skillGain,
}
for i = #skillUsedHandlers, 1, -1 do
if skillUsedHandlers[i](skillid, useType, options) == false then
if skillUsedHandlers[i](skillid, options) == false then
return
end
end
@ -156,8 +163,8 @@ return {
-- end)
--
-- -- Scale sneak skill progression based on active invisibility effects
-- I.SkillProgression.addSkillUsedHandler(function(skillid, useType, params)
-- if skillid == 'sneak' and useType == I.SkillProgression.SKILL_USE_TYPES.Sneak_AvoidNotice then
-- I.SkillProgression.addSkillUsedHandler(function(skillid, params)
-- if skillid == 'sneak' and params.useType == I.SkillProgression.SKILL_USE_TYPES.Sneak_AvoidNotice then
-- local activeEffects = Actor.activeEffects(self)
-- local visibility = activeEffects:getEffect(core.magic.EFFECT_TYPE.Chameleon).magnitude / 100
-- visibility = visibility + activeEffects:getEffect(core.magic.EFFECT_TYPE.Invisibility).magnitude
@ -170,11 +177,12 @@ return {
interface = {
--- Interface 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)
-- 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.
-- 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
end,
--- Add new skillUsed handler for this actor
-- If `handler(skillid, useType, options)` returns false, other handlers (including the default skill progress handler)
-- will be skipped. Where skillid and useType are the parameters passed to @{SkillProgression#skillUsed},
-- and 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:
--
-- * `skillGain` - The numeric amount of skill progress gained, normalized to the range 0 to 1, where 1 is a full level.
--
--- Add new skillUsed handler for this actor.
-- For load order consistency, handlers should be added in the body of your script.
-- If `handler(skillid, options)` returns false, other handlers (including the default skill progress handler)
-- will be skipped. Where options is a modifiable table of skill progression values, and can be modified to change the behavior of later handlers.
-- Contains a `skillGain` value as well as a shallow copy of the options passed to @{#SkillProgression.skillUsed}.
-- @function [parent=#SkillProgression] addSkillUsedHandler
-- @param #function handler The handler.
addSkillUsedHandler = function(handler)
@ -208,8 +213,19 @@ return {
--- Trigger a skill use, activating relevant handlers
-- @function [parent=#SkillProgression] skillUsed
-- @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 #number scale A number that linearly scales the skill progress received from this use. Defaults to 1.
-- @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
-- 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,
--- @{#SkillUseType}
@ -256,11 +272,16 @@ return {
Usage = 'usage',
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 = {
-- Use the interface in these handlers so any overrides will receive the calls.
_onSkillUse = function (skillid, useType, scale)
I.SkillProgression.skillUsed(skillid, useType, scale)
I.SkillProgression.skillUsed(skillid, {useType = useType, scale = scale})
end,
_onSkillLevelUp = function (skillid, source)
I.SkillProgression.skillLevelUp(skillid, source)

Loading…
Cancel
Save