Chat.lua
7.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 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 Chat = require "engine.dialogs.Chat"
local VariableList = require "engine.ui.VariableList"
local Textzone = require "engine.ui.Textzone"
local Separator = require "engine.ui.Separator"
local ChatPortrait = require "mod.dialogs.elements.ChatPortrait"
local Map = require "engine.Map"
local Entity = require "engine.Entity"
module(..., package.seeall, class.inherit(Chat))
function _M:init(chat, id, width)
self.ui = "chat"
self.force_title = ""
self.force_min_h = 256
Chat.init(self, chat, id, math.max(width, game.w * 0.4))
end
function _M:makeUI()
self.c_desc = Textzone.new{has_box=true, ui="chat", font=self.chat.dialog_text_font, width=self.iw - 30, height=1, auto_height=true, text=self.text, can_focus=false}
self.c_list = VariableList.new{font=self.chat.dialog_answer_font, width=self.iw, max_height=game.h * 0.70 - self.c_desc.h, list=self.list, fct=function(item) self:use(item) end, select=function(item) self:select(item) end}
local npc_frame = ChatPortrait.new{ui="chat", side="right", actor=self:getActorPortraitFull(self.chat.npc_force_display_entity or self.npc.chat_display_entity or self.npc)}
local player_frame = ChatPortrait.new{ui="chat", side="left", actor=self:getActorPortraitFull(self.chat.player_force_display_entity or self.player.chat_display_entity or self.player)}
local uis = {
{hcenter=0, top=-12, ui=self.c_desc},
{right=0, bottom=0, ui=self.c_list},
{left=-player_frame.w+self.frame.ox1-5, top=self.frame.oy1-self.iy, ui=player_frame, ignore_size=true},
{right=-npc_frame.w-self.frame.ox2-5, top=self.frame.oy1-self.iy, ui=npc_frame, ignore_size=true},
}
-- Only for size info
local back = self:getUITexture("ui/portrait_frame_back.png")
self:loadUI(uis)
self:setFocus(self.c_list)
self:setupUI(false, true, function(w, h)
local frameh = -self.frame.oy1 + self.frame.oy2
-- Ensure minimal height
if h + frameh < back.h then h = back.h - frameh end
-- Ensure if it's too big but too small to not have the down deco, to increase it a it
if h + frameh > back.h then
if h + frameh < back.h + 16 then h = back.h - frameh + 16
elseif h + frameh < back.h + 32 then h = back.h - frameh + 32
elseif h + frameh < back.h + 48 then h = back.h - frameh + 48
elseif h + frameh < back.h + 64 then h = back.h - frameh + 64
elseif h + frameh < back.h + 80 then h = back.h - frameh + 80
end
end
self.force_x = game.w / 2 - w / 2
self.force_y = game.h - h - 20
return w, h
end)
npc_frame:adjustHeight(self.h)
player_frame:adjustHeight(self.h)
end
function _M:getActorPortraitFull(actor)
local e = self:getActorPortrait(actor)
if e.image and (e.image:find("talents/") or e.image:find("effects/")) then
e = Entity.new{name=e.name, image=e.image, chat_portrait_background="ui/chat_talents_bg.png", chat_portrait_size=0.75}
end
return e
end
function _M:getActorPortrait(actor)
local actor = actor.replace_display or actor
-- Moddable tiles are already portrait sized
if actor.moddable_tile and Map.tiles.no_moddable_tiles then return actor end
-- No image at all ?
if not actor.image then
-- By any chance are we running a talent ?
if self.player.getCurrentTalent and self.player:getCurrentTalent() then
local t = self.player:getTalentFromId(self.player:getCurrentTalent())
if t then
local image = t.image or "portrait/unknown.png"
if image:find("^talents/") and fs.exists("/data/gfx/shockbolt/"..image:gsub("^talents/", "portrait/")) then
image = image:gsub("^talents/", "portrait/")
end
return Entity.new{name=t.name, image=image, chat_ignore_margins=true}
else
return Entity.new{name=actor.name, image="portrait/unknown.png", chat_ignore_margins=true}
end
else
return Entity.new{name=actor.name, image="portrait/unknown.png", chat_ignore_margins=true}
end
end
-- No need for anything special
if actor.image:find("^portrait/") then return actor end
-- Find the portrait
if actor.isClassName and actor:isClassName("engine.Grid") and (actor.add_mos or actor.add_displays) then
-- First one to have a portrait
for i, mo in ripairs(actor.add_displays or {}) do
if mo.image:find("^terrain/") and fs.exists("/data/gfx/shockbolt/"..mo.image:gsub("^terrain/", "portrait/")) then
return Entity.new{name=actor.name, image=mo.image:gsub("^terrain/", "portrait/")}
end
end
for i, mo in ripairs(actor.add_mos or {}) do
if mo.image:find("^terrain/") and fs.exists("/data/gfx/shockbolt/"..mo.image:gsub("^terrain/", "portrait/")) then
return Entity.new{name=actor.name, image=mo.image:gsub("^terrain/", "portrait/")}
end
end
-- If not, first one
if actor.add_displays then local mo = actor.add_displays[#actor.add_displays]
if mo then return Entity.new{name=actor.name, image=mo.image} end
end
if actor.add_mos then local mo = actor.add_mos[#actor.add_mos]
if mo then return Entity.new{name=actor.name, image=mo.image} end
end
-- If not, the terrain itself (how? we checked for one of add_mos & add_displays but heh)
if actor.image:find("^terrain/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^terrain/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^terrain/", "portrait/")}
end
elseif actor.image == "invis.png" and actor.add_mos and actor.add_mos[1] and actor.add_mos[1].image and actor.add_mos[1].image:find("^npc/") and fs.exists("/data/gfx/shockbolt/"..actor.add_mos[1].image:gsub("^npc/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.add_mos[1].image:gsub("^npc/", "portrait/")}
elseif actor.image:find("^npc/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^npc/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^npc/", "portrait/")}
elseif actor.image:find("^player/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^player/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^player/", "portrait/")}
elseif actor.image:find("^object/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^object/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^object/", "portrait/")}
elseif actor.image:find("^object/artifact/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^object/artifact/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^object/artifact/", "portrait/")}
elseif actor.image:find("^talents/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^talents/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^talents/", "portrait/")}
elseif actor.image:find("^faction/") and fs.exists("/data/gfx/shockbolt/"..actor.image:gsub("^faction/", "portrait/")) then
return Entity.new{name=actor.name, image=actor.image:gsub("^faction/", "portrait/")}
end
-- Last resort, use it as it is
return actor
end