diff --git a/game/engines/default/data/keybinds/actions.lua b/game/engines/default/data/keybinds/actions.lua index 64eb679ee91a6b32e61cf8a9c284dccda9098773..9eee906db4fad34497a8392b599d365885b0781d 100644 --- a/game/engines/default/data/keybinds/actions.lua +++ b/game/engines/default/data/keybinds/actions.lua @@ -45,7 +45,7 @@ defineAction{ } defineAction{ - default = { "uni:R" }, + default = { "uni:r", "uni:R" }, type = "REST", group = "actions", name = "Rest for a while", diff --git a/game/engines/default/engine/HotkeysDisplay.lua b/game/engines/default/engine/HotkeysDisplay.lua index d5f0c251070ca8c558f5209eb376b6c39eb683d5..93b967469140e198497b3e5301eb0fd2193fb01c 100644 --- a/game/engines/default/engine/HotkeysDisplay.lua +++ b/game/engines/default/engine/HotkeysDisplay.lua @@ -152,7 +152,8 @@ function _M:onMouse(button, mx, my, click, on_over) local text = "" if a.hotkey[i] and a.hotkey[i][1] == "talent" then local t = self.actor:getTalentFromId(a.hotkey[i][2]) - text = "#GOLD#"..t.name.."#LAST#\n"..self.actor:getTalentFullDescription(t) + text = tstring{{"color","GOLD"}, {"font", "bold"}, t.name, {"font", "normal"}, {"color", "LAST"}, true} + text:merge(self.actor:getTalentFullDescription(t)) elseif a.hotkey[i] and a.hotkey[i][1] == "inventory" then local o = a:findInAllInventories(a.hotkey[i][2]) text = o:getDesc() diff --git a/game/engines/default/engine/Object.lua b/game/engines/default/engine/Object.lua index a876b42e8bec9abcbcf1daff7f22ad4218f587c4..858798a2d815ccab751d4ff01228e78a33ac2dbf 100644 --- a/game/engines/default/engine/Object.lua +++ b/game/engines/default/engine/Object.lua @@ -175,22 +175,22 @@ function _M:getRequirementDesc(who) local req = rawget(self, "require") if not req then return nil end - local str = "Requires:\n" + local str = tstring{"Requires:", true} if req.stat then for s, v in pairs(req.stat) do - local c = (who:getStat(s) >= v) and "#00ff00#" or "#ff0000#" - str = str .. ("- %s%s %d\n"):format(c, who.stats_def[s].name, v) + local c = (who:getStat(s) >= v) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", ("%s %d\n"):format(who.stats_def[s].name, v), true) end end if req.level then - local c = (who.level >= req.level) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sLevel %d\n"):format(c, req.level) + local c = (who.level >= req.level) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", ("Level %d\n"):format(req.level), true) end if req.talent then for _, tid in ipairs(req.talent) do - local c = who:knowTalent(tid) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sTalent %s\n"):format(c, who:getTalentFromId(tid).name) + local c = who:knowTalent(tid) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", ("Talent %s\n"):format(who:getTalentFromId(tid).name), true) end end return str diff --git a/game/engines/default/engine/dialogs/ShowEquipInven.lua b/game/engines/default/engine/dialogs/ShowEquipInven.lua index 64f8374b6cede48e22ac4e69f920f4ba398b3dc9..feb0451dd1f6fd38f25deda53e5e695e63f61e91 100644 --- a/game/engines/default/engine/dialogs/ShowEquipInven.lua +++ b/game/engines/default/engine/dialogs/ShowEquipInven.lua @@ -164,7 +164,6 @@ function _M:generateList() if not self.filter or self.filter(o) then local char = self:makeKeyChar(i) list[#list+1] = { id=#list+1, char=char, name=o:getName{do_color=true}, object=o, inven=inven_id, item=item, cat=o.subtype, encumberance=o.encumber, desc=o:getDesc() } - self.max_h = math.max(self.max_h, #o:getDesc():splitLines(self.iw - 10, self.font)) chars[char] = #list i = i + 1 end @@ -183,7 +182,6 @@ function _M:generateList() if not self.filter or self.filter(o) then local char = self:makeKeyChar(i) list[#list+1] = { id=#list+1, char=char, name=o:getName{do_color=true}, object=o, inven=self.actor.INVEN_INVEN, item=item, cat=o.subtype, encumberance=o.encumber, desc=o:getDesc() } - self.max_h = math.max(self.max_h, #o:getDesc():splitLines(self.iw - 10, self.font)) chars[char] = #list i = i + 1 end @@ -204,7 +202,7 @@ function _M:maxH() local i = 1 for item, o in ipairs(self.actor:getInven("INVEN")) do if not self.filter or self.filter(o) then - self.max_h = math.max(self.max_h, #o:getDesc():splitLines(self.iw - 10, self.font)) + self.max_h = math.max(self.max_h, o:getDesc():splitLines(self.iw - 10, self.font):countLines()) end end end diff --git a/game/engines/default/engine/dialogs/ShowStore.lua b/game/engines/default/engine/dialogs/ShowStore.lua index ff6839f628d2b329ca5934b109042d6829da7d60..6e47b98ff118b87f4aa300efd16c8b6af7325834 100644 --- a/game/engines/default/engine/dialogs/ShowStore.lua +++ b/game/engines/default/engine/dialogs/ShowStore.lua @@ -108,12 +108,12 @@ function _M:maxH() self.max_h = 0 for item, o in ipairs(self.store_inven) do if not self.store_filter or self.store_filter(o) then - self.max_h = math.max(self.max_h, #o:getDesc():splitLines(self.iw - 10, self.font)) + self.max_h = math.max(self.max_h, o:getDesc():splitLines(self.iw - 10, self.font):countLines()) end end for item, o in ipairs(self.actor_inven) do if not self.actor_filter or self.actor_filter(o) then - self.max_h = math.max(self.max_h, #o:getDesc():splitLines(self.iw - 10, self.font)) + self.max_h = math.max(self.max_h, o:getDesc():splitLines(self.iw - 10, self.font):countLines()) end end end diff --git a/game/engines/default/engine/interface/ActorTalents.lua b/game/engines/default/engine/interface/ActorTalents.lua index d9e76f965ec10a4676d6a69a31a6341576f74381..fe3fef566555c5e940e9772b1a877f8c7dc2120b 100644 --- a/game/engines/default/engine/interface/ActorTalents.lua +++ b/game/engines/default/engine/interface/ActorTalents.lua @@ -325,44 +325,44 @@ function _M:getTalentReqDesc(t_id, levmod) local tlev = self:getTalentLevelRaw(t_id) + (levmod or 0) - local str = "" + local str = tstring{} if not t.type_no_req then - str = str .. (self:knowTalentType(t.type[1]) and "#00ff00#" or "#ff0000#") .. "- Talent category known\n" + str:add((self:knowTalentType(t.type[1]) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00}), "- Talent category known", true) end if t.type[2] and t.type[2] > 1 then local known = self:numberKnownTalent(t.type[1], t.id) - local c = (known >= t.type[2] - 1) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sTalents of the same category: %d\n"):format(c, t.type[2] - 1) + local c = (known >= t.type[2] - 1) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("Talents of the same category: %d"):format(t.type[2] - 1), true) end -- Obviously this requires the ActorStats interface if req.stat then for s, v in pairs(req.stat) do v = util.getval(v, tlev) - local c = (self:getStat(s) >= v) and "#00ff00#" or "#ff0000#" - str = str .. ("- %s%s %d\n"):format(c, self.stats_def[s].name, v) + local c = (self:getStat(s) >= v) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("%s %d"):format(self.stats_def[s].name, v), true) end end if req.level then local v = util.getval(req.level, tlev) - local c = (self.level >= v) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sLevel %d\n"):format(c, v) + local c = (self.level >= v) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("Level %d\n"):format(v), true) end if req.talent then for _, tid in ipairs(req.talent) do if type(tid) == "table" then if type(tid[2]) == "boolean" and tid[2] == false then - local c = (not self:knowTalent(tid[1])) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sTalent %s (not known)\n"):format(c, self:getTalentFromId(tid[1]).name) + local c = (not self:knowTalent(tid[1])) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("Talent %s (not known)\n"):format(c, self:getTalentFromId(tid[1]).name), true) else - local c = (self:getTalentLevelRaw(tid[1]) >= tid[2]) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sTalent %s (%d)\n"):format(c, self:getTalentFromId(tid[1]).name, tid[2]) + local c = (self:getTalentLevelRaw(tid[1]) >= tid[2]) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("Talent %s (%d)\n"):format(c, self:getTalentFromId(tid[1]).name, tid[2]), true) end else - local c = self:knowTalent(tid) and "#00ff00#" or "#ff0000#" - str = str .. ("- %sTalent %s\n"):format(c, self:getTalentFromId(tid).name) + local c = self:knowTalent(tid) and {"color", 0x00,0xff,0x00} or {"color", 0xff,0x00,0x00} + str:add("- ", c, ("Talent %s\n"):format(c, self:getTalentFromId(tid).name), true) end end end @@ -373,7 +373,7 @@ end --- Return the full description of a talent -- You may overload it to add more data (like power usage, ...) function _M:getTalentFullDescription(t) - return t.info(self, t) + return tstring{t.info(self, t), true} end --- Do we know this talent type diff --git a/game/engines/default/engine/ui/Textzone.lua b/game/engines/default/engine/ui/Textzone.lua index 166e65c9a954171feb27e600b4941bcfd87da546..8f40019d28aa2269caf9748063b07e73b00715fa 100644 --- a/game/engines/default/engine/ui/Textzone.lua +++ b/game/engines/default/engine/ui/Textzone.lua @@ -25,7 +25,7 @@ local Focusable = require "engine.ui.Focusable" module(..., package.seeall, class.inherit(Base, Focusable)) function _M:init(t) - self.text = assert(t.text, "no textzone text") + self.text = tostring(assert(t.text, "no textzone text")) if t.auto_width then t.width = 1 end self.w = assert(t.width, "no list width") if t.auto_height then t.height = 1 end diff --git a/game/engines/default/engine/ui/TextzoneList.lua b/game/engines/default/engine/ui/TextzoneList.lua index 7a95358a135564af12aa1cb9f1d3fefe3b7317bc..afdcae660d2c15f2bb565b695b06360d3b0f8ee5 100644 --- a/game/engines/default/engine/ui/TextzoneList.lua +++ b/game/engines/default/engine/ui/TextzoneList.lua @@ -73,31 +73,49 @@ function _M:generate() end function _M:createItem(item, text) - local list = text:splitLines(self.w, self.font) - local scroll = 1 - local max = #list - local max_display = math.floor(self.h / self.fh) - - -- Draw the list items - local gen = {} - local r, g, b = 255, 255, 255 - local s = core.display.newSurface(self.fw, self.fh) - for i, l in ipairs(list) do - s:erase() - r, g, b = s:drawColorStringBlended(self.font, l, 0, 0, r, g, b, true) - if self.no_color_bleed then r, g, b = 255, 255, 255 end - - local dat = {} - dat._tex, dat._tex_w, dat._tex_h = s:glTexture() - gen[#gen+1] = dat - end + -- Handle normal text + if type(text) == "string" then + local list = text:splitLines(self.w, self.font) + local scroll = 1 + local max = #list + local max_display = math.floor(self.h / self.fh) + + -- Draw the list items + local gen = {} + local r, g, b = 255, 255, 255 + local s = core.display.newSurface(self.fw, self.fh) + for i, l in ipairs(list) do + s:erase() + r, g, b = s:drawColorStringBlended(self.font, l, 0, 0, r, g, b, true) + if self.no_color_bleed then r, g, b = 255, 255, 255 end + + local dat = {} + dat._tex, dat._tex_w, dat._tex_h = s:glTexture() + gen[#gen+1] = dat + end - self.items[item] = { - list = gen, - scroll = scroll, - max = max, - max_display = max_display, - } + self.items[item] = { + list = gen, + scroll = scroll, + max = max, + max_display = max_display, + } + -- Handle "pre formated" text, as a table + else + -- Draw the list items + local gen = tstring.makeLineTextures(text, self.fw, self.font) + + local scroll = 1 + local max = #gen + local max_display = math.floor(self.h / self.fh) + + self.items[item] = { + list = gen, + scroll = scroll, + max = max, + max_display = max_display, + } + end end function _M:switchItem(item, create_if_needed) diff --git a/game/engines/default/engine/utils.lua b/game/engines/default/engine/utils.lua index 852978ea328c7eadc8dbca8bc0e7bc3eba2bbe3c..4dd4dfc811020ff16ac11c3864cc7f5af387e567 100644 --- a/game/engines/default/engine/utils.lua +++ b/game/engines/default/engine/utils.lua @@ -187,7 +187,10 @@ function string.splitLine(str, max_width, font) local space_w = font:size(" ") local lines = {} local cur_line, cur_size = "", 0 - for _, v in ipairs(str:split(lpeg.S"\n ")) do + local v + local ls = str:split(lpeg.S"\n ") + for i = 1, #ls do + local v = ls[i] local shortv = v:lpegSub("#" * (Puid + Pcolorcodefull + Pcolorname + Pfontstyle) * "#", "") local w, h = font:size(shortv) @@ -206,7 +209,10 @@ end function string.splitLines(str, max_width, font) local lines = {} - for _, v in ipairs(str:split(lpeg.S"\n")) do + local ls = str:split(lpeg.S"\n") + local v + for i = 1, #ls do + v = ls[i] local ls = v:splitLine(max_width, font) if #ls > 0 then for i, l in ipairs(ls) do @@ -228,6 +234,7 @@ function string.split(str, char, keep_separator) return lpeg.match(p, str) end + local hex_to_dec = { ["0"] = 0, ["1"] = 1, @@ -396,12 +403,27 @@ getmetatable(tmps).__index.drawColorStringBlendedCentered = function(s, font, st s:drawColorStringBlended(font, str, x, y, r, g, b, alpha_from_texture, limit_w) end +local font_cache = {} +local oldNewFont = core.display.newFont +core.display.newFont = function(font, size) + if font_cache[font] and font_cache[font][size] then print("Using cached font", font, size) return font_cache[font][size] end + font_cache[font] = font_cache[font] or {} + font_cache[font][size] = oldNewFont(font, size) + return font_cache[font][size] +end + local tmps = core.display.newFont("/data/font/Vera.ttf", 12) +local word_size_cache = {} local fontoldsize = getmetatable(tmps).__index.size getmetatable(tmps).__index.size = function(font, str) local list = str:split("#" * (Puid + Pcolorcodefull + Pcolorname + Pfontstyle) * "#", true) local mw, mh = 0, 0 - for i, v in ipairs(list) do + local fstyle = font:getStyle() + word_size_cache[font] = word_size_cache[font] or {} + word_size_cache[font][fstyle] = word_size_cache[font][fstyle] or {} + local v + for i = 1, #list do + v = list[i] local nr, ng, nb = lpeg.match("#" * lpeg.C(Pcolorcode) * lpeg.C(Pcolorcode) * lpeg.C(Pcolorcode) * "#", v) local col = lpeg.match("#" * lpeg.C(Pcolorname) * "#", v) local uid, mo = lpeg.match("#" * Puid_cap * "#", v) @@ -414,8 +436,16 @@ getmetatable(tmps).__index.size = function(font, str) -- Ignore elseif fontstyle then font:setStyle(fontstyle) + fstyle = fontstyle + word_size_cache[font][fstyle] = word_size_cache[font][fstyle] or {} else - local w, h = fontoldsize(font, v) + local w, h + if word_size_cache[font][fstyle][v] then + w, h = word_size_cache[font][fstyle][v][1], word_size_cache[font][fstyle][v][2] + else + w, h = fontoldsize(font, v) + word_size_cache[font][fstyle][v] = {w, h} + end if h > mh then mh = h end mw = mw + w end @@ -423,6 +453,143 @@ getmetatable(tmps).__index.size = function(font, str) return mw, mh end +tstring = {} + +function tstring:add(...) + local v = {...} + for i = 1, #v do + self[#self+1] = v[i] + end +end + +function tstring:merge(v) + for i = 1, #v do + self[#self+1] = v[i] + end +end + +function tstring:countLines() + local nb = 1 + local v + for i = 1, #self do + v = self[i] + if type(v) == "boolean" then nb = nb + 1 end + end + return nb +end + +--- Tablestrings degrade "peacefully" into normal formated strings +function tstring:toString() + local ret = {} + local v + for i = 1, #self do + v = self[i] + if type(v) == "boolean" then ret[#ret+1] = "\n" + elseif type(v) == "string" then ret[#ret+1] = v + elseif type(v) == "table" then + if v[1] == "color" and v[2] == "LAST" then ret[#ret+1] = "#LAST#" + elseif v[1] == "color" and not v[3] then ret[#ret+1] = "#"..v[2].."#" + elseif v[1] == "color" then ret[#ret+1] = ("#%02x%02x%02x#"):format(v[2], v[3], v[4]):upper() + elseif v[1] == "font" then ret[#ret+1] = "#{"..v[2].."}#" + end + end + end + return table.concat(ret) +end + +function tstring:splitLines(max_width, font) + local space_w = font:size(" ") + local ret = tstring{} + local cur_size =0 + local v + for i = 1, #self do + v = self[i] + if type(v) == "string" then + local ls = v:split(lpeg.S"\n ", true) + for i = 1, #ls do + local vv = ls[i] + if vv == "\n" then + ret[#ret+1] = true + cur_size = 0 + else + local w, h = fontoldsize(font, vv) + if cur_size + w < max_width then + cur_size = cur_size + w + ret[#ret+1] = vv + else + ret[#ret+1] = true + ret[#ret+1] = vv + cur_size = w + end + end + end + elseif type(v) == "table" and v[1] == "font" then + font:setStyle(v[2]) + ret[#ret+1] = v + elseif type(v) == "boolean" then + cur_size = 0 + ret[#ret+1] = v + else + ret[#ret+1] = v + end + end + return ret +end + +function tstring:makeLineTextures(max_width, font) + local list = self:splitLines(max_width, font) + local h = font:lineSkip() + local s = core.display.newSurface(max_width, h) + s:erase(0, 0, 0, 0) + local texs = {} + local w = 0 + local r, g, b = 255, 255, 255 + local oldr, oldg, oldb = 255, 255, 255 + local v + for i = 1, #list do + v = list[i] + if type(v) == "string" then + s:drawStringBlended(font, v, w, 0, r, g, b, true) + w = w + fontoldsize(font, v) + elseif type(v) == "boolean" then + w = 0 + local dat = {} + dat._tex, dat._tex_w, dat._tex_h = s:glTexture() + texs[#texs+1] = dat + s:erase(0, 0, 0, 0) + else + if v[1] == "color" and v[2] == "LAST" then + r, g, b = oldr, oldg, oldb + elseif v[1] == "color" and not v[3] then + oldr, oldg, oldb = r, g, b + r, g, b = unpack(colors.simple(colors[v[2]] or {255,255,255})) + elseif v[1] == "color" then + oldr, oldg, oldb = r, g, b + r, g, b = v[2], v[3], v[4] + elseif v[1] == "font" then + font:setStyle(v[2]) + end + end + end + + -- Last line + local dat = {} + dat._tex, dat._tex_w, dat._tex_h = s:glTexture() + texs[#texs+1] = dat + + return texs +end + +setmetatable(tstring, { + __call = function(self, t) + setmetatable(t, getmetatable(self)) + return t + end, + __index = tstring, + __tostring = tstring.toString, +}) + + dir_to_coord = { [1] = {-1, 1}, [2] = { 0, 1}, diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 750816be7718decf1cc5feb10344b58ae71f03a0..e72bc4710e27cde13b7ca3b7c0797e7d9b81a7d4 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -1350,35 +1350,35 @@ function _M:getTalentFullDescription(t, addlevel) local old = self.talents[t.id] self.talents[t.id] = (self.talents[t.id] or 0) + (addlevel or 0) - local d = {} + local d = tstring{} - d[#d+1] = ("#6fff83#Effective talent level: #00FF00#%.1f"):format(self:getTalentLevel(t)) - if t.mode == "passive" then d[#d+1] = "#6fff83#Use mode: #00FF00#Passive" - elseif t.mode == "sustained" then d[#d+1] = "#6fff83#Use mode: #00FF00#Sustained" - else d[#d+1] = "#6fff83#Use mode: #00FF00#Activated" + d:add({"color",0x6f,0xff,0x83}, "Effective talent level: ", {"color",0x00,0xFF,0x00}, ("%.1f"):format(self:getTalentLevel(t)), true) + if t.mode == "passive" then d:add({"color",0x6f,0xff,0x83}, "Use mode: ", {"color",0x00,0xFF,0x00}, "Passive", true) + elseif t.mode == "sustained" then d:add({"color",0x6f,0xff,0x83}, "Use mode: ", {"color",0x00,0xFF,0x00}, "Sustained", true) + else d:add({"color",0x6f,0xff,0x83}, "Use mode: ", {"color",0x00,0xFF,0x00}, "Activated", true) end - if t.mana or t.sustain_mana then d[#d+1] = "#6fff83#Mana cost: #7fffd4#"..(t.sustain_mana or t.mana * (100 + self.fatigue) / 100) end - if t.stamina or t.sustain_stamina then d[#d+1] = "#6fff83#Stamina cost: #ffcc80#"..(t.sustain_stamina or t.stamina * (100 + self.fatigue) / 100) end - if t.equilibrium or t.sustain_equilibrium then d[#d+1] = "#6fff83#Equilibrium cost: #00ff74#"..(t.equilibrium or t.sustain_equilibrium) end - if t.vim or t.sustain_vim then d[#d+1] = "#6fff83#Vim cost: #888888#"..(t.sustain_vim or t.vim) end - if t.positive or t.sustain_positive then d[#d+1] = "#6fff83#Positive energy cost: #GOLD#"..(t.sustain_positive or t.positive * (100 + self.fatigue) / 100) end - if t.negative or t.sustain_negative then d[#d+1] = "#6fff83#Negative energy cost: #GREY#"..(t.sustain_negative or t.negative * (100 + self.fatigue) / 100) end - if t.hate or t.sustain_hate then d[#d+1] = "#6fff83#Hate cost: #GREY#"..(t.hate or t.sustain_hate) end - if self:getTalentRange(t) > 1 then d[#d+1] = "#6fff83#Range: #FFFFFF#"..self:getTalentRange(t) - else d[#d+1] = "#6fff83#Range: #FFFFFF#melee/personal" + if t.mana or t.sustain_mana then d:add({"color",0x6f,0xff,0x83}, "Mana cost: ", {"color",0x7f,0xff,0xd4}, ""..(t.sustain_mana or t.mana * (100 + self.fatigue) / 100), true) end + if t.stamina or t.sustain_stamina then d:add({"color",0x6f,0xff,0x83}, "Stamina cost: ", {"color",0xff,0xcc,0x80}, ""..(t.sustain_stamina or t.stamina * (100 + self.fatigue) / 100), true) end + if t.equilibrium or t.sustain_equilibrium then d:add({"color",0x6f,0xff,0x83}, "Equilibrium cost: ", {"color",0x00,0xff,0x74}, ""..(t.equilibrium or t.sustain_equilibrium), true) end + if t.vim or t.sustain_vim then d:add({"color",0x6f,0xff,0x83}, "Vim cost: ", {"color",0x88,0x88,0x88}, ""..(t.sustain_vim or t.vim), true) end + if t.positive or t.sustain_positive then d:add({"color",0x6f,0xff,0x83}, "Positive energy cost: #GOLD#"..(t.sustain_positive or t.positive * (100 + self.fatigue) / 100), true) end + if t.negative or t.sustain_negative then d:add({"color",0x6f,0xff,0x83}, "Negative energy cost: #GREY#"..(t.sustain_negative or t.negative * (100 + self.fatigue) / 100), true) end + if t.hate or t.sustain_hate then d:add({"color",0x6f,0xff,0x83}, "Hate cost: #GREY#"..(t.hate or t.sustain_hate), true) end + if self:getTalentRange(t) > 1 then d:add({"color",0x6f,0xff,0x83}, "Range: ", {"color",0xFF,0xFF,0xFF}, ""..self:getTalentRange(t), true) + else d:add({"color",0x6f,0xff,0x83}, "Range: ", {"color",0xFF,0xFF,0xFF}, "melee/personal", true) end - if t.cooldown then d[#d+1] = "#6fff83#Cooldown: #FFFFFF#"..util.getval(t.cooldown, self, t) end + if t.cooldown then d:add({"color",0x6f,0xff,0x83}, "Cooldown: ", {"color",0xFF,0xFF,0xFF}, ""..util.getval(t.cooldown, self, t), true) end local speed = self:getTalentProjectileSpeed(t) - if speed then d[#d+1] = "#6fff83#Travel Speed: #FFFFFF#"..(speed * 100).."% of base" - else d[#d+1] = "#6fff83#Travel Speed: #FFFFFF#instantaneous" + if speed then d:add({"color",0x6f,0xff,0x83}, "Travel Speed: ", {"color",0xFF,0xFF,0xFF}, ""..(speed * 100).."% of base", true) + else d:add({"color",0x6f,0xff,0x83}, "Travel Speed: ", {"color",0xFF,0xFF,0xFF}, "instantaneous", true) end - local ret = table.concat(d, "\n").."\n#6fff83#Description: #FFFFFF#"..t.info(self, t) + d:add({"color",0x6f,0xff,0x83}, "Description: ", {"color",0xFF,0xFF,0xFF}, t.info(self, t), true) self.talents[t.id] = old - return ret + return d end --- Starts a talent cooldown; overloaded from the default to handle talent cooldown reduction diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 79c7ab9fbd63ac92cafc90f67eb2b6611b5fa33e..a265b7059992b1b66a00a8709495590b75e59a0a 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -861,7 +861,7 @@ function _M:setupMouse(reset) end, {button=true}) -- Use hotkeys with mouse self.mouse:registerZone(self.hotkeys_display.display_x, self.hotkeys_display.display_y, self.w, self.h, function(button, mx, my, xrel, yrel, bx, by, event) - self.hotkeys_display:onMouse(button, mx, my, event == "button", function(text) self.tooltip:displayAtMap(nil, nil, self.w, self.h, text) end) + self.hotkeys_display:onMouse(button, mx, my, event == "button", function(text) self.tooltip:displayAtMap(nil, nil, self.w, self.h, tostring(text)) end) end) -- Use icons self.mouse:registerZone(self.icons.display_x, self.icons.display_y, self.icons.w, self.icons.h, function(button, mx, my, xrel, yrel, bx, by) diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua index 17355f703371547ed0acc8fbbdf1e76a1175132a..87c92c1fdd7e920c591980aa8550576b4c0a8ec8 100644 --- a/game/modules/tome/class/Object.lua +++ b/game/modules/tome/class/Object.lua @@ -93,7 +93,7 @@ end --- Returns a tooltip for the object function _M:tooltip() - return self:getDesc{do_color=true} + return tostring(self:getDesc{do_color=true}) end --- Describes an attribute, to expand object name @@ -188,9 +188,9 @@ end --- Gets the full textual desc of the object without the name and requirements function _M:getTextualDesc() - local desc = {} + local desc = tstring{} - desc[#desc+1] = ("Type: %s / %s"):format(self.type, self.subtype) + desc:add(("Type: %s / %s"):format(self.type, self.subtype), true) -- Stop here if unided if not self:isIdentified() then return desc end @@ -200,29 +200,29 @@ function _M:getTextualDesc() for stat, i in pairs(self.combat.dammod or {}) do dm[#dm+1] = ("+%d%% %s"):format(i * 100, Stats.stats_def[stat].name) end - desc[#desc+1] = ("%d Power [Range %0.2f] (%s), %d Attack, %d Armor Penetration, Crit %d%%"):format(self.combat.dam or 0, self.combat.damrange or 1.1, table.concat(dm, ','), self.combat.atk or 0, self.combat.apr or 0, self.combat.physcrit or 0) - desc[#desc+1] = "Damage type: "..DamageType:get(self.combat.damtype or DamageType.PHYSICAL).name - if self.combat.range then desc[#desc+1] = "Firing range: "..self.combat.range end - desc[#desc+1] = "" + desc:add(("%d Power [Range %0.2f] (%s), %d Attack, %d Armor Penetration, Crit %d%%"):format(self.combat.dam or 0, self.combat.damrange or 1.1, table.concat(dm, ','), self.combat.atk or 0, self.combat.apr or 0, self.combat.physcrit or 0), true) + desc:add("Damage type: "..DamageType:get(self.combat.damtype or DamageType.PHYSICAL).name, true) + if self.combat.range then desc:add("Firing range: "..self.combat.range, true) end + desc:add(true) if self.combat.talent_on_hit then for tid, data in pairs(self.combat.talent_on_hit) do - desc[#desc+1] = ("Talent on hit(melee): %d%% chance %s (level %d)."):format(data.chance, self:getTalentFromId(tid).name, data.level) + desc:add(("Talent on hit(melee): %d%% chance %s (level %d)."):format(data.chance, self:getTalentFromId(tid).name, data.level), true) end end end local desc_wielder = function(w) - if w.combat_atk or w.combat_dam or w.combat_apr then desc[#desc+1] = ("Attack %d, Armor Penetration %d, Physical Crit %d%%, Physical power %d"):format(w.combat_atk or 0, w.combat_apr or 0, w.combat_physcrit or 0, w.combat_dam or 0) end - if w.combat_armor or w.combat_def or w.combat_def_ranged then desc[#desc+1] = ("Armor %d, Defense %d, Ranged Defense %d"):format(w.combat_armor or 0, w.combat_def or 0, w.combat_def_ranged or 0) end - if w.fatigue then desc[#desc+1] = ("Fatigue %d%%"):format(w.fatigue) end + if w.combat_atk or w.combat_dam or w.combat_apr then desc:add(("Attack %d, Armor Penetration %d, Physical Crit %d%%, Physical power %d"):format(w.combat_atk or 0, w.combat_apr or 0, w.combat_physcrit or 0, w.combat_dam or 0), true) end + if w.combat_armor or w.combat_def or w.combat_def_ranged then desc:add(("Armor %d, Defense %d, Ranged Defense %d"):format(w.combat_armor or 0, w.combat_def or 0, w.combat_def_ranged or 0), true) end + if w.fatigue then desc:add(("Fatigue %d%%"):format(w.fatigue), true) end if w.inc_stats then local dm = {} for stat, i in pairs(w.inc_stats) do dm[#dm+1] = ("%d %s"):format(i, Stats.stats_def[stat].name) end - desc[#desc+1] = ("Increases stats: %s."):format(table.concat(dm, ',')) + desc:add(("Increases stats: %s."):format(table.concat(dm, ',')), true) end if w.melee_project then @@ -230,7 +230,7 @@ function _M:getTextualDesc() for typ, dam in pairs(w.melee_project) do rs[#rs+1] = ("%d %s"):format(dam, DamageType.dam_def[typ].name) end - desc[#desc+1] = ("Damage on hit(melee): %s."):format(table.concat(rs, ',')) + desc:add(("Damage on hit(melee): %s."):format(table.concat(rs, ',')), true) end if w.ranged_project then @@ -238,7 +238,7 @@ function _M:getTextualDesc() for typ, dam in pairs(w.ranged_project) do rs[#rs+1] = ("%d %s"):format(dam, DamageType.dam_def[typ].name) end - desc[#desc+1] = ("Damage on hit(ranged): %s."):format(table.concat(rs, ',')) + desc:add(("Damage on hit(ranged): %s."):format(table.concat(rs, ',')), true) end if w.on_melee_hit then @@ -246,7 +246,7 @@ function _M:getTextualDesc() for typ, dam in pairs(w.on_melee_hit) do rs[#rs+1] = ("%d %s"):format(dam, DamageType.dam_def[typ].name) end - desc[#desc+1] = ("Damage when hit: %s."):format(table.concat(rs, ',')) + desc:add(("Damage when hit: %s."):format(table.concat(rs, ',')), true) end if w.resists then @@ -254,7 +254,7 @@ function _M:getTextualDesc() for res, i in pairs(w.resists) do rs[#rs+1] = ("%d%% %s"):format(i, res == "all" and "all" or DamageType.dam_def[res].name) end - desc[#desc+1] = ("Increases resistances: %s."):format(table.concat(rs, ',')) + desc:add(("Increases resistances: %s."):format(table.concat(rs, ',')), true) end if w.inc_damage then @@ -262,7 +262,7 @@ function _M:getTextualDesc() for res, i in pairs(w.inc_damage) do rs[#rs+1] = ("%d%% %s"):format(i, res == "all" and "all" or DamageType.dam_def[res].name) end - desc[#desc+1] = ("Increases damage type: %s."):format(table.concat(rs, ',')) + desc:add(("Increases damage type: %s."):format(table.concat(rs, ',')), true) end if w.esp then @@ -279,7 +279,7 @@ function _M:getTextualDesc() end end end - desc[#desc+1] = ("Grants telepathy: %s."):format(table.concat(rs, ',')) + desc:add(("Grants telepathy: %s."):format(table.concat(rs, ',')), true) end if w.talents_types_mastery then @@ -290,7 +290,7 @@ function _M:getTextualDesc() local name = cat:capitalize().." / "..tt.name:capitalize() tms[#tms+1] = ("%0.2f %s"):format(i, name) end - desc[#desc+1] = ("Increases talent masteries: %s."):format(table.concat(tms, ',')) + desc:add(("Increases talent masteries: %s."):format(table.concat(tms, ',')), true) end if w.talent_cd_reduction then @@ -298,7 +298,7 @@ function _M:getTextualDesc() for tid, cd in pairs(w.talent_cd_reduction) do tcds[#tcds+1] = ("%s (%d)"):format(Talents.talents_def[tid].name, cd) end - desc[#desc+1] = ("Reduces talent cooldowns: %s."):format(table.concat(tcds, ',')) + desc:add(("Reduces talent cooldowns: %s."):format(table.concat(tcds, ',')), true) end if w.can_breath then @@ -306,111 +306,114 @@ function _M:getTextualDesc() for what, _ in pairs(w.can_breath) do ts[#ts+1] = what end - desc[#desc+1] = ("Allows you to breathe in: %s."):format(table.concat(ts, ',')) + desc:add(("Allows you to breathe in: %s."):format(table.concat(ts, ',')), true) end - if w.combat_critical_power then desc[#desc+1] = ("Increases critical damage modifier: +%d%%."):format(w.combat_critical_power) end + if w.combat_critical_power then desc:add(("Increases critical damage modifier: +%d%%."):format(w.combat_critical_power), true) end - if w.disarm_bonus then desc[#desc+1] = ("Increases trap disarming bonus: %d."):format(w.disarm_bonus) end - if w.inc_stealth then desc[#desc+1] = ("Increases stealth bonus: %d."):format(w.inc_stealth) end - if w.max_encumber then desc[#desc+1] = ("Increases maximum encumberance: %d."):format(w.max_encumber) end + if w.disarm_bonus then desc:add(("Increases trap disarming bonus: %d."):format(w.disarm_bonus), true) end + if w.inc_stealth then desc:add(("Increases stealth bonus: %d."):format(w.inc_stealth), true) end + if w.max_encumber then desc:add(("Increases maximum encumberance: %d."):format(w.max_encumber), true) end - if w.combat_physresist then desc[#desc+1] = ("Increases physical save: %s."):format(w.combat_physresist) end - if w.combat_spellresist then desc[#desc+1] = ("Increases spell save: %s."):format(w.combat_spellresist) end - if w.combat_mentalresist then desc[#desc+1] = ("Increases mental save: %s."):format(w.combat_mentalresist) end + if w.combat_physresist then desc:add(("Increases physical save: %s."):format(w.combat_physresist), true) end + if w.combat_spellresist then desc:add(("Increases spell save: %s."):format(w.combat_spellresist), true) end + if w.combat_mentalresist then desc:add(("Increases mental save: %s."):format(w.combat_mentalresist), true) end - if w.blind_immune then desc[#desc+1] = ("Increases blindness immunity: %d%%."):format(w.blind_immune * 100) end - if w.poison_immune then desc[#desc+1] = ("Increases poison immunity: %d%%."):format(w.poison_immune * 100) end - if w.cut_immune then desc[#desc+1] = ("Increases cut immunity: %d%%."):format(w.cut_immune * 100) end - if w.silence_immune then desc[#desc+1] = ("Increases silence immunity: %d%%."):format(w.silence_immune * 100) end - if w.disarm_immune then desc[#desc+1] = ("Increases disarm immunity: %d%%."):format(w.disarm_immune * 100) end - if w.confusion_immune then desc[#desc+1] = ("Increases confusion immunity: %d%%."):format(w.confusion_immune * 100) end - if w.pin_immune then desc[#desc+1] = ("Increases pinning immunity: %d%%."):format(w.pin_immune * 100) end - if w.stun_immune then desc[#desc+1] = ("Increases stun immunity: %d%%."):format(w.stun_immune * 100) end - if w.fear_immune then desc[#desc+1] = ("Increases fear immunity: %d%%."):format(w.fear_immune * 100) end - if w.knockback_immune then desc[#desc+1] = ("Increases knockback immunity: %d%%."):format(w.knockback_immune * 100) end - if w.instakill_immune then desc[#desc+1] = ("Increases instant-death immunity: %d%%."):format(w.instakill_immune * 100) end + if w.blind_immune then desc:add(("Increases blindness immunity: %d%%."):format(w.blind_immune * 100), true) end + if w.poison_immune then desc:add(("Increases poison immunity: %d%%."):format(w.poison_immune * 100), true) end + if w.cut_immune then desc:add(("Increases cut immunity: %d%%."):format(w.cut_immune * 100), true) end + if w.silence_immune then desc:add(("Increases silence immunity: %d%%."):format(w.silence_immune * 100), true) end + if w.disarm_immune then desc:add(("Increases disarm immunity: %d%%."):format(w.disarm_immune * 100), true) end + if w.confusion_immune then desc:add(("Increases confusion immunity: %d%%."):format(w.confusion_immune * 100), true) end + if w.pin_immune then desc:add(("Increases pinning immunity: %d%%."):format(w.pin_immune * 100), true) end + if w.stun_immune then desc:add(("Increases stun immunity: %d%%."):format(w.stun_immune * 100), true) end + if w.fear_immune then desc:add(("Increases fear immunity: %d%%."):format(w.fear_immune * 100), true) end + if w.knockback_immune then desc:add(("Increases knockback immunity: %d%%."):format(w.knockback_immune * 100), true) end + if w.instakill_immune then desc:add(("Increases instant-death immunity: %d%%."):format(w.instakill_immune * 100), true) end - if w.life_regen then desc[#desc+1] = ("Regenerates %0.2f hitpoints each turn."):format(w.life_regen) end - if w.stamina_regen then desc[#desc+1] = ("Regenerates %0.2f stamina each turn."):format(w.stamina_regen) end - if w.mana_regen then desc[#desc+1] = ("Regenerates %0.2f mana each turn."):format(w.mana_regen) end + if w.life_regen then desc:add(("Regenerates %0.2f hitpoints each turn."):format(w.life_regen), true) end + if w.stamina_regen then desc:add(("Regenerates %0.2f stamina each turn."):format(w.stamina_regen), true) end + if w.mana_regen then desc:add(("Regenerates %0.2f mana each turn."):format(w.mana_regen), true) end - if w.stamina_regen_on_hit then desc[#desc+1] = ("Regenerates %0.2f stamina when hit."):format(w.stamina_regen_on_hit) end - if w.mana_regen_on_hit then desc[#desc+1] = ("Regenerates %0.2f mana when hit."):format(w.mana_regen_on_hit) end - if w.equilibrium_regen_on_hit then desc[#desc+1] = ("Regenerates %0.2f equilibrium when hit."):format(w.equilibrium_regen_on_hit) end + if w.stamina_regen_on_hit then desc:add(("Regenerates %0.2f stamina when hit."):format(w.stamina_regen_on_hit), true) end + if w.mana_regen_on_hit then desc:add(("Regenerates %0.2f mana when hit."):format(w.mana_regen_on_hit), true) end + if w.equilibrium_regen_on_hit then desc:add(("Regenerates %0.2f equilibrium when hit."):format(w.equilibrium_regen_on_hit), true) end - if w.max_life then desc[#desc+1] = ("Maximum life %d"):format(w.max_life) end - if w.max_mana then desc[#desc+1] = ("Maximum mana %d"):format(w.max_mana) end - if w.max_stamina then desc[#desc+1] = ("Maximum stamina %d"):format(w.max_stamina) end + if w.max_life then desc:add(("Maximum life %d"):format(w.max_life), true) end + if w.max_mana then desc:add(("Maximum mana %d"):format(w.max_mana), true) end + if w.max_stamina then desc:add(("Maximum stamina %d"):format(w.max_stamina), true) end - if w.combat_spellpower or w.combat_spellcrit then desc[#desc+1] = ("Spellpower %d, Spell Crit %d%%"):format(w.combat_spellpower or 0, w.combat_spellcrit or 0) end + if w.combat_spellpower or w.combat_spellcrit then desc:add(("Spellpower %d, Spell Crit %d%%"):format(w.combat_spellpower or 0, w.combat_spellcrit or 0), true) end - if w.lite then desc[#desc+1] = ("Light radius %d"):format(w.lite) end - if w.infravision then desc[#desc+1] = ("Infravision radius %d"):format(w.infravision) end - if w.heightened_senses then desc[#desc+1] = ("Heightened senses radius %d"):format(w.heightened_senses) end + if w.lite then desc:add(("Light radius %d"):format(w.lite), true) end + if w.infravision then desc:add(("Infravision radius %d"):format(w.infravision), true) end + if w.heightened_senses then desc:add(("Heightened senses radius %d"):format(w.heightened_senses), true) end - if w.see_invisible then desc[#desc+1] = ("See invisible: %d"):format(w.see_invisible) end - if w.invisible then desc[#desc+1] = ("Invisibility: %d"):format(w.invisible) end + if w.see_invisible then desc:add(("See invisible: %d"):format(w.see_invisible), true) end + if w.invisible then desc:add(("Invisibility: %d"):format(w.invisible), true) end - if w.movement_speed then desc[#desc+1] = ("Movement speed: %d%%"):format(w.movement_speed * 100) end + if w.movement_speed then desc:add(("Movement speed: %d%%"):format(w.movement_speed * 100), true) end end if self.wielder then - desc[#desc+1] = "#YELLOW#When wielded/worn:#LAST#" + desc:add({"color","YELLOW"}, "When wielded/worn:", {"color", "LAST"}, true) desc_wielder(self.wielder) end if self.carrier then - desc[#desc+1] = "#YELLOW#When carried:#LAST#" + desc:add({"color","YELLOW"}, "When carried:", {"color", "LAST"}, true) desc_wielder(self.carrier) end if self.imbue_powers then - desc[#desc+1] = "#YELLOW#When used to imbue an object:#LAST#" + desc:add({"color","YELLOW"}, "When used to imbue an object:", {"color", "LAST"}, true) desc_wielder(self.imbue_powers) end if self.alchemist_bomb then local a = self.alchemist_bomb - desc[#desc+1] = "#YELLOW#When used as an alchemist bomb:#LAST#" - if a.power then desc[#desc+1] = ("Bomb damage +%d%%"):format(a.power) end - if a.range then desc[#desc+1] = ("Bomb thrown range +%d"):format(a.range) end - if a.mana then desc[#desc+1] = ("Mana regain %d"):format(a.mana) end - if a.daze then desc[#desc+1] = ("%d%% chance to daze for %d turns"):format(a.daze.chance, a.daze.dur) end - if a.stun then desc[#desc+1] = ("%d%% chance to stun for %d turns"):format(a.stun.chance, a.stun.dur) end - if a.splash then desc[#desc+1] = ("Additional %d %s damage"):format(a.splash.dam, DamageType:get(DamageType[a.splash.type]).name) end - if a.leech then desc[#desc+1] = ("Life regen %d%% of max life"):format(a.leech) end + desc:add({"color","YELLOW"}, "When used as an alchemist bomb:", {"color", "LAST"}, true) + if a.power then desc:add(("Bomb damage +%d%%"):format(a.power), true) end + if a.range then desc:add(("Bomb thrown range +%d"):format(a.range), true) end + if a.mana then desc:add(("Mana regain %d"):format(a.mana), true) end + if a.daze then desc:add(("%d%% chance to daze for %d turns"):format(a.daze.chance, a.daze.dur), true) end + if a.stun then desc:add(("%d%% chance to stun for %d turns"):format(a.stun.chance, a.stun.dur), true) end + if a.splash then desc:add(("Additional %d %s damage"):format(a.splash.dam, DamageType:get(DamageType[a.splash.type]).name), true) end + if a.leech then desc:add(("Life regen %d%% of max life"):format(a.leech), true) end end local use_desc = self:getUseDesc() - if use_desc then desc[#desc+1] = use_desc end + if use_desc then desc:add(use_desc) end return desc end --- Gets the full desc of the object function _M:getDesc(name_param) - local _, c = self:getDisplayColor() - local desc + local c, _ = self:getDisplayColor() + local desc = tstring{} if not self:isIdentified() then - desc = { c..self:getName(name_param).."#FFFFFF#" } + desc:add({"color", unpack(c)}, self:getName(name_param), {"color", "WHITE"}) else - desc = { c..self:getName(name_param).."#FFFFFF#", self.desc } + desc:add({"color", unpack(c)}, self:getName(name_param), {"color", "WHITE"}, true) + desc:merge(self.desc) end local reqs = self:getRequirementDesc(game.player) if reqs then - desc[#desc+1] = reqs + desc:add(true) + desc:merge(reqs) end if self.encumber then - desc[#desc+1] = ("#67AD00#%0.2f Encumbrance.#LAST#"):format(self.encumber) + desc:add({"color",0x67,0xAD,0x00}, ("%0.2f Encumbrance."):format(self.encumber), {"color", "LAST"}) end - local textdesc = table.concat(self:getTextualDesc(), "\n") + desc:add(true, true) + desc:merge(self:getTextualDesc()) - return table.concat(desc, "\n").."\n"..textdesc + return desc end local type_sort = { diff --git a/game/modules/tome/class/Store.lua b/game/modules/tome/class/Store.lua index b374b6fe38e161928df9d7adadff935175ed4459..49b8a36da808b2e46fcff860490af3c21eb3e228 100644 --- a/game/modules/tome/class/Store.lua +++ b/game/modules/tome/class/Store.lua @@ -101,12 +101,12 @@ end -- @return a string (possibly multiline) describing the object function _M:descObject(who, what, o) if what == "buy" then - local desc = ("Buy for: %0.2f gold (You have %0.2f gold)\n\n"):format(o:getPrice() * self.sell_percent / 100, who.money) - desc = desc .. o:getDesc() + local desc = tstring({"font", "bold"}, {"color", "GOLD"}, ("Buy for: %0.2f gold (You have %0.2f gold)"):format(o:getPrice() * self.sell_percent / 100, who.money), {"font", "normal"}, {"color", "LAST"}, true, true) + desc:merge(o:getDesc()) return desc else - local desc = ("Sell for: %0.2f gold (You have %0.2f gold)\n\n"):format(o:getPrice() * self.buy_percent / 100, who.money) - desc = desc .. o:getDesc() + local desc = tstring({"font", "bold"}, {"color", "GOLD"}, ("Sell for: %0.2f gold (You have %0.2f gold)"):format(o:getPrice() * self.buy_percent / 100, who.money), {"font", "normal"}, {"color", "LAST"}, true, true) + desc:merge(o:getDesc()) return desc end end diff --git a/game/modules/tome/data/chats/escort-quest.lua b/game/modules/tome/data/chats/escort-quest.lua index d42d61d8ab59002a42d4250813ae6830385e6edd..cfb5bfb18974fad4dee39103619d6ed9006789af 100644 --- a/game/modules/tome/data/chats/escort-quest.lua +++ b/game/modules/tome/data/chats/escort-quest.lua @@ -163,7 +163,7 @@ local function generate_rewards() action=doit, on_select=function(npc, player) game.tooltip_x, game.tooltip_y = 1, 1 - game.tooltip:displayAtMap(nil, nil, game.w, game.h, "#GOLD#"..t.name.."#LAST#\n"..player:getTalentFullDescription(t, 1)) + game.tooltip:displayAtMap(nil, nil, game.w, game.h, "#GOLD#"..t.name.."#LAST#\n"..tostring(player:getTalentFullDescription(t, 1))) end, } end diff --git a/game/modules/tome/data/zones/vor-armoury/zone.lua b/game/modules/tome/data/zones/vor-armoury/zone.lua index f1f62eca4781578a9bcd28e47d193defbc4e8501..2f33a4a5c573a1b6c4136990bce8014d3dfeb362 100644 --- a/game/modules/tome/data/zones/vor-armoury/zone.lua +++ b/game/modules/tome/data/zones/vor-armoury/zone.lua @@ -22,7 +22,7 @@ return { level_range = {35, 50}, level_scheme = "player", max_level = 2, - decay = {300, 800}, +-- decay = {300, 800}, actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end, width = 30, height = 30, persistant = "zone", diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua index 78e267dd85459c02bf7ce848627080cc42a021b8..c18d106ed4d6db2852d495a849af69510e2e7a7a 100644 --- a/game/modules/tome/dialogs/CharacterSheet.lua +++ b/game/modules/tome/dialogs/CharacterSheet.lua @@ -467,7 +467,7 @@ function _M:dump() if not self.filter or self.filter(o) then local char = string.char(string.byte('a') + index) nl(("%s) %s"):format(char, o:getName{force_id=true})) - nl((" %s"):format(table.concat(o:getTextualDesc(), "\n "))) + nl((" %s"):format(tostring(o:getTextualDesc()))) if o.droppedBy then nl((" Dropped by %s"):format(o.droppedBy)) end @@ -498,7 +498,7 @@ function _M:dump() if not self.filter or self.filter(o) then local char = string.char(string.byte('a') + item - 1) nl(("%s) %s"):format(char, o:getName{force_id=true})) - nl((" %s"):format(table.concat(o:getTextualDesc(), "\n "))) + nl((" %s"):format(tostring(o:getTextualDesc()))) if o.droppedBy then nl((" Dropped by %s"):format(o.droppedBy)) end diff --git a/game/modules/tome/dialogs/LevelupTalentsDialog.lua b/game/modules/tome/dialogs/LevelupTalentsDialog.lua index 8724d9f61a52173bcb18fa1fdcc6ebf945a37e75..1ca417e4500480425586949842bd513ce042ecd1 100644 --- a/game/modules/tome/dialogs/LevelupTalentsDialog.lua +++ b/game/modules/tome/dialogs/LevelupTalentsDialog.lua @@ -146,6 +146,7 @@ function _M:generateList() local tshown = (self.actor.__hidden_talent_types[tt.type] == nil and ttknown) or (self.actor.__hidden_talent_types[tt.type] ~= nil and not self.actor.__hidden_talent_types[tt.type]) local node = { name=function(item) return "#{bold}#"..cat:capitalize().." / "..tt.name:capitalize() ..(" (mastery %.02f)"):format(self.actor:getTalentTypeMastery(tt.type)).."#{normal}#" end, + rawname=function(item) return cat:capitalize().." / "..tt.name:capitalize() ..(" (mastery %.02f)"):format(self.actor:getTalentTypeMastery(tt.type)) end, type=tt.type, color=function(item) return self.actor:knowTalentType(item.type) and {0,200,0} or {175,175,175} end, shown = tshown, @@ -166,6 +167,7 @@ function _M:generateList() list[#list+1] = { __id=t.id, name=t.name.." ("..typename..")", + rawname=t.name.." ("..typename..")", talent=t.id, _type=tt.type, color=function(item) return self.actor:knowTalentType(item._type) and {255,255,255} or {175,175,175} end, @@ -217,45 +219,49 @@ end function _M:onDrawItem(item) if not item then return end + local text = tstring{} - local text = {} - - text[#text+1] = util.getval(item.name, item) - text[#text+1] = "" + text:add({"color", "GOLD"}, {"font", "bold"}, util.getval(item.rawname, item), {"color", "LAST"}, {"font", "normal"}) + text:add(true, true) if item.type then - text[#text+1] = "#00FFFF#Talent Category" - text[#text+1] = "#00FFFF#A talent category allows you to learn talents of this category. You gain a talent category point at level 10, 20 and 30. You may also find trainers or artifacts that allow you to learn more.\nA talent category point can be used either to learn a new category or increase the mastery of a known one.\n" + text:add({"color",0x00,0xFF,0xFF}, "Talent Category", true) + text:add({"color",0x00,0xFF,0xFF}, "A talent category allows you to learn talents of this category. You gain a talent category point at level 10, 20 and 30. You may also find trainers or artifacts that allow you to learn more.\nA talent category point can be used either to learn a new category or increase the mastery of a known one.", true, true, {"color", "WHITE"}) + text:add(self.actor:getTalentTypeFrom(item.type).description) else local t = self.actor:getTalentFromId(item.talent) local what if t.generic then what = "generic talent" - text[#text+1] = "#00FFFF#Generic Talent" - text[#text+1] = "#00FFFF#A generic talent allows you to perform various utility actions and improve your character. It represents talents anybody can learn (should they find a trainer for it). You gain one point every levels (except every 5th level). You may also find trainers or artifacts that allow you to learn more.\n" + text:add({"color",0x00,0xFF,0xFF}, "Generic Talent", true) + text:add({"color",0x00,0xFF,0xFF}, "A generic talent allows you to perform various utility actions and improve your character. It represents talents anybody can learn (should they find a trainer for it). You gain one point every levels (except every 5th level). You may also find trainers or artifacts that allow you to learn more.", true, true, {"color", "WHITE"}) else what = "class talent" - text[#text+1] = "#00FFFF#Class talent" - text[#text+1] = "#00FFFF#A class talent allows you to perform new combat moves, cast spells, and improve your character. It represents the core function of your class. You gain one point every level and two every 5th level. You may also find trainers or artifacts that allow you to learn more.\n" + text:add({"color",0x00,0xFF,0xFF}, "Class talent", true) + text:add({"color",0x00,0xFF,0xFF}, "A class talent allows you to perform new combat moves, cast spells, and improve your character. It represents the core function of your class. You gain one point every level and two every 5th level. You may also find trainers or artifacts that allow you to learn more.", true, true, {"color", "WHITE"}) end if self.actor:getTalentLevelRaw(t.id) > 0 then local req = self.actor:getTalentReqDesc(item.talent, 0) - req = "Current "..what.." level: "..self.actor:getTalentLevelRaw(t.id).."\n"..req - text[#text+1] = req - text[#text+1] = self.actor:getTalentFullDescription(t) + text:add{"color","WHITE"} + text:add("Current "..what.." level: "..(self.actor:getTalentLevelRaw(t.id))) + text:add(true) + text:merge(req) + text:merge(self.actor:getTalentFullDescription(t)) end if self.actor:getTalentLevelRaw(t.id) < t.points then local req2 = self.actor:getTalentReqDesc(item.talent, 1) - req2 = "Next "..what.." level: "..(self.actor:getTalentLevelRaw(t.id)+1).."\n"..req2 - text[#text+1] = req2 - text[#text+1] = self.actor:getTalentFullDescription(t, 1) + text:add("Next "..what.." level: "..(self.actor:getTalentLevelRaw(t.id)+1)) + text:add(true) + text:merge(req2) + text:merge(self.actor:getTalentFullDescription(t, 1)) end end - self.c_desc:createItem(item, table.concat(text, "\n")) + self.c_desc:createItem(item, text) + end function _M:select(item) diff --git a/src/core_lua.c b/src/core_lua.c index 7f65235621fe59c6f4a88ac68a5439613e9ab5da..544c30507dcc319d2d6b2491f237a684c34e9c6b 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -530,6 +530,19 @@ static int sdl_font_lineskip(lua_State *L) return 1; } +static int sdl_font_style_get(lua_State *L) +{ + TTF_Font **f = (TTF_Font**)auxiliar_checkclass(L, "sdl{font}", 1); + int style = TTF_GetFontStyle(*f); + + if (style & TTF_STYLE_BOLD) lua_pushstring(L, "bold"); + else if (style & TTF_STYLE_ITALIC) lua_pushstring(L, "italic"); + else if (style & TTF_STYLE_UNDERLINE) lua_pushstring(L, "underline"); + else lua_pushstring(L, "normal"); + + return 1; +} + static int sdl_font_style(lua_State *L) { TTF_Font **f = (TTF_Font**)auxiliar_checkclass(L, "sdl{font}", 1); @@ -1508,6 +1521,7 @@ static const struct luaL_reg sdl_font_reg[] = {"height", sdl_font_height}, {"lineSkip", sdl_font_lineskip}, {"setStyle", sdl_font_style}, + {"getStyle", sdl_font_style_get}, {NULL, NULL}, };