1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-19 17:01:44 +02:00

clang-format files in rwengine/src/engine

This commit is contained in:
Daniel Evans 2016-09-09 21:13:19 +01:00
parent 8534d7ff5d
commit 80e6317c24
13 changed files with 3504 additions and 3709 deletions

View File

@ -1,23 +1,19 @@
#include <engine/Animator.hpp>
#include <loaders/LoaderDFF.hpp>
#include <data/Model.hpp>
#include <data/Skeleton.hpp>
#include <engine/Animator.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <loaders/LoaderDFF.hpp>
Animator::Animator(Model* model, Skeleton* skeleton)
: model(model)
, skeleton(skeleton)
{
: model(model), skeleton(skeleton) {
}
void Animator::tick(float dt)
{
if( model == nullptr || animations.empty() ) {
void Animator::tick(float dt) {
if (model == nullptr || animations.empty()) {
return;
}
struct BoneTransform
{
struct BoneTransform {
glm::vec3 translation;
glm::quat rotation;
};
@ -25,18 +21,17 @@ void Animator::tick(float dt)
// Blend all active animations together
std::map<unsigned int, BoneTransform> blendFrames;
for (AnimationState& state : animations)
{
RW_CHECK(state.animation != nullptr, "AnimationState with no animation");
for (AnimationState& state : animations) {
RW_CHECK(state.animation != nullptr,
"AnimationState with no animation");
if (state.animation == nullptr) continue;
if (state.boneInstances.size() == 0) {
for( unsigned int f = 0; f < model->frames.size(); ++f )
{
auto bit = state.animation->bones.find( model->frames[f]->getName() );
if( bit != state.animation->bones.end() )
{
state.boneInstances.insert( { bit->second, { f } } );
for (unsigned int f = 0; f < model->frames.size(); ++f) {
auto bit =
state.animation->bones.find(model->frames[f]->getName());
if (bit != state.animation->bones.end()) {
state.boneInstances.insert({bit->second, {f}});
}
}
}
@ -44,29 +39,23 @@ void Animator::tick(float dt)
state.time = state.time + dt;
float animTime = state.time;
if (! state.repeat)
{
if (!state.repeat) {
animTime = std::min(animTime, state.animation->duration);
}
else
{
} else {
animTime = fmod(animTime, state.animation->duration);
}
for( auto& b : state.boneInstances )
{
for (auto& b : state.boneInstances) {
if (b.first->frames.size() == 0) continue;
auto kf = b.first->getInterpolatedKeyframe(animTime);
BoneTransform xform;
if(b.first->type == AnimationBone::R00 ) {
if (b.first->type == AnimationBone::R00) {
xform.rotation = kf.rotation;
}
else if(b.first->type == AnimationBone::RT0) {
} else if (b.first->type == AnimationBone::RT0) {
xform.rotation = kf.rotation;
xform.translation = kf.position;
}
else {
} else {
xform.rotation = kf.rotation;
xform.translation = kf.position;
}
@ -88,45 +77,39 @@ void Animator::tick(float dt)
}
}
for (auto& p : blendFrames)
{
for (auto& p : blendFrames) {
auto& data = skeleton->getData(p.first);
Skeleton::FrameData fd;
fd.b = data.a;
fd.enabled = data.enabled;
fd.a.translation = model->frames[p.first]->getDefaultTranslation()
+ p.second.translation;
fd.a.translation = model->frames[p.first]->getDefaultTranslation() +
p.second.translation;
fd.a.rotation = p.second.rotation;
skeleton->setData(p.first, fd);
}
}
bool Animator::isCompleted(unsigned int slot) const
{
if (slot < animations.size())
{
return animations[slot].animation ?
animations[slot].time >= animations[slot].animation->duration
bool Animator::isCompleted(unsigned int slot) const {
if (slot < animations.size()) {
return animations[slot].animation
? animations[slot].time >=
animations[slot].animation->duration
: true;
}
return false;
}
float Animator::getAnimationTime(unsigned int slot) const
{
if (slot < animations.size())
{
float Animator::getAnimationTime(unsigned int slot) const {
if (slot < animations.size()) {
return animations[slot].time;
}
return 0.f;
}
void Animator::setAnimationTime(unsigned int slot, float time)
{
if (slot < animations.size())
{
void Animator::setAnimationTime(unsigned int slot, float time) {
if (slot < animations.size()) {
animations[slot].time = time;
}
}

View File

@ -1,12 +1,12 @@
#pragma once
#ifndef _ANIMATOR_HPP_
#define _ANIMATOR_HPP_
#include <map>
#include <cstdint>
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <rw/defines.hpp>
#include <loaders/LoaderIFP.hpp>
#include <map>
#include <rw/defines.hpp>
class Model;
class ModelFrame;
@ -23,21 +23,19 @@ class Skeleton;
*
* The Animator will blend all active animations together.
*/
class Animator
{
class Animator {
/**
* @brief Stores data required to animate a model frame
*/
struct BoneInstanceData
{
struct BoneInstanceData {
unsigned int frameIndex;
};
/**
* @brief The AnimationState struct stores information about playing animations
* @brief The AnimationState struct stores information about playing
* animations
*/
struct AnimationState
{
struct AnimationState {
Animation* animation;
/// Timestamp of the last frame
float time;
@ -64,32 +62,26 @@ class Animator
std::vector<AnimationState> animations;
public:
Animator(Model* model, Skeleton* skeleton);
Animation* getAnimation(unsigned int slot)
{
if (slot < animations.size())
{
Animation* getAnimation(unsigned int slot) {
if (slot < animations.size()) {
return animations[slot].animation;
}
return nullptr;
}
void playAnimation(unsigned int slot, Animation* anim, float speed, bool repeat)
{
if (slot >= animations.size())
{
animations.resize(slot+1);
void playAnimation(unsigned int slot, Animation* anim, float speed,
bool repeat) {
if (slot >= animations.size()) {
animations.resize(slot + 1);
}
animations[slot] = { anim, 0.f, speed, repeat, {} };
animations[slot] = {anim, 0.f, speed, repeat, {}};
}
void setAnimationSpeed(unsigned int slot, float speed)
{
void setAnimationSpeed(unsigned int slot, float speed) {
RW_CHECK(slot < animations.size(), "Slot out of range");
if (slot < animations.size())
{
if (slot < animations.size()) {
animations[slot].speed = speed;
}
}

View File

@ -1,43 +1,40 @@
#include <engine/GameData.hpp>
#include <engine/GameWorld.hpp>
#include <engine/GameState.hpp>
#include <loaders/LoaderIPL.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderCOL.hpp>
#include <data/Model.hpp>
#include <data/ObjectData.hpp>
#include <data/WeaponData.hpp>
#include <engine/GameData.hpp>
#include <engine/GameState.hpp>
#include <engine/GameWorld.hpp>
#include <loaders/LoaderCOL.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIPL.hpp>
#include <script/SCMFile.hpp>
#include <data/Model.hpp>
#include <core/Logger.hpp>
#include <loaders/BackgroundLoader.hpp>
#include <loaders/GenericDATLoader.hpp>
#include <loaders/LoaderGXT.hpp>
#include <loaders/BackgroundLoader.hpp>
#include <core/Logger.hpp>
#include <platform/FileIndex.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <boost/algorithm/string/predicate.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
GameData::GameData(Logger* log, WorkContext* work, const std::string& path)
: datpath(path), logger(log), workContext(work), engine(nullptr)
{
: datpath(path), logger(log), workContext(work), engine(nullptr) {
}
GameData::~GameData()
{
for(auto& m : models) {
if(m.second->resource) {
GameData::~GameData() {
for (auto& m : models) {
if (m.second->resource) {
delete m.second->resource;
}
}
}
void GameData::load()
{
void GameData::load() {
index.indexGameDirectory(datpath);
index.indexTree(datpath);
@ -65,130 +62,110 @@ void GameData::load()
loadIFP("ped.ifp");
}
void GameData::loadLevelFile(const std::string& path)
{
void GameData::loadLevelFile(const std::string& path) {
auto datpath = index.findFilePath(path);
std::ifstream datfile(datpath.string());
if(!datfile.is_open())
{
if (!datfile.is_open()) {
logger->error("Data", "Failed to open game file " + path);
return;
}
for(std::string line, cmd; std::getline(datfile, line);)
{
if(line.size() == 0 || line[0] == '#') continue;
#ifndef RW_WINDOWS
line.erase(line.size()-1);
#endif
for (std::string line, cmd; std::getline(datfile, line);) {
if (line.size() == 0 || line[0] == '#') continue;
#ifndef RW_WINDOWS
line.erase(line.size() - 1);
#endif
size_t space = line.find_first_of(' ');
if(space != line.npos)
{
if (space != line.npos) {
cmd = line.substr(0, space);
if(cmd == "IDE")
{
auto path = line.substr(space+1);
if (cmd == "IDE") {
auto path = line.substr(space + 1);
loadIDE(path);
}
else if(cmd == "SPLASH")
{
splash = line.substr(space+1);
}
else if(cmd == "COLFILE")
{
int zone = atoi(line.substr(space+1,1).c_str());
auto path = line.substr(space+3);
} else if (cmd == "SPLASH") {
splash = line.substr(space + 1);
} else if (cmd == "COLFILE") {
int zone = atoi(line.substr(space + 1, 1).c_str());
auto path = line.substr(space + 3);
loadCOL(zone, path);
}
else if(cmd == "IPL")
{
auto path = line.substr(space+1);
} else if (cmd == "IPL") {
auto path = line.substr(space + 1);
loadIPL(path);
}
else if(cmd == "TEXDICTION")
{
auto path = line.substr(space+1);
} else if (cmd == "TEXDICTION") {
auto path = line.substr(space + 1);
/// @todo improve TXD handling
auto name = index.findFilePath(path).filename().string();
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
std::transform(name.begin(), name.end(), name.begin(),
::tolower);
loadTXD(name);
}
}
}
}
void GameData::loadIDE(const std::string& path)
{
void GameData::loadIDE(const std::string& path) {
auto systempath = index.findFilePath(path).string();
LoaderIDE idel;
if(idel.load(systempath)) {
if (idel.load(systempath)) {
objectTypes.insert(idel.objects.begin(), idel.objects.end());
}
else {
} else {
logger->error("Data", "Failed to load IDE " + path);
}
}
uint16_t GameData::findModelObject(const std::string model)
{
auto defit = std::find_if(objectTypes.begin(), objectTypes.end(),
[&](const decltype(objectTypes)::value_type& d)
{
if(d.second->class_type == ObjectInformation::_class("OBJS"))
{
uint16_t GameData::findModelObject(const std::string model) {
auto defit = std::find_if(
objectTypes.begin(), objectTypes.end(),
[&](const decltype(objectTypes)::value_type& d) {
if (d.second->class_type == ObjectInformation::_class("OBJS")) {
auto dat = static_cast<ObjectData*>(d.second.get());
return boost::iequals(dat->modelName, model);
}
return false;
});
if( defit != objectTypes.end() ) return defit->first;
if (defit != objectTypes.end()) return defit->first;
return -1;
}
void GameData::loadCOL(const size_t zone, const std::string& name)
{
void GameData::loadCOL(const size_t zone, const std::string& name) {
RW_UNUSED(zone);
LoaderCOL col;
auto systempath = index.findFilePath(name).string();
if(col.load(systempath)) {
for( size_t i = 0; i < col.instances.size(); ++i ) {
if (col.load(systempath)) {
for (size_t i = 0; i < col.instances.size(); ++i) {
collisions[col.instances[i]->name] = std::move(col.instances[i]);
}
}
}
void GameData::loadIMG(const std::string& name)
{
void GameData::loadIMG(const std::string& name) {
auto syspath = index.findFilePath(name).string();
index.indexArchive(syspath);
}
void GameData::loadIPL(const std::string& path)
{
void GameData::loadIPL(const std::string& path) {
auto systempath = index.findFilePath(path).string();
iplLocations.insert({path, systempath});
}
bool GameData::loadZone(const std::string& path)
{
bool GameData::loadZone(const std::string& path) {
LoaderIPL ipll;
if( ipll.load(path)) {
if( ipll.zones.size() > 0) {
for(auto& z : ipll.zones) {
if (ipll.load(path)) {
if (ipll.zones.size() > 0) {
for (auto& z : ipll.zones) {
zones.insert({z.name, z});
}
logger->info("Data", "Loaded " + std::to_string(ipll.zones.size()) + " zones from " + path);
logger->info("Data", "Loaded " + std::to_string(ipll.zones.size()) +
" zones from " + path);
return true;
}
}
else {
} else {
logger->error("Data", "Failed to load zones from " + path);
}
@ -203,50 +180,42 @@ enum ColSection {
CAR4 ///> Used in GTASA, contains quadruple colors
};
void GameData::loadCarcols(const std::string& path)
{
void GameData::loadCarcols(const std::string& path) {
auto syspath = index.findFilePath(path);
std::ifstream fstream(syspath.string());
std::string line;
ColSection currentSection = Unknown;
while( std::getline(fstream, line)) {
if( line.substr(0, 1) == "#") { // Comment
while (std::getline(fstream, line)) {
if (line.substr(0, 1) == "#") { // Comment
continue;
}
else if( currentSection == Unknown) {
if( line.substr(0, 3) == "col") {
} else if (currentSection == Unknown) {
if (line.substr(0, 3) == "col") {
currentSection = COL;
}
else if( line.substr(0, 3) == "car") {
} else if (line.substr(0, 3) == "car") {
currentSection = CAR;
}
}
else if( line.substr(0, 3) == "end") {
} else if (line.substr(0, 3) == "end") {
currentSection = Unknown;
}
else {
if( currentSection == COL) {
} else {
if (currentSection == COL) {
std::string r, g, b;
std::stringstream ss(line);
if( std::getline(ss, r, ',') && std::getline(ss, g, ',') && std::getline(ss, b)) {
if (std::getline(ss, r, ',') && std::getline(ss, g, ',') &&
std::getline(ss, b)) {
vehicleColours.push_back(glm::u8vec3(
atoi(r.c_str()),
atoi(g.c_str()),
atoi(b.c_str())
));
atoi(r.c_str()), atoi(g.c_str()), atoi(b.c_str())));
}
}
else if( currentSection == CAR) {
} else if (currentSection == CAR) {
std::string vehicle, p, s;
std::stringstream ss(line);
std::getline(ss, vehicle, ',');
std::vector<std::pair<size_t, size_t>> colours;
while( std::getline(ss, p, ',') && std::getline(ss, s, ',') ) {
colours.push_back({ atoi(p.c_str()), atoi(s.c_str()) });
while (std::getline(ss, p, ',') && std::getline(ss, s, ',')) {
colours.push_back({atoi(p.c_str()), atoi(s.c_str())});
}
vehiclePalettes.insert({vehicle, colours});
@ -255,22 +224,19 @@ void GameData::loadCarcols(const std::string& path)
}
}
void GameData::loadWeather(const std::string &path)
{
void GameData::loadWeather(const std::string& path) {
auto syspath = index.findFilePath(path).string();
weatherLoader.load(syspath);
}
void GameData::loadHandling(const std::string& path)
{
void GameData::loadHandling(const std::string& path) {
GenericDATLoader l;
auto syspath = index.findFilePath(path).string();
l.loadHandling(syspath, vehicleInfo);
}
SCMFile *GameData::loadSCM(const std::string &path)
{
SCMFile* GameData::loadSCM(const std::string& path) {
auto scm_h = index.openFilePath(path);
SCMFile* scm = new SCMFile;
scm->loadFile(scm_h->data, scm_h->length);
@ -278,38 +244,37 @@ SCMFile *GameData::loadSCM(const std::string &path)
return scm;
}
void GameData::loadGXT(const std::string &name)
{
void GameData::loadGXT(const std::string& name) {
auto file = index.openFilePath(name);
LoaderGXT loader;
loader.load( texts, file );
loader.load(texts, file);
}
void GameData::loadWaterpro(const std::string& path)
{
void GameData::loadWaterpro(const std::string& path) {
auto syspath = index.findFilePath(path);
std::ifstream ifstr(syspath.string(), std::ios_base::binary);
if(ifstr.is_open()) {
if (ifstr.is_open()) {
uint32_t numlevels;
ifstr.read(reinterpret_cast<char*>(&numlevels), sizeof(uint32_t));
ifstr.read(reinterpret_cast<char*>(&waterHeights), sizeof(float)*48);
ifstr.read(reinterpret_cast<char*>(&waterHeights), sizeof(float) * 48);
ifstr.seekg(0x03C4);
ifstr.read(reinterpret_cast<char*>(&visibleWater), sizeof(char)*64*64);
ifstr.read(reinterpret_cast<char*>(&realWater), sizeof(char)*128*128);
ifstr.read(reinterpret_cast<char*>(&visibleWater),
sizeof(char) * 64 * 64);
ifstr.read(reinterpret_cast<char*>(&realWater),
sizeof(char) * 128 * 128);
}
}
void GameData::loadWater(const std::string& path)
{
void GameData::loadWater(const std::string& path) {
std::ifstream ifstr(path.c_str());
std::string line;
while( std::getline(ifstr, line)) {
if( line[0] == ';') {
while (std::getline(ifstr, line)) {
if (line[0] == ';') {
continue;
}
@ -318,26 +283,21 @@ void GameData::loadWater(const std::string& path)
std::string a, b, c, d, e;
float fa, fb, fc, fd, fe;
if( std::getline(ss, a, ',') && std::getline(ss, b, ',') && std::getline(ss, c, ',') && std::getline(ss, d, ',') && std::getline(ss, e, ',')) {
if (std::getline(ss, a, ',') && std::getline(ss, b, ',') &&
std::getline(ss, c, ',') && std::getline(ss, d, ',') &&
std::getline(ss, e, ',')) {
fa = atof(a.c_str());
fb = atof(b.c_str());
fc = atof(c.c_str());
fd = atof(d.c_str());
fe = atof(e.c_str());
waterBlocks.push_back({
fa,
fb,
fc,
fd,
fe
});
waterBlocks.push_back({fa, fb, fc, fd, fe});
}
}
}
void GameData::loadTXD(const std::string& name, bool async)
{
if( loadedFiles.find(name) != loadedFiles.end() ) {
void GameData::loadTXD(const std::string& name, bool async) {
if (loadedFiles.find(name) != loadedFiles.end()) {
return;
}
@ -345,73 +305,64 @@ void GameData::loadTXD(const std::string& name, bool async)
auto j = new LoadTextureArchiveJob(workContext, &index, textures, name);
if( async ) {
workContext->queueJob( j );
}
else {
if (async) {
workContext->queueJob(j);
} else {
j->work();
j->complete();
delete j;
}
}
void GameData::loadDFF(const std::string& name, bool async)
{
void GameData::loadDFF(const std::string& name, bool async) {
auto realname = name.substr(0, name.size() - 4);
if( models.find(realname) != models.end() ) {
if (models.find(realname) != models.end()) {
return;
}
// Before starting the job make sure the file isn't loaded again.
loadedFiles.insert({name, true});
models[realname] = ModelRef( new ResourceHandle<Model>(realname) );
models[realname] = ModelRef(new ResourceHandle<Model>(realname));
auto job = new BackgroundLoaderJob<Model, LoaderDFF>
{ workContext, &this->index, name, models[realname] };
auto job = new BackgroundLoaderJob<Model, LoaderDFF>{
workContext, &this->index, name, models[realname]};
if( async ) {
workContext->queueJob( job );
}
else {
if (async) {
workContext->queueJob(job);
} else {
job->work();
job->complete();
delete job;
}
}
void GameData::loadIFP(const std::string &name)
{
void GameData::loadIFP(const std::string& name) {
auto f = index.openFile(name);
if(f)
{
if (f) {
LoaderIFP loader;
if( loader.loadFromMemory(f->data) ) {
animations.insert(loader.animations.begin(), loader.animations.end());
if (loader.loadFromMemory(f->data)) {
animations.insert(loader.animations.begin(),
loader.animations.end());
}
}
}
void GameData::loadDynamicObjects(const std::string& name)
{
void GameData::loadDynamicObjects(const std::string& name) {
GenericDATLoader l;
l.loadDynamicObjects(name, dynamicObjectData);
}
void GameData::loadWeaponDAT(const std::string &path)
{
void GameData::loadWeaponDAT(const std::string& path) {
GenericDATLoader l;
auto syspath = index.findFilePath(path).string();
l.loadWeapons(syspath, weaponData);
}
bool GameData::loadAudioStream(const std::string &name)
{
bool GameData::loadAudioStream(const std::string& name) {
auto systempath = index.findFilePath("audio/" + name).string();
if (engine->cutsceneAudio.length() > 0) {
@ -426,20 +377,19 @@ bool GameData::loadAudioStream(const std::string &name)
return false;
}
bool GameData::loadAudioClip(const std::string& name, const std::string& fileName)
{
bool GameData::loadAudioClip(const std::string& name,
const std::string& fileName) {
auto systempath = index.findFilePath("audio/" + fileName).string();
if (systempath.find(".mp3") != std::string::npos)
{
if (systempath.find(".mp3") != std::string::npos) {
logger->error("Data", "MP3 Audio unsupported outside cutscenes");
return false;
}
bool loaded = engine->sound.loadSound(name, systempath);
if ( ! loaded) {
logger->error("Data", "Error loading audio clip "+ systempath);
if (!loaded) {
logger->error("Data", "Error loading audio clip " + systempath);
return false;
}
@ -448,8 +398,7 @@ bool GameData::loadAudioClip(const std::string& name, const std::string& fileNam
return true;
}
void GameData::loadSplash(const std::string &name)
{
void GameData::loadSplash(const std::string& name) {
std::string lower(name);
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
@ -458,36 +407,34 @@ void GameData::loadSplash(const std::string &name)
engine->state->currentSplash = lower;
}
int GameData::getWaterIndexAt(const glm::vec3 &ws) const
{
auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
int GameData::getWaterIndexAt(const glm::vec3& ws) const {
auto wX = (int)((ws.x + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
auto wY = (int)((ws.y + WATER_WORLD_SIZE / 2.f) /
(WATER_WORLD_SIZE / WATER_HQ_DATA_SIZE));
if( wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 && wY < WATER_HQ_DATA_SIZE ) {
int i = (wX*WATER_HQ_DATA_SIZE) + wY;
if (wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 &&
wY < WATER_HQ_DATA_SIZE) {
int i = (wX * WATER_HQ_DATA_SIZE) + wY;
return engine->data->realWater[i];
}
return 0;
}
float GameData::getWaveHeightAt(const glm::vec3 &ws) const
{
return (1+sin(engine->getGameTime() + (ws.x + ws.y) * WATER_SCALE)) * WATER_HEIGHT;
float GameData::getWaveHeightAt(const glm::vec3& ws) const {
return (1 + sin(engine->getGameTime() + (ws.x + ws.y) * WATER_SCALE)) *
WATER_HEIGHT;
}
bool GameData::isValidGameDirectory(const std::string& path)
{
if(path.empty())
{
bool GameData::isValidGameDirectory(const std::string& path) {
if (path.empty()) {
return false;
}
LoaderIMG i;
if(! i.load(path + "/models/gta3.img") )
{
if (!i.load(path + "/models/gta3.img")) {
return false;
}
return true;
}

View File

@ -4,17 +4,17 @@
class Logger;
#include <rw/types.hpp>
#include <loaders/LoaderIMG.hpp>
#include <loaders/LoaderTXD.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIFP.hpp>
#include <loaders/WeatherLoader.hpp>
#include <objects/VehicleInfo.hpp>
#include <data/CollisionModel.hpp>
#include <data/GameTexts.hpp>
#include <data/ZoneData.hpp>
#include <loaders/LoaderDFF.hpp>
#include <loaders/LoaderIDE.hpp>
#include <loaders/LoaderIFP.hpp>
#include <loaders/LoaderIMG.hpp>
#include <loaders/LoaderTXD.hpp>
#include <loaders/WeatherLoader.hpp>
#include <objects/VehicleInfo.hpp>
#include <rw/types.hpp>
#include <audio/MADStream.hpp>
#include <gl/TextureData.hpp>
@ -36,17 +36,15 @@ class SCMFile;
* @todo Improve how Loaders and written and used
* @todo Considering implementation of streaming data and object handles.
*/
class GameData
{
class GameData {
private:
std::string datpath;
std::string splash;
Logger* logger;
WorkContext* workContext;
public:
public:
/**
* ctor
* @param path Path to the root of the game data.
@ -59,16 +57,14 @@ public:
/**
* Returns the current platform
*/
std::string getPlatformString()
{
std::string getPlatformString() {
return "PC";
}
/**
* Returns the game data path
*/
const std::string& getDataPath() const
{
const std::string& getDataPath() const {
return datpath;
}
@ -147,8 +143,8 @@ public:
void loadSplash(const std::string& name);
TextureData::Handle findTexture( const std::string& name, const std::string& alpha = "" )
{
TextureData::Handle findTexture(const std::string& name,
const std::string& alpha = "") {
return textures[{name, alpha}];
}
@ -181,13 +177,12 @@ public:
uint16_t findModelObject(const std::string model);
template<class T> std::shared_ptr<T> findObjectType(ObjectID id)
{
template <class T>
std::shared_ptr<T> findObjectType(ObjectID id) {
auto f = objectTypes.find(id);
/// @TODO don't instanciate an object here just to read .type
T tmp;
if( f != objectTypes.end() && f->second->class_type == tmp.class_type )
{
if (f != objectTypes.end() && f->second->class_type == tmp.class_type) {
return std::static_pointer_cast<T>(f->second);
}
return nullptr;
@ -201,7 +196,8 @@ public:
/**
* The vehicle colours for each vehicle type
*/
std::map<std::string, std::vector<std::pair<size_t,size_t>>> vehiclePalettes;
std::map<std::string, std::vector<std::pair<size_t, size_t>>>
vehiclePalettes;
/**
* Vehicle information
@ -254,8 +250,7 @@ public:
* @struct WaterArea
* Stores Water Rectangle Information
*/
struct WaterArea
{
struct WaterArea {
float height;
float xLeft, yBottom;
float xRight, yTop;
@ -274,12 +269,12 @@ public:
/**
* Visible water heights
*/
uint8_t visibleWater[64*64];
uint8_t visibleWater[64 * 64];
/**
* The "real" water heights
*/
uint8_t realWater[128*128];
uint8_t realWater[128 * 128];
int getWaterIndexAt(const glm::vec3& ws) const;
float getWaveHeightAt(const glm::vec3& ws) const;

View File

@ -1,8 +1,7 @@
#ifndef RWENGINE_GAMEINPUTSTATE_HPP
#define RWENGINE_GAMEINPUTSTATE_HPP
struct GameInputState
{
struct GameInputState {
static constexpr float kButtonOnThreshold = 0.1f;
/// Inputs that can be controlled
@ -56,15 +55,13 @@ struct GameInputState
*
* For buttons, this will result in either 0 or 1.
*/
float currentLevels[_MaxControls] = { };
float currentLevels[_MaxControls] = {};
float operator[] (Control c) const
{
float operator[](Control c) const {
return currentLevels[c];
}
bool pressed(Control c) const
{
bool pressed(Control c) const {
return currentLevels[c] > kButtonOnThreshold;
}
};

View File

@ -1,95 +1,95 @@
#include <engine/GameState.hpp>
BasicState::BasicState()
: saveName { 0 }
, saveTime { 0, 0, 0, 0, 0, 0, 0, 0 }
, islandNumber { 0 }
, cameraPosition { }
, gameMinuteMS { 0 }
, lastTick { 0 }
, gameHour { 0 }
, gameMinute { 0 }
, padMode { 0 }
, timeMS { 0 }
, timeScale { 0 }
, timeStep { 0 }
, timeStep_unclipped { 0 }
, frameCounter { 0 }
, timeStep2 { 0 }
, framesPerUpdate { 0 }
, timeScale2 { 0 }
, lastWeather { 0 }
, nextWeather { 0 }
, forcedWeather { 0 }
, weatherInterpolation { 0 }
, weatherType { 0 }
, cameraData { 0 }
, cameraData2 { 0 }
{ }
: saveName{0}
, saveTime{0, 0, 0, 0, 0, 0, 0, 0}
, islandNumber{0}
, cameraPosition{}
, gameMinuteMS{0}
, lastTick{0}
, gameHour{0}
, gameMinute{0}
, padMode{0}
, timeMS{0}
, timeScale{0}
, timeStep{0}
, timeStep_unclipped{0}
, frameCounter{0}
, timeStep2{0}
, framesPerUpdate{0}
, timeScale2{0}
, lastWeather{0}
, nextWeather{0}
, forcedWeather{0}
, weatherInterpolation{0}
, weatherType{0}
, cameraData{0}
, cameraData2{0} {
}
PlayerInfo::PlayerInfo()
: money { 0 }
, displayedMoney { 0 }
, hiddenPackagesCollected { 0 }
, hiddenPackageCount { 0 }
, neverTired { 0 }
, fastReload { 0 }
, thaneOfLibertyCity { 0 }
, singlePayerHealthcare { 0 }
{ }
: money{0}
, displayedMoney{0}
, hiddenPackagesCollected{0}
, hiddenPackageCount{0}
, neverTired{0}
, fastReload{0}
, thaneOfLibertyCity{0}
, singlePayerHealthcare{0} {
}
GameStats::GameStats()
: playerKills { 0 }
, otherKills { 0 }
, carsExploded { 0 }
, shotsHit { 0 }
, pedTypesKilled { }
, helicoptersDestroyed { 0 }
, playerProgress { 0 }
, explosiveKgsUsed { 0 }
, bulletsFired { 0 }
, bulletsHit { 0 }
, carsCrushed { 0 }
, headshots { 0 }
, timesBusted { 0 }
, timesHospital { 0 }
, daysPassed { 0 }
, mmRainfall { 0 }
, insaneJumpMaxDistance { 0 }
, insaneJumpMaxHeight { 0 }
, insaneJumpMaxFlips { 0 }
, insangeJumpMaxRotation { 0 }
, bestStunt { 0 }
, uniqueStuntsFound { 0 }
, uniqueStuntsTotal { 0 }
, missionAttempts { 0 }
, missionsPassed { 0 }
, passengersDroppedOff { 0 }
, taxiRevenue { 0 }
, portlandPassed { 0 }
, stauntonPassed { 0 }
, shoresidePassed { 0 }
, bestTurismoTime { 0 }
, distanceWalked { 0 }
, distanceDriven { 0 }
, patriotPlaygroundTime { 0 }
, aRideInTheParkTime { 0 }
, grippedTime { 0 }
, multistoryMayhemTime { 0 }
, peopleSaved { 0 }
, criminalsKilled { 0 }
, highestParamedicLevel { 0 }
, firesExtinguished { 0 }
, longestDodoFlight { 0 }
, bombDefusalTime { 0 }
, rampagesPassed { 0 }
, totalRampages { 0 }
, totalMissions { 0 }
, highestScore { }
, peopleKilledSinceCheckpoint { 0 }
, peopleKilledSinceLastBustedOrWasted { 0 }
, lastMissionGXT { "" }
{ }
: playerKills{0}
, otherKills{0}
, carsExploded{0}
, shotsHit{0}
, pedTypesKilled{}
, helicoptersDestroyed{0}
, playerProgress{0}
, explosiveKgsUsed{0}
, bulletsFired{0}
, bulletsHit{0}
, carsCrushed{0}
, headshots{0}
, timesBusted{0}
, timesHospital{0}
, daysPassed{0}
, mmRainfall{0}
, insaneJumpMaxDistance{0}
, insaneJumpMaxHeight{0}
, insaneJumpMaxFlips{0}
, insangeJumpMaxRotation{0}
, bestStunt{0}
, uniqueStuntsFound{0}
, uniqueStuntsTotal{0}
, missionAttempts{0}
, missionsPassed{0}
, passengersDroppedOff{0}
, taxiRevenue{0}
, portlandPassed{0}
, stauntonPassed{0}
, shoresidePassed{0}
, bestTurismoTime{0}
, distanceWalked{0}
, distanceDriven{0}
, patriotPlaygroundTime{0}
, aRideInTheParkTime{0}
, grippedTime{0}
, multistoryMayhemTime{0}
, peopleSaved{0}
, criminalsKilled{0}
, highestParamedicLevel{0}
, firesExtinguished{0}
, longestDodoFlight{0}
, bombDefusalTime{0}
, rampagesPassed{0}
, totalRampages{0}
, totalMissions{0}
, highestScore{}
, peopleKilledSinceCheckpoint{0}
, peopleKilledSinceLastBustedOrWasted{0}
, lastMissionGXT{""} {
}
GameState::GameState()
: basic{}
@ -115,22 +115,15 @@ GameState::GameState()
, importExportShoreside(0)
, importExportUnused(0)
, world(nullptr)
, script(nullptr)
{
, script(nullptr) {
}
int GameState::addRadarBlip(BlipData& blip)
{
int GameState::addRadarBlip(BlipData& blip) {
int l = 0;
for ( auto x = radarBlips.begin(); x != radarBlips.end(); ++x )
{
if ( (x->first) != l )
{
l = x->first-1;
}
else
{
for (auto x = radarBlips.begin(); x != radarBlips.end(); ++x) {
if ((x->first) != l) {
l = x->first - 1;
} else {
l++;
}
}
@ -141,11 +134,9 @@ int GameState::addRadarBlip(BlipData& blip)
return l;
}
void GameState::removeBlip(int blip)
{
auto it = radarBlips.find( blip );
if ( it != radarBlips.end() )
{
void GameState::removeBlip(int blip) {
auto it = radarBlips.find(blip);
if (it != radarBlips.end()) {
radarBlips.erase(it);
}
}

View File

@ -1,16 +1,16 @@
#pragma once
#ifndef _GAMESTATE_HPP_
#define _GAMESTATE_HPP_
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <string>
#include <bitset>
#include <map>
#include <vector>
#include <objects/ObjectTypes.hpp>
#include <engine/ScreenText.hpp>
#include <data/VehicleGenerator.hpp>
#include <engine/GameInputState.hpp>
#include <engine/ScreenText.hpp>
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <map>
#include <objects/ObjectTypes.hpp>
#include <string>
#include <vector>
class GameWorld;
class GameObject;
@ -18,8 +18,7 @@ class ScriptMachine;
class PlayerController;
struct CutsceneData;
struct SystemTime
{
struct SystemTime {
uint16_t year;
uint16_t month;
uint16_t dayOfWeek;
@ -31,8 +30,7 @@ struct SystemTime
};
/** Block 0 State */
struct BasicState
{
struct BasicState {
GameStringChar saveName[24];
SystemTime saveTime;
uint32_t unknown;
@ -66,12 +64,11 @@ struct BasicState
float cameraData;
float cameraData2;
BasicState ();
BasicState();
};
/** Block 16 player info */
struct PlayerInfo
{
struct PlayerInfo {
uint32_t money;
uint8_t unknown1;
uint32_t unknown2;
@ -86,12 +83,11 @@ struct PlayerInfo
uint8_t singlePayerHealthcare;
uint8_t unknown5[70];
PlayerInfo ();
PlayerInfo();
};
/** Block 17 */
struct GameStats
{
struct GameStats {
uint32_t playerKills;
uint32_t otherKills;
uint32_t carsExploded;
@ -155,11 +151,10 @@ struct GameStats
uint32_t peopleKilledSinceLastBustedOrWasted;
char lastMissionGXT[8];
GameStats ();
GameStats();
};
struct TextDisplayData
{
struct TextDisplayData {
// This is set by the final display text command.
GameString text;
glm::vec2 position;
@ -171,12 +166,10 @@ struct TextDisplayData
/**
* Data about a blip
*/
struct BlipData
{
struct BlipData {
int id;
enum BlipType
{
enum BlipType {
Location = 0,
Vehicle = 1,
Pickup = 2,
@ -194,23 +187,15 @@ struct BlipData
uint16_t size = 3; // Only used if texture is empty
enum DisplayMode
{
Hide = 0,
MarkerOnly = 1,
RadarOnly = 2,
ShowBoth = 3
};
enum DisplayMode { Hide = 0, MarkerOnly = 1, RadarOnly = 2, ShowBoth = 3 };
/* Should the blip be displayed? */
DisplayMode display;
BlipData()
: id(-1), type(Location), target(0), display(ShowBoth)
{ }
BlipData() : id(-1), type(Location), target(0), display(ShowBoth) {
}
int getScriptObjectID() const
{
int getScriptObjectID() const {
return id;
}
};
@ -218,8 +203,7 @@ struct BlipData
/**
* Data for garages
*/
struct GarageInfo
{
struct GarageInfo {
enum /*GarageType*/ {
GARAGE_MISSION = 1,
GARAGE_BOMBSHOP1 = 2,
@ -248,18 +232,11 @@ struct GarageInfo
glm::vec3 max;
int type;
GarageInfo(int id_,
const glm::vec3 min_,
const glm::vec3 max_,
int type_)
: id(id_)
, min(min_)
, max(max_)
, type(type_)
{ }
GarageInfo(int id_, const glm::vec3 min_, const glm::vec3 max_, int type_)
: id(id_), min(min_), max(max_), type(type_) {
}
int getScriptObjectID() const
{
int getScriptObjectID() const {
return id;
}
};
@ -268,8 +245,7 @@ struct GarageInfo
* Gameplay state object that holds persistent state, and references runtime
* world state.
*/
class GameState
{
class GameState {
public:
/**
Basic Game State
@ -298,7 +274,8 @@ public:
GameObjectID playerObject;
/**
* @brief Stores a pointer to script global that stores the on-mission state.
* @brief Stores a pointer to script global that stores the on-mission
* state.
*/
int32_t* scriptOnMissionFlag;

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,8 @@ class Logger;
class GameData;
class GameState;
#include <ai/AIGraphNode.hpp>
#include <ai/AIGraph.hpp>
#include <ai/AIGraphNode.hpp>
#include <audio/SoundManager.hpp>
class CutsceneObject;
@ -23,8 +23,8 @@ class VehicleObject;
class PickupObject;
class ViewCamera;
#include <render/VisualFX.hpp>
#include <data/ObjectData.hpp>
#include <render/VisualFX.hpp>
struct BlipData;
class InventoryItem;
@ -35,38 +35,32 @@ struct VehicleGenerator;
#include <glm/glm.hpp>
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <vector>
#include <set>
#include <random>
#include <array>
#include <random>
#include <set>
#include <vector>
/**
* Information about "Goal" locations so they can be rendered
* (this doesn't really belong here).
*/
struct AreaIndicatorInfo
{
enum AreaIndicatorType
{
Cylinder
};
struct AreaIndicatorInfo {
enum AreaIndicatorType { Cylinder };
AreaIndicatorType type;
glm::vec3 position;
glm::vec3 radius;
};
/**
* @brief Handles all data relating to object instances and other "worldly" state.
* @brief Handles all data relating to object instances and other "worldly"
* state.
*/
class GameWorld
{
class GameWorld {
public:
GameWorld(Logger* log, WorkContext* work, GameData* dat);
~GameWorld();
@ -90,7 +84,8 @@ public:
void createTraffic(const ViewCamera& viewCamera);
/**
* @brief cleanupTraffic Cleans up traffic too far away from the given camera
* @brief cleanupTraffic Cleans up traffic too far away from the given
* camera
* @param viewCamera
*/
void cleanupTraffic(const ViewCamera& viewCamera);
@ -98,27 +93,36 @@ public:
/**
* Creates an instance
*/
InstanceObject *createInstance(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat());
InstanceObject* createInstance(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat());
/**
* @brief Creates an InstanceObject for use in the current Cutscene.
*/
CutsceneObject *createCutsceneObject(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat());
CutsceneObject* createCutsceneObject(const uint16_t id,
const glm::vec3& pos,
const glm::quat& rot = glm::quat());
/**
* Creates a vehicle
*/
VehicleObject *createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
VehicleObject* createVehicle(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat(),
GameObjectID gid = 0);
/**
* Creates a pedestrian.
*/
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat(),
GameObjectID gid = 0);
/**
* Creates a player
*/
CharacterObject* createPlayer(const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
CharacterObject* createPlayer(const glm::vec3& pos,
const glm::quat& rot = glm::quat(),
GameObjectID gid = 0);
/**
* Creates a pickup
@ -143,7 +147,7 @@ public:
/**
* Performs a weapon scan against things in the world
*/
void doWeaponScan(const WeaponScan &scan );
void doWeaponScan(const WeaponScan& scan);
/**
* Allocates a new VisualFX of the given type
@ -206,8 +210,7 @@ public:
* Each object type is allocated from a pool. This object helps manage
* the individual pools.
*/
struct ObjectPool
{
struct ObjectPool {
std::map<GameObjectID, GameObject*> objects;
/**
@ -248,7 +251,7 @@ public:
* @param blip
* @return The targetted object of the given blip
*/
GameObject *getBlipTarget(const BlipData &blip) const;
GameObject* getBlipTarget(const BlipData& blip) const;
/**
* Map of Model Names to Instances
@ -284,14 +287,16 @@ public:
* @brief physicsNearCallback
* Used to implement uprooting and other physics oddities.
*/
static bool ContactProcessedCallback(btManifoldPoint& mp, void* body0, void* body1);
static bool ContactProcessedCallback(btManifoldPoint& mp, void* body0,
void* body1);
/**
* @brief PhysicsTickCallback updates object each physics tick.
* @param physWorld
* @param timeStep
*/
static void PhysicsTickCallback(btDynamicsWorld* physWorld, btScalar timeStep);
static void PhysicsTickCallback(btDynamicsWorld* physWorld,
btScalar timeStep);
/**
* Work related
@ -314,15 +319,21 @@ public:
/**
* @brief loads a model into a special character slot.
*/
void loadSpecialCharacter(const unsigned short index, const std::string& name);
void loadSpecialCharacter(const unsigned short index,
const std::string& name);
void loadSpecialModel(const unsigned short index, const std::string& name);
void disableAIPaths(AIGraphNode::NodeType type, const glm::vec3& min, const glm::vec3& max);
void enableAIPaths(AIGraphNode::NodeType type, const glm::vec3& min, const glm::vec3& max);
void disableAIPaths(AIGraphNode::NodeType type, const glm::vec3& min,
const glm::vec3& max);
void enableAIPaths(AIGraphNode::NodeType type, const glm::vec3& min,
const glm::vec3& max);
void drawAreaIndicator(AreaIndicatorInfo::AreaIndicatorType type, glm::vec3 position, glm::vec3 radius);
void drawAreaIndicator(AreaIndicatorInfo::AreaIndicatorType type,
glm::vec3 position, glm::vec3 radius);
const std::vector<AreaIndicatorInfo>& getAreaIndicators() const { return areaIndicators; }
const std::vector<AreaIndicatorInfo>& getAreaIndicators() const {
return areaIndicators;
}
void clearTickData();
@ -335,7 +346,6 @@ public:
VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen);
private:
/**
* @brief Used by objects to delete themselves during updates.
*/

View File

@ -1,16 +1,16 @@
#include <engine/SaveGame.hpp>
#include <ai/PlayerController.hpp>
#include <cstring>
#include <engine/GameData.hpp>
#include <engine/GameState.hpp>
#include <engine/GameWorld.hpp>
#include <objects/GameObject.hpp>
#include <engine/GameData.hpp>
#include <objects/VehicleObject.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/InstanceObject.hpp>
#include <script/ScriptMachine.hpp>
#include <script/SCMFile.hpp>
#include <ai/PlayerController.hpp>
#include <engine/SaveGame.hpp>
#include <items/WeaponItem.hpp>
#include <cstring>
#include <objects/CharacterObject.hpp>
#include <objects/GameObject.hpp>
#include <objects/InstanceObject.hpp>
#include <objects/VehicleObject.hpp>
#include <script/SCMFile.hpp>
#include <script/ScriptMachine.hpp>
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
@ -47,7 +47,7 @@ struct Block0RunningScript {
BlockDword unknown1;
BlockWord stackCounter;
BlockWord unknown2;
SCMByte variables[16*4];
SCMByte variables[16 * 4];
BlockDword timerA;
BlockDword timerB;
uint8_t ifFlag;
@ -358,7 +358,6 @@ struct Block10Data {
Block10Blip blips[32];
};
struct Block11Zone {
char name[8];
glm::vec3 coordA;
@ -472,31 +471,31 @@ struct Block19Data {
Block19PedType types[23];
};
void SaveGame::writeGame(GameState& state, const std::string& file)
{
void SaveGame::writeGame(GameState& state, const std::string& file) {
RW_UNUSED(state);
RW_UNUSED(file);
RW_UNIMPLEMENTED("Saving the game is not implemented yet.");
}
template<class T> bool readBlock(std::FILE* str, T& out) {
template <class T>
bool readBlock(std::FILE* str, T& out) {
return std::fread(&out, sizeof(out), 1, str) == 1;
}
#define READ_VALUE(var) \
if (! readBlock(loadFile, 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)) { \
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) { \
if (fread(signature, sizeof(char), 4, loadFile) != 4) { \
std::cerr << "Failed to read signature" << std::endl; \
return false; \
} \
@ -504,14 +503,13 @@ template<class T> bool readBlock(std::FILE* str, T& out) {
std::cerr << "Signature " expected " incorrect" << std::endl; \
return false; \
} \
}
}
#define BLOCK_HEADER(sizevar) \
fseek(loadFile, nextBlock, SEEK_SET); \
READ_SIZE(sizevar) \
nextBlock += sizeof(sizevar) + sizevar;
bool SaveGame::loadGame(GameState& state, const std::string& file)
{
bool SaveGame::loadGame(GameState& state, const std::string& file) {
std::FILE* loadFile = std::fopen(file.c_str(), "rb");
if (loadFile == nullptr) {
std::cerr << "Failed to open save file" << std::endl;
@ -524,7 +522,8 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
BlockDword blockSize;
BLOCK_HEADER(blockSize);
static_assert(sizeof(BasicState) == 0xBC, "BasicState is not the right size");
static_assert(sizeof(BasicState) == 0xBC,
"BasicState is not the right size");
READ_VALUE(state.basic)
BlockDword scriptBlockSize;
@ -537,15 +536,15 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_SIZE(scriptVarCount)
assert(scriptVarCount == state.script->getFile()->getGlobalsSize());
if(fread(state.script->getGlobals(), sizeof(SCMByte), scriptVarCount, loadFile) != scriptVarCount)
{
if (fread(state.script->getGlobals(), sizeof(SCMByte), scriptVarCount,
loadFile) != scriptVarCount) {
std::cerr << "Failed to read script memory" << std::endl;
return false;
}
BlockDword scriptDataBlockSize;
READ_SIZE(scriptDataBlockSize);
if( scriptDataBlockSize != 0x03C8 ) {
if (scriptDataBlockSize != 0x03C8) {
return false;
}
@ -555,8 +554,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
BlockDword numScripts;
READ_SIZE(numScripts)
std::vector<Block0RunningScript> scripts(numScripts);
for (size_t i = 0; i < numScripts; ++i)
{
for (size_t i = 0; i < numScripts; ++i) {
READ_VALUE(scripts[i]);
}
@ -569,7 +567,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_SIZE(playerCount)
std::vector<Block1PlayerPed> players(playerCount);
for(unsigned int p = 0; p < playerCount; ++p) {
for (unsigned int p = 0; p < playerCount; ++p) {
Block1PlayerPed& ped = players[p];
READ_VALUE(ped.unknown0)
READ_VALUE(ped.unknown1)
@ -581,11 +579,13 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(ped.align)
#if RW_DEBUG
std::cout << "Player Health: " << ped.info.health << " (" << ped.info.armour << ")" << std::endl;
std::cout << "Player Health: " << ped.info.health << " ("
<< ped.info.armour << ")" << std::endl;
std::cout << "Player model: " << ped.modelName << std::endl;
for(int w = 0; w < 13; ++w) {
for (int w = 0; w < 13; ++w) {
auto& wep = players[p].info.weapons[w];
std::cout << "ID " << wep.weaponId << " " << wep.inClip << " " << wep.totalBullets << std::endl;
std::cout << "ID " << wep.weaponId << " " << wep.inClip << " "
<< wep.totalBullets << std::endl;
}
#endif
}
@ -610,8 +610,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(garageData.cars)
std::vector<StructGarage> garages(garageData.garageCount);
for (size_t i = 0; i < garageData.garageCount; ++i)
{
for (size_t i = 0; i < garageData.garageCount; ++i) {
READ_VALUE(garages[i]);
}
@ -619,14 +618,17 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
std::cout << "Garages: " << garageData.garageCount << std::endl;
std::cout << "Bombs Free: " << garageData.freeBombs << std::endl;
std::cout << "Sprays Free: " << garageData.freeResprays << std::endl;
std::cout << "Portland IE: " << garageData.bfImportExportPortland << std::endl;
std::cout << "Shoreside IE: " << garageData.bfImportExportShoreside << std::endl;
std::cout << "Portland IE: " << garageData.bfImportExportPortland
<< std::endl;
std::cout << "Shoreside IE: " << garageData.bfImportExportShoreside
<< std::endl;
std::cout << "GA21 last shown: " << garageData.GA_21lastTime << std::endl;
for (int c = 0; c < 18; ++c) {
StructStoredCar& car = garageData.cars[c];
if (car.modelId == 0) continue;
std::cout << " " << car.modelId << " " << uint16_t(car.colorFG) << "/" << uint16_t(car.colorBG)
<< " " << car.immunities << std::endl;
std::cout << " " << car.modelId << " " << uint16_t(car.colorFG) << "/"
<< uint16_t(car.colorBG) << " " << car.immunities
<< std::endl;
}
#endif
@ -642,25 +644,29 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(boatCount)
std::vector<Block3Vehicle> vehicles(vehicleCount);
for(size_t v = 0; v < vehicleCount; ++v) {
for (size_t v = 0; v < vehicleCount; ++v) {
Block3Vehicle& veh = vehicles[v];
READ_VALUE(veh.unknown1)
READ_VALUE(veh.modelId)
READ_VALUE(veh.unknown2)
READ_VALUE(veh.state)
#if RW_DEBUG
std::cout << " v " << veh.modelId << " " << veh.state.position.x << " " << veh.state.position.y << " " << veh.state.position.z << std::endl;
std::cout << " v " << veh.modelId << " " << veh.state.position.x << " "
<< veh.state.position.y << " " << veh.state.position.z
<< std::endl;
#endif
}
std::vector<Block3Boat> boats(boatCount);
for(size_t v = 0; v < boatCount; ++v) {
for (size_t v = 0; v < boatCount; ++v) {
Block3Boat& veh = boats[v];
READ_VALUE(veh.unknown1)
READ_VALUE(veh.modelId)
READ_VALUE(veh.unknown2)
READ_VALUE(veh.state)
#if RW_DEBUG
std::cout << " b " << veh.modelId << " " << veh.state.position.x << " " << veh.state.position.y << " " << veh.state.position.z << std::endl;
std::cout << " b " << veh.modelId << " " << veh.state.position.x << " "
<< veh.state.position.y << " " << veh.state.position.z
<< std::endl;
#endif
}
@ -674,9 +680,8 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(objectCount);
std::vector<Block4Object> objects(objectCount);
for(size_t o = 0; o < objectCount; ++o)
{
Block4Object &obj = objects[o];
for (size_t o = 0; o < objectCount; ++o) {
Block4Object& obj = objects[o];
READ_VALUE(obj.modelId)
READ_VALUE(obj.reference)
READ_VALUE(obj.position)
@ -694,11 +699,15 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
}
for (size_t o = 0; o < objectCount; ++o) {
auto &obj = objects[o];
GameObject* inst = state.world->createInstance(obj.modelId, obj.position);
glm::vec3 right = glm::normalize(glm::vec3(obj.rotation[0], obj.rotation[1], obj.rotation[2]));
glm::vec3 forward = glm::normalize(glm::vec3(obj.rotation[3], obj.rotation[4], obj.rotation[5]));
glm::vec3 down = glm::normalize(glm::vec3(obj.rotation[6], obj.rotation[7], obj.rotation[8]));
auto& obj = objects[o];
GameObject* inst =
state.world->createInstance(obj.modelId, obj.position);
glm::vec3 right = glm::normalize(
glm::vec3(obj.rotation[0], obj.rotation[1], obj.rotation[2]));
glm::vec3 forward = glm::normalize(
glm::vec3(obj.rotation[3], obj.rotation[4], obj.rotation[5]));
glm::vec3 down = glm::normalize(
glm::vec3(obj.rotation[6], obj.rotation[7], obj.rotation[8]));
glm::mat3 m = glm::mat3(right, forward, -down);
inst->setRotation(glm::normalize(static_cast<glm::quat>(m)));
}
@ -706,15 +715,22 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
#if RW_DEBUG
std::cout << "Objects " << objectCount << std::endl;
for (size_t o = 0; o < objectCount; ++o) {
auto &obj = objects[o];
glm::vec3 right = glm::normalize(glm::vec3(obj.rotation[0], obj.rotation[1], obj.rotation[2]));
glm::vec3 forward = glm::normalize(glm::vec3(obj.rotation[3], obj.rotation[4], obj.rotation[5]));
glm::vec3 down = glm::normalize(glm::vec3(obj.rotation[6], obj.rotation[7], obj.rotation[8]));
auto& obj = objects[o];
glm::vec3 right = glm::normalize(
glm::vec3(obj.rotation[0], obj.rotation[1], obj.rotation[2]));
glm::vec3 forward = glm::normalize(
glm::vec3(obj.rotation[3], obj.rotation[4], obj.rotation[5]));
glm::vec3 down = glm::normalize(
glm::vec3(obj.rotation[6], obj.rotation[7], obj.rotation[8]));
std::cout << "modelId " << obj.modelId << " ";
std::cout << "position " << obj.position.x << " "<< obj.position.y << " " << obj.position.z << " ";
std::cout << "right " << right.x << " "<< right.y << " " << right.z << " ";
std::cout << "forward " << forward.x << " "<< forward.y << " " << forward.z << " ";
std::cout << "down " << down.x << " " << down.y << " " << down.z << std::endl;
std::cout << "position " << obj.position.x << " " << obj.position.y
<< " " << obj.position.z << " ";
std::cout << "right " << right.x << " " << right.y << " " << right.z
<< " ";
std::cout << "forward " << forward.x << " " << forward.y << " "
<< forward.z << " ";
std::cout << "down " << down.x << " " << down.y << " " << down.z
<< std::endl;
}
std::cout << std::endl;
#endif
@ -741,17 +757,19 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
Block6Data craneData;
READ_VALUE(craneData.numCranes)
READ_VALUE(craneData.militaryCollected)
for(size_t c = 0; c < craneData.numCranes; ++c) {
Block6Crane &crane = craneData.cranes[c];
for (size_t c = 0; c < craneData.numCranes; ++c) {
Block6Crane& crane = craneData.cranes[c];
READ_VALUE(crane)
}
#if RW_DEBUG
std::cout << "Cranes: " << craneData.numCranes << std::endl;
for(size_t c = 0; c < craneData.numCranes; ++c) {
Block6Crane &crane = craneData.cranes[c];
std::cout << "pickup " << crane.x1Pickup << " " << crane.y1Pickup << " " << crane.x2Pickup << " " << crane.y2Pickup << std::endl;
std::cout << "vehicles collected " << uint16_t(crane.vehiclesCollected) << std::endl;
for (size_t c = 0; c < craneData.numCranes; ++c) {
Block6Crane& crane = craneData.cranes[c];
std::cout << "pickup " << crane.x1Pickup << " " << crane.y1Pickup << " "
<< crane.x2Pickup << " " << crane.y2Pickup << std::endl;
std::cout << "vehicles collected " << uint16_t(crane.vehiclesCollected)
<< std::endl;
}
#endif
@ -765,10 +783,11 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(pickupData);
#if RW_DEBUG
for(int c = 0; c < 336; ++c) {
Block7Pickup &p = pickupData.pickups[c];
for (int c = 0; c < 336; ++c) {
Block7Pickup& p = pickupData.pickups[c];
if (p.type == 0) continue;
std::cout << " " << uint16_t(p.type) << " " << p.position.x << " " << p.position.y << " " << p.position.z << std::endl;
std::cout << " " << uint16_t(p.type) << " " << p.position.x << " "
<< p.position.y << " " << p.position.z << std::endl;
}
#endif
@ -782,15 +801,17 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(phoneData);
std::vector<Block8Phone> phones(phoneData.numPhones);
for (size_t p = 0; p < phoneData.numPhones; ++p) {
Block8Phone &phone = phones[p];
Block8Phone& phone = phones[p];
READ_VALUE(phone)
}
#if RW_DEBUG
std::cout << "Phones: " << phoneData.numPhones << std::endl;
for (size_t p = 0; p < phoneData.numPhones; ++p) {
Block8Phone &phone = phones[p];
std::cout << " " << uint16_t(phone.state) << " " << phone.position.x << " " << phone.position.y << " " << phone.position.z << std::endl;
Block8Phone& phone = phones[p];
std::cout << " " << uint16_t(phone.state) << " " << phone.position.x
<< " " << phone.position.y << " " << phone.position.z
<< std::endl;
}
#endif
@ -806,14 +827,17 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(restartData);
#if RW_DEBUG
std::cout << "Hospitals: " << restartData.numHospitals << " police: " << restartData.numPolice << std::endl;
for(int s = 0; s < restartData.numHospitals; ++s) {
Block9Restart &p = restartData.hospitalRestarts[s];
std::cout << " H " << p.position.x << " " << p.position.y << " " << p.position.z << std::endl;
std::cout << "Hospitals: " << restartData.numHospitals
<< " police: " << restartData.numPolice << std::endl;
for (int s = 0; s < restartData.numHospitals; ++s) {
Block9Restart& p = restartData.hospitalRestarts[s];
std::cout << " H " << p.position.x << " " << p.position.y << " "
<< p.position.z << std::endl;
}
for(int s = 0; s < restartData.numPolice; ++s) {
Block9Restart &p = restartData.policeRestarts[s];
std::cout << " P " << p.position.x << " " << p.position.y << " " << p.position.z << std::endl;
for (int s = 0; s < restartData.numPolice; ++s) {
Block9Restart& p = restartData.policeRestarts[s];
std::cout << " P " << p.position.x << " " << p.position.y << " "
<< p.position.z << std::endl;
}
#endif
@ -829,10 +853,11 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(radarData);
#if RW_DEBUG
for(int b = 0; b < 32; ++b) {
Block10Blip &p = radarData.blips[b];
for (int b = 0; b < 32; ++b) {
Block10Blip& p = radarData.blips[b];
if (p.type == 0) continue;
std::cout << " " << p.position.x << " " << p.position.y << " " << p.position.z << std::endl;
std::cout << " " << p.position.x << " " << p.position.y << " "
<< p.position.z << std::endl;
}
#endif
@ -850,7 +875,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(zoneData.findIndex);
READ_VALUE(zoneData.align);
for (int z = 0; z < 50; z++) {
Block11Zone &zone = zoneData.navZones[z];
Block11Zone& zone = zoneData.navZones[z];
READ_VALUE(zone.name);
READ_VALUE(zone.coordA);
READ_VALUE(zone.coordB);
@ -863,14 +888,14 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(zone.siblingZone);
}
for (int z = 0; z < 100; z++) {
Block11ZoneInfo &info = zoneData.dayNightInfo[z];
Block11ZoneInfo& info = zoneData.dayNightInfo[z];
READ_VALUE(info.density)
READ_VALUE(info.unknown1)
}
READ_VALUE(zoneData.numNavZones);
READ_VALUE(zoneData.numZoneInfos);
for (int z = 0; z < 25; z++) {
Block11Zone &zone = zoneData.mapZones[z];
Block11Zone& zone = zoneData.mapZones[z];
READ_VALUE(zone.name);
READ_VALUE(zone.coordA);
READ_VALUE(zone.coordB);
@ -889,14 +914,15 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(zoneData.numAudioZones);
#if RW_DEBUG
std::cout << "zones: " << zoneData.numNavZones << " " << zoneData.numZoneInfos << " "
<< zoneData.numMapZones << " " << zoneData.numAudioZones << std::endl;
for(int z = 0; z < zoneData.numNavZones; ++z) {
Block11Zone &zone = zoneData.navZones[z];
std::cout << "zones: " << zoneData.numNavZones << " "
<< zoneData.numZoneInfos << " " << zoneData.numMapZones << " "
<< zoneData.numAudioZones << std::endl;
for (int z = 0; z < zoneData.numNavZones; ++z) {
Block11Zone& zone = zoneData.navZones[z];
std::cout << " " << zone.name << std::endl;
}
for(int z = 0; z < zoneData.numMapZones; ++z) {
Block11Zone &zone = zoneData.mapZones[z];
for (int z = 0; z < zoneData.numMapZones; ++z) {
Block11Zone& zone = zoneData.mapZones[z];
std::cout << " " << zone.name << std::endl;
}
#endif
@ -913,9 +939,10 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(gangData);
#if RW_DEBUG
for(int g = 0; g < 9; ++g) {
Block12Gang &p = gangData.gangs[g];
std::cout << " " << p.carModelId << " " << p.weaponPrimary << " " << p.weaponSecondary << std::endl;
for (int g = 0; g < 9; ++g) {
Block12Gang& p = gangData.gangs[g];
std::cout << " " << p.carModelId << " " << p.weaponPrimary << " "
<< p.weaponSecondary << std::endl;
}
#endif
@ -930,16 +957,19 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
Block13Data carGeneratorData;
READ_VALUE(carGeneratorData);
std::vector<Block13CarGenerator> carGenerators(carGeneratorData.generatorCount);
for(size_t g = 0; g < carGeneratorData.generatorCount; ++g) {
std::vector<Block13CarGenerator> carGenerators(
carGeneratorData.generatorCount);
for (size_t g = 0; g < carGeneratorData.generatorCount; ++g) {
READ_VALUE(carGenerators[g])
}
#if RW_DEBUG
std::cout << "Car generators: " << carGeneratorData.generatorCount << std::endl;
for(size_t g = 0; g < carGeneratorData.generatorCount; ++g) {
Block13CarGenerator &gen = carGenerators[g];
std::cout << " " << gen.modelId << " " << gen.position.x << " "<< gen.position.y << " " << gen.position.z << std::endl;
std::cout << "Car generators: " << carGeneratorData.generatorCount
<< std::endl;
for (size_t g = 0; g < carGeneratorData.generatorCount; ++g) {
Block13CarGenerator& gen = carGenerators[g];
std::cout << " " << gen.modelId << " " << gen.position.x << " "
<< gen.position.y << " " << gen.position.z << std::endl;
}
#endif
@ -952,7 +982,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
BlockDword particleCount;
READ_VALUE(particleCount);
std::vector<Block14Particle> particles(particleCount);
for(size_t p = 0; p < particleCount; ++p) {
for (size_t p = 0; p < particleCount; ++p) {
READ_VALUE(particles[p])
}
@ -972,7 +1002,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(audioCount)
std::vector<Block15AudioObject> audioObjects(audioCount);
for(size_t a = 0; a < audioCount; ++a) {
for (size_t a = 0; a < audioCount; ++a) {
READ_VALUE(audioObjects[a])
}
@ -1000,7 +1030,8 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(state.playerInfo.unknown5)
#if RW_DEBUG
std::cout << "Player money: " << state.playerInfo.money << " (" << state.playerInfo.displayedMoney << ")" << std::endl;
std::cout << "Player money: " << state.playerInfo.money << " ("
<< state.playerInfo.displayedMoney << ")" << std::endl;
#endif
// Block 17
@ -1063,7 +1094,8 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
#if RW_DEBUG
std::cout << "Player kills: " << state.gameStats.playerKills << std::endl;
std::cout << "longest flight " << state.gameStats.longestDodoFlight << std::endl;
std::cout << "longest flight " << state.gameStats.longestDodoFlight
<< std::endl;
#endif
// Block 18
@ -1076,14 +1108,13 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
READ_VALUE(streamingData);
#if RW_DEBUG && 0 // No idea what the data in the section means yet
static const size_t streamSize = sqrt(200*8);
static const size_t streamSize = sqrt(200 * 8);
for (int x = 0; x < streamSize; ++x) {
for (int y = 0; y < streamSize; ++y) {
size_t coord = (y * streamSize) + x;
if (streamingData.unknown1[(coord/8)] & (0x1 << (coord%8))) {
if (streamingData.unknown1[(coord / 8)] & (0x1 << (coord % 8))) {
std::cout << "\u2588";
}
else {
} else {
std::cout << " ";
}
}
@ -1105,7 +1136,8 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
#if RW_DEBUG && 0 // Nor this
for (int i = 0; i < 23; ++i) {
if (pedTypeData.types[i].unknown1 & (0x1 << i) != 0) continue;
std::cout << pedTypeData.types[i].unknown1 << " " << pedTypeData.types[i].unknown7 << std::endl;
std::cout << pedTypeData.types[i].unknown1 << " "
<< pedTypeData.types[i].unknown7 << std::endl;
}
#endif
@ -1114,28 +1146,29 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
// We keep track of the game time as a float for now
state.gameTime = state.basic.timeMS / 1000.f;
state.scriptOnMissionFlag = (int32_t*)(state.script->getGlobals() + (size_t)scriptData.onMissionOffset);
state.scriptOnMissionFlag = (int32_t*)(state.script->getGlobals() +
(size_t)scriptData.onMissionOffset);
auto& threads = state.script->getThreads();
for(size_t s = 0; s < numScripts; ++s) {
for (size_t s = 0; s < numScripts; ++s) {
state.script->startThread(scripts[s].programCounter);
SCMThread& thread = threads.back();
// thread.baseAddress // ??
strncpy(thread.name, scripts[s].name, sizeof(SCMThread::name)-1);
strncpy(thread.name, scripts[s].name, sizeof(SCMThread::name) - 1);
thread.conditionResult = scripts[s].ifFlag;
thread.conditionCount = scripts[s].ifNumber;
thread.stackDepth = scripts[s].stackCounter;
for(int i = 0; i < SCM_STACK_DEPTH; ++i) {
for (int i = 0; i < SCM_STACK_DEPTH; ++i) {
thread.calls[i] = scripts[s].stack[i];
}
/* TODO not hardcode +33 ms */
thread.wakeCounter = scripts[s].wakeTimer - state.basic.lastTick + 33;
for(size_t i = 0; i < sizeof(Block0RunningScript::variables); ++i) {
for (size_t i = 0; i < sizeof(Block0RunningScript::variables); ++i) {
thread.locals[i] = scripts[s].variables[i];
}
}
if( playerCount > 0 ) {
if (playerCount > 0) {
auto& ply = players[0];
std::cout << ply.reference << std::endl;
auto player = state.world->createPlayer(players[0].info.position);
@ -1144,7 +1177,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
cs.armour = players[0].info.armour;
state.playerObject = player->getGameObjectID();
state.maxWantedLevel = players[0].maxWantedLevel;
for(int w = 0; w < 13; ++w) {
for (int w = 0; w < 13; ++w) {
auto& wep = ply.info.weapons[w];
cs.weapons[w].weaponId = wep.weaponId;
cs.weapons[w].bulletsClip = wep.inClip;
@ -1154,26 +1187,21 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
// TODO restore garage data
// http://gtaforums.com/topic/758692-gta-iii-save-file-documentation/
for(size_t g = 0; g < garageData.garageCount; ++g) {
for (size_t g = 0; g < garageData.garageCount; ++g) {
auto& garage = garages[g];
state.garages.push_back({
(int)g,
glm::vec3(garage.x1, garage.y1, garage.z1),
glm::vec3(garage.x2, garage.y2, garage.z2),
garage.type
});
state.garages.push_back(
{(int)g, glm::vec3(garage.x1, garage.y1, garage.z1),
glm::vec3(garage.x2, garage.y2, garage.z2), garage.type});
}
for(int c = 0; c < 18; ++c) {
if(garageData.cars[c].modelId == 0) continue;
for (int c = 0; c < 18; ++c) {
if (garageData.cars[c].modelId == 0) continue;
auto& car = garageData.cars[c];
glm::quat rotation(
glm::mat3(
glm::cross(car.rotation, glm::vec3(0.f, 0.f, 1.f)),
car.rotation,
glm::vec3(0.f, 0.f, 1.f)
));
glm::mat3(glm::cross(car.rotation, glm::vec3(0.f, 0.f, 1.f)),
car.rotation, glm::vec3(0.f, 0.f, 1.f)));
VehicleObject* vehicle = state.world->createVehicle(car.modelId, car.position, rotation);
VehicleObject* vehicle =
state.world->createVehicle(car.modelId, car.position, rotation);
vehicle->setPrimaryColour(car.colorFG);
vehicle->setSecondaryColour(car.colorBG);
}
@ -1181,18 +1209,9 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
for (unsigned g = 0; g < carGenerators.size(); ++g) {
auto& gen = carGenerators[g];
state.vehicleGenerators.emplace_back(
g,
gen.position,
gen.angle,
gen.modelId,
gen.colourFG,
gen.colourBG,
gen.force,
gen.alarmChance,
gen.lockedChance,
gen.minDelay,
gen.maxDelay,
gen.timestamp,
g, gen.position, gen.angle, gen.modelId, gen.colourFG, gen.colourBG,
gen.force, gen.alarmChance, gen.lockedChance, gen.minDelay,
gen.maxDelay, gen.timestamp,
101 /// @todo determine where the remainingSpawns should be
);
}
@ -1207,8 +1226,7 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
return true;
}
bool SaveGame::getSaveInfo(const std::string& file, BasicState *basicState)
{
bool SaveGame::getSaveInfo(const std::string& file, BasicState* basicState) {
std::FILE* loadFile = std::fopen(file.c_str(), "rb");
SaveGameInfo info;
@ -1216,12 +1234,12 @@ bool SaveGame::getSaveInfo(const std::string& file, BasicState *basicState)
// BLOCK 0
BlockDword blockSize;
if( fread(&blockSize, sizeof(BlockDword), 1, loadFile) == 0 ) {
if (fread(&blockSize, sizeof(BlockDword), 1, loadFile) == 0) {
return false;
}
// Read block 0 into state
if( fread(basicState, sizeof(BasicState), 1, loadFile) == 0 ) {
if (fread(basicState, sizeof(BasicState), 1, loadFile) == 0) {
return false;
}
@ -1230,13 +1248,12 @@ bool SaveGame::getSaveInfo(const std::string& file, BasicState *basicState)
return true;
}
std::vector<SaveGameInfo> SaveGame::getAllSaveGameInfo()
{
std::vector<SaveGameInfo> SaveGame::getAllSaveGameInfo() {
using namespace boost::filesystem;
// TODO consider windows
auto homedir = getenv("HOME");
if( homedir == nullptr ) {
if (homedir == nullptr) {
std::cerr << "Unable to determine home directory" << std::endl;
return {};
}
@ -1245,15 +1262,17 @@ std::vector<SaveGameInfo> SaveGame::getAllSaveGameInfo()
path gamePath(homedir);
gamePath /= gameDir;
if(!exists(gamePath) || !is_directory(gamePath))
return {};
if (!exists(gamePath) || !is_directory(gamePath)) return {};
std::vector<SaveGameInfo> infos;
for(const path& save_path : boost::make_iterator_range(directory_iterator(gamePath), {})) {
if(save_path.extension() == ".b") {
for (const path& save_path :
boost::make_iterator_range(directory_iterator(gamePath), {})) {
if (save_path.extension() == ".b") {
std::cout << save_path.string() << std::endl;
infos.emplace_back(SaveGameInfo {save_path.string(), false, BasicState()});
infos.back().valid = getSaveInfo(infos.back().savePath, &infos.back().basicState);
infos.emplace_back(
SaveGameInfo{save_path.string(), false, BasicState()});
infos.back().valid =
getSaveInfo(infos.back().savePath, &infos.back().basicState);
}
}

View File

@ -12,8 +12,7 @@
class GameWorld;
class ScriptMachine;
struct SaveGameInfo
{
struct SaveGameInfo {
std::string savePath;
bool valid;
BasicState basicState;
@ -22,10 +21,8 @@ struct SaveGameInfo
/**
* Reads and Writes GameStates to disk, restoring the required state information
*/
class SaveGame
{
class SaveGame {
public:
/**
* Writes the entire game state to a file format that closely approximates
* the format used in GTA III

View File

@ -1,35 +1,29 @@
#include <engine/ScreenText.hpp>
void ScreenText::tick(float dt)
{
void ScreenText::tick(float dt) {
int millis = dt * 1000;
// Remove all the immedate text
m_textQueues[static_cast<size_t>(ScreenTextType::Immediate)].clear();
for (unsigned int t = 0; t < m_textQueues.size(); ++t)
{
for (unsigned int i = 0; i < m_textQueues[t].size();)
{
for (unsigned int t = 0; t < m_textQueues.size(); ++t) {
for (unsigned int i = 0; i < m_textQueues[t].size();) {
auto& big = m_textQueues[t][i];
big.displayedMS += millis;
if (big.displayedMS >= big.durationMS)
{
m_textQueues[t].erase(m_textQueues[t].begin()+i);
}
else
{
if (big.displayedMS >= big.durationMS) {
m_textQueues[t].erase(m_textQueues[t].begin() + i);
} else {
++i;
}
}
}
}
ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameString& str, int style, int durationMS)
{
switch(style) {
ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id,
const GameString& str, int style,
int durationMS) {
switch (style) {
// Color: Blue
// Font: Pricedown
// Style: Italic (lowercase only)
@ -37,19 +31,17 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
// Vertically: Baseline at y = 252 (from top)
// Size: 25 Pixel high letters ('S', 'l')
case 1:
return {
str,
return {str,
{320.f, 252.f},
1,
50,
{ 2, 0, 0, 0},
{2, 0, 0, 0},
{58, 119, 133},
1,
durationMS,
0,
600,
id
};
id};
// Color: Yellow/Gold
// Font: Pricedown
@ -58,19 +50,17 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
// Vertically: Baseline at y = 380 (from top)
// Size: 22 Pixel high letters ('S', 'l')
case 2:
return {
str,
return {str,
{620.f, 380.f},
1,
30,
{ 2, 3, 0, 0},
{2, 3, 0, 0},
{214, 171, 9},
2,
durationMS,
0,
600,
id
};
id};
// Color: Light brown
// Font: Pricedown
@ -79,19 +69,17 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
// Vertically: Baseline at y = 427 (from top)
// Size: 28 Pixel high letters ('S', 'l')
case 3:
return {
str,
return {str,
{320.f, 400.f},
1,
50,
{ 5, 5, 0, 0},
{5, 5, 0, 0},
{169, 123, 88}, /// @todo verify
1,
durationMS,
0,
600,
id
};
id};
// Color: Blue
// Font: Arial
@ -101,19 +89,18 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
// Size: 20 Pixel high letters ('S', 'l')
case 4:
case 5:
return {
str,
return {str,
{320.f, 176.f},
2,
50,
((style == 4) ? glm::u8vec4({ 2, 2, 0, 0}) : glm::u8vec4({ -2, -2, 0, 0 })),
((style == 4) ? glm::u8vec4({2, 2, 0, 0})
: glm::u8vec4({-2, -2, 0, 0})),
{90, 115, 150}, /// @todo verify
1,
durationMS,
0,
600,
id
};
id};
// Color: Brown
// Font: Arial
@ -122,27 +109,24 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
// Vertically: Baseline at y = 240 (from top)
// Size: 16 Pixel high letters ('S', 'l')
case 6:
return {
str,
return {str,
{320.f, 240.f},
2,
50,
{ 2, 2, 0, 0},
{2, 2, 0, 0},
{152, 89, 39},
1,
durationMS,
0,
600,
id
};
id};
default:
RW_ERROR("Unhandled text style");
break;
}
return {
GameStringUtil::fromString("Error, style " + std::to_string(style)),
return {GameStringUtil::fromString("Error, style " + std::to_string(style)),
{320.f, 400.f},
2,
50,
@ -152,20 +136,19 @@ ScreenTextEntry ScreenTextEntry::makeBig(const GameStringKey& id, const GameStri
durationMS,
0,
600,
id
};
id};
}
ScreenTextEntry ScreenTextEntry::makeHighPriority(const GameStringKey& id, const GameString& str, int durationMS)
{
ScreenTextEntry ScreenTextEntry::makeHighPriority(const GameStringKey& id,
const GameString& str,
int durationMS) {
// Color: ?
// Font: Arial
// Style: Italic
// Horizontally: Centered
// @todo verify: Vertically: Baseline at y = 431 (from top)
// @todo verify: Size: 15 Pixel high letters ('S', 'l')
return {
str,
return {str,
{320.f, 420.f},
2,
18,
@ -175,23 +158,11 @@ ScreenTextEntry ScreenTextEntry::makeHighPriority(const GameStringKey& id, const
durationMS,
0,
50,
id
};
id};
}
ScreenTextEntry ScreenTextEntry::makeHelp(const GameStringKey& id, const GameString& str)
{
return {
str,
{20.f, 20.f},
2,
18,
{ 0, 0, 0, 255},
{255, 255, 255},
0,
5000,
0,
35,
id
};
ScreenTextEntry ScreenTextEntry::makeHelp(const GameStringKey& id,
const GameString& str) {
return {str, {20.f, 20.f}, 2, 18, {0, 0, 0, 255}, {255, 255, 255}, 0, 5000,
0, 35, id};
}

View File

@ -1,14 +1,13 @@
#ifndef RWENGINE_SCREENTEXT_HPP
#define RWENGINE_SCREENTEXT_HPP
#include <rw/types.hpp>
#include <data/GameTexts.hpp>
#include <vector>
#include <array>
#include <algorithm>
#include <array>
#include <data/GameTexts.hpp>
#include <rw/types.hpp>
#include <utility>
#include <vector>
enum class ScreenTextType
{
enum class ScreenTextType {
/// Big text will be rendered according to the proscribed style.
/// Adding a 2nd big text will cause the first to terminate.
Big = 0,
@ -23,15 +22,15 @@ enum class ScreenTextType
///
_Count = 5
};
constexpr unsigned int ScreenTypeTextCount = static_cast<unsigned int>(ScreenTextType::_Count);
constexpr unsigned int ScreenTypeTextCount =
static_cast<unsigned int>(ScreenTextType::_Count);
/**
* @brief The ScreenTextEntry struct
*
* Text string and fading information.
*/
struct ScreenTextEntry
{
struct ScreenTextEntry {
/// After processing numbers
GameString text;
/// in the virtual 640x480 screen space
@ -56,8 +55,7 @@ struct ScreenTextEntry
GameStringKey id;
static ScreenTextEntry makeBig(const GameStringKey& id,
const GameString& str,
int style,
const GameString& str, int style,
int durationMS);
static ScreenTextEntry makeHighPriority(const GameStringKey& id,
@ -88,14 +86,11 @@ struct ScreenTextEntry
* Immediate text is only rendered once, the text is removed at the
* start of each tick and must be re-added to keep it on screen.
*/
class ScreenText
{
using EntryList =
std::vector<ScreenTextEntry>;
using EntryQueues =
std::array<EntryList, ScreenTypeTextCount>;
public:
class ScreenText {
using EntryList = std::vector<ScreenTextEntry>;
using EntryQueues = std::array<EntryList, ScreenTypeTextCount>;
public:
///
/// \brief tick Apply display and fading rules to the text
/// \param dt
@ -103,52 +98,50 @@ public:
void tick(float dt);
template <ScreenTextType Q, class... Args>
void addText(Args&&...args)
{
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount, "Queue out of range");
m_textQueues[static_cast<size_t>(Q)].emplace_back(std::forward<Args...>(args...));
void addText(Args&&... args) {
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount,
"Queue out of range");
m_textQueues[static_cast<size_t>(Q)].emplace_back(
std::forward<Args...>(args...));
}
template <ScreenTextType Q>
const EntryList& getText() const
{
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount, "Queue out of range");
const EntryList& getText() const {
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount,
"Queue out of range");
return m_textQueues[static_cast<size_t>(Q)];
}
template <ScreenTextType Q>
void clear()
{
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount, "Queue out of range");
void clear() {
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount,
"Queue out of range");
m_textQueues[static_cast<size_t>(Q)].clear();
}
template <ScreenTextType Q>
void remove(const std::string& id)
{
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount, "Queue out of range");
void remove(const std::string& id) {
static_assert(static_cast<size_t>(Q) < ScreenTypeTextCount,
"Queue out of range");
auto& list = m_textQueues[static_cast<size_t>(Q)];
list.erase(
std::remove_if(list.begin(), list.end(),
[&id](const ScreenTextEntry& e){ return e.id == id; }),
list.end()
);
list.erase(std::remove_if(
list.begin(), list.end(),
[&id](const ScreenTextEntry& e) { return e.id == id; }),
list.end());
}
const EntryQueues& getAllText() const
{
const EntryQueues& getAllText() const {
return m_textQueues;
}
template<class...Args>
static GameString format(GameString format, Args&&...args)
{
template <class... Args>
static GameString format(GameString format, Args&&... args) {
static auto kReplacementMarker = GameStringUtil::fromString("~1~");
const std::array<GameString, sizeof...(args)> vals = { args... };
const std::array<GameString, sizeof...(args)> vals = {args...};
size_t x = 0, val = 0;
// We're only looking for numerical replacement markers
while ((x = format.find(kReplacementMarker)) != GameString::npos && val < vals.size())
{
while ((x = format.find(kReplacementMarker)) != GameString::npos &&
val < vals.size()) {
format = format.substr(0, x) + vals[val++] + format.substr(x + 3);
}
return format;