Merge branch 'master' into blueprints
This commit is contained in:
@@ -7,9 +7,11 @@
|
|||||||
#include "../command_func.h"
|
#include "../command_func.h"
|
||||||
#include "../console_func.h"
|
#include "../console_func.h"
|
||||||
#include "../console_type.h"
|
#include "../console_type.h"
|
||||||
|
#include "../date_func.h"
|
||||||
#include "../fileio_type.h"
|
#include "../fileio_type.h"
|
||||||
#include "../map_type.h"
|
#include "../map_type.h"
|
||||||
#include "../map_func.h"
|
#include "../map_func.h"
|
||||||
|
#include "../network/network_server.h"
|
||||||
#include "../strings_func.h"
|
#include "../strings_func.h"
|
||||||
#include "../town.h"
|
#include "../town.h"
|
||||||
#include "../tree_map.h"
|
#include "../tree_map.h"
|
||||||
@@ -24,11 +26,26 @@ bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y,
|
|||||||
|
|
||||||
namespace citymania {
|
namespace citymania {
|
||||||
|
|
||||||
|
uint32 _replay_save_interval = 0;
|
||||||
|
uint32 _replay_last_save = 0;
|
||||||
|
uint32 _replay_ticks = 0;
|
||||||
|
bool _replay_started = false;
|
||||||
|
|
||||||
static void IConsoleHelp(const char *str)
|
static void IConsoleHelp(const char *str)
|
||||||
{
|
{
|
||||||
IConsolePrintF(CC_WARNING, "- %s", str);
|
IConsolePrintF(CC_WARNING, "- %s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConGameSpeed(byte argc, char *argv[]) {
|
||||||
|
if (argc == 0 || argc > 2) {
|
||||||
|
IConsoleHelp("Changes game speed. Usage: 'cmgamespeed [n]'");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_game_speed = (argc > 1 ? atoi(argv[1]) : 100);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConStep(byte argc, char *argv[]) {
|
bool ConStep(byte argc, char *argv[]) {
|
||||||
if (argc == 0 || argc > 2) {
|
if (argc == 0 || argc > 2) {
|
||||||
IConsoleHelp("Advances the game for a certain amount of ticks (default 1). Usage: 'cmstep [n]'");
|
IConsoleHelp("Advances the game for a certain amount of ticks (default 1). Usage: 'cmstep [n]'");
|
||||||
@@ -135,6 +152,8 @@ bool ConResetTownGrowth(byte argc, char *argv[]) {
|
|||||||
struct FakeCommand {
|
struct FakeCommand {
|
||||||
Date date;
|
Date date;
|
||||||
DateFract date_fract;
|
DateFract date_fract;
|
||||||
|
uint res;
|
||||||
|
uint32 seed;
|
||||||
uint company_id;
|
uint company_id;
|
||||||
uint cmd;
|
uint cmd;
|
||||||
TileIndex tile;
|
TileIndex tile;
|
||||||
@@ -144,32 +163,126 @@ struct FakeCommand {
|
|||||||
|
|
||||||
static std::queue<FakeCommand> _fake_commands;
|
static std::queue<FakeCommand> _fake_commands;
|
||||||
|
|
||||||
|
void MakeReplaySave() {
|
||||||
|
char *filename = str_fmt("replay_%d.sav", _replay_ticks);
|
||||||
|
if (SaveOrLoad(filename, SLO_SAVE, DFT_GAME_FILE, SAVE_DIR) != SL_OK) {
|
||||||
|
IConsolePrintF(CC_ERROR, "Replay save failed");
|
||||||
|
} else {
|
||||||
|
IConsolePrintF(CC_DEFAULT, "Replay saved to %s", filename);
|
||||||
|
}
|
||||||
|
_replay_last_save = _replay_ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DatePredate(Date date1, DateFract date_fract1, Date date2, DateFract date_fract2) {
|
||||||
|
return date1 < date2 || (date1 == date2 && date_fract1 < date_fract2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkipFakeCommands(Date date, DateFract date_fract) {
|
||||||
|
uint commands_skipped = 0;
|
||||||
|
|
||||||
|
while (!_fake_commands.empty() && DatePredate(_fake_commands.front().date, _fake_commands.front().date_fract, date, date_fract)) {
|
||||||
|
_fake_commands.pop();
|
||||||
|
commands_skipped++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commands_skipped) {
|
||||||
|
fprintf(stderr, "Skipped %u commands that predate the current date (%d/%hu)\n", commands_skipped, date, date_fract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExecuteFakeCommands(Date date, DateFract date_fract) {
|
void ExecuteFakeCommands(Date date, DateFract date_fract) {
|
||||||
|
if (!_replay_started) {
|
||||||
|
SkipFakeCommands(_date, _date_fract);
|
||||||
|
_replay_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto backup_company = _current_company;
|
auto backup_company = _current_company;
|
||||||
while (!_fake_commands.empty() && _fake_commands.front().date <= date && _fake_commands.front().date_fract <= date_fract) {
|
while (!_fake_commands.empty() && !DatePredate(date, date_fract, _fake_commands.front().date, _fake_commands.front().date_fract)) {
|
||||||
auto &x = _fake_commands.front();
|
auto &x = _fake_commands.front();
|
||||||
if (x.date < date || x.date_fract < date_fract) IConsolePrintF(CC_WARNING,
|
|
||||||
"Queued command is earlier than execution date: %d/%hu vs %d/%hu",
|
fprintf(stderr, "Executing command: company=%u cmd=%u(%s) tile=%u p1=%u p2=%u text=%s ... ", x.company_id, x.cmd, GetCommandName(x.cmd), x.tile, x.p1, x.p2, x.text.c_str());
|
||||||
x.date, x.date_fract, date, date_fract);
|
if (x.res == 0) {
|
||||||
fprintf(stderr, "Executing command: company=%u cmd=%u tile=%u p1=%u p2=%u text=%s ... ", x.company_id, x.cmd, x.tile, x.p1, x.p2, x.text.c_str());
|
fprintf(stderr, "REJECTED\n");
|
||||||
|
_fake_commands.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_networking) {
|
||||||
|
CommandPacket cp;
|
||||||
|
cp.tile = x.tile;
|
||||||
|
cp.p1 = x.p1;
|
||||||
|
cp.p2 = x.p2;
|
||||||
|
cp.cmd = x.cmd;
|
||||||
|
strecpy(cp.text, x.text.c_str(), lastof(cp.text));
|
||||||
|
cp.company = (CompanyID)x.company_id;
|
||||||
|
cp.frame = _frame_counter_max + 1;
|
||||||
|
cp.callback = nullptr;
|
||||||
|
cp.my_cmd = false;
|
||||||
|
|
||||||
|
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
||||||
|
if (cs->status >= NetworkClientSocket::STATUS_MAP) {
|
||||||
|
cs->outgoing_queue.Append(&cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_current_company = (CompanyID)x.company_id;
|
_current_company = (CompanyID)x.company_id;
|
||||||
auto res = DoCommandPInternal(x.tile, x.p1, x.p2, x.cmd | CMD_NETWORK_COMMAND, nullptr, x.text.c_str(), false, false);
|
auto res = DoCommandPInternal(x.tile, x.p1, x.p2, x.cmd | CMD_NETWORK_COMMAND, nullptr, x.text.c_str(), false, false);
|
||||||
if (res.Failed()) {
|
if (res.Failed() != (x.res != 1)) {
|
||||||
if (res.GetErrorMessage() != INVALID_STRING_ID) {
|
if (!res.Failed()) {
|
||||||
|
fprintf(stderr, "FAIL (Failing command succeeded)\n");
|
||||||
|
} else if (res.GetErrorMessage() != INVALID_STRING_ID) {
|
||||||
char buf[DRAW_STRING_BUFFER];
|
char buf[DRAW_STRING_BUFFER];
|
||||||
GetString(buf, res.GetErrorMessage(), lastof(buf));
|
GetString(buf, res.GetErrorMessage(), lastof(buf));
|
||||||
fprintf(stderr, "%s\n", buf);
|
fprintf(stderr, "FAIL (Successful command failed: %s)\n", buf);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "FAIL\n");
|
fprintf(stderr, "FAIL (Successful command failed)\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "OK\n");
|
fprintf(stderr, "OK\n");
|
||||||
}
|
}
|
||||||
|
if (x.seed != (_random.state[0] & 255)) {
|
||||||
|
fprintf(stderr, "*** DESYNC expected seed %u vs current %u ***\n", x.seed, _random.state[0] & 255);
|
||||||
|
}
|
||||||
_fake_commands.pop();
|
_fake_commands.pop();
|
||||||
}
|
}
|
||||||
_current_company = backup_company;
|
_current_company = backup_company;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckIntervalSave() {
|
||||||
|
if (_pause_mode == PM_UNPAUSED) {
|
||||||
|
_replay_ticks++;
|
||||||
|
if (_replay_save_interval && _replay_ticks - _replay_last_save >= _replay_save_interval) {
|
||||||
|
MakeReplaySave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetReplaySaveInterval(uint32 interval) {
|
||||||
|
_replay_save_interval = interval;
|
||||||
|
_replay_last_save = 0;
|
||||||
|
_replay_ticks = 0;
|
||||||
|
|
||||||
|
if (_replay_save_interval) MakeReplaySave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadCommands(const std::string &filename) {
|
||||||
|
std::queue<FakeCommand>().swap(_fake_commands); // clear queue
|
||||||
|
|
||||||
|
std::ifstream file(filename, std::ios::in);
|
||||||
|
std::string str;
|
||||||
|
while(std::getline(file, str)) {
|
||||||
|
std::istringstream ss(str);
|
||||||
|
FakeCommand cmd;
|
||||||
|
ss >> cmd.date >> cmd.date_fract >> cmd.res >> cmd.seed >> cmd.company_id >> cmd.cmd >> cmd.tile >> cmd.p1 >> cmd.p2;
|
||||||
|
std::string s;
|
||||||
|
ss.get();
|
||||||
|
std::getline(ss, cmd.text);
|
||||||
|
_fake_commands.push(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
_replay_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConLoadCommands(byte argc, char *argv[]) {
|
bool ConLoadCommands(byte argc, char *argv[]) {
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
IConsoleHelp("Loads a file with command queue to execute");
|
IConsoleHelp("Loads a file with command queue to execute");
|
||||||
@@ -177,23 +290,11 @@ bool ConLoadCommands(byte argc, char *argv[]) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 2) return false;
|
if (argc > 3) return false;
|
||||||
|
|
||||||
std::queue<FakeCommand>().swap(_fake_commands); // clear queue
|
LoadCommands(argv[1]);
|
||||||
|
SetReplaySaveInterval(argc > 2 ? atoi(argv[2]) : 0);
|
||||||
|
|
||||||
std::ifstream file(argv[1], std::ios::in);
|
|
||||||
std::string str;
|
|
||||||
while(std::getline(file, str))
|
|
||||||
{
|
|
||||||
std::istringstream ss(str);
|
|
||||||
FakeCommand cmd;
|
|
||||||
ss >> cmd.date >> cmd.date_fract >> cmd.company_id >> cmd.cmd >> cmd.p1 >> cmd.p2 >> cmd.tile;
|
|
||||||
std::string s;
|
|
||||||
ss.get();
|
|
||||||
std::getline(ss, cmd.text);
|
|
||||||
// fprintf(stderr, "PARSED: company=%u cmd=%u tile=%u p1=%u p2=%u text=%s\n", cmd.company_id, cmd.cmd, cmd.tile, cmd.p1, cmd.p2, cmd.text.c_str());
|
|
||||||
_fake_commands.push(cmd);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,12 @@
|
|||||||
|
|
||||||
namespace citymania {
|
namespace citymania {
|
||||||
|
|
||||||
|
void SkipFakeCommands(Date date, DateFract date_fract);
|
||||||
|
void SetReplaySaveInterval(uint32 interval);
|
||||||
|
void LoadCommands(const std::string &filename);
|
||||||
|
void CheckIntervalSave();
|
||||||
|
|
||||||
|
bool ConGameSpeed(byte argc, char *argv[]);
|
||||||
bool ConStep(byte argc, char *argv[]);
|
bool ConStep(byte argc, char *argv[]);
|
||||||
bool ConExport(byte argc, char *argv[]);
|
bool ConExport(byte argc, char *argv[]);
|
||||||
bool ConTreeMap(byte argc, char *argv[]);
|
bool ConTreeMap(byte argc, char *argv[]);
|
||||||
|
|||||||
@@ -1220,9 +1220,11 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) {
|
|||||||
// } else if (((_thd.place_mode & HT_DRAG_MASK) == HT_RECT || ((_thd.place_mode & HT_DRAG_MASK) == HT_SPECIAL && (_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT)) && _thd.new_outersize.x > 0 && !_thd.make_square_red) { // station
|
// } else if (((_thd.place_mode & HT_DRAG_MASK) == HT_RECT || ((_thd.place_mode & HT_DRAG_MASK) == HT_SPECIAL && (_thd.next_drawstyle & HT_DRAG_MASK) == HT_RECT)) && _thd.new_outersize.x > 0 && !_thd.make_square_red) { // station
|
||||||
} else if (_thd.select_proc == CM_DDSP_BUILD_AIRPORT) {
|
} else if (_thd.select_proc == CM_DDSP_BUILD_AIRPORT) {
|
||||||
auto tile = TileXY(_thd.new_pos.x / TILE_SIZE, _thd.new_pos.y / TILE_SIZE);
|
auto tile = TileXY(_thd.new_pos.x / TILE_SIZE, _thd.new_pos.y / TILE_SIZE);
|
||||||
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
if (_selected_airport_index != -1) {
|
||||||
_thd.cm_new = ObjectHighlight::make_airport(tile, as->GetIndex(), _selected_airport_layout);
|
const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
|
||||||
new_drawstyle = HT_RECT;
|
_thd.cm_new = ObjectHighlight::make_airport(tile, as->GetIndex(), _selected_airport_layout);
|
||||||
|
new_drawstyle = HT_RECT;
|
||||||
|
}
|
||||||
} else if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP
|
} else if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP
|
||||||
|| _thd.select_proc == DDSP_BUILD_TRUCKSTOP) { // station
|
|| _thd.select_proc == DDSP_BUILD_TRUCKSTOP) { // station
|
||||||
if (_thd.size.x >= (int)TILE_SIZE && _thd.size.y >= (int)TILE_SIZE) {
|
if (_thd.size.x >= (int)TILE_SIZE && _thd.size.y >= (int)TILE_SIZE) {
|
||||||
|
|||||||
@@ -2459,8 +2459,10 @@ void IConsoleStdLibRegister()
|
|||||||
IConsoleCmdRegister("dump_info", ConDumpInfo);
|
IConsoleCmdRegister("dump_info", ConDumpInfo);
|
||||||
|
|
||||||
IConsoleCmdRegister("cmexport", citymania::ConExport);
|
IConsoleCmdRegister("cmexport", citymania::ConExport);
|
||||||
IConsoleCmdRegister("cmstep", citymania::ConStep, ConHookNoNetwork);
|
|
||||||
IConsoleCmdRegister("cmtreemap", citymania::ConTreeMap, ConHookNoNetwork);
|
IConsoleCmdRegister("cmtreemap", citymania::ConTreeMap, ConHookNoNetwork);
|
||||||
IConsoleCmdRegister("cmresettowngrowth", citymania::ConResetTownGrowth, ConHookNoNetwork);
|
|
||||||
IConsoleCmdRegister("cmloadcommands", citymania::ConLoadCommands, ConHookNoNetwork);
|
IConsoleCmdRegister("cmstep", citymania::ConStep);
|
||||||
|
IConsoleCmdRegister("cmresettowngrowth", citymania::ConResetTownGrowth);
|
||||||
|
IConsoleCmdRegister("cmloadcommands", citymania::ConLoadCommands);
|
||||||
|
IConsoleCmdRegister("cmgamespeed", citymania::ConGameSpeed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ bool _exit_game;
|
|||||||
GameMode _game_mode;
|
GameMode _game_mode;
|
||||||
SwitchMode _switch_mode; ///< The next mainloop command.
|
SwitchMode _switch_mode; ///< The next mainloop command.
|
||||||
PauseMode _pause_mode;
|
PauseMode _pause_mode;
|
||||||
uint32 _pause_countdown;
|
uint32 _pause_countdown = 0;
|
||||||
Palette _cur_palette;
|
Palette _cur_palette;
|
||||||
|
|
||||||
static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of often used characters. @see GetCharacterWidth()
|
static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of often used characters. @see GetCharacterWidth()
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
#include "../gfx_func.h"
|
#include "../gfx_func.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
|
||||||
|
#include "citymania/cm_console_cmds.hpp"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
#ifdef DEBUG_DUMP_COMMANDS
|
#ifdef DEBUG_DUMP_COMMANDS
|
||||||
@@ -1000,6 +1002,8 @@ void NetworkGameLoop()
|
|||||||
NetworkExecuteLocalCommandQueue();
|
NetworkExecuteLocalCommandQueue();
|
||||||
if (_pause_countdown > 0 && --_pause_countdown == 0) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
|
if (_pause_countdown > 0 && --_pause_countdown == 0) DoCommandP(0, PM_PAUSED_NORMAL, 1, CMD_PAUSE);
|
||||||
|
|
||||||
|
citymania::ExecuteFakeCommands(_date, _date_fract);
|
||||||
|
|
||||||
/* Then we make the frame */
|
/* Then we make the frame */
|
||||||
StateGameLoop();
|
StateGameLoop();
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ static void ShowHelp()
|
|||||||
" -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
|
" -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
|
||||||
" -x = Never save configuration changes to disk\n"
|
" -x = Never save configuration changes to disk\n"
|
||||||
" -q savegame = Write some information about the savegame and exit\n"
|
" -q savegame = Write some information about the savegame and exit\n"
|
||||||
|
" -C commands = Load commands to execute (CityMania addition)\n"
|
||||||
|
" -T ticks = Save game every n ticks with filename replay_<tick>.sav (CityMania addition)\n"
|
||||||
"\n",
|
"\n",
|
||||||
lastof(buf)
|
lastof(buf)
|
||||||
);
|
);
|
||||||
@@ -542,6 +544,8 @@ static const OptionData _options[] = {
|
|||||||
GETOPT_SHORT_NOVAL('x'),
|
GETOPT_SHORT_NOVAL('x'),
|
||||||
GETOPT_SHORT_VALUE('q'),
|
GETOPT_SHORT_VALUE('q'),
|
||||||
GETOPT_SHORT_NOVAL('h'),
|
GETOPT_SHORT_NOVAL('h'),
|
||||||
|
GETOPT_SHORT_VALUE('C'),
|
||||||
|
GETOPT_SHORT_VALUE('T'),
|
||||||
GETOPT_END()
|
GETOPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -677,6 +681,19 @@ int openttd_main(int argc, char *argv[])
|
|||||||
case 'G': scanner->generation_seed = strtoul(mgo.opt, nullptr, 10); break;
|
case 'G': scanner->generation_seed = strtoul(mgo.opt, nullptr, 10); break;
|
||||||
case 'c': _config_file = mgo.opt; break;
|
case 'c': _config_file = mgo.opt; break;
|
||||||
case 'x': scanner->save_config = false; break;
|
case 'x': scanner->save_config = false; break;
|
||||||
|
case 'C': {
|
||||||
|
DeterminePaths(argv[0]);
|
||||||
|
if (StrEmpty(mgo.opt)) {
|
||||||
|
ret = 1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
citymania::LoadCommands(mgo.opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'T': {
|
||||||
|
citymania::SetReplaySaveInterval(strtol(mgo.opt, nullptr, 10));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'h':
|
case 'h':
|
||||||
i = -2; // Force printing of help.
|
i = -2; // Force printing of help.
|
||||||
break;
|
break;
|
||||||
@@ -1530,6 +1547,7 @@ void GameLoop()
|
|||||||
citymania::ExecuteFakeCommands(_date, _date_fract);
|
citymania::ExecuteFakeCommands(_date, _date_fract);
|
||||||
/* Singleplayer */
|
/* Singleplayer */
|
||||||
StateGameLoop();
|
StateGameLoop();
|
||||||
|
citymania::CheckIntervalSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_pause_mode && HasBit(_display_opt, DO_FULL_ANIMATION)) DoPaletteAnimations();
|
if (!_pause_mode && HasBit(_display_opt, DO_FULL_ANIMATION)) DoPaletteAnimations();
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
/** @file null_v.cpp The video driver that doesn't blit. */
|
/** @file null_v.cpp The video driver that doesn't blit. */
|
||||||
|
|
||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
|
#include "../console_func.h"
|
||||||
|
#include "../date_func.h"
|
||||||
#include "../gfx_func.h"
|
#include "../gfx_func.h"
|
||||||
#include "../blitter/factory.hpp"
|
#include "../blitter/factory.hpp"
|
||||||
|
#include "../saveload/saveload.h"
|
||||||
#include "../window_func.h"
|
#include "../window_func.h"
|
||||||
#include "null_v.h"
|
#include "null_v.h"
|
||||||
|
|
||||||
@@ -28,6 +31,7 @@ const char *VideoDriver_Null::Start(const StringList &parm)
|
|||||||
this->UpdateAutoResolution();
|
this->UpdateAutoResolution();
|
||||||
|
|
||||||
this->ticks = GetDriverParamInt(parm, "ticks", 1000);
|
this->ticks = GetDriverParamInt(parm, "ticks", 1000);
|
||||||
|
this->savefile = GetDriverParam(parm, "save");
|
||||||
_screen.width = _screen.pitch = _cur_resolution.width;
|
_screen.width = _screen.pitch = _cur_resolution.width;
|
||||||
_screen.height = _cur_resolution.height;
|
_screen.height = _cur_resolution.height;
|
||||||
_screen.dst_ptr = nullptr;
|
_screen.dst_ptr = nullptr;
|
||||||
@@ -47,10 +51,22 @@ void VideoDriver_Null::MainLoop()
|
|||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
for (i = 0; i < this->ticks; i++) {
|
uint16 old_tick;
|
||||||
|
for (i = 0; i < this->ticks; ) {
|
||||||
|
old_tick = _tick_counter;
|
||||||
::GameLoop();
|
::GameLoop();
|
||||||
::InputLoop();
|
::InputLoop();
|
||||||
::UpdateWindows();
|
::UpdateWindows();
|
||||||
|
if (old_tick != _tick_counter) i++;
|
||||||
|
else _pause_mode = PM_UNPAUSED;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Null driver ran for %u tics, save: %s\n", this->ticks, this->savefile.c_str());
|
||||||
|
if (!this->savefile.empty()) {
|
||||||
|
if (SaveOrLoad(this->savefile.c_str(), SLO_SAVE, DFT_GAME_FILE, SAVE_DIR) != SL_OK) {
|
||||||
|
IConsolePrintF(CC_ERROR, "Error saving the final game state.");
|
||||||
|
} else {
|
||||||
|
IConsolePrintF(CC_DEFAULT, "Saved the final game state to %s", this->savefile.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
class VideoDriver_Null : public VideoDriver {
|
class VideoDriver_Null : public VideoDriver {
|
||||||
private:
|
private:
|
||||||
uint ticks; ///< Amount of ticks to run.
|
uint ticks; ///< Amount of ticks to run.
|
||||||
|
std::string savefile;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const char *Start(const StringList ¶m) override;
|
const char *Start(const StringList ¶m) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user