mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Clean up game state structure to better match save format
This commit is contained in:
parent
f69f5c3cd7
commit
909f00b079
@ -32,22 +32,22 @@ struct BasicState
|
||||
/// /!\ This is wchar_t[24] in the original format /!\ we convert on load for convenience
|
||||
char saveName[48];
|
||||
SystemTime saveTime;
|
||||
uint16_t unknown;
|
||||
uint32_t unknown;
|
||||
uint16_t islandNumber;
|
||||
glm::vec3 cameraPosition;
|
||||
uint16_t gameMinuteMS;
|
||||
uint16_t lastTick;
|
||||
uint32_t gameMinuteMS;
|
||||
uint32_t lastTick;
|
||||
uint8_t gameHour;
|
||||
uint8_t _align0[3];
|
||||
uint8_t gameMinute;
|
||||
uint8_t _align1[3];
|
||||
uint16_t padMode;
|
||||
uint8_t _align2[2];
|
||||
uint16_t timeMS;
|
||||
uint32_t timeMS;
|
||||
float timeScale;
|
||||
float timeStep;
|
||||
float timeStep_unclipped; // Unknown purpose
|
||||
uint16_t frameCounter;
|
||||
uint32_t frameCounter;
|
||||
float timeStep2;
|
||||
float framesPerUpdate;
|
||||
float timeScale2;
|
||||
@ -59,11 +59,96 @@ struct BasicState
|
||||
uint8_t _align5[2];
|
||||
float weatherInterpolation;
|
||||
uint8_t dateTime[24]; // Unused
|
||||
uint16_t weatherType;
|
||||
uint32_t weatherType;
|
||||
float cameraData;
|
||||
float cameraData2;
|
||||
};
|
||||
|
||||
/** Block 15 player info */
|
||||
struct PlayerInfo
|
||||
{
|
||||
uint16_t money;
|
||||
uint8_t unknown1;
|
||||
uint16_t unknown2;
|
||||
uint8_t unknown3;
|
||||
float unknown4;
|
||||
uint16_t displayedMoney;
|
||||
uint16_t hiddenPackagesCollected;
|
||||
uint16_t hiddenPackageCount;
|
||||
uint8_t neverTired;
|
||||
uint8_t fastReload;
|
||||
uint8_t thaneOfLibertyCity;
|
||||
uint8_t singlePayerHealthcare;
|
||||
uint8_t unknown5[70];
|
||||
};
|
||||
|
||||
/** Block 17 */
|
||||
struct GameStats
|
||||
{
|
||||
uint16_t playerKills;
|
||||
uint16_t otherKills;
|
||||
uint16_t carsExploded;
|
||||
uint16_t shotsHit;
|
||||
uint16_t pedTypesKilled[23];
|
||||
uint16_t helicoptersDestroyed;
|
||||
uint16_t playerProgress;
|
||||
uint16_t explosiveKgsUsed;
|
||||
uint16_t bulletsFired;
|
||||
uint16_t bulletsHit;
|
||||
uint16_t carsCrushed;
|
||||
uint16_t headshots;
|
||||
uint16_t timesBusted;
|
||||
uint16_t timesHospital;
|
||||
uint16_t daysPassed;
|
||||
uint16_t mmRainfall;
|
||||
uint16_t insaneJumpMaxDistance;
|
||||
uint16_t insaneJumpMaxHeight;
|
||||
uint16_t insaneJumpMaxFlips;
|
||||
uint16_t insangeJumpMaxRotation;
|
||||
/*
|
||||
* 0 none completed
|
||||
* 1 insane stunt
|
||||
* 2 perfect insane stunt
|
||||
* 3 double insane stunt
|
||||
* 4 perfect double insane stunt
|
||||
* 5 triple insane stunt
|
||||
* 6 perfect " " "
|
||||
* 7 quadruple
|
||||
* 8 perfect quadruple
|
||||
*/
|
||||
uint16_t bestStunt;
|
||||
uint16_t uniqueStuntsFound;
|
||||
uint16_t uniqueStuntsTotal;
|
||||
uint16_t missionAttempts;
|
||||
uint16_t missionsPassed;
|
||||
uint16_t passengersDroppedOff;
|
||||
uint16_t taxiRevenue;
|
||||
uint16_t portlandPassed;
|
||||
uint16_t stauntonPassed;
|
||||
uint16_t shoresidePassed;
|
||||
uint16_t bestTurismoTime;
|
||||
float distanceWalked;
|
||||
float distanceDriven;
|
||||
uint16_t patriotPlaygroundTime;
|
||||
uint16_t aRideInTheParkTime;
|
||||
uint16_t grippedTime;
|
||||
uint16_t multistoryMayhemTime;
|
||||
uint16_t peopleSaved;
|
||||
uint16_t criminalsKilled;
|
||||
uint16_t highestParamedicLevel;
|
||||
uint16_t firesExtinguished;
|
||||
uint16_t longestDodoFlight;
|
||||
uint16_t bombDefusalTime;
|
||||
uint16_t rampagesPassed;
|
||||
uint16_t totalRampages;
|
||||
uint16_t totalMissions;
|
||||
uint16_t fastestTime[16]; // not used
|
||||
uint16_t highestScore[16];
|
||||
uint16_t peopleKilledSinceCheckpoint; // ?
|
||||
uint16_t peopleKilledSinceLastBustedOrWasted;
|
||||
char lastMissionGXT[8];
|
||||
};
|
||||
|
||||
struct TextDisplayData
|
||||
{
|
||||
// This is set by the final display text command.
|
||||
@ -196,23 +281,32 @@ struct GarageInfo
|
||||
*/
|
||||
struct GameState
|
||||
{
|
||||
/**
|
||||
Basic Game State
|
||||
*/
|
||||
BasicState basic;
|
||||
|
||||
/**
|
||||
Player stats
|
||||
*/
|
||||
PlayerInfo playerInfo;
|
||||
|
||||
/**
|
||||
Game Stats
|
||||
*/
|
||||
GameStats gameStats;
|
||||
|
||||
/**
|
||||
* Second since game was started
|
||||
*/
|
||||
float gameTime;
|
||||
unsigned int currentProgress;
|
||||
unsigned int maxProgress;
|
||||
unsigned int numMissions;
|
||||
unsigned int numHiddenPackages;
|
||||
unsigned int numHiddenPackagesDiscovered;
|
||||
unsigned int numUniqueJumps;
|
||||
unsigned int numRampages;
|
||||
|
||||
unsigned int maxWantedLevel;
|
||||
|
||||
GameObjectID playerObject;
|
||||
|
||||
unsigned int currentWeather;
|
||||
|
||||
/**
|
||||
* @brief Stores a pointer to script global that stores the on-mission state.
|
||||
*/
|
||||
@ -239,9 +333,6 @@ struct GameState
|
||||
/** Flag for rendering cutscene letterbox */
|
||||
bool isCinematic;
|
||||
|
||||
short hour;
|
||||
short minute;
|
||||
|
||||
std::string lastMissionName;
|
||||
|
||||
/// Stores the "special" character and cutscene model indices.
|
||||
|
@ -1,16 +1,13 @@
|
||||
#include <engine/GameState.hpp>
|
||||
|
||||
GameState::GameState() :
|
||||
gameTime(0.f),
|
||||
GameState::GameState()
|
||||
: basic{}
|
||||
, playerInfo{}
|
||||
, gameStats{}
|
||||
, gameTime(0.f),
|
||||
currentProgress(0),
|
||||
maxProgress(1),
|
||||
numMissions(0),
|
||||
numHiddenPackages(0),
|
||||
numHiddenPackagesDiscovered(0),
|
||||
numUniqueJumps(0),
|
||||
numRampages(0),
|
||||
maxWantedLevel(0),
|
||||
currentWeather(0),
|
||||
scriptOnMissionFlag(nullptr),
|
||||
fadeOut(true),
|
||||
fadeStart(0.f),
|
||||
@ -21,8 +18,6 @@ isIntroPlaying(false),
|
||||
currentCutscene(nullptr),
|
||||
cutsceneStartTime(-1.f),
|
||||
isCinematic(false),
|
||||
hour(0),
|
||||
minute(0),
|
||||
cameraNear(0.1f),
|
||||
cameraFixed(false),
|
||||
cameraTarget(0),
|
||||
|
@ -622,12 +622,12 @@ void GameWorld::doWeaponScan(const WeaponScan &scan)
|
||||
|
||||
int GameWorld::getHour()
|
||||
{
|
||||
return state->hour;
|
||||
return state->basic.gameHour;
|
||||
}
|
||||
|
||||
int GameWorld::getMinute()
|
||||
{
|
||||
return state->minute;
|
||||
return state->basic.gameMinute;
|
||||
}
|
||||
|
||||
glm::vec3 GameWorld::getGroundAtPosition(const glm::vec3 &pos) const
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <items/WeaponItem.hpp>
|
||||
#include <cstring>
|
||||
#include <iconv.h>
|
||||
|
||||
// Original save game file data structures
|
||||
typedef uint16_t BlockWord;
|
||||
@ -102,10 +103,6 @@ struct Block1PlayerPed {
|
||||
uint8_t align[2];
|
||||
};
|
||||
|
||||
template<class T> void read(std::FILE* str, T& out) {
|
||||
std::fread(&out, sizeof(out), 1, str);
|
||||
}
|
||||
|
||||
struct StructStoredCar {
|
||||
BlockDword modelId;
|
||||
glm::vec3 position;
|
||||
@ -210,31 +207,11 @@ void SaveGame::writeGame(GameState& state, const std::string& file)
|
||||
std::FILE* saveFile = std::fopen(file.c_str(), "w");
|
||||
|
||||
// BLOCK 0 - Variables
|
||||
BasicState block0Data = {};
|
||||
//strcpy(block0Data.saveName, "OpenRW Save Game");
|
||||
block0Data.islandNumber = 1;
|
||||
block0Data.cameraPosition = glm::vec3(0.f);
|
||||
block0Data.gameMinuteMS = 1000;
|
||||
block0Data.lastTick = 1;
|
||||
block0Data.gameHour = 12;
|
||||
block0Data.gameMinute = 13;
|
||||
block0Data.padMode = 1;
|
||||
block0Data.timeMS = 10000;
|
||||
block0Data.timeScale = 1.0;
|
||||
block0Data.timeStep = 1.0/60.f;
|
||||
block0Data.timeStep_unclipped = block0Data.timeStep;
|
||||
block0Data.frameCounter = 1000;
|
||||
block0Data.timeStep2 = 1.0;
|
||||
block0Data.framesPerUpdate = 1.0;
|
||||
block0Data.timeScale2 = 1.0;
|
||||
block0Data.lastWeather = 1;
|
||||
block0Data.nextWeather = 1;
|
||||
block0Data.weatherInterpolation = 1.0;
|
||||
block0Data.weatherType = 1;
|
||||
BasicState stateCopy = state.basic;
|
||||
|
||||
BlockSize block0Size = sizeof(block0Data); // TODO calculate correctly.
|
||||
BlockSize block0Size = sizeof(BasicState);
|
||||
fwrite(&block0Size, sizeof(BlockSize), 1, saveFile);
|
||||
fwrite(&block0Data, sizeof(block0Data), 1, saveFile);
|
||||
fwrite(&state.basic, sizeof(BasicState), 1, saveFile);
|
||||
|
||||
// BLOCK 0 - 0 Script
|
||||
const char header[4] = "SCR";
|
||||
@ -282,41 +259,77 @@ void SaveGame::writeGame(GameState& state, const std::string& file)
|
||||
}
|
||||
}
|
||||
|
||||
const size_type DWORDSZ = sizeof(BlockDword);
|
||||
BlockDword readDword(std::FILE* file)
|
||||
{
|
||||
BlockDword sz;
|
||||
fread(&sz, sizeof(BlockDword), 1, file);
|
||||
return sz;
|
||||
template<class T> bool readBlock(std::FILE* str, T& out) {
|
||||
return std::fread(&out, sizeof(out), 1, str) == 1;
|
||||
}
|
||||
|
||||
#define READ_BLOCK(var) \
|
||||
if (! readBlock(loadFile, var)) { \
|
||||
std::cerr << file << ": Failed to load block " #var << std::endl; \
|
||||
return false; \
|
||||
}
|
||||
#define READ_SIZE(var) \
|
||||
if (! readBlock(loadFile, var)) { \
|
||||
std::cerr << file << ": Failed to load size " #var << std::endl; \
|
||||
return false; \
|
||||
}
|
||||
#define CHECK_SIG(expected) \
|
||||
{\
|
||||
char signature[4]; \
|
||||
if(fread(signature, sizeof(char), 4, loadFile) != 4) { \
|
||||
std::cerr << "Failed to read signature" << std::endl; \
|
||||
return false; \
|
||||
} \
|
||||
if (strncmp(signature, expected, 3) != 0) { \
|
||||
std::cerr << "Signature " expected " incorrect" << std::endl; \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
bool SaveGame::loadGame(GameState& state, const std::string& file)
|
||||
{
|
||||
std::FILE* loadFile = std::fopen(file.c_str(), "r");
|
||||
|
||||
// BLOCK 0
|
||||
BlockDword blockSize;
|
||||
fread(&blockSize, sizeof(BlockDword), 1, loadFile);
|
||||
|
||||
BasicState block0Data;
|
||||
fread(&block0Data, sizeof(BasicState), 1, loadFile);
|
||||
|
||||
BlockDword scriptBlockSize;
|
||||
fread(&scriptBlockSize, sizeof(BlockDword), 1, loadFile);
|
||||
|
||||
char signature[4];
|
||||
fread(signature, sizeof(char), 4, loadFile);
|
||||
if( std::strncmp(signature, "SCR", 3) != 0 ) {
|
||||
if (loadFile == nullptr) {
|
||||
std::cerr << "Failed to open save file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fread(&scriptBlockSize, sizeof(BlockDword), 1, loadFile);
|
||||
// BLOCK 0
|
||||
BlockDword blockSize;
|
||||
READ_SIZE(blockSize)
|
||||
|
||||
static_assert(sizeof(BasicState) == 0xBC, "BasicState is not the right size");
|
||||
READ_BLOCK(state.basic)
|
||||
|
||||
// Convert utf-16 to utf-8
|
||||
size_t bytes = 0;
|
||||
for(;; bytes++ ) {
|
||||
if(state.basic.saveName[bytes-1] == 0 && state.basic.saveName[bytes] == 0) break;
|
||||
}
|
||||
size_t outSize = 24;
|
||||
char outBuff[48];
|
||||
char* outCur = outBuff;
|
||||
auto icv = iconv_open("UTF-8", "UTF-16");
|
||||
char* saveName = (char*)state.basic.saveName;
|
||||
|
||||
iconv(icv, &saveName, &bytes, &outCur, &outSize);
|
||||
strcpy(state.basic.saveName, outBuff);
|
||||
|
||||
BlockDword scriptBlockSize;
|
||||
|
||||
READ_SIZE(scriptBlockSize)
|
||||
CHECK_SIG("SCR")
|
||||
READ_SIZE(scriptBlockSize)
|
||||
|
||||
BlockDword scriptVarCount;
|
||||
fread(&scriptVarCount, sizeof(BlockDword), 1, loadFile);
|
||||
READ_SIZE(scriptVarCount)
|
||||
assert(scriptVarCount == state.script->getFile()->getGlobalsSize());
|
||||
|
||||
fread(state.script->getGlobals(), sizeof(SCMByte), scriptVarCount, loadFile);
|
||||
if(fread(state.script->getGlobals(), sizeof(SCMByte), scriptVarCount, loadFile) != scriptVarCount)
|
||||
{
|
||||
std::cerr << "Failed to read script memory" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockDword scriptDataBlockSize;
|
||||
fread(&scriptDataBlockSize, sizeof(BlockDword), 1, loadFile);
|
||||
@ -328,43 +341,37 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
|
||||
fread(&scriptData, sizeof(Block0ScriptData), 1, loadFile);
|
||||
|
||||
BlockDword numScripts;
|
||||
fread(&numScripts, DWORDSZ, 1, loadFile);
|
||||
READ_SIZE(numScripts)
|
||||
Block0RunningScript scripts[numScripts];
|
||||
fread(scripts, sizeof(Block0RunningScript), numScripts, loadFile);
|
||||
|
||||
// BLOCK 1
|
||||
BlockDword playerBlockSize = readDword(loadFile);
|
||||
BlockDword playerInfoSize = readDword(loadFile);
|
||||
BlockDword playerBlockSize;
|
||||
READ_SIZE(playerBlockSize)
|
||||
BlockDword playerInfoSize;
|
||||
READ_SIZE(playerInfoSize)
|
||||
|
||||
BlockDword playerCount = readDword(loadFile);
|
||||
BlockDword playerCount;
|
||||
READ_SIZE(playerCount)
|
||||
Block1PlayerPed players[playerCount];
|
||||
for(unsigned int p = 0; p < playerCount; ++p) {
|
||||
read(loadFile, players[p].unknown0);
|
||||
read(loadFile, players[p].unknown1);
|
||||
read(loadFile, players[p].reference);
|
||||
read(loadFile, players[p].info);
|
||||
read(loadFile, players[p].maxWantedLevel);
|
||||
read(loadFile, players[p].maxChaosLevel);
|
||||
read(loadFile, players[p].modelName);
|
||||
read(loadFile, players[p].align);
|
||||
READ_BLOCK(players[p])
|
||||
}
|
||||
|
||||
// BLOCK 2
|
||||
BlockDword garageBlockSize = readDword(loadFile);
|
||||
BlockDword garageDataSize = readDword(loadFile);
|
||||
BlockDword garageBlockSize;
|
||||
READ_SIZE(garageBlockSize)
|
||||
BlockDword garageDataSize;
|
||||
READ_SIZE(garageDataSize)
|
||||
|
||||
Block2GarageData garageData;
|
||||
fread(&garageData, sizeof(Block2GarageData), 1, loadFile);
|
||||
READ_BLOCK(garageData)
|
||||
|
||||
StructGarage garages[garageData.garageCount];
|
||||
fread(garages, sizeof(StructGarage), garageData.garageCount, loadFile);
|
||||
|
||||
// Insert Game State.
|
||||
state.hour = block0Data.gameHour;
|
||||
state.minute = block0Data.gameMinute;
|
||||
state.gameTime = block0Data.timeMS / 1000.f;
|
||||
state.currentWeather = block0Data.nextWeather;
|
||||
state.cameraPosition = block0Data.cameraPosition;
|
||||
// We keep track of the game time as a float for now
|
||||
state.gameTime = state.basic.timeMS / 1000.f;
|
||||
|
||||
state.scriptOnMissionFlag = (unsigned int*)state.script->getGlobals() + (size_t)scriptData.onMissionOffset;
|
||||
|
||||
@ -381,7 +388,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
|
||||
thread.calls[i] = scripts[s].stack[i];
|
||||
}
|
||||
/* TODO not hardcode +33 ms */
|
||||
thread.wakeCounter = scripts[s].wakeTimer - block0Data.lastTick + 33;
|
||||
thread.wakeCounter = scripts[s].wakeTimer - state.basic.lastTick + 33;
|
||||
for(int i = 0; i < sizeof(Block0RunningScript::variables); ++i) {
|
||||
thread.locals[i] = scripts[s].variables[i];
|
||||
}
|
||||
@ -445,7 +452,6 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <iconv.h>
|
||||
#include <dirent.h>
|
||||
bool SaveGame::getSaveInfo(const std::string& file, BasicState *basicState)
|
||||
{
|
||||
@ -466,6 +472,7 @@ bool SaveGame::getSaveInfo(const std::string& file, BasicState *basicState)
|
||||
}
|
||||
|
||||
std::fclose(loadFile);
|
||||
|
||||
size_t bytes = 0;
|
||||
for(;; bytes++ ) {
|
||||
if(basicState->saveName[bytes-1] == 0 && basicState->saveName[bytes] == 0) break;
|
||||
|
@ -247,10 +247,10 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
|
||||
glBindVertexArray( vao );
|
||||
|
||||
float tod = world->state->hour + world->state->minute/60.f;
|
||||
float tod = world->getHour() + world->getMinute()/60.f;
|
||||
|
||||
// Requires a float 0-24
|
||||
auto weatherID = static_cast<WeatherLoader::WeatherCondition>(world->state->currentWeather * 24);
|
||||
auto weatherID = static_cast<WeatherLoader::WeatherCondition>(world->state->basic.nextWeather * 24);
|
||||
auto weather = world->data->weatherLoader.getWeatherData(weatherID, tod);
|
||||
|
||||
glm::vec3 skyTop = weather.skyTopColor;
|
||||
|
@ -66,8 +66,8 @@ void game_get_time(const ScriptArguments& args)
|
||||
|
||||
void game_set_time(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->hour = args[0].integer;
|
||||
args.getWorld()->state->minute = args[1].integer;
|
||||
args.getWorld()->state->basic.gameHour = args[0].integer;
|
||||
args.getWorld()->state->basic.gameMinute = args[1].integer;
|
||||
}
|
||||
|
||||
bool game_is_button_pressed(const ScriptArguments& args)
|
||||
@ -301,7 +301,7 @@ void game_enable_input(const ScriptArguments& args)
|
||||
|
||||
void game_set_weather(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->currentWeather = args[0].integer;
|
||||
args.getWorld()->state->basic.nextWeather = args[0].integer;
|
||||
}
|
||||
|
||||
void game_get_runtime(const ScriptArguments& args)
|
||||
@ -593,7 +593,7 @@ void game_clear_cutscene(const ScriptArguments& args)
|
||||
|
||||
void game_set_hidden_packages(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->numHiddenPackages = args[0].integer;
|
||||
args.getWorld()->state->playerInfo.hiddenPackageCount = args[0].integer;
|
||||
}
|
||||
|
||||
void game_load_special_model(const ScriptArguments& args)
|
||||
@ -638,7 +638,7 @@ void game_set_max_progress(const ScriptArguments& args)
|
||||
|
||||
void game_set_unique_jumps(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->numUniqueJumps = args[0].integer;
|
||||
args.getWorld()->state->gameStats.uniqueStuntsTotal = args[0].integer;
|
||||
}
|
||||
|
||||
void game_set_last_mission(const ScriptArguments& args)
|
||||
@ -785,7 +785,7 @@ bool game_did_game_save(const ScriptArguments& args)
|
||||
|
||||
void game_get_found_hidden_packages(const ScriptArguments& args)
|
||||
{
|
||||
*args[0].globalInteger = args.getWorld()->state->numHiddenPackagesDiscovered;
|
||||
*args[0].globalInteger = args.getWorld()->state->playerInfo.hiddenPackagesCollected;
|
||||
}
|
||||
|
||||
void game_display_help(const ScriptArguments& args)
|
||||
@ -830,7 +830,7 @@ void game_load_collision(const ScriptArguments& args)
|
||||
|
||||
void game_set_rampages(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->numRampages = args[0].integer;
|
||||
args.getWorld()->state->gameStats.totalRampages = args[0].integer;
|
||||
}
|
||||
|
||||
void game_set_near_clip(const ScriptArguments& args)
|
||||
@ -840,7 +840,7 @@ void game_set_near_clip(const ScriptArguments& args)
|
||||
|
||||
void game_set_missions(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->numMissions = args[0].integer;
|
||||
args.getWorld()->state->gameStats.totalMissions = args[0].integer;
|
||||
}
|
||||
|
||||
void game_set_sound_fade(const ScriptArguments& args)
|
||||
|
@ -365,12 +365,12 @@ void RWGame::tick(float dt)
|
||||
|
||||
clockAccumulator += dt;
|
||||
while( clockAccumulator >= 1.f ) {
|
||||
world->state->minute ++;
|
||||
while( state->minute >= 60 ) {
|
||||
state->minute = 0;
|
||||
state->hour ++;
|
||||
while( state->hour >= 24 ) {
|
||||
state->hour = 0;
|
||||
world->state->basic.gameMinute ++;
|
||||
while( state->basic.gameMinute >= 60 ) {
|
||||
state->basic.gameMinute = 0;
|
||||
state->basic.gameHour ++;
|
||||
while( state->basic.gameHour >= 24 ) {
|
||||
state->basic.gameHour = 0;
|
||||
}
|
||||
}
|
||||
clockAccumulator -= 1.f;
|
||||
@ -685,10 +685,10 @@ void RWGame::globalKeyEvent(const sf::Event& event)
|
||||
{
|
||||
switch (event.key.code) {
|
||||
case sf::Keyboard::LBracket:
|
||||
state->minute -= 30.f;
|
||||
state->basic.gameMinute -= 30.f;
|
||||
break;
|
||||
case sf::Keyboard::RBracket:
|
||||
state->minute += 30.f;
|
||||
state->basic.gameMinute += 30.f;
|
||||
break;
|
||||
case sf::Keyboard::Num9:
|
||||
timescale *= 0.5f;
|
||||
|
Loading…
Reference in New Issue
Block a user