907 lines
26 KiB
Lua
907 lines
26 KiB
Lua
-- ____ _ __
|
|
-- / __ )____ _____ | | / /___ ___________
|
|
-- / __ / __ \/ ___/ | | /| / / __ `/ ___/ ___/
|
|
-- / /_/ / /_/ (__ ) | |/ |/ / /_/ / / (__ )
|
|
-- /_____/\____/____/ |__/|__/\__,_/_/ /____/
|
|
--
|
|
-- A futuristic real-time strategy game.
|
|
-- This file is part of Bos Wars.
|
|
--
|
|
-- guichan.lua - The main UI lua script.
|
|
--
|
|
-- (c) Copyright 2005-2023 by François Beerten
|
|
--
|
|
-- 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; only version 2 of the License.
|
|
--
|
|
-- 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, write to the Free Software
|
|
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
-- 02111-1307, USA.
|
|
--
|
|
|
|
-- Global useful objects for menus ----------
|
|
dark = Color(38, 38, 78, 128)
|
|
darkNoAlpha = Color(38, 38, 78)
|
|
clear = Color(200, 200, 128)
|
|
black = Color(0, 0, 0)
|
|
disabled = Color(112, 112, 112, 128)
|
|
|
|
bckground = CGraphic:New("graphics/screens/menu.png")
|
|
bckground:Load()
|
|
bckground:Resize(Video.Width, Video.Height)
|
|
backgroundWidget = ImageWidget(bckground)
|
|
|
|
local SavedGame = false
|
|
local VersionString = Version.major .. "." .. Version.minor .. "." .. Version.patchlevel
|
|
local VersionInfoLine = "Bos Wars V" .. VersionString .. " (c) 1998-" .. Version.year .. " by the Bos Wars Team"
|
|
|
|
function FilterList(originallist, pattern)
|
|
local filteredlist = {}
|
|
local k, v
|
|
for k, v in ipairs(originallist) do
|
|
if (string.find(v, pattern)) then
|
|
table.insert(filteredlist, v)
|
|
end
|
|
end
|
|
return filteredlist
|
|
end
|
|
|
|
function CreateFilteringLister(pattern, lister)
|
|
function ListFilteredItems(path)
|
|
return FilterList(lister(path), pattern)
|
|
end
|
|
return ListFilteredItems
|
|
end
|
|
|
|
|
|
function AddMenuHelpers(menu)
|
|
function menu:addCentered(widget, x, y)
|
|
self:add(widget, x - widget:getWidth() / 2, y)
|
|
end
|
|
|
|
function menu:addLabel(text, x, y, font, center)
|
|
local label = Label(text)
|
|
if (font == nil) then font = Fonts["large"] end
|
|
label:setFont(font)
|
|
label:adjustSize()
|
|
if (center == nil or center == true) then -- center text by default
|
|
x = x - label:getWidth() / 2
|
|
end
|
|
self:add(label, x, y)
|
|
|
|
return label
|
|
end
|
|
function menu:addMultiLineLabel(text, x, y, font, center, width)
|
|
local label = MultiLineLabel(text)
|
|
if (font == nil) then font = Fonts["large"] end
|
|
label:setFont(font)
|
|
if (width == nil) then width = 240 end
|
|
label:setLineWidth(width)
|
|
label:adjustSize()
|
|
if (center == nil or center == true) then -- center text by default
|
|
x = x - label:getWidth() / 2
|
|
end
|
|
self:add(label, x, y)
|
|
|
|
return label
|
|
end
|
|
|
|
|
|
function menu:writeText(text, x, y)
|
|
return self:addLabel(text, x, y, Fonts["game"], false)
|
|
end
|
|
|
|
function menu:writeLargeText(text, x, y)
|
|
return self:addLabel(text, x, y, Fonts["large"], false)
|
|
end
|
|
|
|
-- Arrange widgets in a grid, with automatic column widths and
|
|
-- padding. Align the left sides of the widgets in each column.
|
|
-- This function moves the widgets only horizontally, leaving
|
|
-- the Y coordinates unchanged.
|
|
--
|
|
-- The grid parameter is a table of rows, each of which is a table
|
|
-- of widgets. Each row should have the same number of widgets.
|
|
-- A rows must be a plain array without specific keys.
|
|
-- (Actually, because this function ignores the Y coordinates,
|
|
-- it might be more natural if the parameter were a table of columns;
|
|
-- but the current format is a bit easier for the caller to provide.)
|
|
function menu:adjustColumnWidths(grid)
|
|
local columnWidths = {}
|
|
local width
|
|
local spareWidth
|
|
local rowNumber
|
|
local row
|
|
local columnNumber
|
|
local maxGap = menu:getWidth() / 16
|
|
local gap
|
|
local x
|
|
-- Compute the width needed for each column.
|
|
for rowNumber,row in ipairs(grid) do
|
|
for columnNumber,widget in ipairs(row) do
|
|
width = widget:getWidth()
|
|
if columnWidths[columnNumber] == nil or columnWidths[columnNumber] < width then
|
|
columnWidths[columnNumber] = width
|
|
end
|
|
end
|
|
end
|
|
-- How much width will be left over from the columns?
|
|
spareWidth = menu:getWidth()
|
|
for k,v in ipairs(columnWidths) do
|
|
spareWidth = spareWidth - v
|
|
end
|
|
-- Keep the columns as far from the edges of the menu
|
|
-- as they are from each other.
|
|
gap = spareWidth / (#columnWidths + 1)
|
|
-- However, if the columns would get too far from each other,
|
|
-- then move them closer, and leave more space at the edges.
|
|
if gap > maxGap then
|
|
gap = maxGap
|
|
end
|
|
-- Move all the widgets to their final positions.
|
|
for rowNumber,row in ipairs(grid) do
|
|
x = (spareWidth - gap * (#columnWidths - 1)) / 2
|
|
for columnNumber,widget in ipairs(row) do
|
|
widget:setX(x)
|
|
x = x + columnWidths[columnNumber] + gap
|
|
end
|
|
end
|
|
end
|
|
|
|
function menu:addButton(caption, x, y, callback, size)
|
|
local b = ButtonWidget(caption)
|
|
b:setActionCallback(callback)
|
|
if (size == nil) then size = {200, 24} end
|
|
b:setSize(size[1], size[2])
|
|
b:setBackgroundColor(dark)
|
|
b:setBaseColor(dark)
|
|
b:setDisabledColor(disabled)
|
|
self:add(b, x, y)
|
|
return b
|
|
end
|
|
|
|
function menu:addSmallButton(caption, x, y, callback)
|
|
return self:addButton(caption, x, y, callback, {106, 28})
|
|
end
|
|
|
|
function menu:addSlider(min, max, w, h, x, y, callback)
|
|
local b = Slider(min, max)
|
|
b:setBaseColor(dark)
|
|
b:setForegroundColor(clear)
|
|
b:setBackgroundColor(clear)
|
|
b:setSize(w, h)
|
|
b:setActionCallback(function(s) callback(b, s) end)
|
|
self:add(b, x, y)
|
|
return b
|
|
end
|
|
|
|
function menu:addListBox(x, y, w, h, list)
|
|
local bq = ListBoxWidget(w, h)
|
|
bq:setList(list)
|
|
bq:setBaseColor(black)
|
|
bq:setForegroundColor(clear)
|
|
bq:setBackgroundColor(dark)
|
|
bq:setFont(Fonts["game"])
|
|
self:add(bq, x, y)
|
|
bq.itemslist = list
|
|
return bq
|
|
end
|
|
|
|
function menu:addBrowser(path, lister, x, y, w, h, default)
|
|
local bq = self:addListBox(x, y, w, h, {})
|
|
bq.origpath = path
|
|
bq.actioncb = nil
|
|
|
|
local function updateList()
|
|
bq.itemslist = lister(bq.path)
|
|
if (bq.path ~= bq.origpath) then
|
|
table.insert(bq.itemslist, 1, "../")
|
|
end
|
|
bq:setList(bq.itemslist)
|
|
end
|
|
|
|
function bq:changeRoot(newpath)
|
|
self.path = newpath
|
|
self.origpath = newpath
|
|
updateList()
|
|
end
|
|
|
|
-- Change to the default directory and select the default file
|
|
if (default == nil) then
|
|
bq.path = path
|
|
updateList()
|
|
else
|
|
local i
|
|
for i = string.len(default) - 1, 1, -1 do
|
|
if (string.sub(default, i, i) == "/") then
|
|
bq.path = string.sub(default, 1, i)
|
|
updateList()
|
|
|
|
local f = string.sub(default, i + 1)
|
|
for i = 1, table.getn(bq.itemslist) do
|
|
if (bq.itemslist[i] == f) then
|
|
bq:setSelected(i - 1)
|
|
end
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function bq:getSelectedItem()
|
|
if (self:getSelected() < 0) then
|
|
return self.itemslist[1]
|
|
end
|
|
return self.itemslist[self:getSelected() + 1]
|
|
end
|
|
|
|
-- If a directory was clicked change dirs
|
|
-- Otherwise call the user's callback
|
|
local function cb(s)
|
|
local f = bq:getSelectedItem()
|
|
|
|
if (f == "../") then
|
|
if (s ~= "select") then
|
|
local i
|
|
for i = string.len(bq.path) - 1, 1, -1 do
|
|
if (string.sub(bq.path, i, i) == "/") then
|
|
bq.path = string.sub(bq.path, 1, i)
|
|
updateList()
|
|
break
|
|
end
|
|
end
|
|
end
|
|
elseif (string.sub(f, string.len(f)) == '/') then
|
|
if (s ~= "select") then
|
|
bq.path = bq.path .. f
|
|
updateList()
|
|
end
|
|
else
|
|
if (bq.actioncb ~= nil) then
|
|
bq:actioncb(s)
|
|
end
|
|
end
|
|
end
|
|
bq:setActionCallback(cb)
|
|
|
|
bq.oldSetActionCallback = bq.setActionCallback
|
|
function bq:setActionCallback(cb)
|
|
bq.actioncb = cb
|
|
end
|
|
|
|
return bq
|
|
end
|
|
|
|
function menu:addMapBrowser(path, x, y, w, h, default)
|
|
local function listFilesAndDirs(path)
|
|
local dirlist = {}
|
|
local filelist = {}
|
|
local dirs = ListDirsInDirectory(path)
|
|
-- Create table of dirs and files
|
|
for i,f in ipairs(dirs) do
|
|
if (string.find(f, "^%w.*%.map$")) then
|
|
table.insert(filelist, f)
|
|
elseif (string.find(f, "^%a")) then
|
|
table.insert(dirlist, f .. "/")
|
|
end
|
|
end
|
|
-- Append files after dirs
|
|
for i,f in ipairs(filelist) do
|
|
table.insert(dirlist, f)
|
|
end
|
|
return dirlist
|
|
end
|
|
local browser = self:addBrowser(path, listFilesAndDirs, x, y, w, h, default)
|
|
local function getMap(browser)
|
|
return browser.path .. browser:getSelectedItem() .. "/presentation.smp"
|
|
end
|
|
browser.getSelectedMap = getMap
|
|
return browser
|
|
end
|
|
|
|
function menu:addCheckBox(caption, x, y, callback)
|
|
local b = CheckBox(caption)
|
|
b:setBaseColor(clear)
|
|
b:setForegroundColor(clear)
|
|
b:setBackgroundColor(dark)
|
|
b:setActionCallback(function(s) callback(b, s) end)
|
|
b:setFont(Fonts["game"])
|
|
self:add(b, x, y)
|
|
return b
|
|
end
|
|
|
|
function menu:addRadioButton(caption, group, x, y, callback)
|
|
local b = RadioButton(caption, group)
|
|
b:setBaseColor(dark)
|
|
b:setForegroundColor(clear)
|
|
b:setBackgroundColor(dark)
|
|
b:setActionCallback(callback)
|
|
self:add(b, x, y)
|
|
return b
|
|
end
|
|
|
|
function menu:addDropDown(list, x, y, callback)
|
|
local dd = DropDownWidget()
|
|
dd:setFont(Fonts["game"])
|
|
dd:setList(list)
|
|
dd:setActionCallback(function(s) callback(dd, s) end)
|
|
dd:setBaseColor(darkNoAlpha)
|
|
dd:setForegroundColor(clear)
|
|
dd:setBackgroundColor(darkNoAlpha)
|
|
self:add(dd, x, y)
|
|
return dd
|
|
end
|
|
|
|
function menu:addTextInputField(text, x, y, w)
|
|
local b = TextField(text)
|
|
b:setActionCallback(function() end) --FIXME: remove this?
|
|
b:setFont(Fonts["game"]:PlainText())
|
|
b:setBaseColor(clear)
|
|
b:setForegroundColor(clear)
|
|
b:setBackgroundColor(dark)
|
|
if (w == nil) then w = 100 end
|
|
b:setSize(w, 18)
|
|
self:add(b, x, y)
|
|
return b
|
|
end
|
|
end
|
|
|
|
function BosMenu(title, background)
|
|
local menu
|
|
local bg
|
|
local bgg
|
|
|
|
menu = MenuScreen()
|
|
|
|
if background == nil then
|
|
bg = backgroundWidget
|
|
else
|
|
bgg = CGraphic:New(background)
|
|
bgg:Load()
|
|
bgg:Resize(Video.Width, Video.Height)
|
|
bg = ImageWidget(bgg)
|
|
end
|
|
menu:add(bg, 0, 0)
|
|
|
|
AddMenuHelpers(menu)
|
|
|
|
if title then
|
|
menu:addLabel(title, Video.Width / 2, Video.Height / 20, Fonts["large"])
|
|
end
|
|
|
|
return menu
|
|
end
|
|
|
|
-- Default configurations -------
|
|
Widget:setGlobalFont(Fonts["large"])
|
|
|
|
|
|
-- Define the different menus ----------
|
|
|
|
function RunResultsMenu(map)
|
|
local menu
|
|
local background = "graphics/screens/menu.png"
|
|
local sx = Video.Width / 20
|
|
local sy = Video.Height / 20
|
|
local result
|
|
local grid
|
|
|
|
if GameResult == GameVictory then
|
|
result = _("Victory !")
|
|
background = "graphics/screens/victory.png"
|
|
elseif GameResult == GameDraw then
|
|
result = _("Draw !")
|
|
elseif GameResult == GameDefeat then
|
|
result = _("Defeat !")
|
|
background = "graphics/screens/defeat.png"
|
|
else
|
|
return
|
|
end
|
|
|
|
if (Cheater) then
|
|
result = result .. " - " .. _("Cheater")
|
|
end
|
|
|
|
menu = BosMenu(_("Results"), background)
|
|
menu:writeLargeText(result, sx*6, sy*5)
|
|
menu:writeText(map, sx*6, sy*6)
|
|
|
|
-- The X coordinates of these widgets will be set after all the
|
|
-- widgets have been created and their sizes are known.
|
|
grid = {{
|
|
menu:writeText(_("Player"), 0, sy*7),
|
|
menu:writeText(_("Units"), 0, sy*7),
|
|
menu:writeText(_("Buildings"), 0, sy*7),
|
|
menu:writeText(_("Kills"), 0, sy*7),
|
|
menu:writeText(_("Razings"), 0, sy*7)
|
|
}}
|
|
|
|
for i=0,7 do
|
|
if (Players[i].TotalUnits > 0) then
|
|
table.insert(grid, {
|
|
menu:writeText(i .. " ".. Players[i].Name, 0, sy*(8+i)),
|
|
menu:writeText(Players[i].TotalUnits, 0, sy*(8+i)),
|
|
menu:writeText(Players[i].TotalBuildings, 0, sy*(8+i)),
|
|
menu:writeText(Players[i].TotalKills, 0, sy*(8+i)),
|
|
menu:writeText(Players[i].TotalRazings, 0, sy*(8+i))
|
|
})
|
|
end
|
|
end
|
|
|
|
menu:adjustColumnWidths(grid)
|
|
|
|
menu:addButton(_("~!Continue"), Video.Width / 2 - 100, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
|
|
menu:run()
|
|
end
|
|
|
|
function RunMap(map, objectives, fow, revealmap)
|
|
if (objectives == nil) then
|
|
SetObjectives(default_objectives)
|
|
else
|
|
SetObjectives(objectives)
|
|
end
|
|
local loop = true
|
|
while (loop) do
|
|
InitGameVariables()
|
|
if fow ~= nil then
|
|
SetFogOfWar(fow)
|
|
end
|
|
if revealmap == true then
|
|
RevealMap()
|
|
end
|
|
StartMap(map)
|
|
if GameResult ~= GameRestart then
|
|
loop = false
|
|
end
|
|
end
|
|
RunResultsMenu(map)
|
|
end
|
|
|
|
current_objectives = {}
|
|
function ClearObjectives()
|
|
current_objectives = {}
|
|
end
|
|
|
|
function AddObjective(objective)
|
|
table.insert(current_objectives, objective)
|
|
end
|
|
|
|
function SetObjectives(objectives)
|
|
current_objectives = objectives
|
|
end
|
|
|
|
function GetObjectives()
|
|
return current_objectives
|
|
end
|
|
|
|
|
|
-- Callback right before the game starts
|
|
function GameStarting()
|
|
local i
|
|
local factor
|
|
|
|
if (not SavedGame) then
|
|
for i=0,7 do
|
|
-- resources can be 1,3,5 - low,medium,high
|
|
if (GameSettings.Resources == 1) then
|
|
factor = 0.5
|
|
elseif (GameSettings.Resources == 3) then
|
|
factor = 1
|
|
else
|
|
factor = 10
|
|
end
|
|
Players[i].MagmaStored = Players[i].MagmaStored * factor
|
|
Players[i].EnergyStored = Players[i].EnergyStored * factor
|
|
end
|
|
end
|
|
|
|
Cheater = false
|
|
|
|
UI.StatusLine:Set(VersionInfoLine)
|
|
end
|
|
|
|
|
|
function ResetMapOptions()
|
|
GameSettings.Resources = 3
|
|
GameSettings.Difficulty = 3
|
|
GameSettings.GameType = SettingsGameTypeMapDefault
|
|
GameSettings.NoFogOfWar = false
|
|
GameSettings.RevealMap = 0
|
|
end
|
|
|
|
|
|
function RunStartGameMenu(s)
|
|
local menu
|
|
local maptext
|
|
local descr
|
|
local numplayers = 2
|
|
local players
|
|
local sx = Video.Width / 20
|
|
local sy = Video.Height / 20
|
|
local selectedmap = "islandwar.map"
|
|
local d
|
|
|
|
menu = BosMenu(_("Start Game"))
|
|
|
|
menu:writeLargeText(_("Map"), sx, sy*3)
|
|
menu:writeText(_("File:"), sx, sy*3+30)
|
|
local maptext = menu:writeText(selectedmap, sx+70, sy*3+30)
|
|
maptext:setWidth(sx * 9 - 50 - 20)
|
|
menu:writeText(_("Size:"), sx, sy*3+50)
|
|
local mapsize = menu:writeText(" ", sx+70, sy*3+50)
|
|
mapsize:setWidth(sx * 9 - 50 - 20)
|
|
menu:writeText(_("Players:"), sx, sy*3+70)
|
|
local players = menu:writeText(" ", sx+70, sy*3+70)
|
|
menu:writeText(_("Description:"), sx, sy*3+90)
|
|
local descr = menu:writeText("No map", sx+20, sy*3+110)
|
|
descr:setWidth(sx * 9 - 20 - 20)
|
|
|
|
local fow = menu:addCheckBox(_("Fog of war"), sx, sy*3+140,
|
|
function(f) GameSettings.NoFogOfWar = not f:isMarked() end)
|
|
fow:setMarked(preferences.FogOfWar)
|
|
local revealmap = menu:addCheckBox(_("Reveal map"), sx, sy*3+160,
|
|
function(f) GameSettings.RevealMap = bool2int(f:isMarked()) end)
|
|
revealmap:setMarked(true)
|
|
|
|
ResetMapOptions()
|
|
menu:writeText(_("Difficulty:"), sx, sy*11)
|
|
d = menu:addDropDown({_("easy"), _("normal"), _("hard")}, sx + 150, sy*11,
|
|
function(dd) GameSettings.Difficulty = (5 - dd:getSelected()*2) end)
|
|
d:setSelected(1)
|
|
menu:writeText(_("Starting resources:"), sx, sy*11+25)
|
|
d = menu:addDropDown({_("high"), _("normal"), _("low")}, sx + 150, sy*11+25,
|
|
function(dd) GameSettings.Resources = (5 - dd:getSelected()*2) end)
|
|
d:setSelected(1)
|
|
menu:writeText(_("Game type:"), sx, sy*11+50)
|
|
d = menu:addDropDown({_("Map Default"), _("Melee"), _("Free For All"), _("Top vs Bottom"), _("Left vs Right"), _("Man vs Machine")}, sx + 150, sy*11+50,
|
|
function(dd) GameSettings.GameType = dd:getSelected() - 1 end)
|
|
d:setSelected(0)
|
|
d:setSize(140, d:getHeight())
|
|
|
|
local OldPresentMap = PresentMap
|
|
PresentMap = function(description, nplayers, w, h, id)
|
|
numplayers = nplayers
|
|
players:setCaption(""..nplayers)
|
|
descr:setCaption(description)
|
|
mapsize:setCaption(""..w.."x"..h)
|
|
OldPresentMap(description, nplayers, w, h, id)
|
|
end
|
|
|
|
Load("maps/"..selectedmap..'/presentation.smp')
|
|
local browser = menu:addMapBrowser("maps/", sx*10+10, sy*2+40, sx*8, sy*11,
|
|
"maps/"..selectedmap)
|
|
local function cb(s)
|
|
maptext:setCaption(browser:getSelectedItem())
|
|
Load(browser:getSelectedMap())
|
|
selectedmap = browser:getSelectedItem()
|
|
end
|
|
browser:setActionCallback(cb)
|
|
local rootpaths = {"maps/", "~maps/"}
|
|
d = menu:addDropDown({_("Standard maps"), _("Custom maps")}, sx*10, sy*2+20,
|
|
function(dd) browser:changeRoot(rootpaths[dd:getSelected() + 1]) end)
|
|
d:setSelected(0)
|
|
d:setSize(sx*8, d:getHeight())
|
|
|
|
AllowAllUnits()
|
|
local function startgamebutton(s)
|
|
preferences.FogOfWar = fow:isMarked()
|
|
SavePreferences()
|
|
DebugPrint("Starting map -------")
|
|
RunMap(browser:getSelectedMap(), nil, fow:isMarked(),
|
|
revealmap:isMarked())
|
|
PresentMap = OldPresentMap
|
|
menu:stop()
|
|
end
|
|
menu:addButton(_("Main Menu (~<Esc~>)"), Video.Width / 2 - 250, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
menu:addButton(_("~!Start"), Video.Width / 2 + 50 , Video.Height - 100,
|
|
startgamebutton)
|
|
|
|
menu:run()
|
|
PresentMap = OldPresentMap
|
|
end
|
|
|
|
function RunReplayMenu(s)
|
|
local menu
|
|
menu = BosMenu(_("Show a Replay"))
|
|
|
|
-- By default allow all units.
|
|
-- Current implementation relies on the hypothesis that the map setup will
|
|
-- configure which units are allowed.
|
|
-- Stratagus should store complete starting conditions in the log.
|
|
AllowAllUnits()
|
|
|
|
local lister = CreateFilteringLister(".log$", ListFilesInDirectory)
|
|
local browser = menu:addBrowser("~logs/", lister, 300, 100, 300, 200)
|
|
local reveal = menu:addCheckBox(_("Reveal map"), 100, 250, function() end)
|
|
|
|
function startreplaybutton(s)
|
|
DebugPrint("Starting map -------")
|
|
ResetMapOptions()
|
|
InitGameVariables()
|
|
StartReplay("~logs/" .. browser:getSelectedItem(), reveal:isMarked())
|
|
RunResultsMenu("Replay")
|
|
menu:stop()
|
|
end
|
|
|
|
menu:addButton(_("Main Menu (~<Esc~>)"), Video.Width / 2 - 250, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
menu:addButton(_("~!Start"), Video.Width / 2 + 50 , Video.Height - 100,
|
|
startreplaybutton)
|
|
|
|
menu:run()
|
|
end
|
|
|
|
|
|
function RunLoadGameMenu(s)
|
|
local menu
|
|
local b
|
|
|
|
menu = BosMenu(_("Load Game"))
|
|
local lister = CreateFilteringLister(".sav.gz$", ListFilesInDirectory)
|
|
local browser = menu:addBrowser("~save", lister,
|
|
Video.Width / 2 - 150, 100, 300, 200)
|
|
function startgamebutton(s)
|
|
DebugPrint("Starting saved game")
|
|
currentCampaign = nil
|
|
local loop = true
|
|
while (loop) do
|
|
InitGameVariables()
|
|
SavedGame = true
|
|
StartSavedGame("~save/" .. browser:getSelectedItem())
|
|
SavedGame = false
|
|
if (GameResult ~= GameRestart) then
|
|
loop = false
|
|
end
|
|
end
|
|
RunResultsMenu("Saved Game")
|
|
if currentCampaign ~= nil then
|
|
if GameResult == GameVictory then
|
|
position = position + 1
|
|
elseif GameResult == GameDefeat then
|
|
position = position
|
|
else
|
|
currentCampaign = nil
|
|
return
|
|
end
|
|
RunCampaign(currentCampaign)
|
|
end
|
|
menu:stop()
|
|
end
|
|
menu:addButton(_("Main Menu (~<Esc~>)"), Video.Width / 2 - 250, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
menu:addButton(_("~!Start"), Video.Width / 2 + 50 , Video.Height - 100,
|
|
startgamebutton)
|
|
|
|
DisallowAllUnits()
|
|
menu:run()
|
|
end
|
|
|
|
function RunEditorMenu(s)
|
|
local menu
|
|
local x = Video.Width / 2 - 100
|
|
local x1 = Video.Width / 3 - 100
|
|
local x2 = Video.Width * 2 / 3 - 100
|
|
|
|
menu = BosMenu(_("Editor"))
|
|
|
|
menu:addButton(_("Create ~!New Map"), x1, 220,
|
|
function()
|
|
if RunEditorNewMenu() then
|
|
menu:stop()
|
|
end
|
|
end)
|
|
menu:addButton(_("~!Load Map"), x1, 260,
|
|
function()
|
|
if RunEditorLoadMenu() then
|
|
menu:stop()
|
|
end
|
|
end)
|
|
|
|
menu:addButton(_("C~!reate New Patch"), x2, 220,
|
|
function()
|
|
if RunNewPatchMenu() then
|
|
menu:stop()
|
|
end
|
|
end)
|
|
menu:addButton(_("Load ~!Patch"), x2, 260,
|
|
function()
|
|
if RunLoadPatchMenu() then
|
|
menu:stop()
|
|
end
|
|
end)
|
|
|
|
menu:addButton(_("Main Menu (~<Esc~>)"), x, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
|
|
menu:run()
|
|
end
|
|
|
|
function RunEditorNewMenu()
|
|
local menu
|
|
local sy = Video.Height / 20
|
|
local xsize
|
|
local ysize
|
|
local defaultSize = {64, 64}
|
|
local returnToMainMenu = false
|
|
|
|
menu = BosMenu(_("Create New Map"))
|
|
|
|
function starteditorbutton(s)
|
|
local n = tonumber(xsize:getText())
|
|
if (n == nil) then n = 64 end
|
|
Map.Info.MapWidth = n
|
|
local n = tonumber(ysize:getText())
|
|
if (n == nil) then n = 64 end
|
|
Map.Info.MapHeight = n
|
|
|
|
ClearAiState()
|
|
StartEditor(nil)
|
|
Load("scripts/uilayout.lua")
|
|
HandleCommandKey = HandleIngameCommandKey
|
|
returnToMainMenu = true
|
|
menu:stop()
|
|
end
|
|
|
|
local l = Label(_("Size:"))
|
|
l:setFont(Fonts["game"])
|
|
l:adjustSize()
|
|
menu:add(l, Video.Width / 2 - 50, 8 * sy)
|
|
|
|
xsize = menu:addTextInputField(tostring(defaultSize[1]),
|
|
Video.Width / 2 + 10, 8 * sy, 40)
|
|
|
|
local l = Label("x")
|
|
l:setFont(Fonts["game"])
|
|
l:adjustSize()
|
|
menu:add(l, Video.Width / 2 + 57, 8 * sy)
|
|
|
|
ysize = menu:addTextInputField(tostring(defaultSize[2]),
|
|
Video.Width / 2 + 10 + 60, 8 * sy, 40)
|
|
|
|
menu:addButton(_("Cancel (~<Esc~>)"), Video.Width / 2 - 250, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
menu:addButton(_("Start ~!Editor"), Video.Width / 2 + 50, Video.Height - 100,
|
|
starteditorbutton)
|
|
|
|
menu:run()
|
|
return returnToMainMenu
|
|
end
|
|
|
|
function RunEditorLoadMenu()
|
|
local menu
|
|
local sx = Video.Width / 20
|
|
local sy = Video.Height / 20
|
|
local selectedmap = "islandwar.map"
|
|
local numplayers = 2
|
|
local returnToMainMenu = false
|
|
|
|
menu = BosMenu(_("Select Map to Edit"))
|
|
|
|
menu:writeLargeText(_("Map"), sx, sy*3)
|
|
menu:writeText(_("File:"), sx, sy*3+30)
|
|
local maptext = menu:writeText(selectedmap .. " ", sx+70, sy*3+30)
|
|
menu:writeText(_("Players:"), sx, sy*3+50)
|
|
local players = menu:writeText(" ", sx+70, sy*3+50)
|
|
menu:writeText(_("Size:"), sx, sy*3+70)
|
|
local mapsize = menu:writeText(" ", sx+70, sy*3+70)
|
|
menu:writeText(_("Description:"), sx, sy*3+90)
|
|
local descr = menu:writeText("No map", sx+20, sy*3+110)
|
|
descr:setWidth(sx * 9 - 20 - 20)
|
|
|
|
local OldPresentMap = PresentMap
|
|
PresentMap = function(description, nplayers, w, h, id)
|
|
numplayers = nplayers
|
|
players:setCaption(""..nplayers)
|
|
mapsize:setCaption(""..h.."x"..w)
|
|
descr:setCaption(description)
|
|
OldPresentMap(description, nplayers, w, h, id)
|
|
end
|
|
|
|
Load("maps/"..selectedmap..'/presentation.smp')
|
|
local browser = menu:addMapBrowser("maps/", sx*10+10, sy*2+40, sx*8, sy*11,
|
|
"maps/"..selectedmap)
|
|
local function selectMap(s)
|
|
maptext:setCaption(browser:getSelectedItem())
|
|
Load(browser:getSelectedMap())
|
|
selectedmap = browser:getSelectedItem()
|
|
end
|
|
browser:setActionCallback(selectMap)
|
|
local rootpaths = {"maps/", "~maps/"}
|
|
d = menu:addDropDown({_("Standard maps"), _("Custom maps")}, sx*10, sy*2+20,
|
|
function(dd) browser:changeRoot(rootpaths[dd:getSelected() + 1]) end)
|
|
d:setSelected(0)
|
|
d:setSize(sx*8, d:getHeight())
|
|
|
|
function starteditorbutton(s)
|
|
ClearAiState()
|
|
StartEditor(browser:getSelectedMap())
|
|
Load("scripts/uilayout.lua")
|
|
HandleCommandKey = HandleIngameCommandKey
|
|
menu:stop()
|
|
returnToMainMenu = true
|
|
end
|
|
menu:addButton(_("Cancel (~<Esc~>)"), Video.Width / 2 - 250, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
menu:addButton(_("Start ~!Editor"), Video.Width / 2 + 50, Video.Height -100,
|
|
starteditorbutton)
|
|
|
|
menu:run()
|
|
PresentMap = OldPresentMap
|
|
return returnToMainMenu
|
|
end
|
|
|
|
function RunTutorial(s)
|
|
DebugPrint("Starting tutorial")
|
|
position = nil
|
|
RunCampaign("campaigns/tutorial/campaign.lua")
|
|
end
|
|
|
|
Load("scripts/menus/network.lua")
|
|
Load("scripts/menus/options.lua")
|
|
Load("scripts/menus/credits.lua")
|
|
Load("scripts/menus/ingame/game.lua")
|
|
Load("scripts/menus/ingame/editor.lua")
|
|
Load("scripts/menus/patch.lua")
|
|
Load("scripts/menus/campaigns.lua")
|
|
|
|
function BuildMainMenu(menu)
|
|
local x = Video.Width / 3
|
|
local ystep = Video.Height / 10
|
|
local x1 = x - 100
|
|
local x2 = 2*x - 100
|
|
|
|
menu:addButton(_("~!Start Game"), x1, ystep * 2, RunStartGameMenu)
|
|
menu:addButton(_("~!Load Game"), x1, ystep * 3, RunLoadGameMenu)
|
|
menu:addButton(_("~!Tutorial"), x2, ystep * 2, RunTutorial)
|
|
menu:addButton(_("~!Campaigns"), x2, ystep * 3, RunCampaignsMenu)
|
|
menu:addButton(_("Show ~!Replay"), x2, ystep * 4, RunReplayMenu)
|
|
|
|
menu:addButton(_("~!MultiPlayer"), x1, ystep * 5, RunMultiPlayerMenu)
|
|
menu:addButton(_("~!Options"), x2, ystep * 5, function() RunOptionsMenu() menu:stop(1) end)
|
|
|
|
menu:addButton(_("Cre~!dits"), x1, ystep * 6, RunCreditsMenu)
|
|
menu:addButton(_("Start ~!Editor"), x2, ystep * 6, RunEditorMenu)
|
|
|
|
menu:addButton(_("E~!xit"), Video.Width / 2 - 100, Video.Height - 100,
|
|
function() menu:stop() end)
|
|
|
|
menu:addLabel(VersionInfoLine, Video.Width / 2, Video.Height - 50)
|
|
|
|
if false then
|
|
menu:addButton("~!Widgets Demo", x2, ystep * 7, RunWidgetsMenu)
|
|
end
|
|
end
|
|
|
|
function RunMainMenu(s)
|
|
local menu
|
|
local continue = 1
|
|
|
|
while continue == 1 do
|
|
menu = BosMenu()
|
|
BuildMainMenu(menu)
|
|
continue = menu:run()
|
|
end
|
|
end
|
|
|
|
function RunMapFromCommandLine()
|
|
ResetMapOptions()
|
|
AllowAllUnits()
|
|
if (CliMapName ~= "") then
|
|
RunMap(CliMapName, nil, true, false)
|
|
end
|
|
end
|
|
|
|
RunMapFromCommandLine()
|
|
RunMainMenu()
|
|
|