From bfffa178c3b257830cd43e24901f35fbcce24a21 Mon Sep 17 00:00:00 2001 From: Hachem_Muche <Hachem_Muche@stanfordalumni.org> Date: Wed, 12 Apr 2017 11:48:06 -0700 Subject: [PATCH] AdvanceActor dialog: Stat values are split into base and bonus values, and base (maximum allowed by level) and bonus stat values (estimated, +40 at level 50) are automatically updated when the character level is updated. Check boxes enable/disable character level and stat values. By default, the actor (player) level is set to 50 and all stats are forced to 60 base, 40 bonus (100 Total), matching standard scaling limits. --- .../tome/dialogs/debug/AdvanceActor.lua | 170 +++++++++++++----- 1 file changed, 121 insertions(+), 49 deletions(-) diff --git a/game/modules/tome/dialogs/debug/AdvanceActor.lua b/game/modules/tome/dialogs/debug/AdvanceActor.lua index e3325807a6..8ef0881356 100644 --- a/game/modules/tome/dialogs/debug/AdvanceActor.lua +++ b/game/modules/tome/dialogs/debug/AdvanceActor.lua @@ -37,16 +37,35 @@ function _M:init(data) Dialog.init(self, ("DEBUG -- Levelup Actor: [%s] %s"):format(self.actor.uid, self.actor.name), 800, 500) - self.inputs = {} + -- set default inputs + self.inputs = {do_level_up=true, levelup=50, set_base_stats=true, set_bonus_stats=true} + self.c_tut = Textzone.new{auto_width=true, auto_height=true, no_color_bleed=true, font=self.font, text=[[Levelup an actor. Optionally set Stat levels, learn all talents possible, and gain points to spend on Levelup. The actor is backed up before changes are made. (Use the "Restore" button to recover.) ]]} local top = self.c_tut.h + 10 - local lev_box = Numberbox.new{title="Advance to level: ", number=self.actor.level or 50, max=1000, min=1, chars=10, fct=function(value) + local do_level_up = Checkbox.new{title="", text="Text", default=self.inputs.do_level_up, check_last=false, + fct=function(checked) + end, + on_change=function(checked) + self.inputs.do_level_up = checked + if not checked then + self.lev_box:setText(tostring(self.actor.level)) + end + end + } + self.do_level_up = do_level_up + + local lev_box = Numberbox.new{title=" Advance to Level: ", number=self.inputs.levelup, max=1000, min=1, chars=6, fct=function(value) self.inputs.levelup = value self:finish() + end, + on_change = function(value) + self.inputs.levelup = value + self.base_stat_box:autovalue(self) + self.bonus_stat_box:autovalue(self) end } self.lev_box = lev_box @@ -63,15 +82,13 @@ The actor is backed up before changes are made. (Use the "Restore" button to re local restore = Button.new{text=rest_text, alpha_unfocus=rest_alpha, fct=function() local last_actor = _M.last_actors[self.actor] - if last_actor and #last_actor > 0 then local uid = self.actor.uid local la = table.remove(last_actor, #last_actor) game.log("#LIGHT_BLUE#Restoring [%s]%s from backup version %d", self.actor.uid, la.name, #last_actor+1) self.actor:replaceWith(la) self.actor.uid = uid - self.lev_box.number = self.actor.level - self.lev_box:updateText(0) + self.lev_box:setText(tostring(self.actor.level)) end self.restore.text, self.restore.alpha_unfocus = restore_text(self) self.restore:generate() -- force redraw @@ -80,7 +97,7 @@ The actor is backed up before changes are made. (Use the "Restore" button to re } self.restore = restore - local get_points = Checkbox.new{title="Set unlimited respec and gain points for stats, talents, and prodigies ", text="Text", default=false, check_last=false, + local get_points = Checkbox.new{title="Gain points for stats, talents, and prodigies (unlimited respec)", text="Text", default=false, check_last=false, fct=function(checked) end, on_change=function(checked) @@ -89,30 +106,56 @@ The actor is backed up before changes are made. (Use the "Restore" button to re } self.get_points = get_points - local set_statlvl = Checkbox.new{title=" Change Stats ", default=false, check_last=true, + local set_base_stats = Checkbox.new{title="", default=self.inputs.set_base_stats, check_last=false, fct=function(checked) - self.inputs.levelup_stats = checked + self.inputs.set_base_stats = checked end, on_change=function(checked) - self.inputs.levelup_stats = checked + self.inputs.set_base_stats = checked end } - self.set_statlvl = set_statlvl - local stat_box = Numberbox.new{title="Force all stats to: ", number="maximum for level", max=1000, min=1, chars=20, fct=function(value) - self.stat_box:updateText(0) - self.inputs.stat_levelup = value - self:finish() + self.set_base_stats = set_base_stats + + local base_stat_box = Numberbox.new{title=" Force all BASE stats to: ", number=self:autoStatLevel(self.inputs.levelup), max=1000, min=1, chars=6, fct=function(value) + self.inputs.base_stat_level = value end, on_change = function(value) - if not self.stat_box.inputted then value = 100 self.stat_box.inputted = true end - if not self.set_statlvl.checked then self.set_statlvl:select() end - self.stat_box.number = value - self.stat_box:updateText(0) - self.inputs.stat_levelup = value + if not self.set_base_stats.checked then self.set_base_stats:select() end + self.inputs.base_stat_level = value end } - self.stat_box = stat_box + base_stat_box.autovalue = function(self, dialog) + if dialog.inputs.set_base_stats then + self:setText(tostring(dialog:autoStatLevel(dialog.inputs.levelup))) + end + end + self.base_stat_box = base_stat_box + local set_bonus_stats = Checkbox.new{title="", default=self.inputs.set_bonus_stats, check_last=false, + fct=function(checked) + self.inputs.set_bonus_stats = checked + end, + on_change=function(checked) + self.inputs.set_bonus_stats = checked + end + } + self.set_bonus_stats = set_bonus_stats + + local bonus_stat_box = Numberbox.new{title=" Force all BONUS stats to: ", number=self:autoStatBonusLevel(self.inputs.levelup), max=1000, min=-50, chars=6, fct=function(value) + self.inputs.bonus_stat_level = value + end, + on_change = function(value) + if not self.set_bonus_stats.checked then self.set_bonus_stats:select() end + self.inputs.bonus_stat_level = value + end, + } + bonus_stat_box.autovalue = function(self, dialog) + if dialog.inputs.set_bonus_stats then + self:setText(tostring(dialog:autoStatBonusLevel(dialog.inputs.levelup))) + end + end + self.bonus_stat_box = bonus_stat_box + local set_tl = Checkbox.new{title="Learn Talents ", text="Text", default=false, check_last=true, fct=function(checked) end, @@ -177,19 +220,22 @@ The actor is backed up before changes are made. (Use the "Restore" button to re local ok = Button.new{text="Accept", fct=function() self:finish() end} local cancel = Button.new{text="Cancel", fct=function() self:cancelclick() end} - local top = lev_box.h + get_points.h + self.c_tut.h + 15 + local top = lev_box.h + self.c_tut.h + 15 self:loadUI{ {left=10, top=0, padding_h=10, ui=self.c_tut}, - {left=10, top=self.c_tut.h+5, padding_h=10, ui=lev_box}, - {left=10, top=self.c_tut.h+lev_box.h+10, padding_h=10, ui=get_points}, + {left=10, top=self.c_tut.h+5, padding_h=10, ui=do_level_up}, + {left=do_level_up.w+10, top=self.c_tut.h+5, padding_h=10, ui=lev_box}, + {left=do_level_up.w+lev_box.w+20, top=self.c_tut.h+5, padding_h=10, ui=get_points}, {right=10, top=0, padding_h=10, ui=restore}, - {left=10, top=top, padding_h=10, ui=set_statlvl}, - {left=set_statlvl.w+20, top=top, padding_h=10, ui=stat_box}, - {left=10, top=top+stat_box.h+5, padding_h=10, ui=set_tl}, - {left=set_tl.w+20, top=top+stat_box.h+5, padding_h=10, ui=tl_box}, - {right=10, top=top+stat_box.h+5, padding_h=10, ui=force_tl}, - {left=10, top=top+stat_box.h+tl_box.h+10, padding_h=10, ui=mastery_box}, - {right=10, top=top+stat_box.h+tl_box.h+10, padding_h=10, ui=learn_all_talents}, + {left=10, top=top, padding_h=10, ui=set_base_stats}, + {left=set_base_stats.w+10, top=top, padding_h=10, ui=base_stat_box}, + {left=10, top=top+set_base_stats.h+5 , padding_h=10, ui=set_bonus_stats}, + {left=set_bonus_stats.w+10, top=top+set_base_stats.h+5, padding_h=10, ui=bonus_stat_box}, + {left=10, top=top+base_stat_box.h+bonus_stat_box.h+10, padding_h=10, ui=set_tl}, + {left=set_tl.w+20, top=top+base_stat_box.h+bonus_stat_box.h+10, padding_h=10, ui=tl_box}, + {right=10, top=top+base_stat_box.h+bonus_stat_box.h+10, padding_h=10, ui=force_tl}, + {left=10, top=top+base_stat_box.h+bonus_stat_box.h+tl_box.h+15, padding_h=10, ui=mastery_box}, + {right=10, top=top+base_stat_box.h+bonus_stat_box.h+tl_box.h+15, padding_h=10, ui=learn_all_talents}, {left=10, bottom=0, ui=ok}, {right=10, bottom=0, ui=cancel}, } @@ -213,13 +259,23 @@ end -- Levelup the actor function _M:finish() - self.inputs.levelup = self.inputs.levelup or tonumber(self.lev_box.number) --- print("[ForceLevelUp] inputs:", self.inputs) table.print(self.inputs, '\t_inputs_') + self.inputs.levelup = self.inputs.do_level_up and (self.inputs.levelup or tonumber(self.lev_box.number)) or self.actor.level + print("[ForceLevelUp] inputs:", self.inputs) table.print(self.inputs, '\t_inputs_') + +-- debugging + local inpts={} + for i, v in pairs(self.inputs) do + inpts[#inpts+1] = ("%s = %s"):format(i, v) + end + game.log("#LIGHT_BLUE#AdvanceActor inputs: %s", table.concatNice(inpts, ", ")) +-- debugging game:unregisterDialog(self) + local data = table.clone(self.inputs) - data.stat_level = self.inputs.levelup_stats and (self.inputs.stat_levelup or self:autoStatLevel(self.inputs.levelup)) + data.base_stat_level = self.inputs.set_base_stats and (self.inputs.base_stat_level or self:autoStatLevel(self.inputs.levelup)) + data.bonus_stat_level = self.inputs.set_bonus_stats and (self.inputs.bonus_stat_level or self:autoStatBonusLevel(self.inputs.levelup)) data.talent_level = self.inputs.levelup_talents and (self.inputs.talent_levelup or self:autoTalentLevel(self.inputs.levelup)) - self:levelupActor(self.actor, self.inputs.levelup, data) + self:levelupActor(self.actor, self.inputs.do_level_up and self.inputs.levelup, data) end function _M:cancelclick() @@ -230,25 +286,32 @@ function _M:autoTalentLevel(charlev) return 5 + math.max(0, math.floor((charlev - 50) / 10)) end +--- returns maximum stat levels vs. character as allowed by dialogs.CharacterSheet.lua function _M:autoStatLevel(charlev) - return math.min(charlev*1.4 + 20, 60 + math.max(0, charlev - 50)) + return math.floor(math.min(charlev*1.4 + 20, 60 + math.max(0, charlev - 50))) +end + +--- returns estimated stat bonuses vs. character level )+40 @ level 50 with diminishing returns) +function _M:autoStatBonusLevel(charlev) + return math.round(math.min(40*((charlev-1)/50)^.5 + 1, charlev*0.8)) end ---- Levelup Actor, possibly increasing stats, and learning talents +--- Levelup Actor, possibly increasing stats and learning talents -- who = actor to level up -- lev = target character level -- data = table of optional levelup parameters: --- stat_level: adjust stat bonuses to force all primary stats to this value +-- base_stat_level: force all primary base stats to this value +-- bonus_stat_level: force all primary stats bonuses to this value -- talent_level: learn all possible talent to this (raw) level -- ignore_talent_limits: ignore restrictions when levelling up talents -- alltalents: unlock all talent types in the game (before learning talents) --- set_mastery: force mastery level for all talent types +-- set_mastery: force mastery level for all known talent types function _M:levelupActor(who, lev, data) who = who or game.player -- backup the character _M.last_actors[who] = _M.last_actors[who] or {} table.insert(_M.last_actors[who], who:cloneFull()) - game.log("#LIGHT_BLUE#Advancing actor %s[%s]", who.name, who.uid) +-- game.log("#LIGHT_BLUE#Advancing actor %s[%s]", who.name, who.uid) local tt_def=who.talents_types_def who.lastLearntTalentsMax = function(what) return 500 end @@ -259,20 +322,20 @@ function _M:levelupActor(who, lev, data) end lev = who.level - game.logPlayer(who, "#LIGHT_BLUE#Level %d: Setting primary stats to %s, maximum talent levels to %s", lev, data.stat_level, data.talent_level) - if data.stat_level then - game.logPlayer(who, "#GOLD#Forcing all Stats to %s", data.stat_level) + if data.base_stat_level then + game.log("%s #GOLD#Forcing all Base Stats to %s", who.name, data.base_stat_level) for stat = 1, 6 do - local inc = data.stat_level - who:getStat(stat) - who:incIncStat(stat, inc) + local inc = data.base_stat_level - who:getStat(stat, nil, nil, true) + who:incStat(stat, inc) end end - if data.set_mastery then game.logPlayer(who, "#GOLD#Resetting all talents_types_mastery to %s", data.set_mastery) end + + if data.set_mastery then game.log("%s #GOLD#Resetting all talents_types_mastery to %s", who.name, data.set_mastery) end if data.alltalents then - game.logPlayer(who, "#GOLD#Unlocking All Talent Types") + game.log("%s #GOLD#Unlocking All Talent Types", who.name) for key, value in ipairs(tt_def) do who:learnTalentType(tt_def[key].type) - game.logPlayer(who, "#LIGHT_BLUE#%s -- %s",key, value.type) + game.log("#LIGHT_BLUE#%s -- %s", key, value.type) end end for tt, _ in pairs(who.talents_types) do @@ -281,7 +344,7 @@ function _M:levelupActor(who, lev, data) who:setTalentTypeMastery(tt, data.set_mastery) end if ttd and data.talent_level then - game.logPlayer(who, "#GOLD#Checking %s Talents (%s)", tt, who:getTalentTypeMastery(tt)) + game.log("#GOLD#Checking %s Talents (%s)", tt, who:getTalentTypeMastery(tt)) who:learnTalentType(tt, true) for i, t in pairs(ttd.talents) do if not (t.is_object_use or t.is_inscription or t.uber) then @@ -294,12 +357,21 @@ function _M:levelupActor(who, lev, data) else break end end - if learned then game.logPlayer(who, "#LIGHT_BLUE#Talent %s learned to level %d", t.id, who:getTalentLevelRaw(t)) end + if learned then game.log("#LIGHT_BLUE#Talent %s learned to level %d", t.id, who:getTalentLevelRaw(t)) end end end end end end + + -- done last to reverse any passive stat bonuses from talents + if data.bonus_stat_level then + game.log("%s #GOLD#Forcing all Bonus Stats to %s", who.name, data.bonus_stat_level) + for stat = 1, 6 do + local inc = data.bonus_stat_level - (who:getStat(stat, nil, nil, false) - who:getStat(stat, nil, nil, true)) + who:incIncStat(stat, inc) + end + end if data.get_points then who:attr("infinite_respec", 1) game.state.birth.ignore_prodigies_special_reqs = true -- GitLab