From 9db1f3f31337559d99e8d37a6a54a5065f8d76db Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Tue, 14 Jun 2011 22:42:01 +0000 Subject: [PATCH] Big UI update, the game log and chat logs are now displayed side by side in transparency over the game map, hotkeys are "flattened" over more width, making room for more map displayed at once git-svn-id: http://svn.net-core.org/repos/t-engine4@3653 51575b47-30f0-44d4-a5cc-537603b46e54 --- .../engines/default/data/keybinds/actions.lua | 2 +- .../engines/default/engine/HotkeysDisplay.lua | 21 +- game/engines/default/engine/LogDisplay.lua | 48 ++- game/engines/default/engine/Map.lua | 2 + game/engines/default/engine/UserChat.lua | 86 +++-- .../engine/interface/GameTargeting.lua | 2 + .../default/engine/interface/PlayerMouse.lua | 1 + game/modules/tome/class/Game.lua | 307 +++++++++--------- game/modules/tome/class/Player.lua | 2 +- game/modules/tome/dialogs/ShowChatLog.lua | 160 +++++++++ 10 files changed, 437 insertions(+), 194 deletions(-) create mode 100644 game/modules/tome/dialogs/ShowChatLog.lua diff --git a/game/engines/default/data/keybinds/actions.lua b/game/engines/default/data/keybinds/actions.lua index 5f43ef94ce..bba236c11d 100644 --- a/game/engines/default/data/keybinds/actions.lua +++ b/game/engines/default/data/keybinds/actions.lua @@ -94,7 +94,7 @@ defineAction{ } defineAction{ - default = { "uni:C" }, + default = { "uni:c", "uni:C" }, type = "SHOW_CHARACTER_SHEET", group = "actions", name = "Show character sheet", diff --git a/game/engines/default/engine/HotkeysDisplay.lua b/game/engines/default/engine/HotkeysDisplay.lua index 4aa713b32f..5e0b247940 100644 --- a/game/engines/default/engine/HotkeysDisplay.lua +++ b/game/engines/default/engine/HotkeysDisplay.lua @@ -50,10 +50,6 @@ function _M:resize(x, y, w, h) self.texture, self.texture_w, self.texture_h = self.surface:glTexture() if self.actor then self.actor.changed = true end - local cw, ch = self.font:size(" ") - self.font_w = cw - self.max_char_w = math.min(127, math.floor(w / self.font_w)) - if self.bg_image then local fill = core.display.loadImage(self.bg_image) local fw, fh = fill:getSize() @@ -73,14 +69,17 @@ function _M:display() local a = self.actor if not a or not a.changed then return self.surface end + local page = a.hotkey_page + if page == 1 and core.key.modState("ctrl") then page = 2 + elseif page == 1 and core.key.modState("shift") then page = 3 end + local hks = {} for i = 1, 12 do - local j = i + (12 * (a.hotkey_page - 1)) - local ks = game.key:formatKeyString(game.key:findBoundKeys("HOTKEY_"..page_to_hotkey[a.hotkey_page]..i)) + local j = i + (12 * (page - 1)) if a.hotkey[j] and a.hotkey[j][1] == "talent" then - hks[#hks+1] = {a.hotkey[j][2], j, "talent", ks} + hks[#hks+1] = {a.hotkey[j][2], i, "talent"} elseif a.hotkey[j] and a.hotkey[j][1] == "inventory" then - hks[#hks+1] = {a.hotkey[j][2], j, "inventory", ks} + hks[#hks+1] = {a.hotkey[j][2], i, "inventory"} end end @@ -122,14 +121,14 @@ function _M:display() end end - txt = ("%1d/%2d) %-"..(self.max_char_w-4-24).."s Key: %s"):format(a.hotkey_page, i - (a.hotkey_page-1) * 12, txt, ts[4]) + txt = ("%1d/%2d) %s"):format(page, i, txt) local w, h, gen if self.cache[txt] then gen = self.cache[txt] w, h = gen.fw, gen.fh else w, h = self.font:size(txt) - gen = self.font:draw(txt, self.w, color[1], color[2], color[3], true)[1] + gen = self.font:draw(txt, self.w / 3, color[1], color[2], color[3], true)[1] gen.fw, gen.fh = w, h end gen.x, gen.y = x, y @@ -138,7 +137,7 @@ function _M:display() self.clics[i] = {x,y,w+4,h+4} if y + self.font_h * 2 > self.h then - x = x + self.w / 2 + x = x + self.w / 3 y = 0 else y = y + self.font_h diff --git a/game/engines/default/engine/LogDisplay.lua b/game/engines/default/engine/LogDisplay.lua index 6b6e3b50bc..83c31877a0 100644 --- a/game/engines/default/engine/LogDisplay.lua +++ b/game/engines/default/engine/LogDisplay.lua @@ -50,6 +50,10 @@ function _M:enableShadow(v) self.shadow = v end +function _M:enableFading(v) + self.fading = v +end + --- Resize the display area function _M:resize(x, y, w, h) self.display_x, self.display_y = math.floor(x), math.floor(y) @@ -72,9 +76,22 @@ function _M:resize(x, y, w, h) self.scrollbar = Slider.new{size=self.h - 20, max=1, inverse=true} end +--- Returns the full log +function _M:getLog() + local log = {} + for i = 1, #self.log do log[#log+1] = self.log[i].str end + return log +end + +function _M:getLogLast(channel) + if not self.log[1] then return 0 end + return self.log[1].timestamp +end + --- Make a dialog popup with the full log function _M:showLogDialog(title, shadow) - local d = require("engine.dialogs.ShowLog").new(title or "Message Log", shadow, self) + local log = self:getLog() + local d = require_first("mod.dialogs.ShowLog", "engine.dialogs.ShowLog").new(title or "Message Log", shadow, {log=log}) game:registerDialog(d) end @@ -86,7 +103,7 @@ function _M:call(str, ...) str = str:format(...) print("[LOG]", str) local tstr = str:toString() - table.insert(self.log, 1, tstr) + table.insert(self.log, 1, {str=tstr, timestamp = core.game.getTime()}) while #self.log > self.max_log do local old = table.remove(self.log) self.cache[old] = nil @@ -109,7 +126,7 @@ function _M:getLines(number) if from > #self.log then from = #self.log end local lines = { } for i = from, 1, -1 do - lines[#lines+1] = tostring(self.log[i]) + lines[#lines+1] = tostring(self.log[i].str) end return lines end @@ -125,7 +142,7 @@ function _M:display() local old_style = self.font:getStyle() for z = 1 + self.scroll, #self.log do local stop = false - local tstr = self.log[z] + local tstr = self.log[z].str local gen if self.cache[tstr] then gen = self.cache[tstr] @@ -134,7 +151,7 @@ function _M:display() self.cache[tstr] = gen end for i = #gen, 1, -1 do - self.dlist[#self.dlist+1] = gen[i] + self.dlist[#self.dlist+1] = {item=gen[i], date=self.log[z].timestamp} h = h + self.fh if h > self.h - self.fh then stop=true break end end @@ -146,16 +163,29 @@ end function _M:toScreen() self:display() + if self.bg_texture then self.bg_texture:toScreenFull(self.display_x, self.display_y, self.w, self.h, self.bg_texture_w, self.bg_texture_h) end + + local now = core.game.getTime() + local h = self.display_y + self.h - self.fh for i = 1, #self.dlist do - local item = self.dlist[i] - if self.shadow then item._tex:toScreenFull(self.display_x+2, h+2, self.fw, self.fh, item._tex_w, item._tex_h, 0,0,0, self.shadow) end - item._tex:toScreenFull(self.display_x, h, self.fw, self.fh, item._tex_w, item._tex_h) + local item = self.dlist[i].item + + local fade = 1 + if self.fading then + fade = now - self.dlist[i].date + if fade < self.fading * 1000 then fade = 1 + elseif fade < self.fading * 2000 then fade = (self.fading * 2000 - fade) / (self.fading * 1000) + else fade = 0 end + end + + if self.shadow then item._tex:toScreenFull(self.display_x+2, h+2, self.fw, self.fh, item._tex_w, item._tex_h, 0,0,0, self.shadow * fade) end + item._tex:toScreenFull(self.display_x, h, self.fw, self.fh, item._tex_w, item._tex_h, 1, 1, 1, fade) h = h - self.fh end - if true then + if not self.fading then self.scrollbar.pos = self.scroll self.scrollbar.max = self.max - self.max_display + 1 self.scrollbar:display(self.display_x + self.w - self.scrollbar.w, self.display_y) diff --git a/game/engines/default/engine/Map.lua b/game/engines/default/engine/Map.lua index 7d74de5e6f..6c5cea8443 100644 --- a/game/engines/default/engine/Map.lua +++ b/game/engines/default/engine/Map.lua @@ -182,6 +182,7 @@ function _M:save() _map = true, _fovcache = true, surface = true, + finished = true, }) end @@ -287,6 +288,7 @@ end --- Recreate the internal map using new dimensions function _M:recreate() + if not self.finished then return end self:makeCMap() self.changed = true diff --git a/game/engines/default/engine/UserChat.lua b/game/engines/default/engine/UserChat.lua index f16d257729..e2251515dc 100644 --- a/game/engines/default/engine/UserChat.lua +++ b/game/engines/default/engine/UserChat.lua @@ -34,6 +34,7 @@ function _M:init() self.cur_channel = "global" self.channels = {} self.max = 500 + self.do_display_chans = true end --- Hook up in the current running game @@ -63,7 +64,7 @@ end function _M:addMessage(channel, login, name, msg, extra_data, no_change) local log = self.channels[channel].log - table.insert(log, 1, {login=login, name=name, msg=msg, extra_data=extra_data}) + table.insert(log, 1, {login=login, name=name, msg=msg, extra_data=extra_data, timestamp=core.game.getTime()}) while #log > self.max do table.remove(log) end self.changed = true if not no_change and channel ~= self.cur_channel then self.channels[channel].changed = true self.channels_changed = true end @@ -254,15 +255,32 @@ end -- UI Section ---------------------------------------------------------------- ---- Make a dialog popup with the full log -function _M:showLogDialog(title, shadow) +--- Returns the full log +function _M:getLog(channel) + channel = channel or self.cur_channel local log = {} - if self.channels[self.cur_channel] then - for _, i in ipairs(self.channels[self.cur_channel].log) do + if self.channels[channel] then + for _, i in ipairs(self.channels[channel].log) do log[#log+1] = ("<%s> %s"):format(i.name, i.msg) end end - local d = require("engine.dialogs.ShowLog").new(title or "Chat Log", shadow, {log=log}) + return log +end + +function _M:getLogLast(channel) + channel = channel or self.cur_channel + if self.channels[channel] then + if not self.channels[channel].log[1] then return 0 end + return self.channels[channel].log[1].timestamp + else + return 0 + end +end + +--- Make a dialog popup with the full log +function _M:showLogDialog(title, shadow) + local log = self:getLog(self.cur_channel) + local d = require_first("mod.dialogs.ShowLog", "engine.dialogs.ShowLog").new(title or "Chat Log", shadow, {log=log}) game:registerDialog(d) end @@ -342,6 +360,14 @@ function _M:enableShadow(v) self.shadow = v end +function _M:enableFading(v) + self.fading = v +end + +function _M:enableDisplayChans(v) + self.do_display_chans = v +end + function _M:onMouse(fct) self.on_mouse = fct end @@ -386,9 +412,9 @@ function _M:display() for i = #gen, 1, -1 do gen[i].login = log[z].login gen[i].extra_data = log[z].extra_data - self.dlist[#self.dlist+1] = gen[i] + self.dlist[#self.dlist+1] = {item=gen[i], date=log[z].timestamp} h = h + self.fh - if h > self.h - self.fh - self.fh then stop=true break end + if h > self.h - self.fh - (self.do_display_chans and self.fh or 0) then stop=true break end end if stop then break end end @@ -400,30 +426,42 @@ function _M:toScreen() self:display() if self.bg_texture then self.bg_texture:toScreenFull(self.display_x, self.display_y, self.w, self.h, self.bg_texture_w, self.bg_texture_h) end local h = self.display_y + self.h - self.fh + local now = core.game.getTime() for i = 1, #self.dlist do - local item = self.dlist[i] + local item = self.dlist[i].item + + local fade = 1 + if self.fading then + fade = now - self.dlist[i].date + if fade < self.fading * 1000 then fade = 1 + elseif fade < self.fading * 2000 then fade = (self.fading * 2000 - fade) / (self.fading * 1000) + else fade = 0 end + end + item.dh = h - if self.shadow then item._tex:toScreenFull(self.display_x+2, h+2, item.w, item.h, item._tex_w, item._tex_h, 0,0,0, self.shadow) end - item._tex:toScreenFull(self.display_x, h, item.w, item.h, item._tex_w, item._tex_h) + if self.shadow then item._tex:toScreenFull(self.display_x+2, h+2, item.w, item.h, item._tex_w, item._tex_h, 0,0,0, self.shadow * fade) end + item._tex:toScreenFull(self.display_x, h, item.w, item.h, item._tex_w, item._tex_h, 1, 1, 1, fade) h = h - self.fh end - local w = 0 - for i = 1, #self.display_chans do - local item = self.display_chans[i] - local f = item.sel and self.frame_sel or self.frame - f.w = item.w - - Base:drawFrame(f, self.display_x + w, self.display_y) - if self.channels[item.name].changed then - local glow = (1+math.sin(core.game.getTime() / 500)) / 2 * 100 + 120 - Base:drawFrame(f, self.display_x + w, self.display_y, 139/255, 210/255, 77/255, glow / 255) + if self.do_display_chans then + local w = 0 + for i = 1, #self.display_chans do + local item = self.display_chans[i] + local f = item.sel and self.frame_sel or self.frame + f.w = item.w + + Base:drawFrame(f, self.display_x + w, self.display_y) + if self.channels[item.name].changed then + local glow = (1+math.sin(core.game.getTime() / 500)) / 2 * 100 + 120 + Base:drawFrame(f, self.display_x + w, self.display_y, 139/255, 210/255, 77/255, glow / 255) + end + item._tex:toScreenFull(self.display_x + w, self.display_y, item.w, item.h, item._tex_w, item._tex_h) + w = w + item.w + 4 end - item._tex:toScreenFull(self.display_x + w, self.display_y, item.w, item.h, item._tex_w, item._tex_h) - w = w + item.w + 4 end - if true then + if not self.fading then self.scrollbar.pos = self.scroll self.scrollbar.max = self.max - self.max_display + 1 self.scrollbar:display(self.display_x + self.w - self.scrollbar.w, self.display_y) diff --git a/game/engines/default/engine/interface/GameTargeting.lua b/game/engines/default/engine/interface/GameTargeting.lua index b9661a75ae..8748664d1d 100644 --- a/game/engines/default/engine/interface/GameTargeting.lua +++ b/game/engines/default/engine/interface/GameTargeting.lua @@ -195,6 +195,8 @@ end --- Handle mouse event for targeting -- @return true if the event was handled function _M:targetMouse(button, mx, my, xrel, yrel, event) + if not self.level then return end + -- Move tooltip self.tooltip_x, self.tooltip_y = mx, my local tmx, tmy = self.level.map:getMouseTile(mx, my) diff --git a/game/engines/default/engine/interface/PlayerMouse.lua b/game/engines/default/engine/interface/PlayerMouse.lua index 75d906890f..426519d9ab 100644 --- a/game/engines/default/engine/interface/PlayerMouse.lua +++ b/game/engines/default/engine/interface/PlayerMouse.lua @@ -120,6 +120,7 @@ end -- @param key the Key object to which to pass the event if not treated, this should be your game default key handler probably -- @param allow_move true if this will allow player movement (you should use it to check that you are not in targetting mode) function _M:mouseHandleDefault(key, allow_move, button, mx, my, xrel, yrel, event) + if not game.level then return end local tmx, tmy = game.level.map:getMouseTile(mx, my) -- Move diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 5e232ccf6e..f517351535 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -81,7 +81,7 @@ function _M:init() end function _M:run() - local size, size_mono, font, font_mono + local size, size_mono, font, font_mono, font_mono_h, font_h local flysize = ({normal=14, small=12, big=16})[config.settings.tome.fonts.size] if config.settings.tome.fonts.type == "fantasy" then size = ({normal=16, small=14, big=18})[config.settings.tome.fonts.size] @@ -94,16 +94,27 @@ function _M:run() font = "/data/font/Vera.ttf" font_mono = "/data/font/VeraMono.ttf" end + local f = core.display.newFont(font, size) + font_h = f:lineSkip() + f = core.display.newFont(font_mono, size_mono) + font_mono_h = f:lineSkip() self.delayed_log_damage = {} self.calendar = Calendar.new("/data/calendar_allied.lua", "Today is the %s %s of the %s year of the Age of Ascendancy of Maj'Eyal.\nThe time is %02d:%02d.", 122, 167, 11) - self.player_display = PlayerDisplay.new(0, 230, 200, self.h * 0.8 - 230, {30,30,0}, font_mono, size_mono) - self.flash = LogFlasher.new(0, 0, self.w, 20, nil, font, size, {255,255,255}, {0,0,0}) - self.logdisplay = LogDisplay.new(0, self.h * 0.8 + 7, self.w * 0.5 - 46, self.h * 0.2 - 7, nil, font, size, {255,255,255}, "/data/gfx/ui/message-log.png") + self.player_display = PlayerDisplay.new(0, 200, 200, self.h - 200, {30,30,0}, font_mono, size_mono) +-- self.flash = LogFlasher.new(0, 0, self.w, 20, nil, font, size, {255,255,255}, {0,0,0}) + self.map_h_stop = self.h - font_mono_h * 4 + self.logdisplay = LogDisplay.new(216, self.map_h_stop - font_h * 5 -16, (self.w - 216) / 2, font_h * 5, nil, font, size, nil, nil) self.logdisplay:enableShadow(0.6) - profile.chat:resize(0, self.h * 0.8 + 7, self.w * 0.5 - 46, self.h * 0.2 - 7, font, size, {255,255,255}, "/data/gfx/ui/message-log.png") - self.hotkeys_display = HotkeysDisplay.new(nil, self.w * 0.5 + 46, self.h * 0.8 + 7, self.w * 0.5 - 46, self.h * 0.2 - 7, "/data/gfx/ui/talents-list.png", font_mono, size_mono) + self.logdisplay:enableFading(2) + + profile.chat:resize(216 + (self.w - 216) / 2, self.map_h_stop - font_h * 5 -16, (self.w - 216) / 2, font_h * 5, font, size, nil, nil) + profile.chat:enableShadow(0.6) + profile.chat:enableFading(6) + profile.chat:enableDisplayChans(false) + + self.hotkeys_display = HotkeysDisplay.new(nil, 216, self.h - font_mono_h * 4, self.w - 216, font_mono_h * 4, "/data/gfx/ui/talents-list.png", font_mono, size_mono) self.hotkeys_display:enableShadow(0.6) self.npcs_display = ActorsSeenDisplay.new(nil, self.w * 0.5 + 46, self.h * 0.8 + 7, self.w * 0.5 - 46, self.h * 0.2 - 7, "/data/gfx/ui/talents-list.png", font_mono, size_mono) self.tooltip = Tooltip.new(font_mono, size, {255,255,255}, {30,30,30,230}) @@ -116,34 +127,22 @@ function _M:run() self.nicer_tiles = NicerTiles.new() self:createSeparators() - self.log = function(style, ...) if type(style) == "number" then self.logdisplay(...) self.flash(style, ...) else self.logdisplay(style, ...) self.flash(self.flash.NEUTRAL, style, ...) end end + self.log = function(style, ...) if type(style) == "number" then self.logdisplay(...) else self.logdisplay(style, ...) end end self.logChat = function(style, ...) - if not config.settings.tome.chat_log then return end + if true or not config.settings.tome.chat_log then return end if type(style) == "number" then local old = self.logdisplay.changed - self.logdisplay(...) self.flash(style, ...) else self.logdisplay(style, ...) self.flash(self.flash.NEUTRAL, style, ...) end + self.logdisplay(...) else self.logdisplay(style, ...) end if self.show_userchat then self.logdisplay.changed = old end end self.logSeen = function(e, style, ...) if e and e.x and e.y and self.level.map.seens(e.x, e.y) then self.log(style, ...) end end self.logPlayer = function(e, style, ...) if e == self.player or e == self.party then self.log(style, ...) end end - self.log(self.flash.GOOD, "Welcome to #00FF00#Tales of Maj'Eyal!") +-- self.log(self.flash.GOOD, "Welcome to #00FF00#Tales of Maj'Eyal!") -- List of stuff to do on tick end self.on_tick_end = {} - -- Setup inputs - self:setupCommands() - self:setupMouse() - - -- Starting from here we create a new game - if not self.player then self:newGame() end - - self.hotkeys_display.actor = self.player - self.npcs_display.actor = self.player - - self:initTargeting() - -- Ok everything is good to go, activate the game in the engine! self:setCurrent() @@ -153,9 +152,21 @@ function _M:run() -- Start time self.real_starttime = os.time() - if self.level then self:setupDisplayMode(false, "postinit") end + self:setupDisplayMode(false, "postinit") if self.level and self.level.data.day_night then self.state:dayNightCycle() end if self.level and self.player then self.calendar = Calendar.new("/data/calendar_"..(self.player.calendar or "allied")..".lua", "Today is the %s %s of the %s year of the Age of Ascendancy of Maj'Eyal.\nThe time is %02d:%02d.", 122, 167, 11) end + + -- Setup inputs + self:setupCommands() + self:setupMouse() + + -- Starting from here we create a new game + if not self.player then self:newGame() end + + self:initTargeting() + + self.hotkeys_display.actor = self.player + self.npcs_display.actor = self.player end --- Checks if the current character is "tainted" by cheating @@ -315,6 +326,7 @@ function _M:loaded() Zone.post_filter = function(...) return self.state:entityFilterPost(...) end Map:setViewerActor(self.player) self:setupDisplayMode(false, "init") + self:setupDisplayMode(false, "postinit") if self.player then self.player.changed = true end self.key = engine.KeyBind.new() @@ -334,6 +346,14 @@ function _M:setupDisplayMode(reboot, mode) util.showMainMenu(false, nil, nil, self.__mod_info.short_name, self.save_name, false) end + local do_bg = true + + Map:resetTiles() + end + + if not mode or mode == "postinit" then + local gfx = config.settings.tome.gfx + -- Show a count for stacked objects Map.object_stack_count = true @@ -345,20 +365,14 @@ function _M:setupDisplayMode(reboot, mode) print("[DISPLAY MODE] Tileset: "..gfx.tiles) print("[DISPLAY MODE] Size: "..gfx.size) - local do_bg = true - if gfx.size == "64x64" then - Map:setViewPort(216, 36, self.w - 216, math.floor(self.h * 0.80) - 36, 64, 64, nil, 44, do_bg) - Map:resetTiles() + Map:setViewPort(216, 0, self.w - 216, (self.map_h_stop or 80) - 16, 64, 64, nil, 44, do_bg) elseif gfx.size == "48x48" then - Map:setViewPort(216, 36, self.w - 216, math.floor(self.h * 0.80) - 36, 48, 48, nil, 36, do_bg) - Map:resetTiles() + Map:setViewPort(216, 0, self.w - 216, (self.map_h_stop or 80) - 16, 48, 48, nil, 36, do_bg) elseif gfx.size == "32x32" then - Map:setViewPort(216, 36, self.w - 216, math.floor(self.h * 0.80) - 36, 32, 32, nil, 22, do_bg) - Map:resetTiles() + Map:setViewPort(216, 0, self.w - 216, (self.map_h_stop or 80) - 16, 32, 32, nil, 22, do_bg) elseif gfx.size == "16x16" then - Map:setViewPort(216, 36, self.w - 216, math.floor(self.h * 0.80) - 36, 16, 16, "/data/font/FSEX300.ttf", 16, do_bg) - Map:resetTiles() + Map:setViewPort(216, 0, self.w - 216, (self.map_h_stop or 80) - 16, 16, 16, "/data/font/FSEX300.ttf", 16, do_bg) end Map.tiles.use_images = true @@ -367,19 +381,19 @@ function _M:setupDisplayMode(reboot, mode) if gfx.tiles == "shockbolt" then Map.tiles.nicer_tiles = true end if gfx.tiles == "oldrpg" then Map.tiles.nicer_tiles = true end - -- Create the framebuffer - self.fbo = core.display.newFBO(Map.viewport.width, Map.viewport.height) - if self.fbo then self.fbo_shader = Shader.new("main_fbo") if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end end - if self.player then self.player:updateMainShader() end - end - - if not mode or mode == "postinit" then if self.level then - self.level.map:recreate() + if self.level.map.finished then + self.level.map:recreate() + self.level.map:moveViewSurround(self.player.x, self.player.y, 8, 8) + end self:initTargeting() - self.level.map:moveViewSurround(self.player.x, self.player.y, 8, 8) end self:setupMiniMap() + + -- Create the framebuffer + self.fbo = core.display.newFBO(Map.viewport.width, Map.viewport.height) + if self.fbo then self.fbo_shader = Shader.new("main_fbo") if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end end + if self.player then self.player:updateMainShader() end end end @@ -389,7 +403,7 @@ end function _M:setupMiniMap() - if self.level and self.level.map then self.level.map._map:setupMiniMapGridSize(4) end + if self.level and self.level.map and self.level.map.finished then self.level.map._map:setupMiniMapGridSize(4) end end function _M:save() @@ -736,13 +750,13 @@ end function _M:displayDelayedLogDamage() for src, tgts in pairs(self.delayed_log_damage) do for target, dams in pairs(tgts) do - local flash = game.flash.NEUTRAL - if target == game.player then flash = game.flash.BAD end - if src == game.player then flash = game.flash.GOOD end +-- local flash = game.flash.NEUTRAL +-- if target == game.player then flash = game.flash.BAD end +-- if src == game.player then flash = game.flash.GOOD end if #dams.descs > 1 then - game.logSeen(target, flash, "%s hits %s for %s damage (total %0.2f).", src.name:capitalize(), target.name, table.concat(dams.descs, ", "), dams.total) + game.logSeen(target, "%s hits %s for %s damage (total %0.2f).", src.name:capitalize(), target.name, table.concat(dams.descs, ", "), dams.total) else - game.logSeen(target, flash, "%s hits %s for %s damage.", src.name:capitalize(), target.name, table.concat(dams.descs, ", ")) + game.logSeen(target, "%s hits %s for %s damage.", src.name:capitalize(), target.name, table.concat(dams.descs, ", ")) end local rsrc = src.resolveSource and src:resolveSource() or src @@ -852,9 +866,9 @@ function _M:display(nb_keyframes) map:displayEmotes(nb_keyframe or 1) -- Minimap display - self.minimap_bg:toScreen(0, 35, 200, 200) + self.minimap_bg:toScreen(0, 0, 200, 200) self.minimap_scroll_x, self.minimap_scroll_y = util.bound(self.player.x - 25, 0, map.w - 50), util.bound(self.player.y - 25, 0, map.h - 50) - map:minimapDisplay(0, 35, self.minimap_scroll_x, self.minimap_scroll_y, 50, 50, 1) + map:minimapDisplay(0, 0, self.minimap_scroll_x, self.minimap_scroll_y, 50, 50, 1) -- Mouse gestures self.gestures:update() @@ -862,10 +876,12 @@ function _M:display(nb_keyframes) end -- We display the player's interface - self.flash:toScreen(nb_keyframe) - if self.show_userchat then profile.chat:toScreen() - else self.logdisplay:toScreen() - end +-- self.flash:toScreen(nb_keyframe) +-- if self.show_userchat then profile.chat:toScreen() +-- else self.logdisplay:toScreen() +-- end + profile.chat:toScreen() + self.logdisplay:toScreen() self.player_display:toScreen(nb_keyframes) if self.show_npc_list then @@ -901,7 +917,7 @@ function _M:onUnregisterDialog(d) -- Clean up tooltip self.tooltip_x, self.tooltip_y = nil, nil self.tooltip2_x, self.tooltip2_y = nil, nil - if self.player then self.player:updateMainShader() end + if self.player then self.player:updateMainShader() self.player.changed = true end end function _M:setupCommands() @@ -955,7 +971,12 @@ function _M:setupCommands() self.key.any_key = function(sym) -- Control resets the tooltip - if sym == self.key._LCTRL or sym == self.key._RCTRL then self.tooltip.old_tmx = nil end + if sym == self.key._LCTRL or sym == self.key._RCTRL then + self.player.changed = true + self.tooltip.old_tmx = nil + elseif sym == self.key._LSHIFT or sym == self.key._RSHIFT then + self.player.changed = true + end end self.key:addBinds { @@ -1129,11 +1150,7 @@ function _M:setupCommands() end, SHOW_MESSAGE_LOG = function() - if not self.show_userchat then - self.logdisplay:showLogDialog(nil, 0.6) - else - profile.chat:showLogDialog(nil, 0.6) - end + self:registerDialog(require("mod.dialogs.ShowChatLog").new("Message Log", 0.6, self.logdisplay, profile.chat)) end, -- Show time @@ -1193,8 +1210,8 @@ function _M:setupCommands() end, LOOK_AROUND = function() - self.flash:empty(true) - self.flash(self.flash.GOOD, "Looking around... (direction keys to select interesting things, shift+direction keys to move freely)") +-- self.flash:empty(true) + self.log("Looking around... (direction keys to select interesting things, shift+direction keys to move freely)") local co = coroutine.create(function() self.player:getTarget{type="hit", no_restrict=true, range=2000} end) local ok, err = coroutine.resume(co) if not ok and err then print(debug.traceback(co)) error(err) end @@ -1244,6 +1261,7 @@ function _M:setupMouse(reset) self.player:mouseHandleDefault(self.key, self.key == self.normal_key, button, mx, my, xrel, yrel, event) end) -- Scroll message log +--[[ self.mouse:registerZone(self.logdisplay.display_x, self.logdisplay.display_y, self.w, self.h, function(button, mx, my, xrel, yrel, bx, by, event) if self.show_userchat then profile.chat.mouse:delegate(button, mx, my, xrel, yrel, bx, by, event) @@ -1253,6 +1271,7 @@ function _M:setupMouse(reset) if button == "left" then self.logdisplay:showLogDialog(nil, 0.6) end end end) +]] -- 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) if event == "button" and button == "left" and self.zone and self.zone.wilderness then return end @@ -1277,11 +1296,11 @@ function _M:setupMouse(reset) if button == "left" then self:clickIcon(bx, by) end end) -- Tooltip over the player pane - self.mouse:registerZone(self.player_display.display_x, self.player_display.display_y, self.player_display.w, self.player_display.h, function(button, mx, my, xrel, yrel, bx, by, event) + self.mouse:registerZone(self.player_display.display_x, self.player_display.display_y, self.player_display.w, self.player_display.h - self.icons.h, function(button, mx, my, xrel, yrel, bx, by, event) self.player_display.mouse:delegate(button, mx, my, xrel, yrel, bx, by, event) end) -- Move using the minimap - self.mouse:registerZone(0, 35, 200, 200, function(button, mx, my, xrel, yrel, bx, by, event) + self.mouse:registerZone(0, 0, 200, 200, function(button, mx, my, xrel, yrel, bx, by, event) if button == "left" and not xrel and not yrel and event == "button" then local tmx, tmy = math.floor(bx / 4), math.floor(by / 4) self.player:mouseMove(tmx + self.minimap_scroll_x, tmy + self.minimap_scroll_y) @@ -1505,6 +1524,7 @@ local _sep_vert = {core.display.loadImage("/data/gfx/ui/separator-vert.png")} _s local _sep_top = {core.display.loadImage("/data/gfx/ui/separator-top.png")} _sep_top.tex = {_sep_top[1]:glTexture()} local _sep_bottom = {core.display.loadImage("/data/gfx/ui/separator-bottom.png")} _sep_bottom.tex = {_sep_bottom[1]:glTexture()} local _sep_bottoml = {core.display.loadImage("/data/gfx/ui/separator-bottom_line_end.png")} _sep_bottoml.tex = {_sep_bottoml[1]:glTexture()} +local _sep_left = {core.display.loadImage("/data/gfx/ui/separator-left.png")} _sep_left.tex = {_sep_left[1]:glTexture()} local _sep_leftl = {core.display.loadImage("/data/gfx/ui/separator-left_line_end.png")} _sep_leftl.tex = {_sep_leftl[1]:glTexture()} local _sep_rightl = {core.display.loadImage("/data/gfx/ui/separator-right_line_end.png")} _sep_rightl.tex = {_sep_rightl[1]:glTexture()} @@ -1521,116 +1541,107 @@ function _M:displayUI() local middle = self.w * 0.5 local bottom = self.h * 0.8 local bottom_h = self.h * 0.2 - local icon_x = middle - (_talents_icon_w*2) / 2 - local icon_x2 = middle + (_talents_icon_w*2) / 2 - local mid_min = icon_x - (_sep_vert[2]) - local mid_max = icon_x2 + local icon_x = 0 + local icon_y = self.h - (_talents_icon_h * 1) + local glow = (1+math.sin(core.game.getTime() / 500)) / 2 * 100 + 77 -- Icons - local x, y = icon_x, bottom + _sep_horiz[3] / 2 - _talents_icon:toScreenFull(x + _talents_icon_w, y, _talents_icon_w, _talents_icon_h, _talents_icon_w, _talents_icon_h) - if not self.show_npc_list then _sel_icon:toScreenFull(x + _talents_icon_w, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end - y = y + _talents_icon_h - _actors_icon:toScreenFull(x + _talents_icon_w, y, _actors_icon_w, _actors_icon_h, _actors_icon_w, _actors_icon_h) - if self.show_npc_list then _sel_icon:toScreenFull(x + _talents_icon_w, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end - y = y + _talents_icon_h - - local glow = (1+math.sin(core.game.getTime() / 500)) / 2 * 100 + 77 - local x, y = icon_x, bottom + _sep_horiz[3] / 2 - if self.logdisplay.changed then core.display.drawQuad(x, y, _sel_icon_w, _sel_icon_h, 139, 210, 77, glow) end + local x, y = icon_x, icon_y + _talents_icon:toScreenFull(x, y, _talents_icon_w, _talents_icon_h, _talents_icon_w, _talents_icon_h) + if not self.show_npc_list then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end + x = x + _talents_icon_w + _actors_icon:toScreenFull(x, y, _actors_icon_w, _actors_icon_h, _actors_icon_w, _actors_icon_h) + if self.show_npc_list then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end + x = x + _talents_icon_w + +-- if self.logdisplay.changed then core.display.drawQuad(x, y, _sel_icon_w, _sel_icon_h, 139, 210, 77, glow) end +-- _log_icon:toScreenFull(x, y, _log_icon_w, _log_icon_h, _log_icon_w, _log_icon_h) +-- if not self.show_userchat then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end +-- x = x + _talents_icon_w + +-- if profile.chat.changed then core.display.drawQuad(x, y, _sel_icon_w, _sel_icon_h, 139, 210, 77, glow) end +-- _chat_icon:toScreenFull(x, y, _chat_icon_w, _chat_icon_h, _chat_icon_w, _chat_icon_h) +-- if self.show_userchat then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end + +-- x = 0 +-- y = y + _chat_icon_h +-- x = x + _talents_icon_w + + _inventory_icon:toScreenFull(x, y, _inventory_icon_w, _inventory_icon_h, _inventory_icon_w, _inventory_icon_h) + x = x + _talents_icon_w + _charsheet_icon:toScreenFull(x, y, _charsheet_icon_w, _charsheet_icon_h, _charsheet_icon_w, _charsheet_icon_h) + x = x + _talents_icon_w + _main_menu_icon:toScreenFull(x, y, _main_menu_icon_w, _main_menu_icon_h, _main_menu_icon_w, _main_menu_icon_h) + x = x + _talents_icon_w _log_icon:toScreenFull(x, y, _log_icon_w, _log_icon_h, _log_icon_w, _log_icon_h) - if not self.show_userchat then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end - y = y + _log_icon_h - if profile.chat.changed then core.display.drawQuad(x, y, _sel_icon_w, _sel_icon_h, 139, 210, 77, glow) end - _chat_icon:toScreenFull(x, y, _chat_icon_w, _chat_icon_h, _chat_icon_w, _chat_icon_h) - if self.show_userchat then _sel_icon:toScreenFull(x, y, _sel_icon_w, _sel_icon_h, _sel_icon_w, _sel_icon_h) end - y = y + _chat_icon_h - - _inventory_icon:toScreenFull(x + _talents_icon_w/2, y, _inventory_icon_w, _inventory_icon_h, _inventory_icon_w, _inventory_icon_h) y = y + _inventory_icon_h - _charsheet_icon:toScreenFull(x + _talents_icon_w/2, y, _charsheet_icon_w, _charsheet_icon_h, _charsheet_icon_w, _charsheet_icon_h) y = y + _charsheet_icon_h - _main_menu_icon:toScreenFull(x + _talents_icon_w/2, y, _main_menu_icon_w, _main_menu_icon_h, _main_menu_icon_w, _main_menu_icon_h) y = y + _main_menu_icon_h -- Separators - _sep_horiz.tex[1]:toScreenFull(0, 20, self.w, _sep_horiz[3], _sep_horiz.tex[2], _sep_horiz.tex[3]) - _sep_horiz.tex[1]:toScreenFull(0, bottom - _sep_horiz[3] / 2, self.w, _sep_horiz[3], _sep_horiz.tex[2], _sep_horiz.tex[3]) +-- _sep_horiz.tex[1]:toScreenFull(0, 20, self.w, _sep_horiz[3], _sep_horiz.tex[2], _sep_horiz.tex[3]) + _sep_horiz.tex[1]:toScreenFull(216, self.map_h_stop - _sep_horiz[3], self.w - 216, _sep_horiz[3], _sep_horiz.tex[2], _sep_horiz.tex[3]) - _sep_vert.tex[1]:toScreenFull(mid_min, bottom, _sep_vert[2], bottom_h, _sep_vert.tex[2], _sep_vert.tex[3]) - _sep_vert.tex[1]:toScreenFull(mid_max, bottom, _sep_vert[2], bottom_h, _sep_vert.tex[2], _sep_vert.tex[3]) +-- _sep_vert.tex[1]:toScreenFull(mid_min, bottom, _sep_vert[2], bottom_h, _sep_vert.tex[2], _sep_vert.tex[3]) +-- _sep_vert.tex[1]:toScreenFull(mid_max, bottom, _sep_vert[2], bottom_h, _sep_vert.tex[2], _sep_vert.tex[3]) - _sep_vert.tex[1]:toScreenFull(200, 20, _sep_vert[2], bottom - 20, _sep_vert.tex[2], _sep_vert.tex[3]) + _sep_vert.tex[1]:toScreenFull(200, 0, _sep_vert[2], self.h, _sep_vert.tex[2], _sep_vert.tex[3]) -- Ornaments - _sep_top.tex[1]:toScreenFull(mid_min - (-_sep_vert[2] + _sep_top[2]) / 2, bottom - 14, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) - _sep_top.tex[1]:toScreenFull(mid_max - (-_sep_vert[2] + _sep_top[2]) / 2, bottom - 14, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) - _sep_bottoml.tex[1]:toScreenFull(mid_min - (-_sep_vert[2] + _sep_bottoml[2]) / 2, self.h - _sep_bottoml[3], _sep_bottoml[2], _sep_bottoml[3], _sep_bottoml.tex[2], _sep_bottoml.tex[3]) - _sep_bottoml.tex[1]:toScreenFull(mid_max - (-_sep_vert[2] + _sep_bottoml[2]) / 2, self.h - _sep_bottoml[3], _sep_bottoml[2], _sep_bottoml[3], _sep_bottoml.tex[2], _sep_bottoml.tex[3]) +-- _sep_top.tex[1]:toScreenFull(mid_min - (-_sep_vert[2] + _sep_top[2]) / 2, bottom - 14, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) +-- _sep_top.tex[1]:toScreenFull(mid_max - (-_sep_vert[2] + _sep_top[2]) / 2, bottom - 14, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) +-- _sep_bottoml.tex[1]:toScreenFull(mid_min - (-_sep_vert[2] + _sep_bottoml[2]) / 2, self.h - _sep_bottoml[3], _sep_bottoml[2], _sep_bottoml[3], _sep_bottoml.tex[2], _sep_bottoml.tex[3]) +-- _sep_bottoml.tex[1]:toScreenFull(mid_max - (-_sep_vert[2] + _sep_bottoml[2]) / 2, self.h - _sep_bottoml[3], _sep_bottoml[2], _sep_bottoml[3], _sep_bottoml.tex[2], _sep_bottoml.tex[3]) - _sep_leftl.tex[1]:toScreenFull(0, 20 - _sep_leftl[3] / 2 + 7, _sep_leftl[2], _sep_leftl[3], _sep_leftl.tex[2], _sep_leftl.tex[3]) - _sep_leftl.tex[1]:toScreenFull(0, bottom - _sep_leftl[3] / 2, _sep_leftl[2], _sep_leftl[3], _sep_leftl.tex[2], _sep_leftl.tex[3]) +-- _sep_leftl.tex[1]:toScreenFull(0, 20 - _sep_leftl[3] / 2 + 7, _sep_leftl[2], _sep_leftl[3], _sep_leftl.tex[2], _sep_leftl.tex[3]) + _sep_left.tex[1]:toScreenFull(200 - 7, self.map_h_stop - 7 - _sep_left[3] / 2, _sep_left[2], _sep_left[3], _sep_left.tex[2], _sep_left.tex[3]) - _sep_rightl.tex[1]:toScreenFull(self.w - _sep_rightl[2], 20 - _sep_rightl[3] / 2 + 7, _sep_rightl[2], _sep_rightl[3], _sep_rightl.tex[2], _sep_rightl.tex[3]) - _sep_rightl.tex[1]:toScreenFull(self.w - _sep_rightl[2], bottom - _sep_rightl[3] / 2, _sep_rightl[2], _sep_rightl[3], _sep_rightl.tex[2], _sep_rightl.tex[3]) +-- _sep_rightl.tex[1]:toScreenFull(self.w - _sep_rightl[2], 20 - _sep_rightl[3] / 2 + 7, _sep_rightl[2], _sep_rightl[3], _sep_rightl.tex[2], _sep_rightl.tex[3]) + _sep_rightl.tex[1]:toScreenFull(self.w - _sep_rightl[2], self.map_h_stop - _sep_left[3] / 2, _sep_rightl[2], _sep_rightl[3], _sep_rightl.tex[2], _sep_rightl.tex[3]) - _sep_top.tex[1]:toScreenFull(200 - (_sep_top[2] - _sep_vert[2]) / 2, 20 - 7, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) - _sep_bottom.tex[1]:toScreenFull(200 - (_sep_bottom[2] - _sep_vert[2]) / 2, bottom - 25, _sep_bottom[2], _sep_bottom[3], _sep_bottom.tex[2], _sep_bottom.tex[3]) + _sep_top.tex[1]:toScreenFull(200 - (_sep_top[2] - _sep_vert[2]) / 2, - 7, _sep_top[2], _sep_top[3], _sep_top.tex[2], _sep_top.tex[3]) +-- _sep_bottom.tex[1]:toScreenFull(200 - (_sep_bottom[2] - _sep_vert[2]) / 2, bottom - 25, _sep_bottom[2], _sep_bottom[3], _sep_bottom.tex[2], _sep_bottom.tex[3]) end function _M:createSeparators() - local middle = self.w * 0.5 - local bottom = self.h * 0.8 - local bottom_h = self.h * 0.2 + local icon_x = 0 + local icon_y = self.h - (_talents_icon_h * 1) self.icons = { - display_x = middle - (_talents_icon_w*2) / 2, - display_y = bottom + _sep_horiz[3] / 2, - w = _talents_icon_w*2, - h = 5*_talents_icon_h + display_x = icon_x, + display_y = icon_y, + w = 200, + h = self.h - icon_y, } end function _M:clickIcon(bx, by) - if by < _talents_icon_h then - if bx >= _talents_icon_w then - self.show_npc_list = false - self.player.changed = true - else - self.show_userchat = false - self.logdisplay.changed = true - end - elseif by < 2*_talents_icon_h then - if bx >= _talents_icon_w then - self.show_npc_list = true - self.player.changed = true - else - self.show_userchat = true - end - elseif by < 3*_talents_icon_h then + if bx < _talents_icon_w then + self.show_npc_list = false + self.player.changed = true + elseif bx < 2*_talents_icon_w then + self.show_npc_list = true + self.player.changed = true + elseif bx < 3*_talents_icon_w then self.key:triggerVirtual("SHOW_INVENTORY") - elseif by < 4*_talents_icon_h then + elseif bx < 4*_talents_icon_w then self.key:triggerVirtual("SHOW_CHARACTER_SHEET") - elseif by < 5*_talents_icon_h then + elseif bx < 5*_talents_icon_w then self.key:triggerVirtual("EXIT") + elseif bx < 6*_talents_icon_w then + self.key:triggerVirtual("SHOW_MESSAGE_LOG") end end function _M:mouseIcon(bx, by) - if by < _talents_icon_h then - if bx >= _talents_icon_w then - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display talents\nToggle with [tab]") - else - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display game log\nToggle with [ctrl+space]") - end - elseif by < 2*_talents_icon_h then - if bx >= _talents_icon_w then - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display creatures\nToggle with [tab]") - else - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display community chat\nToggle with [ctrl+space]") - end - elseif by < 3*_talents_icon_h then - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Inventory") - elseif by < 4*_talents_icon_h then - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Character Sheet") - elseif by < 5*_talents_icon_h then - self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Main menu") + if bx < _talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display talents\nToggle with #{bold}##GOLD#[tab]#LAST##{normal}#") + elseif bx < 2*_talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Display creatures\nToggle with #{bold}##GOLD#[tab]#LAST##{normal}#") + elseif bx < 3*_talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "#{bold}##GOLD#I#LAST##{normal}#nventory") + elseif bx < 4*_talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "#{bold}##GOLD#C#LAST##{normal}#haracter Sheet") + elseif bx < 5*_talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Main menu (#{bold}##GOLD#Esc#LAST##{normal}#)") + elseif bx < 6*_talents_icon_w then + self.tooltip:displayAtMap(nil, nil, self.w, self.h, "Show message/chat log (#{bold}##GOLD#ctrl+m#LAST##{normal}#)") end end diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index fca6fca929..6899a46f0f 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -219,7 +219,7 @@ function _M:act() self.old_life = self.life -- Clean log flasher - game.flash:empty() +-- game.flash:empty() -- Resting ? Running ? Otherwise pause if not self:restStep() and not self:runStep() and self.player then diff --git a/game/modules/tome/dialogs/ShowChatLog.lua b/game/modules/tome/dialogs/ShowChatLog.lua new file mode 100644 index 0000000000..3f5a7c2d76 --- /dev/null +++ b/game/modules/tome/dialogs/ShowChatLog.lua @@ -0,0 +1,160 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +require "engine.class" +local Dialog = require "engine.ui.Dialog" +local Tab = require "engine.ui.Tab" +local Mouse = require "engine.Mouse" +local Slider = require "engine.ui.Slider" + +module(..., package.seeall, class.inherit(Dialog)) + +function _M:init(title, shadow, log, chat) + local w = math.floor(game.w * 0.9) + local h = math.floor(game.h * 0.9) + Dialog.init(self, title, w, h) + if shadow then self.shadow = shadow end + + self.log, self.chat = log, chat + + local tabs = {} + + local order = {} + local list = {} + for name, data in pairs(chat.channels) do list[#list+1] = name end + table.sort(list, function(a,b) if a == "global" then return 1 elseif b == "global" then return nil else return a < b end end) + order[#order+1] = {timestamp=log:getLogLast(), tab="__log"} + + tabs[#tabs+1] = {top=0, left=0, ui = Tab.new{title="Game Log", fct=function() end, on_change=function() local i = #tabs self:switchTo(tabs[1]) end, default=true}, tab_channel="__log" } + for i, name in ipairs(list) do + local oname = name + local nb_users = 0 + for _, _ in pairs(chat.channels[name].users) do nb_users = nb_users + 1 end + name = name:capitalize().." ("..nb_users..")" + + local ii = i + tabs[#tabs+1] = {top=0, left=(#tabs==0) and 0 or tabs[#tabs].ui, ui = Tab.new{title=name, fct=function() end, on_change=function() local i = ii+1 self:switchTo(tabs[i]) end, default=false}, tab_channel=oname } + order[#order+1] = {timestamp=chat:getLogLast(oname), tab=oname} + end + + self.start_y = tabs[1].ui.h + 5 + + self:loadUI(tabs) + self.tabs = tabs + self:setupUI() + + self.scrollbar = Slider.new{size=self.h - 20, max=1, inverse=true} + + table.sort(order, function(a,b) return a.timestamp > b.timestamp end) + self:switchTo(self.last_tab or "__log") +end + +function _M:generate() + Dialog.generate(self) + + -- Add UI controls + local tabs = self.tabs + self.key:addBinds{ + MOVE_UP = function() self:setScroll(self.scroll - 1) end, + MOVE_DOWN = function() self:setScroll(self.scroll + 1) end, + ACCEPT = "EXIT", + EXIT = function() game:unregisterDialog(self) end, + } + self.key:addCommands{ + _TAB = function() local sel = 1 for i=1, #tabs do if tabs[i].ui.selected then sel = i break end end self:switchTo(tabs[util.boundWrap(sel+1, 1, #tabs)]) end, + _HOME = function() self:setScroll(1) end, + _END = function() self:setScroll(self.max) end, + _PAGEUP = function() self:setScroll(self.scroll - self.max_display) end, + _PAGEDOWN = function() self:setScroll(self.scroll + self.max_display) end, + } +end + +function _M:mouseEvent(button, x, y, xrel, yrel, bx, by, event) + Dialog.mouseEvent(self, button, x, y, xrel, yrel, bx, by, event) + + if button == "wheelup" and event == "button" then self.key:triggerVirtual("MOVE_UP") + elseif button == "wheeldown" and event == "button" then self.key:triggerVirtual("MOVE_DOWN") + end +end + +function _M:loadLog(log) + self.lines = {} + for i = #log, 1, -1 do + self.lines[#self.lines+1] = log[i] + end + + self.max_h = self.ih - self.iy + self.max = #log + self.max_display = math.floor(self.max_h / self.font_h) + + self.scrollbar.max = self.max - self.max_display + 1 + self.scroll = nil + self:setScroll(self.max - self.max_display + 1) +end + +function _M:switchTo(ui) + if type(ui) == "string" then for i, tab in ipairs(self.tabs) do if tab.tab_channel == ui then ui = tab end end end + if type(ui) == "string" then ui = self.tabs[1] end + + for i, ui in ipairs(self.tabs) do ui.ui.selected = false end + ui.ui.selected = true + if ui.tab_channel == "__log" then + self:loadLog(self.log:getLog()) + else + self:loadLog(self.chat:getLog(ui.tab_channel)) + end + -- Set it on the class to persist between invocations + _M.last_tab = ui.tab_channel +end + +function _M:setScroll(i) + local old = self.scroll + self.scroll = util.bound(i, 1, math.max(1, self.max - self.max_display + 1)) + if self.scroll == old then return end + + self.dlist = {} + local nb = 0 + local old_style = self.font:getStyle() + for z = 1 + self.scroll, #self.lines do + local stop = false + local tstr = self.lines[z] + if not tstr then break end + local gen = self.font:draw(tstr, self.iw - 10, 255, 255, 255) + for i = 1, #gen do + self.dlist[#self.dlist+1] = gen[i] + nb = nb + 1 + if nb >= self.max_display then stop = true break end + end + if stop then break end + end + self.font:setStyle(old_style) +end + +function _M:innerDisplay(x, y, nb_keyframes) + local h = y + self.iy + self.start_y + for i = 1, #self.dlist do + local item = self.dlist[i] + if self.shadow then item._tex:toScreenFull(x+2, h+2, item.w, item.h, item._tex_w, item._tex_h, 0,0,0, self.shadow) end + item._tex:toScreenFull(x, h, item.w, item.h, item._tex_w, item._tex_h) + h = h + self.font_h + end + + self.scrollbar.pos = self.scrollbar.max - self.scroll + 1 + self.scrollbar:display(x + self.iw - self.scrollbar.w, y) +end -- GitLab