Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1 @@
|
||||
#include "../definitions/empire_data.as"
|
||||
@@ -0,0 +1,11 @@
|
||||
import version;
|
||||
|
||||
void init() {
|
||||
string ver = SCRIPT_VERSION;
|
||||
int pos = ver.findLast(" ");
|
||||
if(pos != -1)
|
||||
ver = ver.substr(pos+2);
|
||||
else if(ver.length != 0)
|
||||
ver = ver.substr(1);
|
||||
errorVersion = toUInt(ver);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "../definitions/icons.as"
|
||||
@@ -0,0 +1,64 @@
|
||||
import elements.IGuiElement;
|
||||
from gui import onMouseEvent, onKeyboardEvent;
|
||||
|
||||
void onMouseMoved(int x, int y) {
|
||||
MouseEvent evt;
|
||||
evt.type = MET_Moved;
|
||||
evt.x = x;
|
||||
evt.y = y;
|
||||
onMouseEvent(evt);
|
||||
}
|
||||
|
||||
bool onMouseButton(int button, bool pressed) {
|
||||
MouseEvent evt;
|
||||
if(pressed)
|
||||
evt.type = MET_Button_Down;
|
||||
else
|
||||
evt.type = MET_Button_Up;
|
||||
evt.button = button;
|
||||
vec2i mpos = mousePos;
|
||||
evt.x = mpos.x;
|
||||
evt.y = mpos.y;
|
||||
return onMouseEvent(evt);
|
||||
}
|
||||
|
||||
bool onCharTyped(int chr) {
|
||||
KeyboardEvent evt;
|
||||
evt.type = KET_Key_Typed;
|
||||
evt.key = chr;
|
||||
return onKeyboardEvent(evt);
|
||||
}
|
||||
|
||||
bool onKeyEvent(int key, int keyaction) {
|
||||
KeyboardEvent evt;
|
||||
bool pressed = (keyaction & KA_Pressed) != 0;
|
||||
if(pressed)
|
||||
evt.type = KET_Key_Down;
|
||||
else
|
||||
evt.type = KET_Key_Up;
|
||||
evt.key = key;
|
||||
return onKeyboardEvent(evt);
|
||||
}
|
||||
|
||||
void onMouseWheel(double x, double y) {
|
||||
MouseEvent evt;
|
||||
evt.type = MET_Scrolled;
|
||||
evt.x = int(floor(x));
|
||||
evt.y = int(floor(y));
|
||||
onMouseEvent(evt);
|
||||
}
|
||||
|
||||
void main_menu(bool pressed) {
|
||||
if(pressed) {
|
||||
if(game_state == GS_Menu) {
|
||||
if(game_running)
|
||||
switchToGame();
|
||||
}
|
||||
else
|
||||
switchToMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void init() {
|
||||
keybinds::Global.addBind(KB_TOGGLE_MENU, "main_menu");
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import menus;
|
||||
import saving;
|
||||
import dialogs.MessageDialog;
|
||||
|
||||
const string DATE_FORMAT("%Y-%m-%d %H:%M");
|
||||
class SaveItem : MenuAction {
|
||||
string fname;
|
||||
int64 mtime;
|
||||
string date;
|
||||
|
||||
SaveItem(const string& filename) {
|
||||
fname = filename;
|
||||
super(getBasename(filename, false), 1);
|
||||
|
||||
mtime = getModifiedTime(filename);
|
||||
date = strftime(DATE_FORMAT, mtime);
|
||||
}
|
||||
|
||||
void draw(GuiListbox@ ele, uint flags, const recti& absPos) override {
|
||||
MenuAction::draw(ele, flags, absPos);
|
||||
|
||||
const Font@ detail = ele.skin.getFont(FT_Small);
|
||||
detail.draw(pos=absPos.padded(6), text=date, vertAlign=1.0, horizAlign=1.0);
|
||||
}
|
||||
|
||||
int opCmp(const SaveItem@ other) const {
|
||||
if(mtime < other.mtime)
|
||||
return -1;
|
||||
if(mtime > other.mtime)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadMenu : MenuBox {
|
||||
LoadMenu() {
|
||||
super();
|
||||
}
|
||||
|
||||
void buildMenu() {
|
||||
title.text = locale::LOAD_GAME;
|
||||
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 11), locale::MENU_BACK, 0));
|
||||
|
||||
string dir = baseProfile["saves"];
|
||||
FileList files(dir, "*.sr2");
|
||||
|
||||
uint cnt = files.length;
|
||||
array<SaveItem@> list;
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
list.insertLast(SaveItem(files.path[i]));
|
||||
list.sortDesc();
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
items.addItem(list[i]);
|
||||
}
|
||||
|
||||
void onSelected(const string& name, int value) {
|
||||
if(value == 0) {
|
||||
if(mpServer && !game_running)
|
||||
mpDisconnect();
|
||||
switchToMenu(main_menu, false);
|
||||
return;
|
||||
}
|
||||
else if(value == 1) {
|
||||
string path = path_join(baseProfile["saves"], name)+".sr2";
|
||||
|
||||
SaveFileInfo info;
|
||||
getSaveFileInfo(path, info);
|
||||
|
||||
if(!info.hasMods()) {
|
||||
message(locale::SAVE_NO_MODS);
|
||||
return;
|
||||
}
|
||||
|
||||
uint version = getSaveVersion(path);
|
||||
if(!isSaveCompatible(version)) {
|
||||
auto@ dialog = message(locale::SAVE_NO_COMPAT);
|
||||
dialog.titleColor = colors::Red;
|
||||
return;
|
||||
}
|
||||
|
||||
switchToMenu(main_menu, false, true);
|
||||
loadGame(path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void hide() {
|
||||
backgroundFile = "";
|
||||
MenuBox::hide();
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
switch(event.type) {
|
||||
case GUI_Hover_Changed:
|
||||
if(event.caller is items) {
|
||||
MenuAction@ act = cast<MenuAction>(items.hoveredItem);
|
||||
if(act !is null && act.value == 1) {
|
||||
backgroundFile = path_join(baseProfile["saves"], act.text)+".png";
|
||||
if(!fileExists(backgroundFile))
|
||||
backgroundFile = "";
|
||||
}
|
||||
else
|
||||
backgroundFile = "";
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MenuBox::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
void init() {
|
||||
@load_menu = LoadMenu();
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
import menus;
|
||||
import settings.game_settings;
|
||||
from new_game import showNewGame;
|
||||
from multiplayer_menu import showMultiplayer;
|
||||
from irc_window import openIRC, closeIRC, LinkableMarkupText;
|
||||
import dialogs.QuestionDialog;
|
||||
import icons;
|
||||
|
||||
// TODO: Switch this out once we fix multiple starts.
|
||||
const bool M_BROKEN = false;
|
||||
|
||||
enum MenuActions {
|
||||
MA_NewGame,
|
||||
MA_EndGame,
|
||||
MA_Tutorial,
|
||||
MA_Campaign,
|
||||
MA_LoadGame,
|
||||
MA_SaveGame,
|
||||
MA_Options,
|
||||
MA_Resume,
|
||||
MA_Quit,
|
||||
MA_OpenIRC,
|
||||
MA_CloseIRC,
|
||||
MA_Multiplayer,
|
||||
MA_Disconnect,
|
||||
MA_Sandbox,
|
||||
MA_Update,
|
||||
MA_Mods,
|
||||
};
|
||||
|
||||
class MainMenu : MenuBox {
|
||||
MenuNews news;
|
||||
|
||||
MainMenu() {
|
||||
super();
|
||||
}
|
||||
|
||||
void buildMenu() {
|
||||
if(game_running && gameSpeed == 0)
|
||||
title.text = locale::PAUSED_MENU;
|
||||
else
|
||||
title.text = locale::MAIN_MENU;
|
||||
|
||||
if(game_running) {
|
||||
if(gameSpeed == 0 && settings::bMenuPause)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 10), locale::RESUME_GAME, MA_Resume));
|
||||
else
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 10), locale::RETURN_TO_GAME, MA_Resume));
|
||||
}
|
||||
|
||||
if(mpClient)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 8), locale::DISCONNECT, MA_Disconnect));
|
||||
else if(game_running)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 8), locale::END_GAME, MA_EndGame));
|
||||
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 3), locale::TUTORIAL, MA_Tutorial));
|
||||
//items.addItem(MenuAction(Sprite(material::TabPlanets), locale::CAMPAIGN, MA_Campaign));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 0), locale::NEW_GAME, MA_NewGame));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 1), locale::LOAD_GAME, MA_LoadGame));
|
||||
|
||||
if(game_running && !mpClient)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 2), locale::SAVE_GAME, MA_SaveGame));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::ResourceIconsSmall, 46), locale::MODS_MENU, MA_Mods));
|
||||
if(!game_running && !STEAM_EQUIV_BUILD)
|
||||
items.addItem(MenuAction(icons::Refresh, locale::CHECK_FOR_UPDATES, MA_Update));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 4), locale::MULTIPLAYER, MA_Multiplayer));
|
||||
items.addItem(MenuAction(Sprite(material::TabDesigns), locale::SANDBOX, MA_Sandbox));
|
||||
if(IRC.running)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 5), locale::CLOSE_IRC, MA_CloseIRC));
|
||||
else
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 6), locale::OPEN_IRC, MA_OpenIRC));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 7), locale::MENU_OPTIONS, MA_Options));
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 8), locale::QUIT_GAME, MA_Quit));
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
if(!game_running && !menu_container.animating && menu_container.visible) {
|
||||
if(mpIsConnected())
|
||||
showNewGame(true);
|
||||
else if(mpIsConnecting() || cloud::queueRequest)
|
||||
showMultiplayer();
|
||||
}
|
||||
}
|
||||
|
||||
void startTutorial() {
|
||||
GameSettings settings;
|
||||
settings.defaults();
|
||||
settings.galaxies[0].map_id = "Tutorial.Tutorial";
|
||||
|
||||
Message msg;
|
||||
settings.write(msg);
|
||||
if(topMod !is baseMod) {
|
||||
array<string> basemods = {"base"};
|
||||
switchToMods(basemods);
|
||||
}
|
||||
startNewGame(msg);
|
||||
}
|
||||
|
||||
void startSandbox() {
|
||||
GameSettings settings;
|
||||
settings.defaults();
|
||||
settings.galaxies[0].map_id = "Sandbox.Sandbox";
|
||||
|
||||
Message msg;
|
||||
settings.write(msg);
|
||||
startNewGame(msg);
|
||||
}
|
||||
|
||||
void _stopGame() {
|
||||
stopGame();
|
||||
refresh();
|
||||
}
|
||||
|
||||
void animate(MenuAnimation type) {
|
||||
if(type == MAni_LeftOut || type == MAni_RightOut)
|
||||
showDescBox(null);
|
||||
MenuBox::animate(type);
|
||||
}
|
||||
|
||||
void completeAnimation(MenuAnimation type) {
|
||||
if(type == MAni_LeftShow || type == MAni_RightShow)
|
||||
showDescBox(news);
|
||||
MenuBox::completeAnimation(type);
|
||||
}
|
||||
|
||||
void onSelected(const string& name, int value) {
|
||||
switch(value) {
|
||||
case MA_Resume:
|
||||
switchToGame();
|
||||
break;
|
||||
case MA_NewGame:
|
||||
showNewGame();
|
||||
break;
|
||||
case MA_Tutorial:
|
||||
if(game_running)
|
||||
question(locale::PROMPT_TUTORIAL, ConfirmChoice(MenuChoice(this.startTutorial)));
|
||||
else
|
||||
startTutorial();
|
||||
break;
|
||||
case MA_Campaign:
|
||||
switchToMenu(campaign_menu);
|
||||
break;
|
||||
case MA_Sandbox:
|
||||
if(game_running)
|
||||
question(locale::PROMPT_SANDBOX, ConfirmChoice(MenuChoice(this.startSandbox)));
|
||||
else
|
||||
startSandbox();
|
||||
break;
|
||||
case MA_Options:
|
||||
switchToMenu(options_menu);
|
||||
break;
|
||||
case MA_LoadGame:
|
||||
switchToMenu(load_menu);
|
||||
break;
|
||||
case MA_SaveGame:
|
||||
switchToMenu(save_menu);
|
||||
break;
|
||||
case MA_Mods:
|
||||
switchToMenu(mods_menu);
|
||||
break;
|
||||
case MA_EndGame:
|
||||
if(game_running)
|
||||
question(locale::PROMPT_END, ConfirmChoice(MenuChoice(this._stopGame)));
|
||||
else
|
||||
_stopGame();
|
||||
break;
|
||||
case MA_Disconnect:
|
||||
if(game_running)
|
||||
question(locale::PROMPT_DISCONNECT, ConfirmChoice(MenuChoice(this._stopGame)));
|
||||
else {
|
||||
mpDisconnect();
|
||||
_stopGame();
|
||||
}
|
||||
break;
|
||||
case MA_OpenIRC:
|
||||
if(!IRC.running) {
|
||||
IRC.nickname = settings::sNickname;
|
||||
IRC.connect();
|
||||
openIRC();
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
case MA_CloseIRC:
|
||||
if(IRC.running) {
|
||||
IRC.disconnect();
|
||||
closeIRC();
|
||||
refresh();
|
||||
}
|
||||
break;
|
||||
case MA_Quit:
|
||||
if(game_running)
|
||||
question(locale::PROMPT_QUIT, ConfirmChoice(quitGame));
|
||||
else
|
||||
quitGame();
|
||||
break;
|
||||
case MA_Multiplayer:
|
||||
showMultiplayer();
|
||||
break;
|
||||
case MA_Update:
|
||||
checkForUpdates();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
funcdef void MenuChoice();
|
||||
|
||||
class ConfirmChoice : QuestionDialogCallback {
|
||||
MenuChoice@ choice;
|
||||
|
||||
ConfirmChoice(MenuChoice@ Choice) {
|
||||
@choice = Choice;
|
||||
}
|
||||
|
||||
void questionCallback(QuestionDialog@ dialog, int answer) {
|
||||
if(answer == QA_Yes)
|
||||
choice();
|
||||
}
|
||||
};
|
||||
|
||||
class MenuNews : DescBox {
|
||||
GuiPanel@ newsPanel;
|
||||
LinkableMarkupText@ newsText;
|
||||
WebData wdata;
|
||||
bool shown = false;
|
||||
|
||||
GuiPanel@ modsPanel;
|
||||
|
||||
GuiMarkupText@ modsText;
|
||||
GuiButton@ modsButton;
|
||||
GuiButton@ workshopButton;
|
||||
GuiButton@ internetButton;
|
||||
|
||||
MenuNews() {
|
||||
@newsPanel = GuiPanel(this, Alignment(Left, Top, Right, Bottom-100));
|
||||
@newsText = LinkableMarkupText(newsPanel, recti_area(12,12,100,100));
|
||||
newsText.text = "...";
|
||||
newsText.paragraphize = true;
|
||||
|
||||
@modsPanel = GuiPanel(this, Alignment(Left, Bottom-88, Right, Bottom));
|
||||
@modsText = GuiMarkupText(modsPanel, Alignment(Left+12, Top+12, Right-12, Bottom-52));
|
||||
modsText.defaultFont = FT_Bold;
|
||||
|
||||
@modsButton = GuiButton(modsPanel, Alignment(Left+0.5f-204, Bottom-50, Width=200, Height=40), locale::MANAGE_MODS);
|
||||
modsButton.buttonIcon = Sprite(spritesheet::ResourceIconsSmall, 46);
|
||||
|
||||
@workshopButton = GuiButton(modsPanel, Alignment(Left+0.5f+4, Bottom-50, Width=200, Height=40), locale::OPEN_WORKSHOP);
|
||||
workshopButton.buttonIcon = icons::Import;
|
||||
|
||||
@internetButton = GuiButton(newsPanel, Alignment(Left+0.5f-200, Top+0.5f-30, Left+0.5f+200, Top+0.5f+30), locale::ENABLE_INTERNET);
|
||||
internetButton.visible = false;
|
||||
|
||||
if(cloud::isActive) {
|
||||
settings::bEnableInternet = true;
|
||||
}
|
||||
else {
|
||||
workshopButton.visible = false;
|
||||
modsButton.alignment.left.pixels += 104;
|
||||
}
|
||||
|
||||
if(settings::bEnableInternet) {
|
||||
getWikiPage("News", wdata);
|
||||
}
|
||||
else {
|
||||
internetButton.visible = true;
|
||||
newsText.text = "[font=Medium]News[/font]";
|
||||
shown = true;
|
||||
}
|
||||
|
||||
refresh();
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
DescBox::updateAbsolutePosition();
|
||||
if(newsText !is null)
|
||||
newsText.size = vec2i(newsPanel.size.width-24, newsText.renderer.height+10);
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
uint installed = 0;
|
||||
uint enabled = 0;
|
||||
for(uint i = 0, cnt = modCount; i < cnt; ++i) {
|
||||
auto@ mod = getMod(i);
|
||||
if(!mod.listed)
|
||||
continue;
|
||||
installed += 1;
|
||||
if(mod.enabled)
|
||||
enabled += 1;
|
||||
}
|
||||
|
||||
modsText.text = format("[center]"+locale::MENU_MOD_COUNTS+"[/center]", toString(installed), toString(enabled));
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) override {
|
||||
if(evt.type == GUI_Clicked) {
|
||||
if(evt.caller is modsButton) {
|
||||
switchToMenu(mods_menu);
|
||||
return true;
|
||||
}
|
||||
else if(evt.caller is workshopButton) {
|
||||
openBrowser("http://steamcommunity.com/app/282590/workshop/");
|
||||
return true;
|
||||
}
|
||||
else if(evt.caller is internetButton) {
|
||||
internetButton.visible = false;
|
||||
shown = false;
|
||||
getWikiPage("News", wdata);
|
||||
|
||||
settings::bEnableInternet = true;
|
||||
saveSettings();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return DescBox::onGuiEvent(evt);
|
||||
}
|
||||
|
||||
void show() {
|
||||
DescBox::show();
|
||||
refresh();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if(!shown && wdata.completed) {
|
||||
string result = wdata.result;
|
||||
newsText.text = result;
|
||||
shown = true;
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
skin.draw(SS_PlainBox, SF_Normal, newsPanel.AbsolutePosition, Color(0xffffffff));
|
||||
skin.draw(SS_PlainBox, SF_Normal, modsPanel.AbsolutePosition, Color(0xffffffff));
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
void init() {
|
||||
MainMenu menu;
|
||||
|
||||
@main_menu = menu;
|
||||
showDescBox(menu.news);
|
||||
switchToMenu(menu);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "../shared/maps.as"
|
||||
@@ -0,0 +1,647 @@
|
||||
#priority init 100
|
||||
#priority draw 100
|
||||
import elements.BaseGuiElement;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiListbox;
|
||||
import elements.GuiText;
|
||||
import elements.GuiSprite;
|
||||
import elements.GuiPanel;
|
||||
import dialogs.MessageDialog;
|
||||
import version;
|
||||
from gui import animate_speed, animate_time, animate_remove;
|
||||
|
||||
enum MenuAnimation {
|
||||
MAni_LeftOut,
|
||||
MAni_RightHide,
|
||||
|
||||
MAni_RightOut,
|
||||
MAni_LeftHide,
|
||||
|
||||
MAni_LeftIn,
|
||||
MAni_RightShow,
|
||||
|
||||
MAni_RightIn,
|
||||
MAni_LeftShow,
|
||||
};
|
||||
|
||||
GuiText@ version;
|
||||
MenuContainer@ menu_container;
|
||||
GuiSprite@ menu_logo;
|
||||
MenuBox@ active_menu;
|
||||
DescBox@ active_desc;
|
||||
|
||||
MenuBox@ main_menu;
|
||||
MenuBox@ campaign_menu;
|
||||
MenuBox@ load_menu;
|
||||
MenuBox@ save_menu;
|
||||
MenuBox@ options_menu;
|
||||
MenuBox@ mods_menu;
|
||||
|
||||
const double MSLIDE_TIME = 0.6;
|
||||
const double MANI_SPEED_1 = 200.0;
|
||||
const double MANI_SPEED_2 = 120.0;
|
||||
const int MANI_SPACE = -240;
|
||||
|
||||
const double MENU_OFFSET_TIME = 0.1;
|
||||
const int MENU_OFFSET = 10;
|
||||
|
||||
const double BG_FADE_TIME = 0.7;
|
||||
const double BG_FADE_DELAY = 0.2;
|
||||
|
||||
DynamicTexture logo;
|
||||
DynamicTexture defaultBackground;
|
||||
bool hasDefaultBackground = false;
|
||||
|
||||
DynamicTexture currentBackground;
|
||||
double bgTimer = 0;
|
||||
string displayedBackground;
|
||||
string backgroundFile;
|
||||
|
||||
string latestSave;
|
||||
|
||||
void init() {
|
||||
//Show the version
|
||||
@version = GuiText(null, Alignment(Right-200, Bottom-20, Right-4, Bottom));
|
||||
version.horizAlign = 1.0;
|
||||
version.text = format("Version: $1 ($2)", GAME_VERSION, SCRIPT_VERSION);
|
||||
version.color = Color(0xaaaaaaaa);
|
||||
|
||||
//Create container
|
||||
@menu_container = MenuContainer();
|
||||
|
||||
//Ready backgrounds
|
||||
@defaultBackground.material.shader = shader::MenuBlur;
|
||||
defaultBackground.material.wrapHorizontal = TW_ClampEdge;
|
||||
defaultBackground.material.wrapVertical = TW_ClampEdge;
|
||||
|
||||
@currentBackground.material.shader = shader::MenuSaveBackground;
|
||||
currentBackground.material.wrapHorizontal = TW_ClampEdge;
|
||||
currentBackground.material.wrapVertical = TW_ClampEdge;
|
||||
|
||||
//Find latest savegame
|
||||
string dir = baseProfile["saves"];
|
||||
FileList files(dir, "*.sr2");
|
||||
|
||||
uint cnt = files.length;
|
||||
int64 lastTime = 0;
|
||||
for(uint i = 0; i < cnt; ++i) {
|
||||
string basename = getBasename(files.basename[i], false);
|
||||
string fname = path_join(dir, basename)+".sr2";
|
||||
|
||||
int64 mtime = getModifiedTime(fname);
|
||||
if(mtime > lastTime) {
|
||||
lastTime = mtime;
|
||||
latestSave = basename;
|
||||
}
|
||||
}
|
||||
|
||||
//Find latest screenshot
|
||||
string latestShot;
|
||||
files.navigate(dir, "*.png");
|
||||
|
||||
lastTime = 0;
|
||||
cnt = files.length;
|
||||
for(uint i = 0; i < cnt; ++i) {
|
||||
string fname = files.path[i];
|
||||
|
||||
int64 mtime = getModifiedTime(fname);
|
||||
if(mtime > lastTime) {
|
||||
lastTime = mtime;
|
||||
latestShot = fname;
|
||||
}
|
||||
}
|
||||
|
||||
//Set background from latest screenshot
|
||||
if(latestShot.length > 0 && fileExists(latestShot) && settings::bMenuBGScreenshot) {
|
||||
hasDefaultBackground = true;
|
||||
defaultBackground.load(latestShot);
|
||||
}
|
||||
else {
|
||||
hasDefaultBackground = true;
|
||||
defaultBackground.load("data/images/title_shot_BG.png");
|
||||
}
|
||||
|
||||
if(hasDLC("Heralds"))
|
||||
logo.load("data/images/heralds_logo.png");
|
||||
else
|
||||
logo.load("data/images/sr_logo.png");
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
mouseLock = (game_state == GS_Game);
|
||||
|
||||
if(backgroundFile.length != 0) {
|
||||
if(backgroundFile != displayedBackground) {
|
||||
if(currentBackground.isLoaded()) {
|
||||
currentBackground.load(backgroundFile);
|
||||
bgTimer = BG_FADE_TIME;
|
||||
displayedBackground = backgroundFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
displayedBackground = "";
|
||||
}
|
||||
|
||||
if(bgTimer >= 0)
|
||||
bgTimer = max(0.0, bgTimer - time);
|
||||
|
||||
if(active_menu !is null)
|
||||
active_menu.tick(time);
|
||||
|
||||
if(isUpdating)
|
||||
updateTick(time);
|
||||
}
|
||||
|
||||
void switchToMenu(MenuBox@ menu, bool left = true, bool snap = false) {
|
||||
if(snap || active_menu is null) {
|
||||
if(active_menu !is null)
|
||||
active_menu.hide();
|
||||
if(menu !is null)
|
||||
menu.show();
|
||||
}
|
||||
else {
|
||||
active_menu.animate(left ? MAni_LeftOut : MAni_RightOut);
|
||||
if(menu !is null)
|
||||
menu.animate(left ? MAni_RightIn : MAni_LeftIn);
|
||||
}
|
||||
|
||||
@active_menu = menu;
|
||||
if(menu_logo !is null)
|
||||
menu_logo.visible = menu !is null;
|
||||
}
|
||||
|
||||
void showDescBox(DescBox@ box) {
|
||||
if(active_desc !is null)
|
||||
active_desc.hide();
|
||||
if(box !is null)
|
||||
box.show();
|
||||
@active_desc = box;
|
||||
}
|
||||
|
||||
class MenuContainer : BaseGuiElement {
|
||||
bool animating = false;
|
||||
bool hide = false;
|
||||
|
||||
MenuContainer() {
|
||||
super(null, recti());
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
if(!animating) {
|
||||
size = parent.size;
|
||||
position = vec2i(0, 0);
|
||||
}
|
||||
BaseGuiElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void animateIn() {
|
||||
animating = true;
|
||||
hide = false;
|
||||
|
||||
rect = recti_area(vec2i(-parent.size.x, 0), parent.size);
|
||||
animate_time(this, recti_area(vec2i(), parent.size), MSLIDE_TIME);
|
||||
}
|
||||
|
||||
void animateOut() {
|
||||
animating = true;
|
||||
hide = true;
|
||||
|
||||
rect = recti_area(vec2i(), parent.size);
|
||||
animate_time(this, recti_area(vec2i(-parent.size.x, 0), parent.size), MSLIDE_TIME);
|
||||
}
|
||||
|
||||
void show() {
|
||||
hide = false;
|
||||
Position = recti_area(vec2i(), parent.size);
|
||||
animate_remove(this);
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
switch(event.type) {
|
||||
case GUI_Animation_Complete:
|
||||
if(event.caller is this) {
|
||||
animating = false;
|
||||
if(hide)
|
||||
visible = false;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseGuiElement::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
class MenuAction : GuiListElement {
|
||||
int value = -1;
|
||||
Sprite icon;
|
||||
string text;
|
||||
bool disabled = false;
|
||||
double offset = 0.0;
|
||||
Color color;
|
||||
|
||||
MenuAction(const string& txt, int val, bool dis = false) {
|
||||
value = val;
|
||||
text = txt;
|
||||
disabled = dis;
|
||||
}
|
||||
|
||||
MenuAction(const Sprite& sprt, const string& txt, int val, bool dis = false) {
|
||||
value = val;
|
||||
text = txt;
|
||||
disabled = dis;
|
||||
icon = sprt;
|
||||
}
|
||||
|
||||
void set(const string& txt) {
|
||||
text = txt;
|
||||
}
|
||||
|
||||
string get() {
|
||||
return text;
|
||||
}
|
||||
|
||||
void draw(GuiListbox@ ele, uint flags, const recti& absPos) override {
|
||||
const Font@ font = ele.skin.getFont(ele.TextFont);
|
||||
int baseLine = font.getBaseline();
|
||||
vec2i textOffset(ele.horizPadding, (ele.lineHeight - baseLine) / 2);
|
||||
textOffset.x += offset * MENU_OFFSET;
|
||||
if(ele.itemStyle == SS_NULL)
|
||||
ele.skin.draw(SS_ListboxItem, flags, absPos);
|
||||
if(icon.valid) {
|
||||
int iSize = absPos.height - 6;
|
||||
recti iPos = recti_area(absPos.topLeft + vec2i(textOffset.x, 4), vec2i(iSize, iSize));
|
||||
iPos = iPos.aspectAligned(icon.aspect);
|
||||
icon.draw(iPos);
|
||||
textOffset.x += iSize + 8;
|
||||
}
|
||||
if(disabled)
|
||||
font.draw(absPos.topLeft + textOffset, text, Color(0x888888ff));
|
||||
else
|
||||
font.draw(absPos.topLeft + textOffset, text, color);
|
||||
if(flags & SF_Hovered != 0)
|
||||
offset = min(1.0, offset + (frameLength / MENU_OFFSET_TIME));
|
||||
else
|
||||
offset = max(0.0, offset - (frameLength / MENU_OFFSET_TIME));
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event) {
|
||||
return disabled;
|
||||
}
|
||||
};
|
||||
|
||||
class MenuBox : BaseGuiElement {
|
||||
GuiListbox@ items;
|
||||
GuiText@ title;
|
||||
|
||||
MenuAnimation anim;
|
||||
bool animating = false;
|
||||
bool selectable = false;
|
||||
|
||||
MenuBox() {
|
||||
super(menu_container, recti());
|
||||
visible = false;
|
||||
|
||||
@title = GuiText(this, Alignment(Left, Top+4, Right, Top+44), "Load Game");
|
||||
title.horizAlign = 0.5;
|
||||
title.font = FT_Big;
|
||||
|
||||
@items = GuiListbox(this, Alignment(Left+4, Top+44, Right-4, Bottom-4));
|
||||
items.itemStyle = SS_MainMenuItem;
|
||||
items.font = FT_Medium;
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
}
|
||||
|
||||
void animate(MenuAnimation type) {
|
||||
switch(type) {
|
||||
case MAni_LeftIn:
|
||||
sendToBack();
|
||||
show();
|
||||
case MAni_LeftOut:
|
||||
animate_speed(this, basePosition-vec2i(size.width/2+MANI_SPACE, 0), MANI_SPEED_1);
|
||||
break;
|
||||
case MAni_RightHide:
|
||||
case MAni_RightShow:
|
||||
animate_speed(this, basePosition, MANI_SPEED_2);
|
||||
break;
|
||||
case MAni_RightIn:
|
||||
sendToBack();
|
||||
show();
|
||||
case MAni_RightOut:
|
||||
animate_speed(this, basePosition+vec2i(size.width/2+MANI_SPACE, 0), MANI_SPEED_1);
|
||||
break;
|
||||
case MAni_LeftHide:
|
||||
case MAni_LeftShow:
|
||||
animate_speed(this, basePosition, MANI_SPEED_2);
|
||||
break;
|
||||
}
|
||||
|
||||
anim = type;
|
||||
animating = true;
|
||||
}
|
||||
|
||||
void completeAnimation(MenuAnimation type) {
|
||||
animating = false;
|
||||
switch(type) {
|
||||
case MAni_LeftOut:
|
||||
sendToBack();
|
||||
animate(MAni_RightHide);
|
||||
break;
|
||||
case MAni_RightHide:
|
||||
hide();
|
||||
break;
|
||||
case MAni_RightOut:
|
||||
sendToBack();
|
||||
animate(MAni_LeftHide);
|
||||
break;
|
||||
case MAni_LeftHide:
|
||||
hide();
|
||||
break;
|
||||
case MAni_LeftIn:
|
||||
bringToFront();
|
||||
animate(MAni_RightShow);
|
||||
break;
|
||||
case MAni_RightShow:
|
||||
break;
|
||||
case MAni_RightIn:
|
||||
bringToFront();
|
||||
animate(MAni_LeftShow);
|
||||
break;
|
||||
case MAni_LeftShow:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!animating)
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
recti get_basePosition() {
|
||||
int width = 576;
|
||||
int height = min(648, int(Parent.size.height * 0.8f - 36));
|
||||
|
||||
vec2i position = vec2i(Parent.size.width / 2 - 12 - width,
|
||||
Parent.size.height * 0.2f + 24);
|
||||
return recti_area(position, vec2i(width, height));
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
if(!animating)
|
||||
rect = basePosition;
|
||||
BaseGuiElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
clearMenu();
|
||||
buildMenu();
|
||||
}
|
||||
|
||||
void clearMenu() {
|
||||
items.clearItems();
|
||||
}
|
||||
|
||||
void buildMenu() {
|
||||
}
|
||||
|
||||
void show() {
|
||||
clearMenu();
|
||||
buildMenu();
|
||||
visible = true;
|
||||
}
|
||||
|
||||
void hide() {
|
||||
visible = false;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
switch(event.type) {
|
||||
case GUI_Changed:
|
||||
if(event.caller is items) {
|
||||
MenuAction@ act = cast<MenuAction>(items.selectedItem);
|
||||
if(act !is null)
|
||||
onSelected(act.text, act.value);
|
||||
if(!selectable)
|
||||
items.clearSelection();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case GUI_Animation_Complete:
|
||||
if(event.caller is this) {
|
||||
completeAnimation(anim);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseGuiElement::onGuiEvent(event);
|
||||
}
|
||||
|
||||
void onSelected(const string& name, int value) {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
skin.draw(SS_MainMenuPanel, SF_Normal, AbsolutePosition);
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class DescBox : BaseGuiElement {
|
||||
GuiText@ title;
|
||||
GuiPanel@ panel;
|
||||
|
||||
DescBox() {
|
||||
super(menu_container, recti());
|
||||
visible = false;
|
||||
|
||||
@title = GuiText(this, Alignment(Left, Top+4, Right, Top+44), "");
|
||||
title.horizAlign = 0.5;
|
||||
title.font = FT_Big;
|
||||
|
||||
@panel = GuiPanel(this, Alignment(Left+3, Top+44, Right-4, Bottom-4));
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
recti get_basePosition() {
|
||||
int width = 576;
|
||||
int height = min(648, int(Parent.size.height * 0.8f - 36));
|
||||
|
||||
vec2i position = vec2i(Parent.size.width / 2 + 12,
|
||||
Parent.size.height * 0.2f + 24);
|
||||
return recti_area(position, vec2i(width, height));
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
rect = basePosition;
|
||||
BaseGuiElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
}
|
||||
|
||||
void show() {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
void hide() {
|
||||
visible = false;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
skin.draw(SS_MainMenuDescPanel, SF_Normal, AbsolutePosition);
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
//Pause the game when entering the menu if we're set to
|
||||
double prevGameSpeed = 0;
|
||||
void onGameStateChange() {
|
||||
if(game_state == GS_Menu) {
|
||||
if(!mpClient && !mpServer) {
|
||||
prevGameSpeed = gameSpeed;
|
||||
if(settings::bMenuPause && gameSpeed != 0)
|
||||
gameSpeed = 0;
|
||||
}
|
||||
active_menu.refresh();
|
||||
}
|
||||
else {
|
||||
if(!mpClient && !mpServer && settings::bMenuPause && gameSpeed == 0)
|
||||
gameSpeed = prevGameSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
//Render client view if a game is active
|
||||
void preRender(double time) {
|
||||
if(game_running)
|
||||
preRenderClient();
|
||||
}
|
||||
|
||||
void render(double time) {
|
||||
if(game_running)
|
||||
renderClient();
|
||||
}
|
||||
|
||||
void drawBackground(DynamicTexture@ bg, double alpha = 1.0) {
|
||||
if(!bg.isLoaded(0))
|
||||
return;
|
||||
|
||||
vec2i screen(screenSize);
|
||||
vec2i matSize(bg.size[0]);
|
||||
|
||||
if(matSize.width == 0 || matSize.height == 0)
|
||||
return;
|
||||
|
||||
float aspect = float(matSize.width) / float(matSize.height);
|
||||
if(aspect > 1.f) {
|
||||
matSize.height = float(screen.width) / aspect;
|
||||
matSize.width = screen.width;
|
||||
}
|
||||
else {
|
||||
matSize.height = screen.height;
|
||||
matSize.width = float(screen.height) * aspect;
|
||||
}
|
||||
|
||||
recti pos = recti_area(
|
||||
vec2i((screen.width - matSize.width) / 2,
|
||||
(screen.height - matSize.height) / 2),
|
||||
matSize);
|
||||
|
||||
Color col(0xffffffff);
|
||||
col.a = alpha * 255;
|
||||
bg.draw(pos, col);
|
||||
}
|
||||
|
||||
bool isUpdating = false;
|
||||
bool startedUpdate = false;
|
||||
WebData updateCheck;
|
||||
void checkForUpdates() {
|
||||
if(isUpdating)
|
||||
return;
|
||||
isUpdating = true;
|
||||
webAPICall("updates/version", updateCheck);
|
||||
}
|
||||
|
||||
void updateTick(double time) {
|
||||
if(startedUpdate) {
|
||||
if(!::updating) {
|
||||
startedUpdate = false;
|
||||
isUpdating = false;
|
||||
if(updateStatus < 0)
|
||||
message(format(locale::UPDATE_FAIL, toString(updateStatus)));
|
||||
else
|
||||
quitGame();
|
||||
}
|
||||
}
|
||||
else if(updateCheck.completed) {
|
||||
if(updateCheck.error) {
|
||||
message(locale::CHECK_UPDATE_FAIL+":\n"+updateCheck.errorStr);
|
||||
isUpdating = false;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
string ver = updateCheck.result.trimmed();
|
||||
if(ver == GAME_VERSION) {
|
||||
message(locale::CHECK_UPDATE_UPTODATE);
|
||||
isUpdating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//Do update
|
||||
startedUpdate = true;
|
||||
updateGame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw() {
|
||||
//Draw background screenshot
|
||||
if(!game_running && defaultBackground.isLoaded() && hasDefaultBackground)
|
||||
drawBackground(defaultBackground);
|
||||
if(currentBackground.isLoaded() && backgroundFile.length != 0) {
|
||||
if(BG_FADE_TIME - bgTimer > BG_FADE_DELAY)
|
||||
drawBackground(currentBackground, (BG_FADE_TIME - bgTimer) / BG_FADE_TIME);
|
||||
}
|
||||
|
||||
//Draw top and bottom bars
|
||||
vec2i screen = screenSize;
|
||||
double size = double(screen.x) / 1920;
|
||||
|
||||
if(isUpdating) {
|
||||
gui_root.visible = false;
|
||||
|
||||
string txt;
|
||||
if(updating)
|
||||
txt = format(locale::UPDATE_PROGRESS, toString(updateProgress, 0));
|
||||
else
|
||||
txt = locale::CHECKING_UPDATES;
|
||||
|
||||
auto@ ft = gui_root.skin.getFont(FT_Big);
|
||||
ft.draw(pos=recti_area(vec2i(),screenSize), horizAlign=0.5, vertAlign=0.5,
|
||||
stroke=colors::Black, color=colors::Green, text=txt);
|
||||
}
|
||||
else if(inGalaxyCreation && !mpClient) {
|
||||
gui_root.visible = false;
|
||||
auto@ ft = gui_root.skin.getFont(FT_Big);
|
||||
ft.draw(pos=recti_area(vec2i(),screenSize), horizAlign=0.5, vertAlign=0.5,
|
||||
stroke=colors::Black, color=colors::Green, text=locale::MENU_LOADING);
|
||||
}
|
||||
else {
|
||||
gui_root.visible = true;
|
||||
if(menu_container.visible && logo.isLoaded()) {
|
||||
vec2i size = logo.material.size;
|
||||
int logoWidth = min(840, menu_container.size.width);
|
||||
int logoHeight = min(350, int(floor(0.2 * menu_container.size.height) + 23));
|
||||
recti area = recti_area(vec2i((menu_container.size.width-logoWidth)/2, 0), vec2i(logoWidth, logoHeight));
|
||||
area += menu_container.absolutePosition.topLeft;
|
||||
|
||||
area = area.aspectAligned(float(size.x) / float(size.y), 0.5, 0.5);
|
||||
logo.draw(area, colors::White);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
import menus;
|
||||
import saving;
|
||||
import dialogs.MessageDialog;
|
||||
import dialogs.QuestionDialog;
|
||||
import dialogs.InputDialog;
|
||||
import elements.GuiMarkupText;
|
||||
import settings.game_settings;
|
||||
from irc_window import LinkableMarkupText;
|
||||
import icons;
|
||||
|
||||
class ModAction : MenuAction {
|
||||
Mod@ mod;
|
||||
DynamicTexture@ tex;
|
||||
bool prevEnabled;
|
||||
|
||||
ModAction(Mod@ mod, DynamicTexture@ tex) {
|
||||
super(Sprite(tex.material), mod.name, 0);
|
||||
@this.mod = mod;
|
||||
@this.tex = tex;
|
||||
prevEnabled = mod.enabled;
|
||||
}
|
||||
|
||||
void draw(GuiListbox@ ele, uint flags, const recti& absPos) override {
|
||||
if(!mod.forCurrentVersion)
|
||||
color = Color(0xaa4040ff);
|
||||
else if(!mod.enabled)
|
||||
color = Color(0x888888ff);
|
||||
else
|
||||
color = colors::White;
|
||||
MenuAction::draw(ele, flags, absPos);
|
||||
|
||||
int h = absPos.height;
|
||||
recti iPos = recti_area(vec2i(absPos.botRight.x-h-80+8, absPos.topLeft.y+10), vec2i(h-18, h-18));
|
||||
recti tPos = recti_area(vec2i(absPos.botRight.x-80, absPos.topLeft.y+2), vec2i(78, h-2));
|
||||
const Font@ ft = ele.skin.getFont(FT_Bold);
|
||||
if(mod.enabled) {
|
||||
icons::Plus.draw(iPos);
|
||||
ft.draw(pos=tPos, text=locale::ENABLED, stroke=colors::Black, color=colors::Green);
|
||||
}
|
||||
else {
|
||||
icons::Minus.draw(iPos);
|
||||
ft.draw(pos=tPos, text=locale::DISABLED, stroke=colors::Black, color=colors::Red);
|
||||
}
|
||||
|
||||
if(mod.isNew && mod.forCurrentVersion) {
|
||||
recti iPos = recti_area(vec2i(absPos.botRight.x-h-80*2+4, absPos.topLeft.y+6), vec2i(h-10, h-10));
|
||||
recti tPos = recti_area(vec2i(absPos.botRight.x-80*2, absPos.topLeft.y+2), vec2i(78, h-2));
|
||||
const Font@ ft = ele.skin.getFont(FT_Bold);
|
||||
spritesheet::CardCategoryIcons.draw(5, iPos);
|
||||
ft.draw(pos=tPos, text=locale::NEW, stroke=colors::Black, color=Color(0xffff00ff));
|
||||
}
|
||||
}
|
||||
|
||||
int opCmp(const ModAction@ other) const {
|
||||
if(mod.isNew && !other.mod.isNew)
|
||||
return -1;
|
||||
if(other.mod.isNew && !mod.isNew)
|
||||
return 1;
|
||||
if(mod.enabled && !other.mod.enabled)
|
||||
return -1;
|
||||
if(other.mod.enabled && !mod.enabled)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
bool inOpenPage = false;
|
||||
class ModsMenu : MenuBox, IInputDialogCallback {
|
||||
ModBox box;
|
||||
int prevSelected = -1;
|
||||
array<ModAction@> actions;
|
||||
|
||||
GuiButton@ newButton;
|
||||
GuiButton@ editButton;
|
||||
|
||||
ModsMenu() {
|
||||
super();
|
||||
items.alignment.bottom.pixels = 40;
|
||||
@newButton = GuiButton(this, Alignment(Left+0.5f-202, Bottom-35, Width=200, Height=30), locale::NEW_MOD);
|
||||
newButton.visible = !inOpenPage;
|
||||
@editButton = GuiButton(this, Alignment(Left+0.5f+2, Bottom-35, Width=200, Height=30), locale::EDIT_MOD);
|
||||
editButton.visible = items.selected >= 1 && !inOpenPage;
|
||||
}
|
||||
|
||||
void buildMenu() {
|
||||
title.text = locale::MODS_MENU;
|
||||
selectable = true;
|
||||
items.required = true;
|
||||
|
||||
if(inOpenPage)
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 10), locale::MENU_CONTINUE_MAIN, 0));
|
||||
else
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 11), locale::MENU_BACK, 0));
|
||||
|
||||
string sel = "";
|
||||
if(prevSelected >= 1 && uint(prevSelected-1) < actions.length)
|
||||
sel = actions[prevSelected-1].mod.name;
|
||||
actions.length = 0;
|
||||
|
||||
for(uint i = 0, cnt = modCount; i < cnt; ++i) {
|
||||
auto@ mod = getMod(i);
|
||||
if(!mod.listed)
|
||||
continue;
|
||||
|
||||
DynamicTexture tex;
|
||||
|
||||
if(fileExists(path_join(mod.abspath, "logo.png")))
|
||||
tex.load(path_join(mod.abspath, "logo.png"));
|
||||
|
||||
ModAction action(mod, tex);
|
||||
actions.insertLast(action);
|
||||
}
|
||||
actions.sortAsc();
|
||||
for(uint i = 0, cnt = actions.length; i < cnt; ++i) {
|
||||
actions[i].value = int(i+1);
|
||||
if(actions[i].mod.name == sel)
|
||||
prevSelected = i;
|
||||
if(prevSelected == -1 && actions[i].mod.isNew)
|
||||
prevSelected = i+1;
|
||||
items.addItem(actions[i]);
|
||||
}
|
||||
if(prevSelected < 1)
|
||||
prevSelected = 1;
|
||||
if(items.selected < 1)
|
||||
items.selected = min(prevSelected, items.itemCount-1);
|
||||
update();
|
||||
}
|
||||
|
||||
void update() {
|
||||
if(items.selected < 1 || uint(items.selected-1) >= actions.length)
|
||||
return;
|
||||
auto@ mod = actions[items.selected-1].mod;
|
||||
if(mod !is null)
|
||||
box.update(mod, actions[items.selected-1].tex.material);
|
||||
editButton.visible = items.selected >= 1 && !inOpenPage;
|
||||
newButton.visible = !inOpenPage;
|
||||
}
|
||||
|
||||
void changeCallback(InputDialog@ dialog) {}
|
||||
void inputCallback(InputDialog@ dialog, bool accepted) {
|
||||
if(accepted) {
|
||||
string dirname = dialog.getTextInput(0);
|
||||
if(!createNewMod(dirname)) {
|
||||
message("Could not create mod: invalid directory '"+dirname+"'");
|
||||
return;
|
||||
}
|
||||
editMod(dirname);
|
||||
}
|
||||
}
|
||||
|
||||
void editMod(const string& modName) {
|
||||
array<string> mods;
|
||||
mods.insertLast(modName);
|
||||
|
||||
GameSettings settings;
|
||||
settings.defaults();
|
||||
settings.galaxies[0].map_id = "ModEditor.ModEditor";
|
||||
|
||||
Message msg;
|
||||
settings.write(msg);
|
||||
|
||||
watchResources = true;
|
||||
switchToMods(mods);
|
||||
startNewGame(msg);
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.type == GUI_Clicked) {
|
||||
if(event.caller is newButton) {
|
||||
InputDialog@ dialog = InputDialog(this, this);
|
||||
dialog.addTitle("Create New Mod");
|
||||
dialog.accept.text = "Create";
|
||||
dialog.addTextInput("Mod Directory", "");
|
||||
|
||||
auto@ tbox = cast<GuiTextbox>(dialog.getInput(0));
|
||||
tbox.setIdentifierLimit();
|
||||
tbox.characterLimit.insert(' ');
|
||||
|
||||
addDialog(dialog);
|
||||
dialog.focusInput();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is editButton) {
|
||||
if(items.selected < 1 || uint(items.selected-1) >= actions.length)
|
||||
return true;
|
||||
Mod@ mod = actions[items.selected-1].mod;
|
||||
editMod(mod.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return MenuBox::onGuiEvent(event);
|
||||
}
|
||||
|
||||
void onSelected(const string& name, int value) {
|
||||
if(value == 0) {
|
||||
switchToMenu(main_menu, false);
|
||||
saveModState();
|
||||
inOpenPage = false;
|
||||
|
||||
if(!game_running) {
|
||||
array<string> mods;
|
||||
bool changed = false;
|
||||
for(uint i = 0, cnt = actions.length; i < cnt; ++i) {
|
||||
if(actions[i].mod.enabled != actions[i].prevEnabled)
|
||||
changed = true;
|
||||
if(actions[i].mod.enabled)
|
||||
mods.insertLast(actions[i].mod.name);
|
||||
}
|
||||
if(changed)
|
||||
switchToMods(mods);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
prevSelected = value;
|
||||
items.selected = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void animate(MenuAnimation type) {
|
||||
if(type == MAni_LeftOut || type == MAni_RightOut)
|
||||
showDescBox(null);
|
||||
MenuBox::animate(type);
|
||||
}
|
||||
|
||||
void completeAnimation(MenuAnimation type) {
|
||||
if(type == MAni_LeftShow || type == MAni_RightShow)
|
||||
showDescBox(box);
|
||||
MenuBox::completeAnimation(type);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
for(uint i = 0, cnt = actions.length; i < cnt; ++i)
|
||||
actions[i].tex.stream();
|
||||
MenuBox::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class ModBox : DescBox {
|
||||
Mod@ mod;
|
||||
GuiPanel@ descPanel;
|
||||
GuiSprite@ picture;
|
||||
GuiMarkupText@ description;
|
||||
GuiButton@ toggleButton;
|
||||
|
||||
ModBox() {
|
||||
super();
|
||||
|
||||
@picture = GuiSprite(this, Alignment(Left, Top+44, Right, Top+244));
|
||||
|
||||
@descPanel = GuiPanel(this, Alignment(Left+16, Top+254, Right-16, Bottom-50));
|
||||
@description = LinkableMarkupText(descPanel, recti_area(0,0,100,100));
|
||||
description.fitWidth = true;
|
||||
|
||||
@toggleButton = GuiButton(this, Alignment(Left+0.5f-100, Bottom-50, Left+0.5f+100, Bottom-8));
|
||||
toggleButton.font = FT_Subtitle;
|
||||
toggleButton.visible = false;
|
||||
|
||||
updateAbsolutePosition();
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void update(Mod@ mod, const Material@ mat = null) {
|
||||
@this.mod = mod;
|
||||
title.text = mod.name;
|
||||
if(mat !is null)
|
||||
picture.desc = Sprite(mat);
|
||||
string descText;
|
||||
if(!mod.forCurrentVersion)
|
||||
descText += locale::MOD_COMPATIBILITY_WARN;
|
||||
descText += mod.description;
|
||||
toggleButton.visible = true;
|
||||
toggleButton.disabled = false;
|
||||
|
||||
if(mod.enabled) {
|
||||
toggleButton.color = colors::Red;
|
||||
toggleButton.buttonIcon = icons::Minus;
|
||||
toggleButton.text = locale::DISABLE_MOD;
|
||||
}
|
||||
else {
|
||||
toggleButton.color = colors::Green;
|
||||
toggleButton.buttonIcon = icons::Plus;
|
||||
toggleButton.text = locale::ENABLE_MOD;
|
||||
}
|
||||
|
||||
//Check for conflicts
|
||||
for(uint i = 0, cnt = modCount; i < cnt; ++i) {
|
||||
auto@ other = getMod(i);
|
||||
if(other !is mod && other.enabled) {
|
||||
if(!other.isCompatible(mod)) {
|
||||
array<string> conflicts;
|
||||
mod.getConflicts(other, conflicts);
|
||||
|
||||
descText += "\n\n[color=#f00][b]";
|
||||
descText += format(locale::MOD_INCOMPATIBLE, other.name);
|
||||
if(mod.isBase && other.isBase) {
|
||||
descText += "\n"+locale::MOD_CONFLICT_BASE;
|
||||
descText += "[/b]";
|
||||
}
|
||||
else {
|
||||
descText += "\n"+locale::MOD_CONFLICT;
|
||||
descText += "[/b]\n ";
|
||||
for(uint i = 0, cnt = conflicts.length; i < cnt; ++i) {
|
||||
if(i != 0)
|
||||
descText += ", ";
|
||||
descText += conflicts[i];
|
||||
}
|
||||
}
|
||||
descText += "[/color]";
|
||||
toggleButton.disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
description.text = makebbLinks(descText);
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) override {
|
||||
if(evt.type == GUI_Clicked && evt.caller is toggleButton) {
|
||||
bool enable = !mod.enabled;
|
||||
if(enable && !mod.forCurrentVersion) {
|
||||
question(locale::MOD_COMPATIBILITY, ModEnable(this, mod));
|
||||
}
|
||||
else {
|
||||
mod.enabled = enable;
|
||||
mod.forced = false;
|
||||
update(mod);
|
||||
saveModState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return DescBox::onGuiEvent(evt);
|
||||
}
|
||||
};
|
||||
|
||||
class ModEnable : QuestionDialogCallback {
|
||||
ModBox@ menu;
|
||||
Mod@ mod;
|
||||
|
||||
ModEnable(ModBox@ menu, Mod@ mod) {
|
||||
@this.menu = menu;
|
||||
@this.mod = mod;
|
||||
}
|
||||
|
||||
void questionCallback(QuestionDialog@ dialog, int answer) {
|
||||
if(answer == QA_Yes) {
|
||||
mod.enabled = true;
|
||||
mod.forced = true;
|
||||
menu.update(mod);
|
||||
saveModState();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void init() {
|
||||
@mods_menu = ModsMenu();
|
||||
}
|
||||
|
||||
void postInit() {
|
||||
for(uint i = 0, cnt = modCount; i < cnt; ++i) {
|
||||
if(getMod(i).isNew) {
|
||||
inOpenPage = true;
|
||||
switchToMenu(mods_menu, snap=true);
|
||||
showDescBox(cast<ModsMenu>(mods_menu).box);
|
||||
mods_menu.updateAbsolutePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,790 @@
|
||||
import menus;
|
||||
import elements.BaseGuiElement;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiPanel;
|
||||
import elements.GuiText;
|
||||
import elements.GuiTextbox;
|
||||
import elements.GuiSpinbox;
|
||||
import elements.GuiCheckbox;
|
||||
import elements.GuiOverlay;
|
||||
import elements.GuiProgressbar;
|
||||
import elements.GuiBackgroundPanel;
|
||||
import dialogs.MessageDialog;
|
||||
import dialogs.InputDialog;
|
||||
import icons;
|
||||
from irc_window import showIRC;
|
||||
from new_game import showNewGame;
|
||||
|
||||
from maps import Map, maps, mapCount, getMap;
|
||||
|
||||
import util.game_options;
|
||||
|
||||
class ServerDesc {
|
||||
GameServer srv;
|
||||
bool found = false;
|
||||
};
|
||||
|
||||
class ServerElement : GuiListElement {
|
||||
string text;
|
||||
Color color;
|
||||
bool disabled = false;
|
||||
|
||||
void set(const string& txt) {
|
||||
text = txt;
|
||||
}
|
||||
|
||||
string get() {
|
||||
return text;
|
||||
}
|
||||
|
||||
void draw(GuiListbox@ ele, uint flags, const recti& absPos) {
|
||||
const Font@ font = ele.skin.getFont(ele.TextFont);
|
||||
int baseLine = font.getBaseline();
|
||||
vec2i textOffset(ele.horizPadding, (absPos.size.height - baseLine) / 2);
|
||||
|
||||
if(ele.itemStyle == SS_NULL)
|
||||
ele.skin.draw(SS_ListboxItem, flags, absPos);
|
||||
font.draw(absPos.topLeft + textOffset, text, color);
|
||||
}
|
||||
|
||||
bool get_isSelectable() {
|
||||
return !disabled;
|
||||
}
|
||||
};
|
||||
|
||||
class PasswordDialog : InputDialogCallback {
|
||||
void inputCallback(InputDialog@ dialog, bool accepted) {
|
||||
if(accepted) {
|
||||
string pwd = dialog.getTextInput(0);
|
||||
mp_list.join(pwd);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class IPJoin : InputDialogCallback {
|
||||
void inputCallback(InputDialog@ dialog, bool accepted) {
|
||||
if(accepted)
|
||||
mp_list.join(dialog.getTextInput(0), toInt(dialog.getTextInput(1)), dialog.getTextInput(2));
|
||||
}
|
||||
};
|
||||
|
||||
class Multiplayer : BaseGuiElement {
|
||||
GuiBackgroundPanel@ gamesBG;
|
||||
GuiBackgroundPanel@ optionsBG;
|
||||
GuiBackgroundPanel@ hostBG;
|
||||
|
||||
GuiProgressbar@ transferProgress;
|
||||
|
||||
GuiButton@ backButton, joinButton, queueButton;
|
||||
GuiButton@ hostButton, hostLoadButton;
|
||||
GuiButton@ refreshButton;
|
||||
GuiButton@ ircButton;
|
||||
GuiButton@ ipButton;
|
||||
|
||||
GuiText@ nickLabel;
|
||||
GuiTextbox@ nick;
|
||||
|
||||
GuiText@ serverNameLabel;
|
||||
GuiTextbox@ serverName;
|
||||
|
||||
GuiText@ passwordLabel;
|
||||
GuiTextbox@ passwordBox;
|
||||
|
||||
GuiText@ portLabel;
|
||||
GuiTextbox@ portBox;
|
||||
|
||||
GuiCheckbox@ publicToggle;
|
||||
GuiCheckbox@ punchToggle;
|
||||
|
||||
GuiText@ noServers;
|
||||
GuiListbox@ servers;
|
||||
array<ServerDesc@> gameServers;
|
||||
array<GameServer> newServers;
|
||||
|
||||
GuiText@ inQueue;
|
||||
GuiButton@ queueAccept, queueReject, queueLeave;
|
||||
|
||||
GuiText@ connectingText;
|
||||
GuiButton@ cancelButton;
|
||||
|
||||
bool animating = false;
|
||||
bool hide = false;
|
||||
bool connecting = false;
|
||||
double nextRefresh = 0.0;
|
||||
|
||||
Multiplayer() {
|
||||
super(null, recti());
|
||||
|
||||
@gamesBG = GuiBackgroundPanel(this, Alignment(
|
||||
Left+0.05f, Top+0.1f, Right-0.05f, Bottom-0.1f-242));
|
||||
gamesBG.title = locale::MENU_GAMES;
|
||||
gamesBG.titleColor = Color(0x00ff00ff);
|
||||
|
||||
@optionsBG = GuiBackgroundPanel(this, Alignment(
|
||||
Left+0.05f, Bottom-0.1f-230, Right-0.5f-6, Bottom-0.1f));
|
||||
optionsBG.title = locale::MP_OPTIONS;
|
||||
optionsBG.titleColor = Color(0xd0ffefff);
|
||||
|
||||
@hostBG = GuiBackgroundPanel(this, Alignment(
|
||||
Left+0.5f+6, Bottom-0.1f-230, Right-0.05f, Bottom-0.1f));
|
||||
hostBG.title = locale::MP_HOST_OPTIONS;
|
||||
hostBG.titleColor = Color(0xd0ffefff);
|
||||
|
||||
@noServers = GuiText(gamesBG, Alignment(Left+12,Top+33,Right-4,Top+55), locale::MP_NO_GAMES);
|
||||
noServers.color = Color(0xaaaaaaff);
|
||||
noServers.font = FT_Italic;
|
||||
@servers = GuiListbox(gamesBG, Alignment(Left+4,Top+33,Right-4,Bottom-42));
|
||||
servers.visible = false;
|
||||
|
||||
@nickLabel = GuiText(optionsBG, recti(12, 33, 110, 60), locale::NICKNAME);
|
||||
@nick = GuiTextbox(optionsBG, recti(122, 33, 280, 60), settings::sNickname);
|
||||
|
||||
@serverNameLabel = GuiText(hostBG, recti(12, 33, 110, 60), locale::MP_SERVER_NAME);
|
||||
@serverName = GuiTextbox(hostBG, recti(122, 33, 380, 60), settings::sNickname+"'s Game");
|
||||
serverName.tabIndex = 1;
|
||||
|
||||
@passwordLabel = GuiText(hostBG, recti(11, 66, 110, 93), locale::PASSWORD);
|
||||
@passwordBox = GuiTextbox(hostBG, recti(122, 66, 380, 93), "");
|
||||
passwordBox.tabIndex = 2;
|
||||
|
||||
@publicToggle = GuiCheckbox(hostBG, recti(12, 99, 140, 126), locale::MP_PUBLIC, true);
|
||||
publicToggle.tabIndex = 3;
|
||||
@punchToggle = GuiCheckbox(hostBG, recti(150, 99, 280, 126), locale::MP_PUNCHTHROUGH, true);
|
||||
punchToggle.tabIndex = 4;
|
||||
|
||||
@portLabel = GuiText(hostBG, recti(12, 132, 110, 158), locale::MP_PORT);
|
||||
@portBox = GuiTextbox(hostBG, recti(122, 132, 250, 158), "2048");
|
||||
portBox.tabIndex = 5;
|
||||
|
||||
@refreshButton = GuiButton(gamesBG, Alignment(
|
||||
Right-174, Bottom-40, Width=170, Height=36),
|
||||
locale::REFRESH);
|
||||
refreshButton.buttonIcon = Sprite(spritesheet::MenuIcons, 12);
|
||||
|
||||
@ircButton = GuiButton(gamesBG, Alignment(
|
||||
Left+4, Bottom-40, Width=200, Height=36),
|
||||
locale::MP_IRC_CHAT);
|
||||
ircButton.buttonIcon = icons::Chat;
|
||||
|
||||
@ipButton = GuiButton(gamesBG, Alignment(
|
||||
Left+208, Bottom-40, Width=200, Height=36),
|
||||
locale::MP_JOIN_IP);
|
||||
ipButton.buttonIcon = Sprite(spritesheet::MenuIcons, 13);
|
||||
|
||||
@joinButton = GuiButton(this, Alignment(
|
||||
Right-0.05f-200, Bottom-0.1f+6, Width=200, Height=46),
|
||||
locale::MP_JOIN);
|
||||
joinButton.buttonIcon = Sprite(spritesheet::MenuIcons, 13);
|
||||
|
||||
@hostButton = GuiButton(this, Alignment(
|
||||
Right-0.05f-412, Bottom-0.1f+6, Width=200, Height=46),
|
||||
locale::MP_HOST);
|
||||
hostButton.buttonIcon = Sprite(spritesheet::MenuIcons, 14);
|
||||
|
||||
@hostLoadButton = GuiButton(this, Alignment(
|
||||
Right-0.05f-624, Bottom-0.1f+6, Width=200, Height=46),
|
||||
locale::MP_HOST_LOAD);
|
||||
hostLoadButton.buttonIcon = Sprite(spritesheet::MenuIcons, 15);
|
||||
|
||||
@backButton = GuiButton(this, Alignment(
|
||||
Left+0.05f, Bottom-0.1f+6, Width=200, Height=46),
|
||||
locale::BACK);
|
||||
backButton.buttonIcon = Sprite(spritesheet::MenuIcons, 11);
|
||||
|
||||
if(cloud::isActive) {
|
||||
@queueButton = GuiButton(this, Alignment(
|
||||
Right-0.05f-836, Bottom-0.1f+6, Width=200, Height=46),
|
||||
locale::MP_QUEUE);
|
||||
queueButton.buttonIcon = Sprite(spritesheet::MenuIcons, 4);
|
||||
|
||||
@inQueue = GuiText(gamesBG, Alignment(Left+12,Top+33,Right-4,Top+61), locale::MP_QUEUE_ACTIVE);
|
||||
inQueue.font = FT_Medium;
|
||||
inQueue.horizAlign = 0.5;
|
||||
inQueue.visible = false;
|
||||
|
||||
@queueAccept = GuiButton(gamesBG, Alignment(
|
||||
Left+0.5f-205, Top+65, Width=200, Height=46),
|
||||
locale::MP_QUEUE_ACCEPT);
|
||||
queueAccept.font = FT_Medium;
|
||||
queueAccept.color = Color(0x88ff88ff);
|
||||
queueAccept.visible = false;
|
||||
|
||||
@queueReject = GuiButton(gamesBG, Alignment(
|
||||
Left+0.5f+5, Top+65, Width=200, Height=46),
|
||||
locale::MP_QUEUE_REJECT);
|
||||
queueReject.font = FT_Medium;
|
||||
queueReject.color = Color(0xff8888ff);
|
||||
queueReject.visible = false;
|
||||
|
||||
@queueLeave = GuiButton(gamesBG, Alignment(
|
||||
Left+0.5f-100, Top+65, Width=200, Height=46),
|
||||
locale::MP_QUEUE_LEAVE);
|
||||
queueLeave.font = FT_Medium;
|
||||
queueLeave.visible = false;
|
||||
}
|
||||
|
||||
@connectingText = GuiText(this, Alignment(Left, Top+0.5f-56, Right, Top+0.5f));
|
||||
connectingText.font = FT_Medium;
|
||||
connectingText.horizAlign = 0.5;
|
||||
connectingText.visible = false;
|
||||
|
||||
@cancelButton = GuiButton(this, Alignment(
|
||||
Left+0.5f-100, Top+0.5f-16, Width=200, Height=46),
|
||||
locale::CANCEL);
|
||||
cancelButton.visible = false;
|
||||
|
||||
@transferProgress = GuiProgressbar(this, Alignment(Left+0.25f, Bottom-0.25f-25, Right-0.25f, Bottom-0.25f+25));
|
||||
transferProgress.frontColor = colors::Orange;
|
||||
transferProgress.visible = false;
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
if(mpIsQuerying())
|
||||
return;
|
||||
mpQueryServers();
|
||||
for(uint n = 0, ncnt = gameServers.length; n < ncnt; ++n)
|
||||
gameServers[n].found = false;
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
if(!visible)
|
||||
return;
|
||||
|
||||
if(gamesBG.visible) {
|
||||
if(!cloud::isActive || !cloud::inQueue) {
|
||||
if(queueButton !is null) {
|
||||
inQueue.visible = false;
|
||||
queueAccept.visible = false;
|
||||
queueReject.visible = false;
|
||||
queueLeave.visible = false;
|
||||
|
||||
queueButton.visible = true;
|
||||
}
|
||||
|
||||
joinButton.visible = true;
|
||||
ipButton.visible = true;
|
||||
refreshButton.visible = true;
|
||||
hostButton.disabled = false;
|
||||
hostLoadButton.disabled = false;
|
||||
|
||||
servers.visible = gameServers.length != 0;
|
||||
noServers.visible = gameServers.length == 0;
|
||||
}
|
||||
else {
|
||||
inQueue.visible = true;
|
||||
bool queueRequested = cloud::queueRequest;
|
||||
queueAccept.visible = queueRequested;
|
||||
queueReject.visible = queueRequested;
|
||||
queueLeave.visible = !queueRequested;
|
||||
|
||||
uint ready = 0, players = 0;
|
||||
|
||||
if(queueRequested)
|
||||
inQueue.text = locale::MP_QUEUE_READY;
|
||||
else if(cloud::getQueuePlayerWait(ready, players)) {
|
||||
inQueue.text = format(locale::MP_QUEUE_WAITING, ready, players);
|
||||
queueLeave.visible = false;
|
||||
}
|
||||
else {
|
||||
uint players = cloud::queuePlayers;
|
||||
if(players == 0)
|
||||
inQueue.text = locale::MP_QUEUE_ACTIVE;
|
||||
else
|
||||
inQueue.text = format(locale::MP_QUEUE_ACTIVE_PLAYERS, players);
|
||||
}
|
||||
|
||||
queueButton.visible = false;
|
||||
joinButton.visible = false;
|
||||
ipButton.visible = false;
|
||||
refreshButton.visible = false;
|
||||
hostButton.disabled = true;
|
||||
hostLoadButton.disabled = true;
|
||||
|
||||
servers.visible = false;
|
||||
noServers.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!connectingText.visible) {
|
||||
if(!menu_container.animating && cloud::isQueueReady) {
|
||||
if(mpClient) {
|
||||
showConnecting();
|
||||
showMenu();
|
||||
hideMultiplayer(snap=true);
|
||||
showNewGame(true);
|
||||
return;
|
||||
}
|
||||
if(mpServer) {
|
||||
showMenu();
|
||||
hideMultiplayer(snap=true);
|
||||
showNewGame();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(awaitingGalaxy)
|
||||
showConnecting();
|
||||
}
|
||||
|
||||
if(connectingText.visible) {
|
||||
if(awaitingGalaxy) {
|
||||
connectingText.text = locale::MP_WAITING_TRANSFER;
|
||||
}
|
||||
else if(mpIsConnected()) {
|
||||
connectingText.text = locale::MP_WAITING_START;
|
||||
showMenu();
|
||||
hideMultiplayer();
|
||||
showNewGame(true);
|
||||
}
|
||||
else if(!mpIsConnecting()) {
|
||||
mpDisconnect();
|
||||
showMenu();
|
||||
message(locale::MP_CANNOT_CONNECT+":\n "
|
||||
+localize("DISCONNECT_"+uint(mpDisconnectReason)));
|
||||
}
|
||||
}
|
||||
else if(mpIsConnecting()) {
|
||||
connectingText.text = "Connecting...";
|
||||
showConnecting();
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
if(awaitingGalaxy) {
|
||||
float pct = galaxySendProgress;
|
||||
transferProgress.visible = true;
|
||||
transferProgress.progress = pct;
|
||||
transferProgress.text = toString(pct * 100.f, 0)+"%";
|
||||
}
|
||||
else {
|
||||
transferProgress.visible = false;
|
||||
}
|
||||
|
||||
nextRefresh -= time;
|
||||
if(nextRefresh <= 0.0) {
|
||||
nextRefresh = 30.0;
|
||||
refresh();
|
||||
}
|
||||
|
||||
bool serversChanged = false;
|
||||
int sel = servers.selected;
|
||||
GameAddress selAddr;
|
||||
if(sel != -1 && uint(sel) < gameServers.length)
|
||||
selAddr = gameServers[sel].srv.address;
|
||||
|
||||
//Get new servers
|
||||
mpGetServers(newServers);
|
||||
if(newServers.length != 0) {
|
||||
for(uint i = 0, cnt = newServers.length; i < cnt; ++i) {
|
||||
//See if we already have this server
|
||||
bool found = false;
|
||||
for(uint n = 0, ncnt = gameServers.length; n < ncnt; ++n) {
|
||||
if(gameServers[n].srv.address == newServers[i].address) {
|
||||
gameServers[n].srv = newServers[i];
|
||||
gameServers[n].found = true;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
ServerDesc desc;
|
||||
desc.srv = newServers[i];
|
||||
desc.found = true;
|
||||
gameServers.insertLast(desc);
|
||||
}
|
||||
}
|
||||
newServers.length = 0;
|
||||
serversChanged = true;
|
||||
}
|
||||
|
||||
//Prune old servers
|
||||
if(!mpIsQuerying()){
|
||||
for(uint n = 0, ncnt = gameServers.length; n < ncnt; ++n) {
|
||||
if(!gameServers[n].found) {
|
||||
gameServers.removeAt(n);
|
||||
--n; --ncnt;
|
||||
serversChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update servers list
|
||||
if(serversChanged) {
|
||||
servers.clearItems();
|
||||
servers.selected = -1;
|
||||
|
||||
for(uint n = 0, ncnt = gameServers.length; n < ncnt; ++n) {
|
||||
ServerDesc@ desc = gameServers[n];
|
||||
string name = desc.srv.name;
|
||||
bool haveMods = true;
|
||||
if(name.length == 0)
|
||||
name = "Game at "+desc.srv.address.toString();
|
||||
if(desc.srv.players > 0) {
|
||||
name += " ("+desc.srv.players;
|
||||
if(desc.srv.maxPlayers > 0) {
|
||||
name += "/"+desc.srv.maxPlayers;
|
||||
name += " Players)";
|
||||
}
|
||||
else if(desc.srv.players > 1) {
|
||||
name += " Players)";
|
||||
}
|
||||
else {
|
||||
name += " Player)";
|
||||
}
|
||||
}
|
||||
if(desc.srv.started)
|
||||
name += " (In Progress)";
|
||||
if(desc.srv.isLocal)
|
||||
name += " (LAN)";
|
||||
if(desc.srv.password)
|
||||
name += " ("+locale::PASSWORD+")";
|
||||
if(desc.srv.mod.length != 0) {
|
||||
string modString;
|
||||
array<string>@ modList = desc.srv.mod.split("\n");
|
||||
for(uint i = 0, cnt = modList.length; i < cnt; ++i) {
|
||||
if(i != 0)
|
||||
modString += ", ";
|
||||
modString += modList[i];
|
||||
if(getMod(modList[i]) is null)
|
||||
haveMods = false;
|
||||
}
|
||||
name += " (Mods: "+modString+")";
|
||||
}
|
||||
|
||||
ServerElement elem;
|
||||
if(desc.srv.version != MP_VERSION) {
|
||||
elem.disabled = true;
|
||||
elem.color = colors::Red;
|
||||
name += " "+locale::MP_VERSION_MISMATCH;
|
||||
}
|
||||
else if(!haveMods) {
|
||||
elem.disabled = true;
|
||||
elem.color = colors::Red;
|
||||
name += " "+locale::MP_MISSING_MODS;
|
||||
}
|
||||
else if(desc.srv.password) {
|
||||
elem.color = Color(0xfffa00ff);
|
||||
}
|
||||
|
||||
elem.text = name;
|
||||
servers.addItem(elem);
|
||||
|
||||
if(desc.srv.address == selAddr)
|
||||
servers.selected = n;
|
||||
}
|
||||
|
||||
if(joinButton.visible) {
|
||||
servers.visible = gameServers.length != 0;
|
||||
noServers.visible = gameServers.length == 0;
|
||||
}
|
||||
}
|
||||
|
||||
joinButton.disabled = (servers.selected == -1);
|
||||
refreshButton.disabled = mpIsQuerying();
|
||||
portLabel.visible = !punchToggle.checked;
|
||||
portBox.visible = !punchToggle.checked;
|
||||
}
|
||||
|
||||
void host() {
|
||||
mpHost(gamename = serverName.text,
|
||||
port = max(toUInt(portBox.text), 1),
|
||||
isPublic = publicToggle.checked,
|
||||
punchthrough = punchToggle.checked,
|
||||
password = passwordBox.text);
|
||||
}
|
||||
|
||||
void join(const string& pwd = "") {
|
||||
int index = servers.selected;
|
||||
if(index >= 0 && index <= int(gameServers.length)) {
|
||||
if(game_running) {
|
||||
stopGame();
|
||||
if(mpServer)
|
||||
mpDisconnect();
|
||||
}
|
||||
GameServer srv = gameServers[index].srv;
|
||||
if(pwd.length == 0 && srv.password) {
|
||||
InputDialog@ dialog = InputDialog(PasswordDialog(), this);
|
||||
dialog.addTitle(locale::MP_ENTER_PASSWORD);
|
||||
dialog.accept.text = locale::MP_JOIN;
|
||||
dialog.addTextInput("", "");
|
||||
|
||||
addDialog(dialog);
|
||||
dialog.focusInput();
|
||||
return;
|
||||
}
|
||||
|
||||
mpConnect(srv, password=pwd);
|
||||
|
||||
showConnecting();
|
||||
if(srv.punchPort != -1 && srv.name.length != 0) {
|
||||
connectingText.text = "Connecting to "+srv.name+"...";
|
||||
}
|
||||
else {
|
||||
string addr = srv.address.toString(false);
|
||||
int port = srv.address.port;
|
||||
connectingText.text = "Connecting to "+addr+":"+port+"...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void join(const string& hostname, int port, const string& pwd = "") {
|
||||
if(game_running) {
|
||||
stopGame();
|
||||
if(mpServer || mpClient)
|
||||
mpDisconnect();
|
||||
}
|
||||
mpConnect(hostname, port, pwd);
|
||||
showConnecting();
|
||||
connectingText.text = "Connecting to "+hostname+":"+port+"...";
|
||||
}
|
||||
|
||||
void applyNick() {
|
||||
if(nick.text.length != 0 && nick.text != settings::sNickname) {
|
||||
settings::sNickname = nick.text;
|
||||
IRC.nickname = settings::sNickname;
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
switch(event.type) {
|
||||
case GUI_Clicked:
|
||||
if(event.caller is backButton) {
|
||||
applyNick();
|
||||
if(mpServer && !game_running)
|
||||
mpDisconnect();
|
||||
hideMultiplayer();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is queueButton) {
|
||||
if(!cloud::inQueue)
|
||||
cloud::enterQueue("1v1", 2, toString(MP_VERSION));
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is queueLeave) {
|
||||
if(cloud::inQueue)
|
||||
cloud::leaveQueue();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is queueAccept) {
|
||||
cloud::acceptQueue();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is queueReject) {
|
||||
cloud::rejectQueue();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is cancelButton) {
|
||||
mpDisconnect();
|
||||
showMenu();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is hostButton) {
|
||||
if(game_running) {
|
||||
stopGame();
|
||||
if(mpServer || mpClient)
|
||||
mpDisconnect();
|
||||
}
|
||||
applyNick();
|
||||
host();
|
||||
hideMultiplayer();
|
||||
showNewGame();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is refreshButton) {
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is ircButton) {
|
||||
showIRC();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is ipButton) {
|
||||
InputDialog@ dialog = InputDialog(IPJoin(), this);
|
||||
dialog.addTitle(locale::MP_JOIN_IP);
|
||||
dialog.accept.text = locale::MP_JOIN;
|
||||
dialog.addTextInput(locale::MP_IP, "127.0.0.1");
|
||||
dialog.addTextInput(locale::MP_PORT, "2048");
|
||||
dialog.addTextInput(locale::PASSWORD, "");
|
||||
|
||||
addDialog(dialog);
|
||||
dialog.focusTextInput(0, selectAll=true);
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is hostLoadButton) {
|
||||
if(game_running) {
|
||||
stopGame();
|
||||
if(mpServer || mpClient)
|
||||
mpDisconnect();
|
||||
}
|
||||
applyNick();
|
||||
host();
|
||||
hideMultiplayer();
|
||||
switchToMenu(load_menu);
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is joinButton) {
|
||||
applyNick();
|
||||
join();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case GUI_Confirmed:
|
||||
if(event.caller is servers) {
|
||||
join();
|
||||
return true;
|
||||
}
|
||||
else if(event.caller is nick) {
|
||||
applyNick();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case GUI_Focus_Lost:
|
||||
if(event.caller is nick) {
|
||||
applyNick();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case GUI_Animation_Complete:
|
||||
animating = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseGuiElement::onGuiEvent(event);
|
||||
}
|
||||
|
||||
void showConnecting() {
|
||||
gamesBG.visible = false;
|
||||
optionsBG.visible = false;
|
||||
joinButton.visible = false;
|
||||
backButton.visible = false;
|
||||
hostButton.visible = false;
|
||||
hostLoadButton.visible = false;
|
||||
hostBG.visible = false;
|
||||
if(queueButton !is null)
|
||||
queueButton.visible = false;
|
||||
|
||||
connectingText.visible = true;
|
||||
cancelButton.visible = true;
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void showMenu() {
|
||||
gamesBG.visible = true;
|
||||
optionsBG.visible = true;
|
||||
joinButton.visible = true;
|
||||
backButton.visible = true;
|
||||
hostButton.visible = true;
|
||||
hostLoadButton.visible = true;
|
||||
hostBG.visible = true;
|
||||
if(queueButton !is null)
|
||||
queueButton.visible = true;
|
||||
|
||||
connectingText.visible = false;
|
||||
cancelButton.visible = false;
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
if(!animating) {
|
||||
if(!hide) {
|
||||
size = parent.size;
|
||||
position = vec2i(0, 0);
|
||||
}
|
||||
else {
|
||||
size = parent.size;
|
||||
position = vec2i(size.x, 0);
|
||||
}
|
||||
}
|
||||
BaseGuiElement::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void animateIn() {
|
||||
animating = true;
|
||||
showMenu();
|
||||
|
||||
rect = recti_area(vec2i(parent.size.x, 0), parent.size);
|
||||
animate_time(this, recti_area(vec2i(), parent.size), MSLIDE_TIME);
|
||||
}
|
||||
|
||||
void animateOut() {
|
||||
animating = true;
|
||||
hide = true;
|
||||
|
||||
rect = recti_area(vec2i(), parent.size);
|
||||
animate_time(this, recti_area(vec2i(parent.size.x, 0), parent.size), MSLIDE_TIME);
|
||||
}
|
||||
};
|
||||
|
||||
class AcceptQueue : ConsoleCommand {
|
||||
void execute(const string& args) {
|
||||
if(cloud::queueRequest)
|
||||
cloud::acceptQueue();
|
||||
}
|
||||
};
|
||||
|
||||
class RejectQueue : ConsoleCommand {
|
||||
void execute(const string& args) {
|
||||
if(cloud::queueRequest)
|
||||
cloud::rejectQueue();
|
||||
}
|
||||
};
|
||||
|
||||
class LeaveQueue : ConsoleCommand {
|
||||
void execute(const string& args) {
|
||||
if(cloud::inQueue)
|
||||
cloud::leaveQueue();
|
||||
}
|
||||
};
|
||||
|
||||
Multiplayer@ mp_list;
|
||||
void init() {
|
||||
if(cloud::isActive) {
|
||||
if(settings::sNickname == "SRPlayer" || settings::sNickname.length == 0) {
|
||||
settings::sNickname = cloud::getNickname();
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
@mp_list = Multiplayer();
|
||||
mp_list.visible = false;
|
||||
|
||||
addConsoleCommand("accept_queue", AcceptQueue());
|
||||
addConsoleCommand("reject_queue", RejectQueue());
|
||||
addConsoleCommand("leave_queue", LeaveQueue());
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
if(mp_list.visible)
|
||||
mp_list.tick(time);
|
||||
}
|
||||
|
||||
void showMultiplayer() {
|
||||
mp_list.visible = true;
|
||||
menu_container.animateOut();
|
||||
mp_list.animateIn();
|
||||
mp_list.nextRefresh = 0.0;
|
||||
}
|
||||
|
||||
void onGameStateChange() {
|
||||
if(game_state == GS_Menu) {
|
||||
if(game_running && !mp_list.gamesBG.visible) {
|
||||
mp_list.showMenu();
|
||||
hideMultiplayer(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hideMultiplayer(bool snap = false) {
|
||||
menu_container.visible = true;
|
||||
if(!snap) {
|
||||
menu_container.animateIn();
|
||||
mp_list.animateOut();
|
||||
}
|
||||
else {
|
||||
mp_list.visible = false;
|
||||
animate_remove(mp_list);
|
||||
animate_remove(menu_container);
|
||||
menu_container.show();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
import menus;
|
||||
import elements.GuiTextbox;
|
||||
from load_menu import SaveItem;
|
||||
|
||||
class SaveData {
|
||||
string filename;
|
||||
|
||||
SaveData(const string& Filename) {
|
||||
filename = Filename;
|
||||
}
|
||||
};
|
||||
|
||||
double SaveThread(double time, ScriptThread& thread) {
|
||||
SaveData@ data;
|
||||
thread.getObject(@data);
|
||||
|
||||
saveGame(path_join(baseProfile["saves"], data.filename)+".sr2");
|
||||
|
||||
thread.stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
class SaveMenu : MenuBox {
|
||||
GuiTextbox@ saveName;
|
||||
GuiButton@ saveButton;
|
||||
|
||||
SaveMenu() {
|
||||
super();
|
||||
|
||||
items.alignment.top = Top+40;
|
||||
items.alignment.bottom = Bottom-40;
|
||||
|
||||
@saveName = GuiTextbox(this, Alignment(Left+12, Bottom-36, Right-212, Bottom-4));
|
||||
saveName.text = "quicksave";
|
||||
saveName.font = FT_Medium;
|
||||
|
||||
@saveButton = GuiButton(this, Alignment(Right-206, Bottom-36, Right-12, Bottom-4), "Save");
|
||||
saveButton.font = FT_Medium;
|
||||
}
|
||||
|
||||
void buildMenu() {
|
||||
title.text = locale::SAVE_GAME;
|
||||
|
||||
items.addItem(MenuAction(Sprite(spritesheet::MenuIcons, 11), locale::MENU_BACK, 0));
|
||||
|
||||
string dir = baseProfile["saves"];
|
||||
FileList files(dir, "*.sr2");
|
||||
|
||||
uint cnt = files.length;
|
||||
array<SaveItem@> list;
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
list.insertLast(SaveItem(files.path[i]));
|
||||
list.sortDesc();
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
items.addItem(list[i]);
|
||||
}
|
||||
|
||||
void onSelected(const string& name, int value) {
|
||||
if(value == 0) {
|
||||
switchToMenu(main_menu, false);
|
||||
return;
|
||||
}
|
||||
else if(value == 1) {
|
||||
saveName.text = name;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if((event.type == GUI_Clicked && event.caller is saveButton) ||
|
||||
(event.type == GUI_Confirmed && event.caller is saveName))
|
||||
{
|
||||
//double start = getExactTime();
|
||||
ScriptThread@ thread = ScriptThread("save_menu::SaveThread", @SaveData(saveName.text));
|
||||
saveWorldScreen(path_join(baseProfile["saves"], saveName.text)+".png");
|
||||
|
||||
while(thread.running)
|
||||
sleep(0);
|
||||
|
||||
//double end = getExactTime();
|
||||
//print(format("Saving took $1 seconds", string(end-start)));
|
||||
switchToMenu(main_menu, false, true);
|
||||
switchToGame();
|
||||
return true;
|
||||
}
|
||||
return MenuBox::onGuiEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
void init() {
|
||||
@save_menu = SaveMenu();
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "../definitions/saving.as"
|
||||
@@ -0,0 +1,47 @@
|
||||
import util.settings_page;
|
||||
|
||||
GamePage page;
|
||||
class GamePage : GameSettingsPage {
|
||||
void makeSettings() {
|
||||
color = colors::Green;
|
||||
header = locale::NG_GAME_OPTIONS;
|
||||
icon = Sprite(material::TabPlanets);
|
||||
|
||||
Title(locale::NG_UNIVERSE_GENERATION);
|
||||
Frequency(locale::NG_PLANET_FREQUENCY, "PLANET_FREQUENCY", min = 0.2, max = 3.0);
|
||||
Occurance(locale::NG_ANOMALY_OCCURANCE, "ANOMALY_OCCURANCE");
|
||||
Occurance(locale::NG_REMNANT_OCCURANCE, "REMNANT_OCCURANCE");
|
||||
Occurance(locale::NG_ASTEROID_OCCURANCE, "ASTEROID_OCCURANCE");
|
||||
Occurance(locale::NG_RESOURCE_ASTEROID_OCCURANCE, "RESOURCE_ASTEROID_OCCURANCE");
|
||||
Occurance(locale::NG_UNIQUE_SYSTEM_OCCURANCE, "UNIQUE_SYSTEM_OCCURANCE");
|
||||
Occurance(locale::NG_UNIQUE_RESOURCE_OCCURANCE, "UNIQUE_RESOURCE_OCCURANCE");
|
||||
Occurance(locale::NG_RESOURCE_SCARCITY, "RESOURCE_SCARCITY", max=2.0, tooltip=locale::NGTT_RESOURCE_SCARCITY);
|
||||
Occurance(locale::NG_CIVILIAN_TRADE, "CIVILIAN_TRADE_MULT", max=10.0, tooltip=locale::NGTT_CIVILIAN_TRADE);
|
||||
Frequency(locale::NG_ARTIFACT_FREQUENCY, "ARTIFACT_FREQUENCY", min = 0.2, max = 3.0);
|
||||
Frequency(locale::NG_SYSTEM_SIZE, "SYSTEM_SIZE", min = 0.2, max = 3.0);
|
||||
|
||||
emptyline();
|
||||
Title(locale::NG_GAME_OPTIONS);
|
||||
//Occurance(locale::NG_RANDOM_EVENTS, "RANDOM_EVENT_OCCURRENCE", max=3.0);
|
||||
Toggle(locale::NG_ENABLE_DREAD_PIRATE, "ENABLE_DREAD_PIRATE", halfWidth=true, tooltip=locale::NGTT_ENABLE_DREAD_PIRATE);
|
||||
/*Toggle(locale::NG_ENABLE_CIVILIAN_TRADE, "ENABLE_CIVILIAN_TRADE", halfWidth=true);*/
|
||||
Toggle(locale::NG_ENABLE_INFLUENCE_EVENTS, "ENABLE_INFLUENCE_EVENTS", halfWidth=true, tooltip=locale::NGTT_ENABLE_INFLUENCE_EVENTS);
|
||||
Toggle(locale::NG_DISABLE_STARTING_FLEETS, "DISABLE_STARTING_FLEETS", halfWidth=true, tooltip=locale::NGTT_DISABLE_STARTING_FLEETS);
|
||||
Toggle(locale::NG_REMNANT_AGGRESSION, "REMNANT_AGGRESSION", halfWidth=true, tooltip=locale::NGTT_REMNANT_AGGRESSION);
|
||||
Toggle(locale::NG_ALLOW_TEAM_SURRENDER, "ALLOW_TEAM_SURRENDER", halfWidth=true, tooltip=locale::NGTT_ALLOW_TEAM_SURRENDER);
|
||||
Toggle(locale::NG_START_EXPLORED_MAP, "START_EXPLORED_MAP", halfWidth=true, tooltip=locale::NGTT_START_EXPLORED_MAP);
|
||||
|
||||
auto@ tforming = Toggle(locale::NG_ENABLE_TERRAFORMING, "ENABLE_TERRAFORMING", halfWidth=true, tooltip=locale::NGTT_ENABLE_TERRAFORMING);
|
||||
if(hasDLC("Heralds")) {
|
||||
tforming.DefaultValue = false;
|
||||
tforming.set(false);
|
||||
}
|
||||
|
||||
emptyline();
|
||||
Title(locale::NG_VICTORY_OPTIONS);
|
||||
Number(locale::NG_TIME_LIMIT, "GAME_TIME_LIMIT", tooltip=locale::NGTT_TIME_LIMIT, halfWidth=true, step=10);
|
||||
Toggle(locale::NG_ENABLE_REVENANT_PARTS, "ENABLE_REVENANT_PARTS", tooltip=locale::NGTT_ENABLE_REVENANT_PARTS);
|
||||
if(hasDLC("Heralds"))
|
||||
Toggle(locale::NG_ENABLE_INFLUENCE_VICTORY, "ENABLE_INFLUENCE_VICTORY", tooltip=locale::NGTT_ENABLE_INFLUENCE_VICTORY);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../shared/settings/game_settings.as"
|
||||
@@ -0,0 +1,67 @@
|
||||
Sound@ theme;
|
||||
|
||||
bool played = false;
|
||||
const double themeVolume = 1.5;
|
||||
double volume = 0.0;
|
||||
double restartDelay = 0.5;
|
||||
|
||||
double musicVolume = 1.0;
|
||||
double prevMusicVol = 1.0, prevMasterVol = 1.0, prevSFXVol = 1.0;
|
||||
void tick(double time) {
|
||||
if(!soundEnabled)
|
||||
return;
|
||||
|
||||
if(prevMusicVol != settings::dMusicVolume || prevSFXVol != settings::dSFXVolume || prevMasterVol != settings::dMasterVolume) {
|
||||
if(settings::dSFXVolume < 0.01)
|
||||
{
|
||||
musicVolume = settings::dMusicVolume;
|
||||
soundVolume = settings::dMasterVolume;
|
||||
}
|
||||
else {
|
||||
musicVolume = settings::dMusicVolume / settings::dSFXVolume;
|
||||
soundVolume = settings::dMasterVolume * settings::dSFXVolume;
|
||||
}
|
||||
|
||||
prevMusicVol = settings::dMusicVolume;
|
||||
prevMasterVol = settings::dMasterVolume;
|
||||
prevSFXVol = settings::dSFXVolume;
|
||||
}
|
||||
|
||||
if(game_running) {
|
||||
played = false;
|
||||
restartDelay = 5.0;
|
||||
if(theme !is null) {
|
||||
volume = max(0.0, volume - (time / 4.0));
|
||||
theme.volume = settings::dMusicVolume * settings::dMasterVolume * volume * themeVolume;
|
||||
if(volume <= 0.0) {
|
||||
theme.stop();
|
||||
@theme = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(theme is null) {
|
||||
if(!played) {
|
||||
restartDelay -= time;
|
||||
if(restartDelay <= 0.0) {
|
||||
restartDelay = 5.0;
|
||||
|
||||
@theme = playTrack("data/music/title.ogg", loop = false, pause = true);
|
||||
if(theme !is null) {
|
||||
theme.volume = 0;
|
||||
volume = 0;
|
||||
theme.paused = false;
|
||||
played = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(theme.playing) {
|
||||
volume = min(1.0, volume + time);
|
||||
theme.volume = musicVolume * volume * themeVolume;
|
||||
}
|
||||
else {
|
||||
@theme = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
#include "../definitions/traits.as"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../shared/util/formatting.as"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../definitions/version.as"
|
||||
Reference in New Issue
Block a user