diff --git a/game/engines/default/engine/Module.lua b/game/engines/default/engine/Module.lua index 5c19bf02e69963e098e01909404f8b31b1cfecbc..00ef183d0897ae5a540a2f0ec69251f4f16aba3f 100644 --- a/game/engines/default/engine/Module.lua +++ b/game/engines/default/engine/Module.lua @@ -289,7 +289,7 @@ end --- List all available addons function _M:listAddons(mod, ignore_compat) local adds = {} - local load = function(dir, teaa) + local load = function(dir, teaa, teaac) local add_def = loadfile(dir.."/init.lua") if add_def then local add = {} @@ -299,6 +299,7 @@ function _M:listAddons(mod, ignore_compat) if (ignore_compat or engine.version_nearly_same(mod.version, add.version)) and add.for_module == mod.short_name then add.dir = dir add.teaa = teaa + add.teaac = teaac add.natural_compatible = engine.version_nearly_same(mod.version, add.version) add.version_txt = ("%d.%d.%d"):format(add.version[1], add.version[2], add.version[3]) if add.dlc and not profile:isDonator(add.dlc) then add.dlc = "no" end @@ -309,7 +310,7 @@ function _M:listAddons(mod, ignore_compat) end local parse = function(basedir) - for i, short_name in ipairs(fs.list(basedir)) do if short_name:find("^"..mod.short_name.."%-") then + for i, short_name in ipairs(fs.list(basedir)) do if short_name:find("^"..mod.short_name.."%-") or short_name:find(".teaac$") then local dir = basedir..short_name print("Checking addon", short_name, ":: (as dir)", fs.exists(dir.."/init.lua"), ":: (as teaa)", short_name:find(".teaa$"), "") if fs.exists(dir.."/init.lua") then @@ -321,6 +322,16 @@ function _M:listAddons(mod, ignore_compat) load("/testload", dir) end fs.umount(fs.getRealPath(dir)) + elseif short_name:find(".teaac$") then + fs.mount(fs.getRealPath(dir), "/testload", false) + for sdir in fs.iterate("/testload", function(p) return p:find("%-") end) do + print(" * Addon collection subaddon", sdir) + local mod + if fs.exists("/testload/"..sdir.."/init.lua") then + load("/testload/"..sdir, dir, sdir) + end + end + fs.umount(fs.getRealPath(dir)) end end end end @@ -454,13 +465,15 @@ You may try to force loading if you are sure the savefile does not use that addo if add.data then print(" * with data") - if add.teaa then fs.mount("subdir:/data/|"..fs.getRealPath(add.teaa), "/data-"..add.short_name, true) + if add.teaac then fs.mount("subdir:/"..add.teaac.."/data/|"..fs.getRealPath(add.teaa), "/data-"..add.short_name, true) + elseif add.teaa then fs.mount("subdir:/data/|"..fs.getRealPath(add.teaa), "/data-"..add.short_name, true) else fs.mount(base.."/data", "/data-"..add.short_name, true) end end if add.superload then print(" * with superload") - if add.teaa then fs.mount("subdir:/superload/|"..fs.getRealPath(add.teaa), "/mod/addons/"..add.short_name.."/superload", true) + if add.teaac then fs.mount("subdir:/"..add.teaac.."/superload/|"..fs.getRealPath(add.teaa), "/mod/addons/"..add.short_name.."/superload", true) + elseif add.teaa then fs.mount("subdir:/superload/|"..fs.getRealPath(add.teaa), "/mod/addons/"..add.short_name.."/superload", true) else fs.mount(base.."/superload", "/mod/addons/"..add.short_name.."/superload", true) end @@ -468,12 +481,14 @@ You may try to force loading if you are sure the savefile does not use that addo end if add.overload then print(" * with overload") - if add.teaa then fs.mount("subdir:/overload/|"..fs.getRealPath(add.teaa), "/", false) + if add.teaac then fs.mount("subdir:/"..add.teaac.."/overload/|"..fs.getRealPath(add.teaa), "/", false) + elseif add.teaa then fs.mount("subdir:/overload/|"..fs.getRealPath(add.teaa), "/", false) else fs.mount(base.."/overload", "/", false) end end if add.hooks then - if add.teaa then fs.mount("subdir:/hooks/|"..fs.getRealPath(add.teaa), "/hooks/"..add.short_name, true) + if add.teaac then fs.mount("subdir:/"..add.teaac.."/hooks/|"..fs.getRealPath(add.teaa), "/hooks/"..add.short_name, true) + elseif add.teaa then fs.mount("subdir:/hooks/|"..fs.getRealPath(add.teaa), "/hooks/"..add.short_name, true) else fs.mount(base.."/hooks", "/hooks/"..add.short_name, true) end diff --git a/game/engines/default/engine/utils.lua b/game/engines/default/engine/utils.lua index eb432ea61fbe95db992faa81f3f5d4fc2444b283..578a387908c001e107fcf57121e962fc9f62ca82 100644 --- a/game/engines/default/engine/utils.lua +++ b/game/engines/default/engine/utils.lua @@ -988,6 +988,20 @@ function core.display.loadImage(path) return oldloadimage(path) end +function fs.iterate(path, filter) + local list = fs.list(path) + if filter then + for i = #list, 1, -1 do if not filter(list[i]) then + table.remove(list, i) + end end + end + local i = 0 + return function() + i = i + 1 + return list[i] + end +end + local oldfsexists = fs.exists function fs.exists(path) if virtualimages[path] then return true end diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua index 6cd0143bde60eb7199818d95fcd16506fbed0a9b..0eb8cf1aabc52d772a00d5e0d6632b3b68095fb8 100644 --- a/game/modules/tome/class/Object.lua +++ b/game/modules/tome/class/Object.lua @@ -548,7 +548,9 @@ function _M:getTextualDesc(compare_with, use_actor) combat = combat[field] or {} compare_with = compare_with or {} local dm = {} - for stat, i in pairs(combat.dammod or {}) do + local dammod = {} + if next(combat.dammod or {}) then dammod = use_actor:getDammod(combat) end + for stat, i in pairs(dammod) do local name = Stats.stats_def[stat].short_name:capitalize() if use_actor:knowTalent(use_actor.T_STRENGTH_OF_PURPOSE) then if name == "Str" then name = "Mag" end diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua index e927d0b9a587229f8c612930b47567926404188d..59a621c71da1ed15f385b3021669c190c5c10aef 100644 --- a/game/modules/tome/class/interface/Combat.lua +++ b/game/modules/tome/class/interface/Combat.lua @@ -1061,6 +1061,10 @@ _M.weapon_talents = { } --- Static! +-- Training Talents can have the following fields: +-- getMasteryPriority(self, t, kind) - Only the talent with the highest is used. Defaults to the talent level. +-- getDamage(self, t, kind) - Extra physical power granted. Defaults to level * 10. +-- getPercentInc(self, t, kind) - Percentage increase to damage overall. Defaults to sqrt(level / 5) / 2. function _M:addCombatTraining(kind, tid) local wt = _M.weapon_talents if not wt[kind] then wt[kind] = tid return end @@ -1079,35 +1083,42 @@ function _M:combatGetTraining(weapon) if not weapon.talented then return nil end if not _M.weapon_talents[weapon.talented] then return nil end if type(_M.weapon_talents[weapon.talented]) == "table" then - local ktid, max = _M.weapon_talents[weapon.talented][1], self:getTalentLevel(_M.weapon_talents[weapon.talented][1]) - for i, tid in ipairs(_M.weapon_talents[weapon.talented]) do + local get_priority = function(tid) + local t = self:getTalentFromId(tid) + if t.getMasteryPriority then return util.getval(t.getMasteryPriority, self, t, weapon.talented) end + return self:getTalentLevel(t) + end + local max_tid -- = _M.weapon_talents[weapon.talented][1] + local max_priority = -math.huge -- get_priority(max_tid) + for _, tid in ipairs(_M.weapon_talents[weapon.talented]) do if self:knowTalent(tid) then - if self:getTalentLevel(tid) > max then - ktid = tid - max = self:getTalentLevel(tid) + local priority = get_priority(tid) + if priority > max_priority then + max_tid = tid + max_priority = priority end end end - return self:getTalentFromId(ktid) + return self:getTalentFromId(max_tid) else return self:getTalentFromId(_M.weapon_talents[weapon.talented]) end end ---- Checks weapon training -function _M:combatCheckTraining(weapon) - if not weapon then return 0 end - if not weapon.talented then return 0 end - if not _M.weapon_talents[weapon.talented] then return 0 end - if type(_M.weapon_talents[weapon.talented]) == "table" then - local max = 0 - for i, tid in ipairs(_M.weapon_talents[weapon.talented]) do - max = math.max(max, self:getTalentLevel(tid)) - end - return max - else - return self:getTalentLevel(_M.weapon_talents[weapon.talented]) - end +-- Gets the added damage for a weapon based on training. +function _M:combatTrainingDamage(weapon) + local t = self:combatGetTraining(weapon) + if not t then return 0 end + if t.getDamage then return util.getval(t.getDamage, self, t, weapon.talented) end + return self:getTalentLevel(t) * 10 +end + +-- Gets the percent increase for a weapon based on training. +function _M:combatTrainingPercentInc(weapon) + local t = self:combatGetTraining(weapon) + if not t then return 0 end + if t.getPercentInc then return util.getval(t.getPercentInc, self, t, weapon.talented) end + return math.sqrt(self:getTalentLevel(t) / 5) / 2 end --- Gets the defense @@ -1481,22 +1492,46 @@ function _M:combatStatLimit(stat, limit, low, high) end end +--- Gets the dammod table for a given weapon. +function _M:getDammod(combat) + combat = combat or self.combat or {} + + local dammod = table.clone(combat.dammod or {str = 0.6}, true) + + local sub = function(from, to) + dammod[to] = (dammod[from] or 0) + (dammod[to] or 0) + dammod[from] = nil + end + + if combat.talented == 'knife' and self:knowTalent('T_LETHALITY') then sub('str', 'cun') end + if combat.talented and self:knowTalent('T_STRENGTH_OF_PURPOSE') then sub('str', 'mag') end + if self:attr 'use_psi_combat' then + sub('str', 'wil') + sub('dex', 'cun') + end + + -- Add stuff like lethality here. + local hd = {"Combat:getDammod:subs", combat=combat, dammod=dammod, sub=sub} + if self:triggerHook(hd) then dammod = hd.dammod end + + local add = function(stat, val) + dammod[stat] = (dammod[stat] or 0) + val + end + + if self:knowTalent(self.T_SUPERPOWER) then add('wil', 0.3) end + if self:knowTalent(self.T_ARCANE_MIGHT) then add('mag', 0.5) end + + return dammod +end + --- Gets the damage function _M:combatDamage(weapon, adddammod) weapon = weapon or self.combat or {} - local sub_cun_to_str = false - if weapon.talented and weapon.talented == "knife" and self:knowTalent(Talents.T_LETHALITY) then sub_cun_to_str = true end - local sub_mag_to_str = false - if weapon.talented and self:knowTalent(Talents.T_STRENGTH_OF_PURPOSE) then sub_mag_to_str = true end + local dammod = self:getDammod(weapon) local totstat = 0 - local dammod = weapon.dammod or {str=0.6} for stat, mod in pairs(dammod) do - if sub_cun_to_str and stat == "str" then stat = "cun" end - if sub_mag_to_str and stat == "str" then stat = "mag" end - if self:attr("use_psi_combat") and stat == "str" then stat = "wil" end - if self:attr("use_psi_combat") and stat == "dex" then stat = "cun" end totstat = totstat + self:getStat(stat) * mod end if adddammod then @@ -1509,15 +1544,7 @@ function _M:combatDamage(weapon, adddammod) totstat = totstat * (0.8 + self:callTalent(self.T_RESONANT_FOCUS, "bonus")/100) end - if self:knowTalent(self.T_SUPERPOWER) then - totstat = totstat + self:getStat("wil") * 0.3 - end - - if self:knowTalent(self.T_ARCANE_MIGHT) then - totstat = totstat + self:getStat("mag") * 0.5 - end - - local talented_mod = math.sqrt(self:combatCheckTraining(weapon) / 5) / 2 + 1 + local talented_mod = 1 + self:combatTrainingPercentInc(weapon) local power = math.max((weapon.dam or 1), 1) power = (math.sqrt(power / 10) - 1) * 0.5 + 1 @@ -1550,7 +1577,7 @@ function _M:combatPhysicalpower(mod, weapon, add) if inven and inven[1] then weapon = self:getObjectCombat(inven[1], "mainhand") else weapon = self.combat end end - add = add + 10 * self:combatCheckTraining(weapon) + add = add + self:combatTrainingDamage(weapon) local str = self:getStr() if self:knowTalent(Talents.T_STRENGTH_OF_PURPOSE) then