diff --git a/game/engines/default/engine/ui/Base.lua b/game/engines/default/engine/ui/Base.lua index b8ef5741150b8530cdbe4e15b18cd193db2e656f..14e15f301e3aee44b06b35b65351293b10f5a73b 100644 --- a/game/engines/default/engine/ui/Base.lua +++ b/game/engines/default/engine/ui/Base.lua @@ -160,11 +160,13 @@ function _M:makeFrame(base, w, h) return f end -function _M:drawFrame(f, x, y, r, g, b, a) +function _M:drawFrame(f, x, y, r, g, b, a, w, h) if not f.b7 then return end x = math.floor(x) y = math.floor(y) + f.w = w or f.w + f.h = h or f.h -- Sides f.b8.t:toScreenFull(x + f.b7.w, y, f.w - f.b7.w - f.b9.w + 1, f.b8.h, f.b8.tw, f.b8.th, r, g, b, a) diff --git a/game/modules/tome/data/general/events/weird-pedestals.lua b/game/modules/tome/data/general/events/weird-pedestals.lua index eb35e3d60fe458d6ceafaa94d08a22dbae5e5b53..7f9a8f09ca8bcfef50622f9d7731abef169ff293 100644 --- a/game/modules/tome/data/general/events/weird-pedestals.lua +++ b/game/modules/tome/data/general/events/weird-pedestals.lua @@ -59,7 +59,7 @@ for i = 1, 3 do who:restInit(20, "refitting", "refitted", function(cnt, max) if cnt > max then self.pedestal_activated = true - require("engine.ui.Dialog"):simplePopup("Weird Pedestal", "As you inspect it a shadow materializes near you, and suddently it is no more a shadow!") + require("engine.ui.Dialog"):simplePopup("Weird Pedestal", "As you inspect it a shadow materializes near you, and suddenly it is no more a shadow!") local m = game.zone:makeEntity(game.level, "actor", { base_list=mod.class.NPC:loadList("/data/general/npcs/humanoid_random_boss.lua"), diff --git a/game/modules/tome/data/gfx/stats/con.png b/game/modules/tome/data/gfx/stats/con.png new file mode 100644 index 0000000000000000000000000000000000000000..aa1f3e9724b068078d41146703cb568a1e6d6d7f Binary files /dev/null and b/game/modules/tome/data/gfx/stats/con.png differ diff --git a/game/modules/tome/data/gfx/stats/cun.png b/game/modules/tome/data/gfx/stats/cun.png new file mode 100644 index 0000000000000000000000000000000000000000..c32dc2b4ecf1046675a78ad9505d61c0a28b28cb Binary files /dev/null and b/game/modules/tome/data/gfx/stats/cun.png differ diff --git a/game/modules/tome/data/gfx/stats/dex.png b/game/modules/tome/data/gfx/stats/dex.png new file mode 100644 index 0000000000000000000000000000000000000000..570bc0dc8edc88132a80497ef1d2b235d4525565 Binary files /dev/null and b/game/modules/tome/data/gfx/stats/dex.png differ diff --git a/game/modules/tome/data/gfx/stats/mag.png b/game/modules/tome/data/gfx/stats/mag.png new file mode 100644 index 0000000000000000000000000000000000000000..b651f7090c01f98200ce2ba71b1ffb6038b41be2 Binary files /dev/null and b/game/modules/tome/data/gfx/stats/mag.png differ diff --git a/game/modules/tome/data/gfx/stats/str.png b/game/modules/tome/data/gfx/stats/str.png new file mode 100644 index 0000000000000000000000000000000000000000..75d2dbcb7d53fbecc9f57f6378b9359f25c94d69 Binary files /dev/null and b/game/modules/tome/data/gfx/stats/str.png differ diff --git a/game/modules/tome/data/gfx/stats/wil.png b/game/modules/tome/data/gfx/stats/wil.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5d8103b7a1911d9891f0c4763f1fca3ac4e933 Binary files /dev/null and b/game/modules/tome/data/gfx/stats/wil.png differ diff --git a/game/modules/tome/dialogs/Levelup2Dialog.lua b/game/modules/tome/dialogs/Levelup2Dialog.lua index 9b01f7833a0a42f47fb100fe2dbc5b4673bc4317..8e7dc35061116cecdb0533918f9790a670213e45 100644 --- a/game/modules/tome/dialogs/Levelup2Dialog.lua +++ b/game/modules/tome/dialogs/Levelup2Dialog.lua @@ -21,7 +21,9 @@ require "engine.class" require "mod.class.interface.TooltipsData" local Dialog = require "engine.ui.Dialog" +local Textzone = require "engine.ui.Textzone" local TalentTrees = require "mod.dialogs.elements.TalentTrees" +local Separator = require "engine.ui.Separator" local DamageType = require "engine.DamageType" module(..., package.seeall, class.inherit(Dialog, mod.class.interface.TooltipsData)) @@ -154,71 +156,31 @@ function _M:finish() return true end -function _M:incStat(v) +function _M:incStat(sid, v) if v == 1 then if self.actor.unused_stats <= 0 then self:simplePopup("Not enough stat points", "You have no stat points left!") return end - if self.actor:getStat(self.sel, nil, nil, true) >= self.actor.level * 1.4 + 20 then + if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 then self:simplePopup("Stat is at the maximum for your level", "You cannot increase this stat further until next level!") return end - if self.actor:isStatMax(self.sel) or self.actor:getStat(self.sel, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then + if self.actor:isStatMax(sid) or self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then self:simplePopup("Stat is at the maximum", "You cannot increase this stat further!") return end else - if self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true) then + if self.actor_dup:getStat(sid, nil, nil, true) == self.actor:getStat(sid, nil, nil, true) then self:simplePopup("Impossible", "You cannot take out more points!") return end end - local sel = self.sel - self.actor:incStat(sel, v) + self.actor:incStat(sid, v) self.actor.unused_stats = self.actor.unused_stats - v - self.c_list.list[sel].base = self.actor:getStat(sel, nil, nil, true) - self.c_list.list[sel].val = self.actor:getStat(sel) - self.c_list.list[sel].color = {(self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true)) and {255, 255, 255} or {255, 215, 0}, - (self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true)) and {255, 255, 255} or {255, 215, 0}, - (self.actor:getStat(self.sel, nil, nil, true) - self.actor_dup:getStat(self.sel, nil, nil, true) + self.actor_dup:getStat(self.sel) == self.actor:getStat(self.sel)) and {255, 255, 255} or {255, 215, 0}} - self.c_list.sel = sel - - local stats = { "str", "dex", "mag", "wil", "cun", "con" } - for i = 1,6 do - stat_sel = stats[i] - if self.talent_stats_req[stat_sel] then - to_remove = {} - for j=1,#self.talent_stats_req[stat_sel] do - local t = self.talent_stats_req[stat_sel][j][2] - if type(t.require) == "function" then - stats_req = t.require(self.actor, t).stat - for stat, _ in pairs(stats_req) do - if stat ~= stat_sel then - self.talent_stats_req[stat] = self.talent_stats_req[stat] or {} - self.talent_stats_req[stat][#self.talent_stats_req[stat] + 1] = { self.talent_stats_req[stat_sel][j][1], t } - to_remove[#to_remove+1] = j - end - end - end - end - local off = 0 - for j=1,#to_remove do - table.remove(self.talent_stats_req[stat_sel], to_remove[j] - off) - off = off + 1 - end - end - end - self.stats_increased[sel] = (self.stats_increased[sel] or 0) + v - - self.c_list:onSelect(true) - self.c_list:drawItem(self.c_list.list[self.c_list.sel]) - self.c_points.text = _points_text:format(self.actor.unused_stats) - self.c_points:generate() - self.new_stats_changed = true - self:onSelectStat(self.c_list.list[self.c_list.sel], true) + self.stats_increased[sid] = (self.stats_increased[sid] or 0) + v end function _M:computeDeps(t) @@ -452,7 +414,6 @@ end function _M:generateList() self.actor.__show_special_talents = self.actor.__show_special_talents or {} - self.talent_stats_req = {} -- Makes up the list local tree = {} @@ -515,48 +476,100 @@ function _M:generateList() end end end - - if t.require then - local stats = {} - if type(t.require) == "table" and t.require.stat then - stats = t.require.stat - elseif type(t.require) == "function" and t.require(self.actor,t).stat then - stats = t.require(self.actor,t).stat - end - for stat, _ in pairs(stats) do - self.talent_stats_req[stat] = self.talent_stats_req[stat] or {} - self.talent_stats_req[stat][#self.talent_stats_req[stat] + 1] = { list[#list], t } - end - end end end end end - table.sort(tree, function(a, b) + table.sort(tree, function(a, b) if a.isgeneric == b.isgeneric then return a.order_id < b.order_id else - return a.isgeneric < b.isgeneric + return a.isgeneric < b.isgeneric end end) self.tree = tree + + -- Makes up the stats list + local phys, mind = {}, {} + self.tree_stats = {{shown=true, nodes=phys, name="Physical Stats", type_stat=true}, {shown=true, nodes=mind, name="Mental Stats", type_stat=true}} + + for i, sid in ipairs{self.actor.STAT_STR, self.actor.STAT_DEX, self.actor.STAT_CON, self.actor.STAT_MAG, self.actor.STAT_WIL, self.actor.STAT_CUN } do + local s = self.actor.stats_def[sid] + local e = engine.Entity.new{image="stats/"..s.short_name:lower()..".png", is_stat=true} + e:getMapObjects(game.uiset.hotkeys_display_icons.tiles, {}, 1) + + local stats = (i <= 3) and phys or mind + stats[#stats+1] = { + name=s.name, + rawname=s.name, + entity=e, + stat=sid, + desc=s.description, + color=function(item) + if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 or + self.actor:isStatMax(sid) or + self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then + return {255, 0, 0} + else + return {175,175,175} + end + end, + status = function(item) + if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 or + self.actor:isStatMax(sid) or + self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then + return tstring{{"color", 0xFF, 0x00, 0x00}, tostring(self.actor:getStat(sid))} + else + return tstring{{"color", 0x00, 0xFF, 0x00}, tostring(self.actor:getStat(sid))} + end + end, + } + end end ----------------------------------------------------------------- -- UI Stuff ----------------------------------------------------------------- +local _points_left = [[ +Stats points left: #00FF00#%d#LAST# +Category points left: #00FF00#%d#LAST# +Class talent points left: #00FF00#%d#LAST# +Generic talent points left: #00FF00#%d#LAST#]] + function _M:createDisplay() self.c_tree = TalentTrees.new{ - tiles=game.uiset.hotkeys_display_icons, - tree=self.tree, - width=self.iw-10, height=self.ih-10, - tooltip=function(item) return self:getTalentDesc(item) end, + tiles=game.uiset.hotkeys_display_icons, + tree=self.tree, + width=self.iw-200-10, height=self.ih-10, + tooltip=function(item) return self:getTalentDesc(item), self.uis[3].x - game.tooltip.max, nil end, + on_use = function(item, inc) self:onUseTalent(item, inc) end, + } + + self.c_stat = TalentTrees.new{ + tiles=game.uiset.hotkeys_display_icons, + tree=self.tree_stats, no_cross = true, + width=200, height=210, + tooltip=function(item) return item.desc end, on_use = function(item, inc) self:onUseTalent(item, inc) end, + on_expand = function(item) self.actor.__hidden_talent_types[item.type] = not item.shown end, + } + + self.c_points = Textzone.new{ + width=200, height=1, auto_height=true, + text=_points_left:format(self.actor.unused_stats, self.actor.unused_talents_types, self.actor.unused_talents, self.actor.unused_generics) } + local vsep = Separator.new{dir="horizontal", size=self.ih - 20} + local hsep = Separator.new{dir="vertical", size=180} + return { - {left=0, top=0, ui=self.c_tree}, + {left=0, top=0, ui=self.c_stat}, + {left=self.c_stat, top=10, ui=vsep}, + {left=vsep, top=0, ui=self.c_tree}, + + {left=10, top=210, ui=hsep}, + {left=0, top=hsep, ui=self.c_points}, } end @@ -625,10 +638,19 @@ end function _M:onUseTalent(item, inc) if item.type then self:learnType(item.type, inc) + item.shown = (self.actor.__hidden_talent_types[item.type] == nil and self.actor:knowTalentType(item.type)) or (self.actor.__hidden_talent_types[item.type] ~= nil and not self.actor.__hidden_talent_types[item.type]) + self.c_tree:redrawAllItems() elseif item.talent then self:learnTalent(item.talent, inc) + self.c_tree:redrawAllItems() + elseif item.stat then + self:incStat(item.stat, inc and 1 or -1) + self.c_stat:redrawAllItems() + self.c_tree:redrawAllItems() end - self.c_tree:drawItem(item) + + self.c_points.text = _points_left:format(self.actor.unused_stats, self.actor.unused_talents_types, self.actor.unused_talents, self.actor.unused_generics) + self.c_points:generate() end function _M:updateTooltip() diff --git a/game/modules/tome/dialogs/elements/TalentTrees.lua b/game/modules/tome/dialogs/elements/TalentTrees.lua index 7c1df4648b1b46502dcaa0b6a46a804a12a9c18d..d3b10edfc25117b5df02ba0758aa66285535e739 100644 --- a/game/modules/tome/dialogs/elements/TalentTrees.lua +++ b/game/modules/tome/dialogs/elements/TalentTrees.lua @@ -32,6 +32,8 @@ function _M:init(t) self.h = assert(t.height, "no height") self.tooltip = assert(t.tooltip, "no tooltip") self.on_use = assert(t.on_use, "no on_use") + self.on_expand = t.on_expand + self.no_cross = t.no_cross self.icon_size = 48 self.frame_size = 50 @@ -40,6 +42,8 @@ function _M:init(t) self.shadow = 0.7 + self.frame_sel = self:makeFrame("ui/selector-sel", self.frame_size, self.frame_size) + self.frame_usel = self:makeFrame("ui/selector", self.frame_size, self.frame_size) self.talent_frame = self:makeFrame("ui/icon-frame/frame", self.frame_size, self.frame_size) self.plus = _M:getUITexture("ui/plus.png") self.minus = _M:getUITexture("ui/minus.png") @@ -51,14 +55,19 @@ function _M:onUse(item, inc) self.on_use(item, inc) end +function _M:onExpand(item, inc) + item.shown = not item.shown + if self.on_expand then self.on_expand(item) end +end + function _M:updateTooltip() if not self.last_mz then game.tooltip_x = nil - return + return end local mz = self.last_mz local str = self.tooltip(mz.item) - game:tooltipDisplayAtMap(self.last_display_x + mz.x2, self.last_display_y + mz.y1, str) + game:tooltipDisplayAtMap(mz.tx or (self.last_display_x + mz.x2), mz.ty or (self.last_display_y + mz.y1), str) end function _M:doScroll(v) @@ -78,14 +87,7 @@ function _M:generate() self.mousezones = {} - for i = 1, #self.tree do - local tree = self.tree[i] - self:drawItem(tree) - for j = 1, #tree.nodes do - local tal = tree.nodes[j] - self:drawItem(tal) - end - end + self:redrawAllItems() -- Add UI controls self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event) @@ -98,12 +100,20 @@ function _M:generate() local mz = self.mousezones[i] if x >= mz.x1 and x <= mz.x2 and y >= mz.y1 and y <= mz.y2 then if not self.last_mz or mz.item ~= self.last_mz.item then - local str = self.tooltip(mz.item) - game:tooltipDisplayAtMap(self.last_display_x + mz.x2, self.last_display_y + mz.y1, str) + local str, fx, fy = self.tooltip(mz.item) + mz.tx, mz.ty = fx or (self.last_display_x + mz.x2), fy or (self.last_display_y + mz.y1) + game:tooltipDisplayAtMap(mz.tx, mz.ty, str) + end + + if event == "button" and (button == "left" or button == "right") then + if mz.item.type then + if x - mz.x1 >= self.plus.w then self:onUse(mz.item, button == "left") + else self:onExpand(mz.item, button == "left") end + else + self:onUse(mz.item, button == "left") + end end - if event == "button" and (button == "left" or button == "right") then self:onUse(mz.item, button == "left") end - self.last_mz = mz done = true break @@ -133,17 +143,41 @@ function _M:generate() end function _M:drawItem(item) - if item.talent then + if item.stat then + local str = item:status():toString() + local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1] + item.text_status = d + elseif item.type_stat then + local str = item.name:toString() + self.font:setStyle("bold") + local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1] + self.font:setStyle("normal") + item.text_status = d + elseif item.talent then local str = item:status():toString() local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1] item.text_status = d elseif item.type then local str = item:rawname():toString() - local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1] + local c = item:color() + self.font:setStyle("bold") + local d = self.font:draw(str, self.font:size(str), c[1], c[2], c[3], true)[1] + self.font:setStyle("normal") item.text_status = d end end +function _M:redrawAllItems() + for i = 1, #self.tree do + local tree = self.tree[i] + self:drawItem(tree) + for j = 1, #tree.nodes do + local tal = tree.nodes[j] + self:drawItem(tal) + end + end +end + function _M:display(x, y, nb_keyframes, screen_x, screen_y) self.last_display_x = screen_x self.last_display_y = screen_y @@ -153,19 +187,32 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y) local dx, dy = 0, 0 + if self.last_mz then + self:drawFrame(self.focused and self.frame_sel or self.frame_usel, x+self.last_mz.x1-2, y+self.last_mz.y1-2, 1, 1, 1, 1, self.last_mz.x2-self.last_mz.x1+4, self.last_mz.y2-self.last_mz.y1+4) + end + self.max_display = 1 for i = self.scroll, #self.tree do local tree = self.tree[i] if tree.text_status then local key = tree.text_status + local cross = not tree.shown and self.plus or self.minus + + mz[#mz+1] = {item=tree, x1=dx, y1=dy, x2=dx+cross.w + 3 + key.w, y2=dy+cross.h} + + if not self.no_cross then + cross.t:toScreenFull(dx+x, dy+y + (-cross.h + key.h) / 2, cross.w, cross.h, cross.tw, cross.th) + dx = dx + cross.w + 3 + end + if self.shadow then key._tex:toScreenFull(dx+x + 2, dy+y + 2, key.w, key.h, key._tex_w, key._tex_h, 0, 0, 0, self.shadow) end key._tex:toScreenFull(dx+x, dy+y, key.w, key.h, key._tex_w, key._tex_h) dy = dy + key.h + 4 end local addh = 0 - for j = 1, #tree.nodes do + if tree.shown then for j = 1, #tree.nodes do local tal = tree.nodes[j] tal.entity:toScreen(self.tiles, dx+x + self.icon_offset, dy+y + self.icon_offset, self.icon_size, self.icon_size) @@ -173,8 +220,6 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y) local rgb = tal:color() self:drawFrame(self.talent_frame, dx+x, dy+y, rgb[1]/255, rgb[2]/255, rgb[3]/255, 1) - mz[#mz+1] = {item=tal, x1=dx, y1=dy, x2=dx+self.frame_size, y2=dy+self.frame_size} - if tal.text_status then local key = tal.text_status if self.shadow then key._tex:toScreenFull(dx+x + (self.frame_size - key.w)/2 + 2, dy+y + self.frame_size + 4, key.w, key.h, key._tex_w, key._tex_h, 0, 0, 0, self.shadow) end @@ -182,11 +227,14 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y) addh = key.h end + mz[#mz+1] = {item=tal, x1=dx, y1=dy, x2=dx+self.frame_size, y2=dy+self.frame_size+addh} + dx = dx + self.frame_size + self.frame_offset - end + addh = addh + self.frame_size + end end self.max_display = i dx = 0 - dy = dy + self.frame_size + addh + 12 + dy = dy + addh + 12 if dy + self.frame_size >= self.h then break end end