309 lines
7.8 KiB
Lua
309 lines
7.8 KiB
Lua
gmpanel.scenarios = gmpanel.scenarios or {}
|
|
gmpanel.scenarios.list = gmpanel.scenarios.list or {}
|
|
gmpanel.scenarios.active = gmpanel.scenarios.active or {}
|
|
|
|
pcall(function()
|
|
local f = file.Read('gmpanel_scenarios.dat')
|
|
if f then gmpanel.scenarios.list = pon.decode(f) or {} end
|
|
end)
|
|
|
|
gmpanel.scenarios.save = octolib.func.debounce(function()
|
|
file.Write('gmpanel_scenarios.dat', pon.encode(gmpanel.scenarios.list))
|
|
end, 1)
|
|
|
|
local pan, left, editor, scenarios, actionsPan, actions
|
|
|
|
local function defaultLinePaint(self, w, h, off)
|
|
off = off or 0
|
|
if self.id % 2 == 1 then
|
|
draw.RoundedBox(4, off, off, w - off, h - off, Color(0,0,0, 35))
|
|
end
|
|
end
|
|
|
|
local colors = CFG.skinColors
|
|
local function scenarioPaint(self, w, h)
|
|
local off, off2 = 0, 0
|
|
if IsValid(editor) and editor.editUid == self.uid then
|
|
draw.RoundedBox(4, 0, 0, w, h, colors.g)
|
|
off, off2 = 1, 2
|
|
end
|
|
if self.sel then
|
|
draw.RoundedBox(4, off, off, w - off2, h - off2, Color(170,119,102))
|
|
else defaultLinePaint(self, w, h, off2) end
|
|
end
|
|
|
|
local function addedLineSelect(self)
|
|
for _,v in ipairs(scenarios:GetChildren()) do
|
|
v.sel = nil
|
|
end
|
|
self.sel = true
|
|
end
|
|
|
|
local function onModified(self)
|
|
local byUid = {}
|
|
for _,v in ipairs(gmpanel.scenarios.list) do
|
|
byUid[v.uid] = v
|
|
end
|
|
gmpanel.scenarios.list = {}
|
|
for _,v in ipairs(self:GetChildren()) do
|
|
gmpanel.scenarios.list[#gmpanel.scenarios.list + 1] = byUid[v.uid]
|
|
v.sel = v.uid == editor.editUid or nil
|
|
end
|
|
gmpanel.scenarios.save()
|
|
end
|
|
|
|
local function addedLineClick(self, mcode)
|
|
|
|
if isfunction(self.oldMP) then self:oldMP(mcode) end
|
|
if mcode ~= MOUSE_RIGHT then return end
|
|
|
|
self:Select()
|
|
|
|
local saved = gmpanel.scenarios.list[self.id]
|
|
if not saved then return end
|
|
|
|
local menu = DermaMenu()
|
|
|
|
menu:AddOption('Экспортировать', function()
|
|
local data = table.Copy(saved)
|
|
data.uid = nil
|
|
SetClipboardText(pon.encode(data))
|
|
octolib.notify.show('Код сценария скопирован в буфер обмена')
|
|
end):SetIcon(octolib.icons.silk16('page_go'))
|
|
|
|
menu:AddOption('Редактировать', function()
|
|
if IsValid(editor) then
|
|
editor:OpenEditor(saved)
|
|
end
|
|
end):SetIcon(octolib.icons.silk16('pencil'))
|
|
|
|
menu:AddOption('Удалить', function()
|
|
gmpanel.scenarios.edit(self.uid)
|
|
end):SetIcon(octolib.icons.silk16('cross'))
|
|
menu:Open()
|
|
|
|
end
|
|
|
|
local function rebuildScenarios()
|
|
|
|
if not IsValid(left) then return end
|
|
if IsValid(scenarios) then scenarios:Remove() end
|
|
|
|
scenarios = left:Add('DScrollPanel')
|
|
scenarios:Dock(FILL)
|
|
scenarios = scenarios:Add('DListLayout')
|
|
scenarios:Dock(FILL)
|
|
scenarios:MakeDroppable('gmpanel.scenarios')
|
|
|
|
function scenarios:AddPanel(i, data)
|
|
local cont = self:Add('DPanel')
|
|
cont:SetTall(20)
|
|
cont.Paint = scenarioPaint
|
|
cont:SetMouseInputEnabled(true)
|
|
cont.id = i
|
|
cont.uid = data.uid
|
|
cont.oldMP, cont.OnMouseReleased, cont.Select = cont.OnMouseReleased, addedLineClick, addedLineSelect
|
|
|
|
local icon = cont:Add('DImage')
|
|
icon:Dock(LEFT)
|
|
icon:SetWide(16)
|
|
icon:DockMargin(0, 2, 5, 2)
|
|
icon:SetImage(data._icon)
|
|
|
|
local name = cont:Add('DLabel')
|
|
name:Dock(FILL)
|
|
name:SetText(data._name)
|
|
|
|
return cont
|
|
end
|
|
|
|
for i,v in ipairs(gmpanel.scenarios.list) do
|
|
scenarios:AddPanel(i, v)
|
|
end
|
|
scenarios.OnModified = onModified
|
|
|
|
end
|
|
|
|
function gmpanel.scenarios.execute(scenData, players)
|
|
local uid = table.Count(gmpanel.scenarios.active) + 1
|
|
|
|
local actions, size = {}, #scenData.actions
|
|
for num, action in ipairs(scenData.actions) do
|
|
local predefined = gmpanel.actions.available[action.id]
|
|
if predefined then
|
|
actions[#actions + 1] = function(nxt)
|
|
netstream.Request('dbg-event.mapPlayerNames', players):Then(function(names)
|
|
gmpanel.scenarios.active[uid] = { num .. ' / ' .. size, predefined.name, table.concat(names, ', ') }
|
|
timer.Create('gmpanel.scenario.' .. uid, action._delay or 0, 1, function()
|
|
local func = predefined.execute or gmpanel.actions.defaultExecute
|
|
func(action, players)
|
|
nxt()
|
|
end)
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
actions[#actions + 1] = function(nxt)
|
|
gmpanel.scenarios.active[uid] = nil
|
|
end
|
|
|
|
octolib.func.chain(actions)
|
|
end
|
|
|
|
function gmpanel.scenarios.add(scenData)
|
|
scenData.uid = octolib.string.uuid():sub(1, 8)
|
|
gmpanel.scenarios.list[#gmpanel.scenarios.list + 1] = scenData
|
|
gmpanel.scenarios.save()
|
|
rebuildScenarios()
|
|
return true
|
|
end
|
|
|
|
function gmpanel.scenarios.edit(uid, scenData)
|
|
|
|
if not uid then return end
|
|
local idx
|
|
for i,v in ipairs(gmpanel.scenarios.list) do
|
|
if v.uid == uid then
|
|
idx = i
|
|
break
|
|
end
|
|
end
|
|
if not idx then return end
|
|
|
|
if not scenData then
|
|
|
|
table.remove(gmpanel.scenarios.list, idx)
|
|
if IsValid(editor) and editor.editUid == uid then editor.editUid = nil end
|
|
rebuildScenarios()
|
|
|
|
else
|
|
gmpanel.scenarios.list[idx] = scenData
|
|
if IsValid(scenarios) then
|
|
local cont = scenarios:GetChildren()[idx]
|
|
cont:GetChildren()[1]:SetImage(scenData._icon)
|
|
cont:GetChildren()[2]:SetText(scenData._name)
|
|
end
|
|
end
|
|
|
|
gmpanel.scenarios.save()
|
|
|
|
end
|
|
|
|
hook.Add('gmpanel.populateActionsMenu', 'gmpanel.scenarios', function(menu, players)
|
|
for _,v in ipairs(gmpanel.scenarios.list) do
|
|
menu:AddOption(v._name, function()
|
|
gmpanel.scenarios.execute(v, players)
|
|
end):SetIcon(v._icon)
|
|
end
|
|
menu:AddSpacer()
|
|
end)
|
|
|
|
function gmpanel.scenarios.close()
|
|
if IsValid(pan) then
|
|
pan:Close()
|
|
end
|
|
end
|
|
|
|
function gmpanel.scenarios.updateActions()
|
|
|
|
if IsValid(actions) then actions:Remove() end
|
|
if not IsValid(actionsPan) then return end
|
|
|
|
actions = actionsPan:Add('DListLayout')
|
|
actions:Dock(FILL)
|
|
actions:MakeDroppable('gmpanel.actions.added')
|
|
|
|
-- timer.Simple(0, function()
|
|
for i,data in ipairs(gmpanel.actions.added) do
|
|
|
|
local cont = actions:Add('DPanel')
|
|
cont:Dock(TOP)
|
|
cont:SetTall(20)
|
|
cont.Paint = defaultLinePaint
|
|
cont:SetMouseInputEnabled(true)
|
|
cont.data = data
|
|
cont.id = i
|
|
|
|
local icon = cont:Add('DImage')
|
|
icon:Dock(LEFT)
|
|
icon:SetWide(16)
|
|
icon:DockMargin(0, 2, 5, 2)
|
|
icon:SetImage(data._icon)
|
|
|
|
local name = cont:Add('DLabel')
|
|
name:Dock(FILL)
|
|
name:SetText(data._name)
|
|
|
|
end
|
|
-- end)
|
|
|
|
end
|
|
|
|
local function build()
|
|
gmpanel.groups.close()
|
|
|
|
pan = vgui.Create('DFrame')
|
|
pan:SetSize(700, 500)
|
|
pan:SetTitle('Сценарии')
|
|
pan:Center()
|
|
pan:MakePopup()
|
|
pan:SetDeleteOnClose(true)
|
|
pan:SetSizable(true)
|
|
pan:SetMinWidth(700)
|
|
pan:SetMinHeight(500)
|
|
|
|
left = pan:Add('DPanel')
|
|
left:Dock(LEFT)
|
|
left:SetWide(150)
|
|
|
|
rebuildScenarios()
|
|
|
|
local btnImport = left:Add('DButton')
|
|
btnImport:Dock(BOTTOM)
|
|
btnImport:SetTall(20)
|
|
btnImport:DockMargin(0, 5, 0, 0)
|
|
btnImport:SetText('Импорт сценария')
|
|
btnImport:SetIcon(octolib.icons.silk16('page_code'))
|
|
function btnImport:DoClick()
|
|
Derma_StringRequest('Импорт сценария', 'Вставь код сценария, полученный при экспорте', '', function(inp)
|
|
local succ, data = pcall(pon.decode, inp)
|
|
if not succ or not istable(data) then
|
|
return octolib.notify.show('warning', 'Кажется, код сценария поврежден')
|
|
end
|
|
gmpanel.scenarios.add(data)
|
|
end)
|
|
end
|
|
|
|
local btnCreate = left:Add('DButton')
|
|
btnCreate:Dock(BOTTOM)
|
|
btnCreate:SetTall(20)
|
|
btnCreate:DockMargin(0, 5, 0, 0)
|
|
btnCreate:SetText('Создать сценарий')
|
|
btnCreate:SetIcon('octoteam/icons-16/page_white_put.png')
|
|
function btnCreate:DoClick()
|
|
editor:OpenEditor({})
|
|
for _,v in ipairs(scenarios:GetChildren()) do
|
|
v.sel = nil
|
|
end
|
|
end
|
|
|
|
editor = pan:Add('gmp_scenario_editor')
|
|
editor:Dock(FILL)
|
|
|
|
actionsPan = pan:Add('DPanel')
|
|
actionsPan:Dock(RIGHT)
|
|
actionsPan:SetWide(150)
|
|
actionsPan:SetPaintBackground(false)
|
|
actionsPan = actionsPan:Add('DScrollPanel')
|
|
actionsPan:Dock(FILL)
|
|
actionsPan:DockMargin(5, 0, 0, 0)
|
|
local lbl = octolib.label(actionsPan, 'Заготовленные действия')
|
|
lbl:DockMargin(0, 0, 0, 5)
|
|
lbl:SetContentAlignment(5)
|
|
gmpanel.scenarios.updateActions()
|
|
|
|
end
|
|
|
|
function gmpanel.scenarios.open()
|
|
build()
|
|
end
|