1-- Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details 2-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt 3 4local Engine = require 'Engine' 5local Game = require 'Game' 6local Ship = require 'Ship' 7local ShipDef = require 'ShipDef' 8local SystemPath = require 'SystemPath' 9local Equipment = require 'Equipment' 10local Format = require 'Format' 11local MusicPlayer = require 'modules.MusicPlayer' 12local Lang = require 'Lang' 13local FlightLog = require ("FlightLog") 14 15local lc = Lang.GetResource("core") 16local lui = Lang.GetResource("ui-core") 17local qlc = Lang.GetResource("quitconfirmation-core") 18local elc = Lang.GetResource("equipment-core") 19local clc = Lang.GetResource("commodity") 20 21local ui = require 'pigui' 22 23local cargo = Equipment.cargo 24local misc = Equipment.misc 25local laser = Equipment.laser 26local hyperspace = Equipment.hyperspace 27 28local player = nil 29local colors = ui.theme.colors 30local pionillium = ui.fonts.pionillium 31local orbiteer = ui.fonts.orbiteer 32local icons = ui.theme.icons 33 34local mainButtonSize = Vector2(400,46) * (ui.screenHeight / 1200) 35local dialogButtonSize = Vector2(150,46) * (ui.screenHeight / 1200) 36local mainButtonFontSize = 24 * (ui.screenHeight / 1200) 37 38local showQuitConfirm = false 39local quitConfirmMsg 40local max_flavours = 22 41 42local startLocations = { 43 {['name']=lui.START_AT_MARS, 44 ['desc']=lui.START_AT_MARS_DESC, 45 ['location']=SystemPath.New(0,0,0,0,18), 46 ['logmsg']=lui.START_LOG_ENTRY_1, 47 ['shipType']='sinonatrix',['money']=100,['hyperdrive']=true, 48 ['equipment']={ 49 {laser.pulsecannon_1mw,1}, 50 {misc.atmospheric_shielding,1}, 51 {misc.autopilot,1}, 52 {misc.radar,1}, 53 {cargo.hydrogen,2}}}, 54 {['name']=lui.START_AT_NEW_HOPE, 55 ['desc']=lui.START_AT_NEW_HOPE_DESC, 56 ['location']=SystemPath.New(1,-1,-1,0,4), 57 ['logmsg']=lui.START_LOG_ENTRY_2, 58 ['shipType']='pumpkinseed',['money']=100,['hyperdrive']=true, 59 ['equipment']={ 60 {laser.pulsecannon_1mw,1}, 61 {misc.atmospheric_shielding,1}, 62 {misc.autopilot,1}, 63 {misc.radar,1}, 64 {cargo.hydrogen,2}}}, 65 {['name']=lui.START_AT_BARNARDS_STAR, 66 ['desc']=lui.START_AT_BARNARDS_STAR_DESC, 67 ['location']=SystemPath.New(-1,0,0,0,16), 68 ['logmsg']=lui.START_LOG_ENTRY_3, 69 ['shipType']='xylophis',['money']=100,['hyperdrive']=false, 70 ['equipment']={ 71 {misc.atmospheric_shielding,1}, 72 {misc.autopilot,1}, 73 {misc.radar,1}, 74 {cargo.hydrogen,2}}} 75} 76 77local function dialogTextButton(label, enabled, callback) 78 local bgcolor = enabled and colors.buttonBlue or colors.grey 79 80 local button 81 ui.withFont(pionillium.large.name, mainButtonFontSize, function() 82 button = ui.coloredSelectedButton(label, dialogButtonSize, false, bgcolor, nil, enabled) 83 end) 84 if button then 85 callback() 86 end 87 return button 88end 89 90local function mainTextButton(label, tooltip, enabled, callback) 91 local bgcolor = enabled and colors.buttonBlue or colors.grey 92 93 local button 94 ui.withFont(pionillium.large.name, mainButtonFontSize, function() 95 button = ui.coloredSelectedButton(label, mainButtonSize, false, bgcolor, tooltip, enabled) 96 end) 97 if button and enabled then 98 callback() 99 end 100 return button 101end --mainTextButton 102 103local function confirmQuit() 104 ui.setNextWindowPosCenter('Always') 105 106 ui.withStyleColors({["WindowBg"] = colors.commsWindowBackground}, function() 107 -- TODO: this window should be ShowBorders 108 ui.window("MainMenuQuitConfirm", {"NoTitleBar", "NoResize", "AlwaysAutoResize"}, function() 109 ui.withFont(pionillium.large.name, mainButtonFontSize, function() 110 ui.text(qlc.QUIT) 111 end) 112 ui.withFont(pionillium.large.name, pionillium.large.size, function() 113 ui.pushTextWrapPos(450) 114 ui.textWrapped(quitConfirmMsg) 115 ui.popTextWrapPos() 116 end) 117 ui.dummy(Vector2(5,15)) -- small vertical spacing 118 ui.dummy(Vector2(30, 5)) 119 ui.sameLine() 120 dialogTextButton(qlc.YES, true, Engine.Quit) 121 ui.sameLine() 122 ui.dummy(Vector2(30, 5)) 123 ui.sameLine() 124 dialogTextButton(qlc.NO, true, function() showQuitConfirm = false end) 125 end) 126 end) 127end 128 129local function showOptions() 130 ui.optionsWindow:open() 131end 132 133local function quitGame() 134 if Engine.GetConfirmQuit() then 135 quitConfirmMsg = string.interp(qlc["MSG_" .. Engine.rand:Integer(1, max_flavours)],{yes = qlc.YES, no = qlc.NO}) 136 showQuitConfirm = true 137 else 138 Engine.Quit() 139 end 140end 141 142local function continueGame() 143 if Game.CanLoadGame('_exit') and ( Engine.GetAutosaveEnabled() or not Game.CanLoadGame('_quicksave') ) then 144 Game.LoadGame("_exit") 145 else 146 Game.LoadGame('_quicksave') 147 end 148end 149 150local function canContinue() 151 return Game.CanLoadGame('_exit') or Game.CanLoadGame('_quicksave') 152end 153 154local hasMusicList = false -- required false at init, see showMainMenu() for usage 155local function startAtLocation(location) 156 hasMusicList = false -- set false so that player restarts music 157 Game.StartGame(location.location) 158 Game.player:SetShipType(location.shipType) 159 Game.player:SetLabel(Ship.MakeRandomLabel()) 160 if location.hyperdrive then 161 Game.player:AddEquip(hyperspace['hyperdrive_'..ShipDef[Game.player.shipId].hyperdriveClass]) 162 end 163 Game.player:SetMoney(location.money) 164 for _,equip in pairs(location.equipment) do 165 Game.player:AddEquip(equip[1],equip[2]) 166 end 167 -- XXX horrible hack here to avoid paying a spawn-in docking fee 168 Game.player:setprop("is_first_spawn", true) 169 FlightLog.MakeCustomEntry(location.logmsg) 170end 171 172local function callModules(mode) 173 for k,v in ipairs(ui.getModules(mode)) do 174 v.draw() 175 end 176end 177 178local overlayWindowFlags = ui.WindowFlags {"NoTitleBar", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus", "AlwaysAutoResize"} 179local mainMenuFlags = ui.WindowFlags{"NoTitleBar", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus"} 180local function showMainMenu() 181 if not hasMusicList then 182 hasMusicList = true 183 MusicPlayer.rebuildSongList() 184 MusicPlayer.playRandomSongFromCategory("menu", true) 185 end 186 187 local showContinue = canContinue() 188 local buttons = 4 189 190 local winPos = Vector2(ui.screenWidth - mainButtonSize.x - 100, ui.screenHeight/2 - (buttons * mainButtonSize.y)/2 - (2*mainButtonSize.y)/2 - 8) 191 192 ui.setNextWindowPos(Vector2(110,65),'Always') 193 ui.withStyleColors({["WindowBg"]=colors.transparent}, function() 194 ui.window("headingWindow", overlayWindowFlags, function() 195 ui.withFont("orbiteer",36 * (ui.screenHeight/1200),function() ui.text("Pioneer") end) 196 end) 197 end) 198 if Engine.IsIntroZooming() then 199 ui.setNextWindowPos(Vector2(0,0),'Always') 200 ui.setNextWindowSize(Vector2(ui.screenWidth, ui.screenHeight), 'Always') 201 ui.withStyleColors({["WindowBg"]=colors.transparent}, function() 202 ui.window("shipinfoWindow", overlayWindowFlags, function() 203 local mn = Engine.GetIntroCurrentModelName() 204 if mn then 205 local sd = ShipDef[mn] 206 if sd then 207 ui.addFancyText(Vector2(ui.screenWidth / 3, ui.screenHeight / 5.0 * 4), ui.anchor.center, ui.anchor.bottom, {{text=sd.name, color=colors.white, font=orbiteer.medlarge}}, colors.transparent) 208 ui.addFancyText(Vector2(ui.screenWidth / 3, ui.screenHeight / 5.0 * 4.02), ui.anchor.center, ui.anchor.top, {{text=lui[sd.shipClass:upper()], color=colors.white, font=orbiteer.medium}}, colors.transparent) 209 end 210 end 211 end) 212 end) 213 end 214 local build_text = Engine.version 215 ui.withFont("orbiteer", 16 * (ui.screenHeight/1200), 216 function() 217 ui.setNextWindowPos(Vector2(ui.screenWidth - ui.calcTextSize(build_text).x * 1.2,ui.screenHeight - 50), 'Always') 218 ui.withStyleColors({["WindowBg"] = colors.transparent}, function() 219 ui.window("buildLabel", overlayWindowFlags, function() 220 ui.text(build_text) 221 end) 222 end) 223 end) 224 225 ui.setNextWindowPos(winPos,'Always') 226 ui.setNextWindowSize(Vector2(0,0), 'Always') 227 ui.withStyleColors({["WindowBg"] = colors.lightBlackBackground}, function() 228 ui.window("MainMenuButtons", mainMenuFlags, function() 229 mainTextButton(lui.CONTINUE_GAME, nil, showContinue, continueGame) 230 231 for _,loc in pairs(startLocations) do 232 local desc = loc.desc .. "\n" 233 local name = loc.shipType 234 local sd = ShipDef[loc.shipType] 235 if sd then 236 name = sd.name 237 end 238 desc = desc .. lc.SHIP .. ": " .. name .. "\n" 239 desc = desc .. lui.CREDITS .. ": " .. Format.Money(loc.money) .. "\n" 240 desc = desc .. lui.HYPERDRIVE .. ": " .. (loc.hyperdrive and lui.YES or lui.NO) .. "\n" 241 desc = desc .. lui.EQUIPMENT .. ":\n" 242 for _,eq in pairs(loc.equipment) do 243 local equipname = rawget(elc, eq[1].l10n_key) or rawget(clc, eq[1].l10n_key) 244 desc = desc .. " - " .. equipname 245 if eq[2] > 1 then 246 desc = desc .. " x" .. eq[2] .. "\n" 247 else desc = desc .. "\n" 248 end 249 end 250 mainTextButton(loc.name, desc, true, function() startAtLocation(loc) end) 251 end 252 253 mainTextButton(lui.LOAD_GAME, nil, true, function() 254 ui.saveLoadWindow.mode = "LOAD" 255 ui.saveLoadWindow:open() 256 end) 257 258 mainTextButton(lui.OPTIONS, nil, true, showOptions) 259 mainTextButton(lui.QUIT, nil, true, quitGame) 260 261 if showQuitConfirm then confirmQuit() end 262 end) 263 end) 264 265 callModules('mainMenu') 266 callModules('modal') 267end -- showMainMenu 268 269ui.registerHandler('mainMenu',function(delta) 270 showMainMenu() 271end) 272