summaryrefslogtreecommitdiff
path: root/lobby.lua
blob: 0cfbc6ee0f31e22770c076dd7d9dff3085d18674 (plain)
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
local client = require("client")
local util = require("util")
local ui = require("ui")
local dialog = require("dialog")
local socket = require("socket")
local L = require("lang").get
local C = ui.color

local teams = {
    { id = "attack", name = "ATK", col = C(0xEF8131) },
    { id = "defend", name = "DEF", col = C(0x6F8AAC) },
    { id = "third_party", name = "PO3", col = C(0xF1E816) },
}

local color = {
    greyed = C(0x606060),
    hover = C(0x404040),
    normal = C(0x000000),
    me = C(0x000000),
}

local function make_selection(lobby, key, dir)
    local list = key == "team" and teams or lobby.game.client.content[key.."s"]
    local current = lobby.game.client.player[key]
    local index

    if current then
        index = util.find_index_by(list, "id", current)
    elseif not current then
        index = 1
        if dir == 1 then dir = 0 end
    end

    index = (index-1+dir)%#list+1
    client.select(lobby.game.client, key, list[index].id)
end

local function insert_row(columns, elems, cell)
    cell = cell or function(x) return x end
    local size = 0
    for i = 1, #columns do
        if elems[i] then
            size = math.max(size, ui.min_size(elems[i], "y"))
        end
    end
    for i = 1, #columns do
        table.insert(columns[i], cell({ { size = { y = size } }, elems[i] }))
    end
end

local function clear_table(t)
    while #t > 0 do
        table.remove(t)
    end
end

local function invite_display(lobby)
    local copy_btn = ui.copy_button(function()
        return lobby.game.server.invite
    end, 25)
    local reveal_btn = ui.click(ui.center_x(ui.text(L("dialog.lobby.invite_reveal"), 30, C(0x000000))),
        function(self) self.active = false end)

    for _, b in ipairs({ reveal_btn, copy_btn }) do
        b.line = C(0x000000)
        b.line_width = 4
        b.fill_hover = C(0x8080a0)
        b.fill_normal = C(0xEFE3AF)
    end

    local code = ui.text(code, 30, color.normal)

    local elem = ui.align_right(ui.stack_x(
        ui.center_y(ui.text(L("dialog.lobby.invite"), 30, color.normal)),
        { code, reveal_btn },
        ui.pad_x(8),
        copy_btn
    ))

    function elem:show()
        if lobby.game.server then
            code.text:set(lobby.game.server.invite)
        else
            elem.active = false
        end
    end

    return elem
end

local function text(x, col)
    return ui.text(x, 30, col or C(0x000000))
end

local function fill_player_columns(lobby, columns)
    local info = lobby.game.client.info
    local me = lobby.game.client.player
    local teams_by_id = util.index_by(teams, "id")

    for _, c in ipairs(columns) do
         clear_table(c)
    end

    local function cell(x)
        return { line = C(0x000000), line_width = 4, line_segments = { 1, 3 }, ui.pad_x(10, ui.pad_y(10, x)) }
    end

    local function player_name(name, me, active)
        return text(name, (me and color.me) or (active and color.normal) or color.greyed)
    end

    for _, p in ipairs(info.players) do
        local name_cell = player_name(p.name, p == me, p.active)
        local team_cell = p.team and ui.align_left({ fill = teams_by_id[p.team].col, text(teams_by_id[p.team].name, C(0x000000)) }) or {}
        local faction_cell = p.faction and text(lobby.game.client.factions_by_id[p.faction].name) or {}

        local ready = text(L("dialog.lobby.ready"))
        local ready_size = ready.text:getHeight()
        local ready_elem = ui.pad_x(5, ready, {
            fill = p.ready and C(0x1EB251) or C(0xEF1B22),
            line = C(0x000000),
            line_width = 4,
            size = { x = ready_size, y = ready_size },
        })
        if p == me then
            ready_elem = ui.click(ready_elem, function()
                client.select(lobby.game.client, "ready", not lobby.game.client.player.ready)
            end)
        end
        local ready_cell = ui.align_right(ready_elem)

        insert_row(columns, { name_cell, team_cell, faction_cell, ready_cell }, cell)
    end

    if not info.started then
        insert_row(columns, { player_name(L("dialog.lobby.empty_slot")) }, cell)
    end
end

local function player_display(lobby)
    local columns = ui.stack_x()
    for i = 1, 4 do
        local column = ui.stack_y()
        column.flex = ({ 2, nil, nil, 3 })[i]
        table.insert(columns, column)
    end

    local player_columns = {}
    for i = 1, #columns do
        local angle = -75/180*math.pi
        local column = ui.stack_y()
        column.line = C(0x000000)
        column.line_width = 4
        column.angle = { x = { i ~= 1 and angle, i ~= #columns and angle } }
        column.flex = 1
        column.debug = "col_"..i
        table.insert(player_columns, column)
    end

    local button_image = {}

    local function header(id)
        local t = text(L("dialog.lobby", id))

        local function vbtn(sym, dir)
            local image = ui.image("assets/icon/angle_"..sym..".png", "scale", { y = t.text:getHeight() })
            image.color_hover = color.hover
            image.color_normal = color.normal
            table.insert(button_image, image)
            return ui.click(image, function()
                if not lobby.game.client.info.started then
                    make_selection(lobby, id, dir)
                end
            end)
        end

        return ui.pad_x(2, ui.stack_x(vbtn("left", -1), ui.flex(1, ui.center_x(t)), vbtn("right", 1)))
    end

    insert_row(columns, { nil, header("team"), header("faction"), nil })
    insert_row(columns, player_columns)

    function columns:show()
        fill_player_columns(lobby, player_columns)
        if lobby.game.client.info.started then
            for _, img in ipairs(button_image) do
                img.color = color.greyed
            end
        end
    end

    return columns
end

local function countdown_display(lobby)
    local text = ui.text("", 40, C(0x000000))
    function text:update()
        if lobby.countdown_time then
            text.visible = true
            local secs = math.max(0, math.ceil(lobby.countdown_time - socket.gettime()))
            if secs ~= lobby.countdown_secs then
                text.text:set(L("dialog.lobby.countdown") .. " " .. secs .. "...")
                lobby.countdown_secs = secs
            end
            if secs == 0 then
                lobby.countdown_time = nil
            end
        else
            text.visible = false
        end
    end
    return ui.align_right(ui.align_top(ui.pad_x(10, ui.pad_y(10, text))))
end

local function dialog_lobby(lobby)
    local invite = invite_display(lobby)
    local players = player_display(lobby)
    local countdown = countdown_display(lobby)

    local box = ui.gradient(135, 0.3, { C(0x0060AA), C(0x0060AA), C(0xDFDB4B), C(0xB36910), C(0xB36910) }, {
        line = C(0x000000),
        line_width = 4,
        ui.stack_x(ui.flex(1, ui.stack_y(ui.pad_y(10), invite, players)), ui.pad_x(15)) })

    local dg = ui.new({
        ui.image("assets/bg/rainbow_six_siege_x_clash.jpg", "cover"),
        ui.stack_x(
            ui.flex(1),
            ui.flex(1, ui.stack_y(
                ui.flex(1),
                ui.center_x(ui.text(L("dialog.lobby.players"), 150, C(0x000000))),
                ui.flex(2, box)
            )),
            ui.flex(1)
        ),
        countdown
    })

    function dg:show()
        invite:show()
        players:show()
    end

    return dg
end


local function show(lobby)
    dialog.show(lobby.ui)
end

local function set_countdown(lobby, time)
    if time then
        lobby.countdown_time = socket.gettime()+time
    else
        lobby.countdown_time = nil
    end
end

local function create(game)
    local lobby = { game = game }

    lobby.ui = dialog_lobby(lobby)

    lobby.show = show
    lobby.countdown = set_countdown
    return lobby
end

return {
    create = create,
}