mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-19 08:52:33 +02:00
clang-format files in rwengine/src/engine
This commit is contained in:
parent
8534d7ff5d
commit
80e6317c24
@ -1,75 +1,64 @@
|
||||
#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() ) {
|
||||
return;
|
||||
}
|
||||
void Animator::tick(float dt) {
|
||||
if (model == nullptr || animations.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct BoneTransform
|
||||
{
|
||||
glm::vec3 translation;
|
||||
glm::quat rotation;
|
||||
};
|
||||
struct BoneTransform {
|
||||
glm::vec3 translation;
|
||||
glm::quat rotation;
|
||||
};
|
||||
|
||||
// Blend all active animations together
|
||||
std::map<unsigned int, BoneTransform> blendFrames;
|
||||
// Blend all active animations together
|
||||
std::map<unsigned int, BoneTransform> blendFrames;
|
||||
|
||||
for (AnimationState& state : animations)
|
||||
{
|
||||
RW_CHECK(state.animation != nullptr, "AnimationState with no animation");
|
||||
if (state.animation == nullptr) continue;
|
||||
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 } } );
|
||||
}
|
||||
}
|
||||
}
|
||||
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}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.time = state.time + dt;
|
||||
state.time = state.time + dt;
|
||||
|
||||
float animTime = state.time;
|
||||
if (! state.repeat)
|
||||
{
|
||||
animTime = std::min(animTime, state.animation->duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
animTime = fmod(animTime, state.animation->duration);
|
||||
}
|
||||
float animTime = state.time;
|
||||
if (!state.repeat) {
|
||||
animTime = std::min(animTime, state.animation->duration);
|
||||
} else {
|
||||
animTime = fmod(animTime, state.animation->duration);
|
||||
}
|
||||
|
||||
for( auto& b : state.boneInstances )
|
||||
{
|
||||
if (b.first->frames.size() == 0) continue;
|
||||
auto kf = b.first->getInterpolatedKeyframe(animTime);
|
||||
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 ) {
|
||||
xform.rotation = kf.rotation;
|
||||
}
|
||||
else if(b.first->type == AnimationBone::RT0) {
|
||||
xform.rotation = kf.rotation;
|
||||
xform.translation = kf.position;
|
||||
}
|
||||
else {
|
||||
xform.rotation = kf.rotation;
|
||||
xform.translation = kf.position;
|
||||
}
|
||||
BoneTransform xform;
|
||||
if (b.first->type == AnimationBone::R00) {
|
||||
xform.rotation = kf.rotation;
|
||||
} else if (b.first->type == AnimationBone::RT0) {
|
||||
xform.rotation = kf.rotation;
|
||||
xform.translation = kf.position;
|
||||
} else {
|
||||
xform.rotation = kf.rotation;
|
||||
xform.translation = kf.position;
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto prevAnim = blendFrames.find(b.second.frameIndex);
|
||||
@ -83,50 +72,44 @@ void Animator::tick(float dt)
|
||||
blendFrames[b.second.frameIndex] = xform;
|
||||
}
|
||||
#else
|
||||
blendFrames[b.second.frameIndex] = xform;
|
||||
blendFrames[b.second.frameIndex] = xform;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& p : blendFrames)
|
||||
{
|
||||
auto& data = skeleton->getData(p.first);
|
||||
Skeleton::FrameData fd;
|
||||
fd.b = data.a;
|
||||
fd.enabled = data.enabled;
|
||||
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.rotation = p.second.rotation;
|
||||
fd.a.translation = model->frames[p.first]->getDefaultTranslation() +
|
||||
p.second.translation;
|
||||
fd.a.rotation = p.second.rotation;
|
||||
|
||||
skeleton->setData(p.first, fd);
|
||||
}
|
||||
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
|
||||
: true;
|
||||
}
|
||||
return false;
|
||||
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())
|
||||
{
|
||||
return animations[slot].time;
|
||||
}
|
||||
return 0.f;
|
||||
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())
|
||||
{
|
||||
animations[slot].time = time;
|
||||
}
|
||||
void Animator::setAnimationTime(unsigned int slot, float time) {
|
||||
if (slot < animations.size()) {
|
||||
animations[slot].time = time;
|
||||
}
|
||||
}
|
||||
|
@ -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,89 +23,81 @@ class Skeleton;
|
||||
*
|
||||
* The Animator will blend all active animations together.
|
||||
*/
|
||||
class Animator
|
||||
{
|
||||
/**
|
||||
* @brief Stores data required to animate a model frame
|
||||
*/
|
||||
struct BoneInstanceData
|
||||
{
|
||||
unsigned int frameIndex;
|
||||
};
|
||||
class Animator {
|
||||
/**
|
||||
* @brief Stores data required to animate a model frame
|
||||
*/
|
||||
struct BoneInstanceData {
|
||||
unsigned int frameIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The AnimationState struct stores information about playing animations
|
||||
*/
|
||||
struct AnimationState
|
||||
{
|
||||
Animation* animation;
|
||||
/// Timestamp of the last frame
|
||||
float time;
|
||||
/// Speed multiplier
|
||||
float speed;
|
||||
/// Automatically restart
|
||||
bool repeat;
|
||||
std::map<AnimationBone*, BoneInstanceData> boneInstances;
|
||||
};
|
||||
/**
|
||||
* @brief The AnimationState struct stores information about playing
|
||||
* animations
|
||||
*/
|
||||
struct AnimationState {
|
||||
Animation* animation;
|
||||
/// Timestamp of the last frame
|
||||
float time;
|
||||
/// Speed multiplier
|
||||
float speed;
|
||||
/// Automatically restart
|
||||
bool repeat;
|
||||
std::map<AnimationBone*, BoneInstanceData> boneInstances;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief model The model being animated.
|
||||
*/
|
||||
Model* model;
|
||||
|
||||
/**
|
||||
* @brief Skeleton instance.
|
||||
*/
|
||||
Skeleton* skeleton;
|
||||
/**
|
||||
* @brief model The model being animated.
|
||||
*/
|
||||
Model* model;
|
||||
|
||||
/**
|
||||
* @brief Currently playing animations
|
||||
*/
|
||||
std::vector<AnimationState> animations;
|
||||
/**
|
||||
* @brief Skeleton instance.
|
||||
*/
|
||||
Skeleton* skeleton;
|
||||
|
||||
/**
|
||||
* @brief Currently playing animations
|
||||
*/
|
||||
std::vector<AnimationState> animations;
|
||||
|
||||
public:
|
||||
Animator(Model* model, Skeleton* skeleton);
|
||||
|
||||
Animator(Model* model, Skeleton* skeleton);
|
||||
Animation* getAnimation(unsigned int slot) {
|
||||
if (slot < animations.size()) {
|
||||
return animations[slot].animation;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
animations[slot] = {anim, 0.f, speed, repeat, {}};
|
||||
}
|
||||
|
||||
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, {} };
|
||||
}
|
||||
void setAnimationSpeed(unsigned int slot, float speed) {
|
||||
RW_CHECK(slot < animations.size(), "Slot out of range");
|
||||
if (slot < animations.size()) {
|
||||
animations[slot].speed = speed;
|
||||
}
|
||||
}
|
||||
|
||||
void setAnimationSpeed(unsigned int slot, float speed)
|
||||
{
|
||||
RW_CHECK(slot < animations.size(), "Slot out of range");
|
||||
if (slot < animations.size())
|
||||
{
|
||||
animations[slot].speed = speed;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief tick Update animation paramters for server-side data.
|
||||
* @param dt
|
||||
*/
|
||||
void tick(float dt);
|
||||
|
||||
/**
|
||||
* @brief tick Update animation paramters for server-side data.
|
||||
* @param dt
|
||||
*/
|
||||
void tick(float dt);
|
||||
|
||||
/**
|
||||
* Returns true if the animation has finished playing.
|
||||
*/
|
||||
bool isCompleted(unsigned int slot) const;
|
||||
float getAnimationTime(unsigned int slot) const;
|
||||
void setAnimationTime(unsigned int slot, float time);
|
||||
/**
|
||||
* Returns true if the animation has finished playing.
|
||||
*/
|
||||
bool isCompleted(unsigned int slot) const;
|
||||
float getAnimationTime(unsigned int slot) const;
|
||||
void setAnimationTime(unsigned int slot, float time);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,493 +1,440 @@
|
||||
#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) {
|
||||
delete m.second->resource;
|
||||
}
|
||||
}
|
||||
GameData::~GameData() {
|
||||
for (auto& m : models) {
|
||||
if (m.second->resource) {
|
||||
delete m.second->resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::load()
|
||||
{
|
||||
index.indexGameDirectory(datpath);
|
||||
index.indexTree(datpath);
|
||||
void GameData::load() {
|
||||
index.indexGameDirectory(datpath);
|
||||
index.indexTree(datpath);
|
||||
|
||||
loadIMG("models/gta3.img");
|
||||
/// @todo cuts.img files should be loaded differently to gta3.img
|
||||
loadIMG("anim/cuts.img");
|
||||
loadIMG("models/gta3.img");
|
||||
/// @todo cuts.img files should be loaded differently to gta3.img
|
||||
loadIMG("anim/cuts.img");
|
||||
|
||||
loadLevelFile("data/default.dat");
|
||||
loadLevelFile("data/gta3.dat");
|
||||
|
||||
loadDFF("wheels.dff");
|
||||
loadDFF("weapons.dff");
|
||||
loadDFF("arrow.dff");
|
||||
loadTXD("particle.txd");
|
||||
loadTXD("icons.txd");
|
||||
loadTXD("hud.txd");
|
||||
loadTXD("fonts.txd");
|
||||
|
||||
loadCarcols("data/carcols.dat");
|
||||
loadWeather("data/timecyc.dat");
|
||||
loadHandling("data/handling.cfg");
|
||||
loadWaterpro("data/waterpro.dat");
|
||||
loadWeaponDAT("data/weapon.dat");
|
||||
loadLevelFile("data/default.dat");
|
||||
loadLevelFile("data/gta3.dat");
|
||||
|
||||
loadIFP("ped.ifp");
|
||||
loadDFF("wheels.dff");
|
||||
loadDFF("weapons.dff");
|
||||
loadDFF("arrow.dff");
|
||||
loadTXD("particle.txd");
|
||||
loadTXD("icons.txd");
|
||||
loadTXD("hud.txd");
|
||||
loadTXD("fonts.txd");
|
||||
|
||||
loadCarcols("data/carcols.dat");
|
||||
loadWeather("data/timecyc.dat");
|
||||
loadHandling("data/handling.cfg");
|
||||
loadWaterpro("data/waterpro.dat");
|
||||
loadWeaponDAT("data/weapon.dat");
|
||||
|
||||
loadIFP("ped.ifp");
|
||||
}
|
||||
|
||||
void GameData::loadLevelFile(const std::string& path)
|
||||
{
|
||||
auto datpath = index.findFilePath(path);
|
||||
std::ifstream datfile(datpath.string());
|
||||
void GameData::loadLevelFile(const std::string& path) {
|
||||
auto datpath = index.findFilePath(path);
|
||||
std::ifstream datfile(datpath.string());
|
||||
|
||||
if(!datfile.is_open())
|
||||
{
|
||||
logger->error("Data", "Failed to open game file " + path);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
cmd = line.substr(0, space);
|
||||
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);
|
||||
loadCOL(zone, path);
|
||||
}
|
||||
else if(cmd == "IPL")
|
||||
{
|
||||
auto path = line.substr(space+1);
|
||||
loadIPL(path);
|
||||
}
|
||||
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);
|
||||
loadTXD(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t space = line.find_first_of(' ');
|
||||
if (space != line.npos) {
|
||||
cmd = line.substr(0, space);
|
||||
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);
|
||||
loadCOL(zone, path);
|
||||
} else if (cmd == "IPL") {
|
||||
auto path = line.substr(space + 1);
|
||||
loadIPL(path);
|
||||
} 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);
|
||||
loadTXD(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadIDE(const std::string& path)
|
||||
{
|
||||
auto systempath = index.findFilePath(path).string();
|
||||
LoaderIDE idel;
|
||||
void GameData::loadIDE(const std::string& path) {
|
||||
auto systempath = index.findFilePath(path).string();
|
||||
LoaderIDE idel;
|
||||
|
||||
if(idel.load(systempath)) {
|
||||
objectTypes.insert(idel.objects.begin(), idel.objects.end());
|
||||
}
|
||||
else {
|
||||
logger->error("Data", "Failed to load IDE " + path);
|
||||
}
|
||||
if (idel.load(systempath)) {
|
||||
objectTypes.insert(idel.objects.begin(), idel.objects.end());
|
||||
} 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"))
|
||||
{
|
||||
auto dat = static_cast<ObjectData*>(d.second.get());
|
||||
return boost::iequals(dat->modelName, model);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if( defit != objectTypes.end() ) return defit->first;
|
||||
return -1;
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GameData::loadCOL(const size_t zone, const std::string& name)
|
||||
{
|
||||
RW_UNUSED(zone);
|
||||
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 ) {
|
||||
collisions[col.instances[i]->name] = std::move(col.instances[i]);
|
||||
}
|
||||
}
|
||||
LoaderCOL col;
|
||||
|
||||
auto systempath = index.findFilePath(name).string();
|
||||
|
||||
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)
|
||||
{
|
||||
auto syspath = index.findFilePath(name).string();
|
||||
index.indexArchive(syspath);
|
||||
void GameData::loadIMG(const std::string& name) {
|
||||
auto syspath = index.findFilePath(name).string();
|
||||
index.indexArchive(syspath);
|
||||
}
|
||||
|
||||
void GameData::loadIPL(const std::string& path)
|
||||
{
|
||||
auto systempath = index.findFilePath(path).string();
|
||||
iplLocations.insert({path, systempath});
|
||||
void GameData::loadIPL(const std::string& path) {
|
||||
auto systempath = index.findFilePath(path).string();
|
||||
iplLocations.insert({path, systempath});
|
||||
}
|
||||
|
||||
bool GameData::loadZone(const std::string& path)
|
||||
{
|
||||
LoaderIPL ipll;
|
||||
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger->error("Data", "Failed to load zones from " + path);
|
||||
}
|
||||
|
||||
return false;
|
||||
bool GameData::loadZone(const std::string& path) {
|
||||
LoaderIPL ipll;
|
||||
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
logger->error("Data", "Failed to load zones from " + path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
enum ColSection {
|
||||
Unknown,
|
||||
COL,
|
||||
CAR,
|
||||
CAR3, ///> Used in GTASA, contains extra specular color
|
||||
CAR4 ///> Used in GTASA, contains quadruple colors
|
||||
Unknown,
|
||||
COL,
|
||||
CAR,
|
||||
CAR3, ///> Used in GTASA, contains extra specular color
|
||||
CAR4 ///> Used in GTASA, contains quadruple colors
|
||||
};
|
||||
|
||||
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
|
||||
continue;
|
||||
}
|
||||
else if( currentSection == Unknown) {
|
||||
if( line.substr(0, 3) == "col") {
|
||||
currentSection = COL;
|
||||
}
|
||||
else if( line.substr(0, 3) == "car") {
|
||||
currentSection = CAR;
|
||||
}
|
||||
}
|
||||
else if( line.substr(0, 3) == "end") {
|
||||
currentSection = Unknown;
|
||||
}
|
||||
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)) {
|
||||
vehicleColours.push_back(glm::u8vec3(
|
||||
atoi(r.c_str()),
|
||||
atoi(g.c_str()),
|
||||
atoi(b.c_str())
|
||||
));
|
||||
}
|
||||
}
|
||||
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()) });
|
||||
}
|
||||
|
||||
vehiclePalettes.insert({vehicle, colours});
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
continue;
|
||||
} else if (currentSection == Unknown) {
|
||||
if (line.substr(0, 3) == "col") {
|
||||
currentSection = COL;
|
||||
} else if (line.substr(0, 3) == "car") {
|
||||
currentSection = CAR;
|
||||
}
|
||||
} else if (line.substr(0, 3) == "end") {
|
||||
currentSection = Unknown;
|
||||
} 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)) {
|
||||
vehicleColours.push_back(glm::u8vec3(
|
||||
atoi(r.c_str()), atoi(g.c_str()), atoi(b.c_str())));
|
||||
}
|
||||
} 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())});
|
||||
}
|
||||
|
||||
vehiclePalettes.insert({vehicle, colours});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadWeather(const std::string &path)
|
||||
{
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
weatherLoader.load(syspath);
|
||||
void GameData::loadWeather(const std::string& path) {
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
weatherLoader.load(syspath);
|
||||
}
|
||||
|
||||
void GameData::loadHandling(const std::string& path)
|
||||
{
|
||||
GenericDATLoader l;
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
void GameData::loadHandling(const std::string& path) {
|
||||
GenericDATLoader l;
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
|
||||
l.loadHandling(syspath, vehicleInfo);
|
||||
l.loadHandling(syspath, vehicleInfo);
|
||||
}
|
||||
|
||||
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);
|
||||
scm_h.reset();
|
||||
return scm;
|
||||
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);
|
||||
scm_h.reset();
|
||||
return scm;
|
||||
}
|
||||
|
||||
void GameData::loadGXT(const std::string &name)
|
||||
{
|
||||
auto file = index.openFilePath(name);
|
||||
void GameData::loadGXT(const std::string& name) {
|
||||
auto file = index.openFilePath(name);
|
||||
|
||||
LoaderGXT loader;
|
||||
LoaderGXT loader;
|
||||
|
||||
loader.load( texts, file );
|
||||
loader.load(texts, file);
|
||||
}
|
||||
|
||||
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()) {
|
||||
uint32_t numlevels;
|
||||
ifstr.read(reinterpret_cast<char*>(&numlevels), sizeof(uint32_t));
|
||||
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);
|
||||
}
|
||||
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()) {
|
||||
uint32_t numlevels;
|
||||
ifstr.read(reinterpret_cast<char*>(&numlevels), sizeof(uint32_t));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadWater(const std::string& path)
|
||||
{
|
||||
std::ifstream ifstr(path.c_str());
|
||||
|
||||
std::string line;
|
||||
while( std::getline(ifstr, line)) {
|
||||
if( line[0] == ';') {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ss(line);
|
||||
|
||||
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, ',')) {
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
void GameData::loadWater(const std::string& path) {
|
||||
std::ifstream ifstr(path.c_str());
|
||||
|
||||
std::string line;
|
||||
while (std::getline(ifstr, line)) {
|
||||
if (line[0] == ';') {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ss(line);
|
||||
|
||||
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, ',')) {
|
||||
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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadTXD(const std::string& name, bool async)
|
||||
{
|
||||
if( loadedFiles.find(name) != loadedFiles.end() ) {
|
||||
return;
|
||||
}
|
||||
void GameData::loadTXD(const std::string& name, bool async) {
|
||||
if (loadedFiles.find(name) != loadedFiles.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadedFiles[name] = true;
|
||||
loadedFiles[name] = true;
|
||||
|
||||
auto j = new LoadTextureArchiveJob(workContext, &index, textures, name);
|
||||
auto j = new LoadTextureArchiveJob(workContext, &index, textures, name);
|
||||
|
||||
if( async ) {
|
||||
workContext->queueJob( j );
|
||||
}
|
||||
else {
|
||||
j->work();
|
||||
j->complete();
|
||||
delete j;
|
||||
}
|
||||
if (async) {
|
||||
workContext->queueJob(j);
|
||||
} else {
|
||||
j->work();
|
||||
j->complete();
|
||||
delete j;
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadDFF(const std::string& name, bool async)
|
||||
{
|
||||
auto realname = name.substr(0, name.size() - 4);
|
||||
if( models.find(realname) != models.end() ) {
|
||||
return;
|
||||
}
|
||||
void GameData::loadDFF(const std::string& name, bool async) {
|
||||
auto realname = name.substr(0, name.size() - 4);
|
||||
if (models.find(realname) != models.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Before starting the job make sure the file isn't loaded again.
|
||||
loadedFiles.insert({name, true});
|
||||
// Before starting the job make sure the file isn't loaded again.
|
||||
loadedFiles.insert({name, true});
|
||||
|
||||
models[realname] = ModelRef( new ResourceHandle<Model>(realname) );
|
||||
|
||||
auto job = new BackgroundLoaderJob<Model, LoaderDFF>
|
||||
{ workContext, &this->index, name, models[realname] };
|
||||
models[realname] = ModelRef(new ResourceHandle<Model>(realname));
|
||||
|
||||
if( async ) {
|
||||
workContext->queueJob( job );
|
||||
}
|
||||
else {
|
||||
job->work();
|
||||
job->complete();
|
||||
delete job;
|
||||
}
|
||||
auto job = new BackgroundLoaderJob<Model, LoaderDFF>{
|
||||
workContext, &this->index, name, models[realname]};
|
||||
|
||||
if (async) {
|
||||
workContext->queueJob(job);
|
||||
} else {
|
||||
job->work();
|
||||
job->complete();
|
||||
delete job;
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadIFP(const std::string &name)
|
||||
{
|
||||
auto f = index.openFile(name);
|
||||
void GameData::loadIFP(const std::string& name) {
|
||||
auto f = index.openFile(name);
|
||||
|
||||
if(f)
|
||||
{
|
||||
LoaderIFP loader;
|
||||
if( loader.loadFromMemory(f->data) ) {
|
||||
animations.insert(loader.animations.begin(), loader.animations.end());
|
||||
}
|
||||
|
||||
}
|
||||
if (f) {
|
||||
LoaderIFP loader;
|
||||
if (loader.loadFromMemory(f->data)) {
|
||||
animations.insert(loader.animations.begin(),
|
||||
loader.animations.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadDynamicObjects(const std::string& name)
|
||||
{
|
||||
GenericDATLoader l;
|
||||
void GameData::loadDynamicObjects(const std::string& name) {
|
||||
GenericDATLoader l;
|
||||
|
||||
l.loadDynamicObjects(name, dynamicObjectData);
|
||||
l.loadDynamicObjects(name, dynamicObjectData);
|
||||
}
|
||||
|
||||
void GameData::loadWeaponDAT(const std::string &path)
|
||||
{
|
||||
GenericDATLoader l;
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
void GameData::loadWeaponDAT(const std::string& path) {
|
||||
GenericDATLoader l;
|
||||
auto syspath = index.findFilePath(path).string();
|
||||
|
||||
l.loadWeapons(syspath, weaponData);
|
||||
l.loadWeapons(syspath, weaponData);
|
||||
}
|
||||
|
||||
bool GameData::loadAudioStream(const std::string &name)
|
||||
{
|
||||
auto systempath = index.findFilePath("audio/" + name).string();
|
||||
|
||||
if (engine->cutsceneAudio.length() > 0) {
|
||||
engine->sound.stopMusic(engine->cutsceneAudio);
|
||||
}
|
||||
bool GameData::loadAudioStream(const std::string& name) {
|
||||
auto systempath = index.findFilePath("audio/" + name).string();
|
||||
|
||||
if (engine->sound.loadMusic(name, systempath)) {
|
||||
engine->cutsceneAudio = name;
|
||||
return true;
|
||||
}
|
||||
if (engine->cutsceneAudio.length() > 0) {
|
||||
engine->sound.stopMusic(engine->cutsceneAudio);
|
||||
}
|
||||
|
||||
return false;
|
||||
if (engine->sound.loadMusic(name, systempath)) {
|
||||
engine->cutsceneAudio = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameData::loadAudioClip(const std::string& name, const std::string& fileName)
|
||||
{
|
||||
auto systempath = index.findFilePath("audio/" + fileName).string();
|
||||
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)
|
||||
{
|
||||
logger->error("Data", "MP3 Audio unsupported outside cutscenes");
|
||||
return false;
|
||||
}
|
||||
if (systempath.find(".mp3") != std::string::npos) {
|
||||
logger->error("Data", "MP3 Audio unsupported outside cutscenes");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loaded = engine->sound.loadSound(name, systempath);
|
||||
bool loaded = engine->sound.loadSound(name, systempath);
|
||||
|
||||
if ( ! loaded) {
|
||||
logger->error("Data", "Error loading audio clip "+ systempath);
|
||||
return false;
|
||||
}
|
||||
if (!loaded) {
|
||||
logger->error("Data", "Error loading audio clip " + systempath);
|
||||
return false;
|
||||
}
|
||||
|
||||
engine->missionAudio = name;
|
||||
engine->missionAudio = name;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameData::loadSplash(const std::string &name)
|
||||
{
|
||||
std::string lower(name);
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||||
void GameData::loadSplash(const std::string& name) {
|
||||
std::string lower(name);
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
|
||||
|
||||
loadTXD(lower + ".txd", false);
|
||||
loadTXD(lower + ".txd", false);
|
||||
|
||||
engine->state->currentSplash = lower;
|
||||
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;
|
||||
return engine->data->realWater[i];
|
||||
}
|
||||
return 0;
|
||||
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())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LoaderIMG i;
|
||||
if(! i.load(path + "/models/gta3.img") )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool GameData::isValidGameDirectory(const std::string& path) {
|
||||
if (path.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LoaderIMG i;
|
||||
if (!i.load(path + "/models/gta3.img")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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,260 +36,255 @@ 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;
|
||||
std::string datpath;
|
||||
std::string splash;
|
||||
|
||||
Logger* logger;
|
||||
WorkContext* workContext;
|
||||
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
* @param path Path to the root of the game data.
|
||||
*/
|
||||
GameData(Logger* log, WorkContext* work, const std::string& path = "");
|
||||
~GameData();
|
||||
|
||||
/**
|
||||
* ctor
|
||||
* @param path Path to the root of the game data.
|
||||
*/
|
||||
GameData(Logger* log, WorkContext* work, const std::string& path = "");
|
||||
~GameData();
|
||||
|
||||
GameWorld* engine;
|
||||
|
||||
/**
|
||||
* Returns the current platform
|
||||
*/
|
||||
std::string getPlatformString()
|
||||
{
|
||||
return "PC";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game data path
|
||||
*/
|
||||
const std::string& getDataPath() const
|
||||
{
|
||||
return datpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads items defined in the given IDE
|
||||
*/
|
||||
void loadIDE(const std::string& path);
|
||||
GameWorld* engine;
|
||||
|
||||
/**
|
||||
* Handles the parsing of a COL file.
|
||||
*/
|
||||
void loadCOL(const size_t zone, const std::string& name);
|
||||
|
||||
/**
|
||||
* Handles the loading of an IMG's data
|
||||
*/
|
||||
void loadIMG(const std::string& name);
|
||||
|
||||
void loadIPL(const std::string& path);
|
||||
|
||||
/**
|
||||
* Loads the Zones from a zon/IPL file
|
||||
*/
|
||||
bool loadZone(const std::string& path);
|
||||
|
||||
void loadCarcols(const std::string& path);
|
||||
/**
|
||||
* Returns the current platform
|
||||
*/
|
||||
std::string getPlatformString() {
|
||||
return "PC";
|
||||
}
|
||||
|
||||
void loadWeather(const std::string& path);
|
||||
/**
|
||||
* Returns the game data path
|
||||
*/
|
||||
const std::string& getDataPath() const {
|
||||
return datpath;
|
||||
}
|
||||
|
||||
void loadHandling(const std::string& path);
|
||||
/**
|
||||
* Loads items defined in the given IDE
|
||||
*/
|
||||
void loadIDE(const std::string& path);
|
||||
|
||||
SCMFile* loadSCM(const std::string& path);
|
||||
/**
|
||||
* Handles the parsing of a COL file.
|
||||
*/
|
||||
void loadCOL(const size_t zone, const std::string& name);
|
||||
|
||||
void loadGXT(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads water level data
|
||||
*/
|
||||
void loadWaterpro(const std::string& path);
|
||||
void loadWater(const std::string& path);
|
||||
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Loads model, placement, models and textures from a level file
|
||||
*/
|
||||
void loadLevelFile(const std::string& path);
|
||||
|
||||
/**
|
||||
* Attempts to load a TXD, or does nothing if it has already been loaded
|
||||
*/
|
||||
void loadTXD(const std::string& name, bool async = false);
|
||||
/**
|
||||
* Handles the loading of an IMG's data
|
||||
*/
|
||||
void loadIMG(const std::string& name);
|
||||
|
||||
/**
|
||||
* Attempts to load a DFF or does nothing if is already loaded
|
||||
*/
|
||||
void loadDFF(const std::string& name, bool async = false);
|
||||
void loadIPL(const std::string& path);
|
||||
|
||||
/**
|
||||
* Loads the Zones from a zon/IPL file
|
||||
*/
|
||||
bool loadZone(const std::string& path);
|
||||
|
||||
void loadCarcols(const std::string& path);
|
||||
|
||||
void loadWeather(const std::string& path);
|
||||
|
||||
void loadHandling(const std::string& path);
|
||||
|
||||
SCMFile* loadSCM(const std::string& path);
|
||||
|
||||
void loadGXT(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads water level data
|
||||
*/
|
||||
void loadWaterpro(const std::string& path);
|
||||
void loadWater(const std::string& path);
|
||||
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Loads model, placement, models and textures from a level file
|
||||
*/
|
||||
void loadLevelFile(const std::string& path);
|
||||
|
||||
/**
|
||||
* Attempts to load a TXD, or does nothing if it has already been loaded
|
||||
*/
|
||||
void loadTXD(const std::string& name, bool async = false);
|
||||
|
||||
/**
|
||||
* Attempts to load a DFF or does nothing if is already loaded
|
||||
*/
|
||||
void loadDFF(const std::string& name, bool async = false);
|
||||
|
||||
/**
|
||||
* Loads an IFP file containing animations
|
||||
*/
|
||||
void loadIFP(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads data from an object definition dat.
|
||||
*/
|
||||
void loadDynamicObjects(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads weapon.dat
|
||||
*/
|
||||
void loadWeaponDAT(const std::string& path);
|
||||
/**
|
||||
* Loads data from an object definition dat.
|
||||
*/
|
||||
void loadDynamicObjects(const std::string& name);
|
||||
|
||||
bool loadAudioStream(const std::string& name);
|
||||
bool loadAudioClip(const std::string& name, const std::string& fileName);
|
||||
/**
|
||||
* Loads weapon.dat
|
||||
*/
|
||||
void loadWeaponDAT(const std::string& path);
|
||||
|
||||
void loadSplash(const std::string& name);
|
||||
bool loadAudioStream(const std::string& name);
|
||||
bool loadAudioClip(const std::string& name, const std::string& fileName);
|
||||
|
||||
TextureData::Handle findTexture( const std::string& name, const std::string& alpha = "" )
|
||||
{
|
||||
return textures[{name, alpha}];
|
||||
}
|
||||
|
||||
FileIndex index;
|
||||
|
||||
/**
|
||||
* Files that have been loaded previously
|
||||
*/
|
||||
std::map<std::string, bool> loadedFiles;
|
||||
|
||||
/**
|
||||
* IPL file locations
|
||||
*/
|
||||
std::map<std::string, std::string> iplLocations;
|
||||
void loadSplash(const std::string& name);
|
||||
|
||||
/**
|
||||
* Map of loaded archives
|
||||
*/
|
||||
std::map<std::string, LoaderIMG> archives;
|
||||
|
||||
/**
|
||||
* Map Zones
|
||||
*/
|
||||
std::map<std::string, ZoneData> zones;
|
||||
TextureData::Handle findTexture(const std::string& name,
|
||||
const std::string& alpha = "") {
|
||||
return textures[{name, alpha}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Object Definitions
|
||||
*/
|
||||
std::map<ObjectID, ObjectInformationPtr> objectTypes;
|
||||
FileIndex index;
|
||||
|
||||
uint16_t findModelObject(const std::string model);
|
||||
/**
|
||||
* Files that have been loaded previously
|
||||
*/
|
||||
std::map<std::string, bool> loadedFiles;
|
||||
|
||||
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 )
|
||||
{
|
||||
return std::static_pointer_cast<T>(f->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
/**
|
||||
* IPL file locations
|
||||
*/
|
||||
std::map<std::string, std::string> iplLocations;
|
||||
|
||||
/**
|
||||
* The vehicle colour palettes
|
||||
*/
|
||||
std::vector<glm::u8vec3> vehicleColours;
|
||||
|
||||
/**
|
||||
* The vehicle colours for each vehicle type
|
||||
*/
|
||||
std::map<std::string, std::vector<std::pair<size_t,size_t>>> vehiclePalettes;
|
||||
/**
|
||||
* Map of loaded archives
|
||||
*/
|
||||
std::map<std::string, LoaderIMG> archives;
|
||||
|
||||
/**
|
||||
* Vehicle information
|
||||
*/
|
||||
std::map<std::string, VehicleInfoHandle> vehicleInfo;
|
||||
|
||||
/**
|
||||
* Texture Loader
|
||||
*/
|
||||
TextureLoader textureLoader;
|
||||
/**
|
||||
* Map Zones
|
||||
*/
|
||||
std::map<std::string, ZoneData> zones;
|
||||
|
||||
/**
|
||||
* Weather Loader
|
||||
*/
|
||||
WeatherLoader weatherLoader;
|
||||
/**
|
||||
* Object Definitions
|
||||
*/
|
||||
std::map<ObjectID, ObjectInformationPtr> objectTypes;
|
||||
|
||||
/**
|
||||
* Loaded models
|
||||
*/
|
||||
std::map<std::string, ResourceHandle<Model>::Ref> models;
|
||||
uint16_t findModelObject(const std::string model);
|
||||
|
||||
/**
|
||||
* Loaded textures (Textures are ID by name and alpha pairs)
|
||||
*/
|
||||
std::map<std::pair<std::string, std::string>, TextureData::Handle> textures;
|
||||
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) {
|
||||
return std::static_pointer_cast<T>(f->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Texture atlases.
|
||||
*/
|
||||
std::vector<TextureAtlas*> atlases;
|
||||
/**
|
||||
* The vehicle colour palettes
|
||||
*/
|
||||
std::vector<glm::u8vec3> vehicleColours;
|
||||
|
||||
/**
|
||||
* The vehicle colours for each vehicle type
|
||||
*/
|
||||
std::map<std::string, std::vector<std::pair<size_t, size_t>>>
|
||||
vehiclePalettes;
|
||||
|
||||
/**
|
||||
* Vehicle information
|
||||
*/
|
||||
std::map<std::string, VehicleInfoHandle> vehicleInfo;
|
||||
|
||||
/**
|
||||
* Texture Loader
|
||||
*/
|
||||
TextureLoader textureLoader;
|
||||
|
||||
/**
|
||||
* Weather Loader
|
||||
*/
|
||||
WeatherLoader weatherLoader;
|
||||
|
||||
/**
|
||||
* Loaded models
|
||||
*/
|
||||
std::map<std::string, ResourceHandle<Model>::Ref> models;
|
||||
|
||||
/**
|
||||
* Loaded textures (Textures are ID by name and alpha pairs)
|
||||
*/
|
||||
std::map<std::pair<std::string, std::string>, TextureData::Handle> textures;
|
||||
|
||||
/**
|
||||
* Texture atlases.
|
||||
*/
|
||||
std::vector<TextureAtlas*> atlases;
|
||||
|
||||
/**
|
||||
* Loaded Animations
|
||||
*/
|
||||
AnimationSet animations;
|
||||
|
||||
/**
|
||||
* CollisionModel data.
|
||||
*/
|
||||
std::map<std::string, std::unique_ptr<CollisionModel>> collisions;
|
||||
|
||||
/**
|
||||
* DynamicObjectData
|
||||
*/
|
||||
std::map<std::string, std::shared_ptr<DynamicObjectData>> dynamicObjectData;
|
||||
|
||||
std::vector<std::shared_ptr<WeaponData>> weaponData;
|
||||
/**
|
||||
* CollisionModel data.
|
||||
*/
|
||||
std::map<std::string, std::unique_ptr<CollisionModel>> collisions;
|
||||
|
||||
/**
|
||||
* @struct WaterArea
|
||||
* Stores Water Rectangle Information
|
||||
*/
|
||||
struct WaterArea
|
||||
{
|
||||
float height;
|
||||
float xLeft, yBottom;
|
||||
float xRight, yTop;
|
||||
};
|
||||
/**
|
||||
* DynamicObjectData
|
||||
*/
|
||||
std::map<std::string, std::shared_ptr<DynamicObjectData>> dynamicObjectData;
|
||||
|
||||
/**
|
||||
* Water Areas
|
||||
*/
|
||||
std::vector<WaterArea> waterBlocks;
|
||||
|
||||
/**
|
||||
* Water heights
|
||||
*/
|
||||
float waterHeights[48];
|
||||
|
||||
/**
|
||||
* Visible water heights
|
||||
*/
|
||||
uint8_t visibleWater[64*64];
|
||||
|
||||
/**
|
||||
* The "real" water heights
|
||||
*/
|
||||
uint8_t realWater[128*128];
|
||||
std::vector<std::shared_ptr<WeaponData>> weaponData;
|
||||
|
||||
int getWaterIndexAt(const glm::vec3& ws) const;
|
||||
float getWaveHeightAt(const glm::vec3& ws) const;
|
||||
/**
|
||||
* @struct WaterArea
|
||||
* Stores Water Rectangle Information
|
||||
*/
|
||||
struct WaterArea {
|
||||
float height;
|
||||
float xLeft, yBottom;
|
||||
float xRight, yTop;
|
||||
};
|
||||
|
||||
GameTexts texts;
|
||||
|
||||
/**
|
||||
* Determines whether the given path is a valid game directory.
|
||||
*/
|
||||
static bool isValidGameDirectory(const std::string& path);
|
||||
/**
|
||||
* Water Areas
|
||||
*/
|
||||
std::vector<WaterArea> waterBlocks;
|
||||
|
||||
/**
|
||||
* Water heights
|
||||
*/
|
||||
float waterHeights[48];
|
||||
|
||||
/**
|
||||
* Visible water heights
|
||||
*/
|
||||
uint8_t visibleWater[64 * 64];
|
||||
|
||||
/**
|
||||
* The "real" water heights
|
||||
*/
|
||||
uint8_t realWater[128 * 128];
|
||||
|
||||
int getWaterIndexAt(const glm::vec3& ws) const;
|
||||
float getWaveHeightAt(const glm::vec3& ws) const;
|
||||
|
||||
GameTexts texts;
|
||||
|
||||
/**
|
||||
* Determines whether the given path is a valid game directory.
|
||||
*/
|
||||
static bool isValidGameDirectory(const std::string& path);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,72 +1,69 @@
|
||||
#ifndef RWENGINE_GAMEINPUTSTATE_HPP
|
||||
#define RWENGINE_GAMEINPUTSTATE_HPP
|
||||
|
||||
struct GameInputState
|
||||
{
|
||||
static constexpr float kButtonOnThreshold = 0.1f;
|
||||
struct GameInputState {
|
||||
static constexpr float kButtonOnThreshold = 0.1f;
|
||||
|
||||
/// Inputs that can be controlled
|
||||
/// @todo find any sensible values
|
||||
enum Control {
|
||||
/* On Foot */
|
||||
FireWeapon = 0,
|
||||
NextWeapon,
|
||||
NextTarget = NextWeapon,
|
||||
LastWeapon,
|
||||
LastTarget = LastWeapon,
|
||||
GoForward,
|
||||
GoBackwards,
|
||||
GoLeft,
|
||||
GoRight,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
EnterExitVehicle,
|
||||
ChangeCamera,
|
||||
Jump,
|
||||
Sprint,
|
||||
AimWeapon,
|
||||
Crouch,
|
||||
Walk,
|
||||
LookBehind,
|
||||
/// Inputs that can be controlled
|
||||
/// @todo find any sensible values
|
||||
enum Control {
|
||||
/* On Foot */
|
||||
FireWeapon = 0,
|
||||
NextWeapon,
|
||||
NextTarget = NextWeapon,
|
||||
LastWeapon,
|
||||
LastTarget = LastWeapon,
|
||||
GoForward,
|
||||
GoBackwards,
|
||||
GoLeft,
|
||||
GoRight,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
EnterExitVehicle,
|
||||
ChangeCamera,
|
||||
Jump,
|
||||
Sprint,
|
||||
AimWeapon,
|
||||
Crouch,
|
||||
Walk,
|
||||
LookBehind,
|
||||
|
||||
/* In Vehicle */
|
||||
VehicleFireWeapon = FireWeapon,
|
||||
VehicleAccelerate,
|
||||
VehicleBrake,
|
||||
VehicleLeft = GoLeft,
|
||||
VehicleRight = GoRight,
|
||||
VehicleDown,
|
||||
VehicleUp,
|
||||
ChangeRadio,
|
||||
Horn,
|
||||
Submission,
|
||||
Handbrake,
|
||||
LookLeft,
|
||||
LookRight,
|
||||
VehicleAimLeft,
|
||||
VehicleAimRight,
|
||||
VehicleAimUp,
|
||||
VehicleAimDown,
|
||||
/* In Vehicle */
|
||||
VehicleFireWeapon = FireWeapon,
|
||||
VehicleAccelerate,
|
||||
VehicleBrake,
|
||||
VehicleLeft = GoLeft,
|
||||
VehicleRight = GoRight,
|
||||
VehicleDown,
|
||||
VehicleUp,
|
||||
ChangeRadio,
|
||||
Horn,
|
||||
Submission,
|
||||
Handbrake,
|
||||
LookLeft,
|
||||
LookRight,
|
||||
VehicleAimLeft,
|
||||
VehicleAimRight,
|
||||
VehicleAimUp,
|
||||
VehicleAimDown,
|
||||
|
||||
_MaxControls
|
||||
};
|
||||
_MaxControls
|
||||
};
|
||||
|
||||
/**
|
||||
* Current state of each control [0 to 1].
|
||||
*
|
||||
* For buttons, this will result in either 0 or 1.
|
||||
*/
|
||||
float currentLevels[_MaxControls] = { };
|
||||
/**
|
||||
* Current state of each control [0 to 1].
|
||||
*
|
||||
* For buttons, this will result in either 0 or 1.
|
||||
*/
|
||||
float currentLevels[_MaxControls] = {};
|
||||
|
||||
float operator[] (Control c) const
|
||||
{
|
||||
return currentLevels[c];
|
||||
}
|
||||
float operator[](Control c) const {
|
||||
return currentLevels[c];
|
||||
}
|
||||
|
||||
bool pressed(Control c) const
|
||||
{
|
||||
return currentLevels[c] > kButtonOnThreshold;
|
||||
}
|
||||
bool pressed(Control c) const {
|
||||
return currentLevels[c] > kButtonOnThreshold;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,151 +1,142 @@
|
||||
#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{}
|
||||
, gameTime(0.f)
|
||||
, currentProgress(0)
|
||||
, maxProgress(1)
|
||||
, maxWantedLevel(0)
|
||||
, playerObject(0)
|
||||
, scriptOnMissionFlag(nullptr)
|
||||
, fadeOut(true)
|
||||
, fadeStart(0.f)
|
||||
, fadeTime(0.f)
|
||||
, fadeSound(false)
|
||||
, skipCutscene(false)
|
||||
, isIntroPlaying(false)
|
||||
, currentCutscene(nullptr)
|
||||
, cutsceneStartTime(-1.f)
|
||||
, isCinematic(false)
|
||||
, cameraNear(0.1f)
|
||||
, cameraFixed(false)
|
||||
, cameraTarget(0)
|
||||
, importExportPortland(0)
|
||||
, importExportShoreside(0)
|
||||
, importExportUnused(0)
|
||||
, world(nullptr)
|
||||
, script(nullptr)
|
||||
{
|
||||
|
||||
: basic{}
|
||||
, gameTime(0.f)
|
||||
, currentProgress(0)
|
||||
, maxProgress(1)
|
||||
, maxWantedLevel(0)
|
||||
, playerObject(0)
|
||||
, scriptOnMissionFlag(nullptr)
|
||||
, fadeOut(true)
|
||||
, fadeStart(0.f)
|
||||
, fadeTime(0.f)
|
||||
, fadeSound(false)
|
||||
, skipCutscene(false)
|
||||
, isIntroPlaying(false)
|
||||
, currentCutscene(nullptr)
|
||||
, cutsceneStartTime(-1.f)
|
||||
, isCinematic(false)
|
||||
, cameraNear(0.1f)
|
||||
, cameraFixed(false)
|
||||
, cameraTarget(0)
|
||||
, importExportPortland(0)
|
||||
, importExportShoreside(0)
|
||||
, importExportUnused(0)
|
||||
, world(nullptr)
|
||||
, script(nullptr) {
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
blip.id = l;
|
||||
radarBlips.insert({l, blip});
|
||||
|
||||
return l;
|
||||
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 {
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
blip.id = l;
|
||||
radarBlips.insert({l, blip});
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void GameState::removeBlip(int blip)
|
||||
{
|
||||
auto it = radarBlips.find( blip );
|
||||
if ( it != radarBlips.end() )
|
||||
{
|
||||
radarBlips.erase(it);
|
||||
}
|
||||
void GameState::removeBlip(int blip) {
|
||||
auto it = radarBlips.find(blip);
|
||||
if (it != radarBlips.end()) {
|
||||
radarBlips.erase(it);
|
||||
}
|
||||
}
|
||||
|
@ -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,373 +18,350 @@ class ScriptMachine;
|
||||
class PlayerController;
|
||||
struct CutsceneData;
|
||||
|
||||
struct SystemTime
|
||||
{
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t dayOfWeek;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
uint16_t minute;
|
||||
uint16_t second;
|
||||
uint16_t millisecond;
|
||||
struct SystemTime {
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t dayOfWeek;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
uint16_t minute;
|
||||
uint16_t second;
|
||||
uint16_t millisecond;
|
||||
};
|
||||
|
||||
/** Block 0 State */
|
||||
struct BasicState
|
||||
{
|
||||
GameStringChar saveName[24];
|
||||
SystemTime saveTime;
|
||||
uint32_t unknown;
|
||||
uint16_t islandNumber;
|
||||
glm::vec3 cameraPosition;
|
||||
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];
|
||||
uint32_t timeMS;
|
||||
float timeScale;
|
||||
float timeStep;
|
||||
float timeStep_unclipped; // Unknown purpose
|
||||
uint32_t frameCounter;
|
||||
float timeStep2;
|
||||
float framesPerUpdate;
|
||||
float timeScale2;
|
||||
uint16_t lastWeather;
|
||||
uint8_t _align3[2];
|
||||
uint16_t nextWeather;
|
||||
uint8_t _align4[2];
|
||||
uint16_t forcedWeather;
|
||||
uint8_t _align5[2];
|
||||
float weatherInterpolation;
|
||||
uint8_t dateTime[24]; // Unused
|
||||
uint32_t weatherType;
|
||||
float cameraData;
|
||||
float cameraData2;
|
||||
struct BasicState {
|
||||
GameStringChar saveName[24];
|
||||
SystemTime saveTime;
|
||||
uint32_t unknown;
|
||||
uint16_t islandNumber;
|
||||
glm::vec3 cameraPosition;
|
||||
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];
|
||||
uint32_t timeMS;
|
||||
float timeScale;
|
||||
float timeStep;
|
||||
float timeStep_unclipped; // Unknown purpose
|
||||
uint32_t frameCounter;
|
||||
float timeStep2;
|
||||
float framesPerUpdate;
|
||||
float timeScale2;
|
||||
uint16_t lastWeather;
|
||||
uint8_t _align3[2];
|
||||
uint16_t nextWeather;
|
||||
uint8_t _align4[2];
|
||||
uint16_t forcedWeather;
|
||||
uint8_t _align5[2];
|
||||
float weatherInterpolation;
|
||||
uint8_t dateTime[24]; // Unused
|
||||
uint32_t weatherType;
|
||||
float cameraData;
|
||||
float cameraData2;
|
||||
|
||||
BasicState ();
|
||||
BasicState();
|
||||
};
|
||||
|
||||
/** Block 16 player info */
|
||||
struct PlayerInfo
|
||||
{
|
||||
uint32_t money;
|
||||
uint8_t unknown1;
|
||||
uint32_t unknown2;
|
||||
uint16_t unknown3;
|
||||
float unknown4;
|
||||
uint32_t displayedMoney;
|
||||
uint32_t hiddenPackagesCollected;
|
||||
uint32_t hiddenPackageCount;
|
||||
uint8_t neverTired;
|
||||
uint8_t fastReload;
|
||||
uint8_t thaneOfLibertyCity;
|
||||
uint8_t singlePayerHealthcare;
|
||||
uint8_t unknown5[70];
|
||||
struct PlayerInfo {
|
||||
uint32_t money;
|
||||
uint8_t unknown1;
|
||||
uint32_t unknown2;
|
||||
uint16_t unknown3;
|
||||
float unknown4;
|
||||
uint32_t displayedMoney;
|
||||
uint32_t hiddenPackagesCollected;
|
||||
uint32_t hiddenPackageCount;
|
||||
uint8_t neverTired;
|
||||
uint8_t fastReload;
|
||||
uint8_t thaneOfLibertyCity;
|
||||
uint8_t singlePayerHealthcare;
|
||||
uint8_t unknown5[70];
|
||||
|
||||
PlayerInfo ();
|
||||
PlayerInfo();
|
||||
};
|
||||
|
||||
/** Block 17 */
|
||||
struct GameStats
|
||||
{
|
||||
uint32_t playerKills;
|
||||
uint32_t otherKills;
|
||||
uint32_t carsExploded;
|
||||
uint32_t shotsHit;
|
||||
uint32_t pedTypesKilled[23];
|
||||
uint32_t helicoptersDestroyed;
|
||||
uint32_t playerProgress;
|
||||
uint32_t explosiveKgsUsed;
|
||||
uint32_t bulletsFired;
|
||||
uint32_t bulletsHit;
|
||||
uint32_t carsCrushed;
|
||||
uint32_t headshots;
|
||||
uint32_t timesBusted;
|
||||
uint32_t timesHospital;
|
||||
uint32_t daysPassed;
|
||||
uint32_t mmRainfall;
|
||||
uint32_t insaneJumpMaxDistance;
|
||||
uint32_t insaneJumpMaxHeight;
|
||||
uint32_t insaneJumpMaxFlips;
|
||||
uint32_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
|
||||
*/
|
||||
uint32_t bestStunt;
|
||||
uint32_t uniqueStuntsFound;
|
||||
uint32_t uniqueStuntsTotal;
|
||||
uint32_t missionAttempts;
|
||||
uint32_t missionsPassed;
|
||||
uint32_t passengersDroppedOff;
|
||||
uint32_t taxiRevenue;
|
||||
uint32_t portlandPassed;
|
||||
uint32_t stauntonPassed;
|
||||
uint32_t shoresidePassed;
|
||||
uint32_t bestTurismoTime;
|
||||
float distanceWalked;
|
||||
float distanceDriven;
|
||||
uint32_t patriotPlaygroundTime;
|
||||
uint32_t aRideInTheParkTime;
|
||||
uint32_t grippedTime;
|
||||
uint32_t multistoryMayhemTime;
|
||||
uint32_t peopleSaved;
|
||||
uint32_t criminalsKilled;
|
||||
uint32_t highestParamedicLevel;
|
||||
uint32_t firesExtinguished;
|
||||
uint32_t longestDodoFlight;
|
||||
uint32_t bombDefusalTime;
|
||||
uint32_t rampagesPassed;
|
||||
uint32_t totalRampages;
|
||||
uint32_t totalMissions;
|
||||
uint32_t fastestTime[16]; // not used
|
||||
uint32_t highestScore[16];
|
||||
uint32_t peopleKilledSinceCheckpoint; // ?
|
||||
uint32_t peopleKilledSinceLastBustedOrWasted;
|
||||
char lastMissionGXT[8];
|
||||
struct GameStats {
|
||||
uint32_t playerKills;
|
||||
uint32_t otherKills;
|
||||
uint32_t carsExploded;
|
||||
uint32_t shotsHit;
|
||||
uint32_t pedTypesKilled[23];
|
||||
uint32_t helicoptersDestroyed;
|
||||
uint32_t playerProgress;
|
||||
uint32_t explosiveKgsUsed;
|
||||
uint32_t bulletsFired;
|
||||
uint32_t bulletsHit;
|
||||
uint32_t carsCrushed;
|
||||
uint32_t headshots;
|
||||
uint32_t timesBusted;
|
||||
uint32_t timesHospital;
|
||||
uint32_t daysPassed;
|
||||
uint32_t mmRainfall;
|
||||
uint32_t insaneJumpMaxDistance;
|
||||
uint32_t insaneJumpMaxHeight;
|
||||
uint32_t insaneJumpMaxFlips;
|
||||
uint32_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
|
||||
*/
|
||||
uint32_t bestStunt;
|
||||
uint32_t uniqueStuntsFound;
|
||||
uint32_t uniqueStuntsTotal;
|
||||
uint32_t missionAttempts;
|
||||
uint32_t missionsPassed;
|
||||
uint32_t passengersDroppedOff;
|
||||
uint32_t taxiRevenue;
|
||||
uint32_t portlandPassed;
|
||||
uint32_t stauntonPassed;
|
||||
uint32_t shoresidePassed;
|
||||
uint32_t bestTurismoTime;
|
||||
float distanceWalked;
|
||||
float distanceDriven;
|
||||
uint32_t patriotPlaygroundTime;
|
||||
uint32_t aRideInTheParkTime;
|
||||
uint32_t grippedTime;
|
||||
uint32_t multistoryMayhemTime;
|
||||
uint32_t peopleSaved;
|
||||
uint32_t criminalsKilled;
|
||||
uint32_t highestParamedicLevel;
|
||||
uint32_t firesExtinguished;
|
||||
uint32_t longestDodoFlight;
|
||||
uint32_t bombDefusalTime;
|
||||
uint32_t rampagesPassed;
|
||||
uint32_t totalRampages;
|
||||
uint32_t totalMissions;
|
||||
uint32_t fastestTime[16]; // not used
|
||||
uint32_t highestScore[16];
|
||||
uint32_t peopleKilledSinceCheckpoint; // ?
|
||||
uint32_t peopleKilledSinceLastBustedOrWasted;
|
||||
char lastMissionGXT[8];
|
||||
|
||||
GameStats ();
|
||||
GameStats();
|
||||
};
|
||||
|
||||
struct TextDisplayData
|
||||
{
|
||||
// This is set by the final display text command.
|
||||
GameString text;
|
||||
glm::vec2 position;
|
||||
struct TextDisplayData {
|
||||
// This is set by the final display text command.
|
||||
GameString text;
|
||||
glm::vec2 position;
|
||||
|
||||
glm::vec4 colourFG;
|
||||
glm::vec4 colourBG;
|
||||
glm::vec4 colourFG;
|
||||
glm::vec4 colourBG;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data about a blip
|
||||
*/
|
||||
struct BlipData
|
||||
{
|
||||
int id;
|
||||
|
||||
enum BlipType
|
||||
{
|
||||
Location = 0,
|
||||
Vehicle = 1,
|
||||
Pickup = 2,
|
||||
Character = 3,
|
||||
Instance = 4,
|
||||
};
|
||||
BlipType type;
|
||||
GameObjectID target;
|
||||
// If target is null then use coord
|
||||
glm::vec3 coord;
|
||||
|
||||
std::string texture; // Texture for use in the radar
|
||||
uint32_t colour = 0; // Color value (index or RGBA)
|
||||
bool dimmed = false; // Color dimming if not in RGBA mode
|
||||
struct BlipData {
|
||||
int id;
|
||||
|
||||
uint16_t size = 3; // Only used if texture is empty
|
||||
enum BlipType {
|
||||
Location = 0,
|
||||
Vehicle = 1,
|
||||
Pickup = 2,
|
||||
Character = 3,
|
||||
Instance = 4,
|
||||
};
|
||||
BlipType type;
|
||||
GameObjectID target;
|
||||
// If target is null then use coord
|
||||
glm::vec3 coord;
|
||||
|
||||
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)
|
||||
{ }
|
||||
std::string texture; // Texture for use in the radar
|
||||
uint32_t colour = 0; // Color value (index or RGBA)
|
||||
bool dimmed = false; // Color dimming if not in RGBA mode
|
||||
|
||||
int getScriptObjectID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
uint16_t size = 3; // Only used if texture is empty
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
int getScriptObjectID() const {
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Data for garages
|
||||
*/
|
||||
struct GarageInfo
|
||||
{
|
||||
enum /*GarageType*/ {
|
||||
GARAGE_MISSION = 1,
|
||||
GARAGE_BOMBSHOP1 = 2,
|
||||
GARAGE_BOMBSHOP2 = 3,
|
||||
GARAGE_BOMBSHOP3 = 4,
|
||||
GARAGE_RESPRAY = 5,
|
||||
GARAGE_INVALID = 6,
|
||||
GARAGE_SPECIFIC_CARS_ONLY = 7, /* See Opcode 0x21B */
|
||||
GARAGE_COLLECTCARS1 = 8, /* See Opcode 0x03D4 */
|
||||
GARAGE_COLLECTCARS2 = 9,
|
||||
GARAGE_COLLECTCARS3 = 10, /* Unused */
|
||||
GARAGE_OPENFOREXIT = 11,
|
||||
GARAGE_INVALID2 = 12,
|
||||
GARAGE_CRUSHER = 13,
|
||||
GARAGE_MISSION_KEEPCAR = 14,
|
||||
GARAGE_FOR_SCRIPT = 15,
|
||||
GARAGE_HIDEOUT_ONE = 16, /* Portland */
|
||||
GARAGE_HIDEOUT_TWO = 17, /* Staunton */
|
||||
GARAGE_HIDEOUT_THREE = 18, /* Shoreside */
|
||||
GARAGE_FOR_SCRIPT2 = 19,
|
||||
GARAGE_OPENS_FOR_SPECIFIC_CAR = 20,
|
||||
GARAGE_OPENS_ONCE = 21
|
||||
};
|
||||
int id;
|
||||
glm::vec3 min;
|
||||
glm::vec3 max;
|
||||
int type;
|
||||
struct GarageInfo {
|
||||
enum /*GarageType*/ {
|
||||
GARAGE_MISSION = 1,
|
||||
GARAGE_BOMBSHOP1 = 2,
|
||||
GARAGE_BOMBSHOP2 = 3,
|
||||
GARAGE_BOMBSHOP3 = 4,
|
||||
GARAGE_RESPRAY = 5,
|
||||
GARAGE_INVALID = 6,
|
||||
GARAGE_SPECIFIC_CARS_ONLY = 7, /* See Opcode 0x21B */
|
||||
GARAGE_COLLECTCARS1 = 8, /* See Opcode 0x03D4 */
|
||||
GARAGE_COLLECTCARS2 = 9,
|
||||
GARAGE_COLLECTCARS3 = 10, /* Unused */
|
||||
GARAGE_OPENFOREXIT = 11,
|
||||
GARAGE_INVALID2 = 12,
|
||||
GARAGE_CRUSHER = 13,
|
||||
GARAGE_MISSION_KEEPCAR = 14,
|
||||
GARAGE_FOR_SCRIPT = 15,
|
||||
GARAGE_HIDEOUT_ONE = 16, /* Portland */
|
||||
GARAGE_HIDEOUT_TWO = 17, /* Staunton */
|
||||
GARAGE_HIDEOUT_THREE = 18, /* Shoreside */
|
||||
GARAGE_FOR_SCRIPT2 = 19,
|
||||
GARAGE_OPENS_FOR_SPECIFIC_CAR = 20,
|
||||
GARAGE_OPENS_ONCE = 21
|
||||
};
|
||||
int id;
|
||||
glm::vec3 min;
|
||||
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
|
||||
{
|
||||
return id;
|
||||
}
|
||||
int getScriptObjectID() const {
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gameplay state object that holds persistent state, and references runtime
|
||||
* world state.
|
||||
*/
|
||||
class GameState
|
||||
{
|
||||
class GameState {
|
||||
public:
|
||||
/**
|
||||
Basic Game State
|
||||
*/
|
||||
BasicState basic;
|
||||
/**
|
||||
Basic Game State
|
||||
*/
|
||||
BasicState basic;
|
||||
|
||||
/**
|
||||
Player stats
|
||||
*/
|
||||
PlayerInfo playerInfo;
|
||||
/**
|
||||
Player stats
|
||||
*/
|
||||
PlayerInfo playerInfo;
|
||||
|
||||
/**
|
||||
Game Stats
|
||||
*/
|
||||
GameStats gameStats;
|
||||
/**
|
||||
Game Stats
|
||||
*/
|
||||
GameStats gameStats;
|
||||
|
||||
/**
|
||||
* Second since game was started
|
||||
*/
|
||||
float gameTime;
|
||||
unsigned int currentProgress;
|
||||
unsigned int maxProgress;
|
||||
/**
|
||||
* Second since game was started
|
||||
*/
|
||||
float gameTime;
|
||||
unsigned int currentProgress;
|
||||
unsigned int maxProgress;
|
||||
|
||||
unsigned int maxWantedLevel;
|
||||
unsigned int maxWantedLevel;
|
||||
|
||||
GameObjectID playerObject;
|
||||
GameObjectID playerObject;
|
||||
|
||||
/**
|
||||
* @brief Stores a pointer to script global that stores the on-mission state.
|
||||
*/
|
||||
int32_t* scriptOnMissionFlag;
|
||||
|
||||
/** Objects created by the current mission */
|
||||
std::vector<GameObject*> missionObjects;
|
||||
|
||||
bool overrideNextStart;
|
||||
glm::vec4 nextRestartLocation;
|
||||
/**
|
||||
* @brief Stores a pointer to script global that stores the on-mission
|
||||
* state.
|
||||
*/
|
||||
int32_t* scriptOnMissionFlag;
|
||||
|
||||
bool fadeOut;
|
||||
float fadeStart;
|
||||
float fadeTime;
|
||||
bool fadeSound;
|
||||
glm::u16vec3 fadeColour;
|
||||
/** Objects created by the current mission */
|
||||
std::vector<GameObject*> missionObjects;
|
||||
|
||||
std::string currentSplash;
|
||||
bool overrideNextStart;
|
||||
glm::vec4 nextRestartLocation;
|
||||
|
||||
bool skipCutscene;
|
||||
bool isIntroPlaying;
|
||||
CutsceneData* currentCutscene;
|
||||
float cutsceneStartTime;
|
||||
/** Flag for rendering cutscene letterbox */
|
||||
bool isCinematic;
|
||||
|
||||
std::string lastMissionName;
|
||||
|
||||
/// Stores the "special" character and cutscene model indices.
|
||||
std::map<unsigned short, std::string> specialCharacters;
|
||||
std::map<unsigned short, std::string> specialModels;
|
||||
bool fadeOut;
|
||||
float fadeStart;
|
||||
float fadeTime;
|
||||
bool fadeSound;
|
||||
glm::u16vec3 fadeColour;
|
||||
|
||||
/// Handles on screen text behaviour
|
||||
ScreenText text;
|
||||
std::string currentSplash;
|
||||
|
||||
TextDisplayData nextText;
|
||||
/**
|
||||
* Stores temporary, one-tick messages
|
||||
*/
|
||||
std::vector<TextDisplayData> texts;
|
||||
bool skipCutscene;
|
||||
bool isIntroPlaying;
|
||||
CutsceneData* currentCutscene;
|
||||
float cutsceneStartTime;
|
||||
/** Flag for rendering cutscene letterbox */
|
||||
bool isCinematic;
|
||||
|
||||
/** The camera near value currently set by the script */
|
||||
float cameraNear;
|
||||
bool cameraFixed;
|
||||
glm::vec3 cameraPosition;
|
||||
glm::quat cameraRotation;
|
||||
std::string lastMissionName;
|
||||
|
||||
GameObjectID cameraTarget;
|
||||
|
||||
std::vector<VehicleGenerator> vehicleGenerators;
|
||||
|
||||
std::map<int, BlipData> radarBlips;
|
||||
/// Stores the "special" character and cutscene model indices.
|
||||
std::map<unsigned short, std::string> specialCharacters;
|
||||
std::map<unsigned short, std::string> specialModels;
|
||||
|
||||
std::vector<GarageInfo> garages;
|
||||
/// Handles on screen text behaviour
|
||||
ScreenText text;
|
||||
|
||||
/**
|
||||
* Bitsets for the car import / export list mission
|
||||
*/
|
||||
std::bitset<32> importExportPortland;
|
||||
std::bitset<32> importExportShoreside;
|
||||
std::bitset<32> importExportUnused;
|
||||
TextDisplayData nextText;
|
||||
/**
|
||||
* Stores temporary, one-tick messages
|
||||
*/
|
||||
std::vector<TextDisplayData> texts;
|
||||
|
||||
/**
|
||||
* State of the game input
|
||||
*/
|
||||
GameInputState input;
|
||||
/** The camera near value currently set by the script */
|
||||
float cameraNear;
|
||||
bool cameraFixed;
|
||||
glm::vec3 cameraPosition;
|
||||
glm::quat cameraRotation;
|
||||
|
||||
/**
|
||||
* World to use for this state, this isn't saved, just used at runtime
|
||||
*/
|
||||
GameWorld* world;
|
||||
GameObjectID cameraTarget;
|
||||
|
||||
/**
|
||||
* Script Machine associated with this state if it exists.
|
||||
*/
|
||||
ScriptMachine* script;
|
||||
std::vector<VehicleGenerator> vehicleGenerators;
|
||||
|
||||
GameState();
|
||||
std::map<int, BlipData> radarBlips;
|
||||
|
||||
/**
|
||||
* Adds a blip to the state, returning it's ID.
|
||||
*/
|
||||
int addRadarBlip(BlipData& blip);
|
||||
|
||||
/**
|
||||
* Removes a blip
|
||||
*/
|
||||
void removeBlip(int blip);
|
||||
std::vector<GarageInfo> garages;
|
||||
|
||||
/**
|
||||
* Bitsets for the car import / export list mission
|
||||
*/
|
||||
std::bitset<32> importExportPortland;
|
||||
std::bitset<32> importExportShoreside;
|
||||
std::bitset<32> importExportUnused;
|
||||
|
||||
/**
|
||||
* State of the game input
|
||||
*/
|
||||
GameInputState input;
|
||||
|
||||
/**
|
||||
* World to use for this state, this isn't saved, just used at runtime
|
||||
*/
|
||||
GameWorld* world;
|
||||
|
||||
/**
|
||||
* Script Machine associated with this state if it exists.
|
||||
*/
|
||||
ScriptMachine* script;
|
||||
|
||||
GameState();
|
||||
|
||||
/**
|
||||
* Adds a blip to the state, returning it's ID.
|
||||
*/
|
||||
int addRadarBlip(BlipData& blip);
|
||||
|
||||
/**
|
||||
* Removes a blip
|
||||
*/
|
||||
void removeBlip(int blip);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,323 +35,333 @@ 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
|
||||
};
|
||||
|
||||
AreaIndicatorType type;
|
||||
glm::vec3 position;
|
||||
glm::vec3 radius;
|
||||
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(Logger* log, WorkContext* work, GameData* dat);
|
||||
~GameWorld();
|
||||
|
||||
~GameWorld();
|
||||
Logger* logger;
|
||||
|
||||
Logger* logger;
|
||||
/**
|
||||
* Loads an IPL into the game.
|
||||
* @param name The name of the IPL as it appears in the games' gta.dat
|
||||
*/
|
||||
bool placeItems(const std::string& name);
|
||||
|
||||
/**
|
||||
* Loads an IPL into the game.
|
||||
* @param name The name of the IPL as it appears in the games' gta.dat
|
||||
*/
|
||||
bool placeItems(const std::string& name);
|
||||
/**
|
||||
* @brief createTraffic spawn transitory peds and vehicles
|
||||
* @param viewCamera The camera to create traffic near
|
||||
*
|
||||
* The position and frustum of the passed in camera is used to determine
|
||||
* the radius where traffic can be spawned, and the frustum is used to avoid
|
||||
* spawning traffic in view of the player.
|
||||
*/
|
||||
void createTraffic(const ViewCamera& viewCamera);
|
||||
|
||||
/**
|
||||
* @brief createTraffic spawn transitory peds and vehicles
|
||||
* @param viewCamera The camera to create traffic near
|
||||
*
|
||||
* The position and frustum of the passed in camera is used to determine
|
||||
* the radius where traffic can be spawned, and the frustum is used to avoid
|
||||
* spawning traffic in view of the player.
|
||||
*/
|
||||
void createTraffic(const ViewCamera& viewCamera);
|
||||
/**
|
||||
* @brief cleanupTraffic Cleans up traffic too far away from the given
|
||||
* camera
|
||||
* @param viewCamera
|
||||
*/
|
||||
void cleanupTraffic(const ViewCamera& viewCamera);
|
||||
|
||||
/**
|
||||
* @brief cleanupTraffic Cleans up traffic too far away from the given camera
|
||||
* @param viewCamera
|
||||
*/
|
||||
void cleanupTraffic(const ViewCamera& viewCamera);
|
||||
/**
|
||||
* Creates an instance
|
||||
*/
|
||||
InstanceObject* createInstance(const uint16_t id, const glm::vec3& pos,
|
||||
const glm::quat& rot = glm::quat());
|
||||
|
||||
/**
|
||||
* Creates an instance
|
||||
*/
|
||||
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());
|
||||
|
||||
/**
|
||||
* @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());
|
||||
|
||||
/**
|
||||
* Creates a vehicle
|
||||
*/
|
||||
VehicleObject *createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
|
||||
/**
|
||||
* Creates a vehicle
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Creates a pedestrian.
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Creates a player
|
||||
*/
|
||||
CharacterObject* createPlayer(const glm::vec3& pos,
|
||||
const glm::quat& rot = glm::quat(),
|
||||
GameObjectID gid = 0);
|
||||
|
||||
/**
|
||||
* Creates a pickup
|
||||
*/
|
||||
PickupObject* createPickup(const glm::vec3& pos, int id, int type);
|
||||
/**
|
||||
* Creates a pickup
|
||||
*/
|
||||
PickupObject* createPickup(const glm::vec3& pos, int id, int type);
|
||||
|
||||
/**
|
||||
* Destroys an existing Object
|
||||
*/
|
||||
void destroyObject(GameObject* object);
|
||||
/**
|
||||
* Destroys an existing Object
|
||||
*/
|
||||
void destroyObject(GameObject* object);
|
||||
|
||||
/**
|
||||
* @brief Put an object on the deletion queue.
|
||||
*/
|
||||
void destroyObjectQueued(GameObject* object);
|
||||
/**
|
||||
* @brief Put an object on the deletion queue.
|
||||
*/
|
||||
void destroyObjectQueued(GameObject* object);
|
||||
|
||||
/**
|
||||
* @brief Destroys all objects on the destruction queue.
|
||||
*/
|
||||
void destroyQueuedObjects();
|
||||
/**
|
||||
* @brief Destroys all objects on the destruction queue.
|
||||
*/
|
||||
void destroyQueuedObjects();
|
||||
|
||||
/**
|
||||
* Performs a weapon scan against things in the world
|
||||
*/
|
||||
void doWeaponScan(const WeaponScan &scan );
|
||||
/**
|
||||
* Performs a weapon scan against things in the world
|
||||
*/
|
||||
void doWeaponScan(const WeaponScan& scan);
|
||||
|
||||
/**
|
||||
* Allocates a new VisualFX of the given type
|
||||
*/
|
||||
VisualFX* createEffect(VisualFX::EffectType type);
|
||||
|
||||
/**
|
||||
* Immediately destoys the given effect
|
||||
*/
|
||||
void destroyEffect(VisualFX* effect);
|
||||
/**
|
||||
* Allocates a new VisualFX of the given type
|
||||
*/
|
||||
VisualFX* createEffect(VisualFX::EffectType type);
|
||||
|
||||
/**
|
||||
* Returns the current hour
|
||||
*/
|
||||
int getHour();
|
||||
|
||||
/**
|
||||
* Returns the current minute
|
||||
*/
|
||||
int getMinute();
|
||||
/**
|
||||
* Immediately destoys the given effect
|
||||
*/
|
||||
void destroyEffect(VisualFX* effect);
|
||||
|
||||
/**
|
||||
* Modifies the game time and handles the circular nature of clock numbers
|
||||
* Supports negative numbers
|
||||
*/
|
||||
void offsetGameTime(int minutes);
|
||||
/**
|
||||
* Returns the current hour
|
||||
*/
|
||||
int getHour();
|
||||
|
||||
glm::vec3 getGroundAtPosition(const glm::vec3& pos) const;
|
||||
/**
|
||||
* Returns the current minute
|
||||
*/
|
||||
int getMinute();
|
||||
|
||||
float getGameTime() const;
|
||||
/**
|
||||
* Modifies the game time and handles the circular nature of clock numbers
|
||||
* Supports negative numbers
|
||||
*/
|
||||
void offsetGameTime(int minutes);
|
||||
|
||||
/**
|
||||
* @brief getInventoryItem
|
||||
* @param weaponId The Weapon ID (inventory slot) of the weapon to fetch
|
||||
* @return Instance of the weapon
|
||||
*/
|
||||
InventoryItem* getInventoryItem(uint16_t weaponId) const;
|
||||
glm::vec3 getGroundAtPosition(const glm::vec3& pos) const;
|
||||
|
||||
/**
|
||||
* Game data
|
||||
*/
|
||||
GameData* data;
|
||||
float getGameTime() const;
|
||||
|
||||
/**
|
||||
* Gameplay state
|
||||
*/
|
||||
GameState* state;
|
||||
|
||||
/**
|
||||
* State of playing sounds
|
||||
*/
|
||||
SoundManager sound;
|
||||
/**
|
||||
* @brief getInventoryItem
|
||||
* @param weaponId The Weapon ID (inventory slot) of the weapon to fetch
|
||||
* @return Instance of the weapon
|
||||
*/
|
||||
InventoryItem* getInventoryItem(uint16_t weaponId) const;
|
||||
|
||||
/**
|
||||
* Chase state
|
||||
*/
|
||||
ChaseCoordinator chase;
|
||||
/**
|
||||
* Game data
|
||||
*/
|
||||
GameData* data;
|
||||
|
||||
/**
|
||||
* Each object type is allocated from a pool. This object helps manage
|
||||
* the individual pools.
|
||||
*/
|
||||
struct ObjectPool
|
||||
{
|
||||
std::map<GameObjectID, GameObject*> objects;
|
||||
|
||||
/**
|
||||
* Allocates the game object a GameObjectID and inserts it into
|
||||
* the pool
|
||||
*/
|
||||
void insert(GameObject* object);
|
||||
/**
|
||||
* Gameplay state
|
||||
*/
|
||||
GameState* state;
|
||||
|
||||
/**
|
||||
* Removes a game object from this pool
|
||||
*/
|
||||
void remove(GameObject* object);
|
||||
/**
|
||||
* State of playing sounds
|
||||
*/
|
||||
SoundManager sound;
|
||||
|
||||
/**
|
||||
* Finds a game object if it exists in this pool
|
||||
*/
|
||||
GameObject* find(GameObjectID id) const;
|
||||
};
|
||||
/**
|
||||
* Chase state
|
||||
*/
|
||||
ChaseCoordinator chase;
|
||||
|
||||
/**
|
||||
* Stores all game objects
|
||||
*/
|
||||
std::vector<GameObject*> allObjects;
|
||||
/**
|
||||
* Each object type is allocated from a pool. This object helps manage
|
||||
* the individual pools.
|
||||
*/
|
||||
struct ObjectPool {
|
||||
std::map<GameObjectID, GameObject*> objects;
|
||||
|
||||
ObjectPool pedestrianPool;
|
||||
ObjectPool instancePool;
|
||||
ObjectPool vehiclePool;
|
||||
ObjectPool pickupPool;
|
||||
ObjectPool cutscenePool;
|
||||
ObjectPool projectilePool;
|
||||
/**
|
||||
* Allocates the game object a GameObjectID and inserts it into
|
||||
* the pool
|
||||
*/
|
||||
void insert(GameObject* object);
|
||||
|
||||
ObjectPool& getTypeObjectPool(GameObject* object);
|
||||
/**
|
||||
* Removes a game object from this pool
|
||||
*/
|
||||
void remove(GameObject* object);
|
||||
|
||||
std::vector<PlayerController*> players;
|
||||
/**
|
||||
* Finds a game object if it exists in this pool
|
||||
*/
|
||||
GameObject* find(GameObjectID id) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief getBlipTarget
|
||||
* @param blip
|
||||
* @return The targetted object of the given blip
|
||||
*/
|
||||
GameObject *getBlipTarget(const BlipData &blip) const;
|
||||
/**
|
||||
* Stores all game objects
|
||||
*/
|
||||
std::vector<GameObject*> allObjects;
|
||||
|
||||
/**
|
||||
* Map of Model Names to Instances
|
||||
*/
|
||||
std::map<std::string, InstanceObject*> modelInstances;
|
||||
ObjectPool pedestrianPool;
|
||||
ObjectPool instancePool;
|
||||
ObjectPool vehiclePool;
|
||||
ObjectPool pickupPool;
|
||||
ObjectPool cutscenePool;
|
||||
ObjectPool projectilePool;
|
||||
|
||||
/**
|
||||
* AI Graph
|
||||
*/
|
||||
AIGraph aigraph;
|
||||
|
||||
/**
|
||||
* Visual Effects
|
||||
* @todo Consider using lighter handing mechanism
|
||||
*/
|
||||
std::vector<VisualFX*> effects;
|
||||
ObjectPool& getTypeObjectPool(GameObject* object);
|
||||
|
||||
/**
|
||||
* Randomness Engine
|
||||
*/
|
||||
std::default_random_engine randomEngine;
|
||||
|
||||
/**
|
||||
* Bullet
|
||||
*/
|
||||
btDefaultCollisionConfiguration* collisionConfig;
|
||||
btCollisionDispatcher* collisionDispatcher;
|
||||
btBroadphaseInterface* broadphase;
|
||||
btSequentialImpulseConstraintSolver* solver;
|
||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
||||
std::vector<PlayerController*> players;
|
||||
|
||||
/**
|
||||
* @brief physicsNearCallback
|
||||
* Used to implement uprooting and other physics oddities.
|
||||
*/
|
||||
static bool ContactProcessedCallback(btManifoldPoint& mp, void* body0, void* body1);
|
||||
/**
|
||||
* @brief getBlipTarget
|
||||
* @param blip
|
||||
* @return The targetted object of the given blip
|
||||
*/
|
||||
GameObject* getBlipTarget(const BlipData& blip) const;
|
||||
|
||||
/**
|
||||
* @brief PhysicsTickCallback updates object each physics tick.
|
||||
* @param physWorld
|
||||
* @param timeStep
|
||||
*/
|
||||
static void PhysicsTickCallback(btDynamicsWorld* physWorld, btScalar timeStep);
|
||||
/**
|
||||
* Map of Model Names to Instances
|
||||
*/
|
||||
std::map<std::string, InstanceObject*> modelInstances;
|
||||
|
||||
/**
|
||||
* Work related
|
||||
*/
|
||||
WorkContext* _work;
|
||||
/**
|
||||
* AI Graph
|
||||
*/
|
||||
AIGraph aigraph;
|
||||
|
||||
/**
|
||||
* @brief Loads and starts the named cutscene.
|
||||
* @param name
|
||||
*/
|
||||
void loadCutscene(const std::string& name);
|
||||
void startCutscene();
|
||||
void clearCutscene();
|
||||
bool isCutsceneDone();
|
||||
/**
|
||||
* Visual Effects
|
||||
* @todo Consider using lighter handing mechanism
|
||||
*/
|
||||
std::vector<VisualFX*> effects;
|
||||
|
||||
std::string cutsceneAudio;
|
||||
bool cutsceneAudioLoaded;
|
||||
std::string missionAudio;
|
||||
/**
|
||||
* Randomness Engine
|
||||
*/
|
||||
std::default_random_engine randomEngine;
|
||||
|
||||
/**
|
||||
* @brief loads a model into a special character slot.
|
||||
*/
|
||||
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 drawAreaIndicator(AreaIndicatorInfo::AreaIndicatorType type, glm::vec3 position, glm::vec3 radius);
|
||||
|
||||
const std::vector<AreaIndicatorInfo>& getAreaIndicators() const { return areaIndicators; }
|
||||
|
||||
void clearTickData();
|
||||
|
||||
void setPaused(bool pause);
|
||||
bool isPaused() const;
|
||||
/**
|
||||
* Bullet
|
||||
*/
|
||||
btDefaultCollisionConfiguration* collisionConfig;
|
||||
btCollisionDispatcher* collisionDispatcher;
|
||||
btBroadphaseInterface* broadphase;
|
||||
btSequentialImpulseConstraintSolver* solver;
|
||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
||||
|
||||
/**
|
||||
* Attempt to spawn a vehicle at a vehicle generator
|
||||
*/
|
||||
VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen);
|
||||
/**
|
||||
* @brief physicsNearCallback
|
||||
* Used to implement uprooting and other physics oddities.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Work related
|
||||
*/
|
||||
WorkContext* _work;
|
||||
|
||||
/**
|
||||
* @brief Loads and starts the named cutscene.
|
||||
* @param name
|
||||
*/
|
||||
void loadCutscene(const std::string& name);
|
||||
void startCutscene();
|
||||
void clearCutscene();
|
||||
bool isCutsceneDone();
|
||||
|
||||
std::string cutsceneAudio;
|
||||
bool cutsceneAudioLoaded;
|
||||
std::string missionAudio;
|
||||
|
||||
/**
|
||||
* @brief loads a model into a special character slot.
|
||||
*/
|
||||
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 drawAreaIndicator(AreaIndicatorInfo::AreaIndicatorType type,
|
||||
glm::vec3 position, glm::vec3 radius);
|
||||
|
||||
const std::vector<AreaIndicatorInfo>& getAreaIndicators() const {
|
||||
return areaIndicators;
|
||||
}
|
||||
|
||||
void clearTickData();
|
||||
|
||||
void setPaused(bool pause);
|
||||
bool isPaused() const;
|
||||
|
||||
/**
|
||||
* Attempt to spawn a vehicle at a vehicle generator
|
||||
*/
|
||||
VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Used by objects to delete themselves during updates.
|
||||
*/
|
||||
std::set<GameObject*> deletionQueue;
|
||||
|
||||
/**
|
||||
* @brief Used by objects to delete themselves during updates.
|
||||
*/
|
||||
std::set<GameObject*> deletionQueue;
|
||||
std::vector<AreaIndicatorInfo> areaIndicators;
|
||||
|
||||
std::vector<AreaIndicatorInfo> areaIndicators;
|
||||
/**
|
||||
* Inventory Item instances
|
||||
*/
|
||||
std::vector<InventoryItem*> inventoryItems;
|
||||
|
||||
/**
|
||||
* Inventory Item instances
|
||||
*/
|
||||
std::vector<InventoryItem*> inventoryItems;
|
||||
|
||||
/**
|
||||
* Flag for pausing the simulation
|
||||
*/
|
||||
bool paused;
|
||||
/**
|
||||
* Flag for pausing the simulation
|
||||
*/
|
||||
bool paused;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,42 +12,39 @@
|
||||
class GameWorld;
|
||||
class ScriptMachine;
|
||||
|
||||
struct SaveGameInfo
|
||||
{
|
||||
std::string savePath;
|
||||
bool valid;
|
||||
BasicState basicState;
|
||||
struct SaveGameInfo {
|
||||
std::string savePath;
|
||||
bool valid;
|
||||
BasicState basicState;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static void writeGame(GameState& state, const std::string& file);
|
||||
|
||||
/**
|
||||
* Writes the entire game state to a file format that closely approximates
|
||||
* the format used in GTA III
|
||||
*/
|
||||
static void writeGame(GameState& state, const std::string& file);
|
||||
/**
|
||||
* Loads an entire Game State from a file, using a format similar to the
|
||||
* format used by GTA III.
|
||||
*
|
||||
* It assumes that the state already has a world and script that have been
|
||||
* initalized to the same state as the game being loaded.
|
||||
* @return status, false if failure occured.
|
||||
*/
|
||||
static bool loadGame(GameState& state, const std::string& file);
|
||||
|
||||
/**
|
||||
* Loads an entire Game State from a file, using a format similar to the
|
||||
* format used by GTA III.
|
||||
*
|
||||
* It assumes that the state already has a world and script that have been
|
||||
* initalized to the same state as the game being loaded.
|
||||
* @return status, false if failure occured.
|
||||
*/
|
||||
static bool loadGame(GameState& state, const std::string& file);
|
||||
static bool getSaveInfo(const std::string& file, BasicState* outState);
|
||||
|
||||
static bool getSaveInfo(const std::string& file, BasicState* outState);
|
||||
|
||||
/**
|
||||
* Returns save game information for all found saves
|
||||
*/
|
||||
static std::vector<SaveGameInfo> getAllSaveGameInfo();
|
||||
/**
|
||||
* Returns save game information for all found saves
|
||||
*/
|
||||
static std::vector<SaveGameInfo> getAllSaveGameInfo();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,197 +1,168 @@
|
||||
#include <engine/ScreenText.hpp>
|
||||
|
||||
void ScreenText::tick(float dt)
|
||||
{
|
||||
int millis = dt * 1000;
|
||||
void ScreenText::tick(float dt) {
|
||||
int millis = dt * 1000;
|
||||
|
||||
// Remove all the immedate text
|
||||
m_textQueues[static_cast<size_t>(ScreenTextType::Immediate)].clear();
|
||||
// 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();)
|
||||
{
|
||||
auto& big = m_textQueues[t][i];
|
||||
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
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
big.displayedMS += millis;
|
||||
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)
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 252 (from top)
|
||||
// Size: 25 Pixel high letters ('S', 'l')
|
||||
case 1:
|
||||
return {str,
|
||||
{320.f, 252.f},
|
||||
1,
|
||||
50,
|
||||
{2, 0, 0, 0},
|
||||
{58, 119, 133},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
|
||||
// Color: Blue
|
||||
// Font: Pricedown
|
||||
// Style: Italic (lowercase only)
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 252 (from top)
|
||||
// Size: 25 Pixel high letters ('S', 'l')
|
||||
case 1:
|
||||
return {
|
||||
str,
|
||||
{320.f, 252.f},
|
||||
1,
|
||||
50,
|
||||
{ 2, 0, 0, 0},
|
||||
{58, 119, 133},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
// Color: Yellow/Gold
|
||||
// Font: Pricedown
|
||||
// Style: Italic (lowercase only)
|
||||
// Horizontally: Right at x = 620 (from left)
|
||||
// Vertically: Baseline at y = 380 (from top)
|
||||
// Size: 22 Pixel high letters ('S', 'l')
|
||||
case 2:
|
||||
return {str,
|
||||
{620.f, 380.f},
|
||||
1,
|
||||
30,
|
||||
{2, 3, 0, 0},
|
||||
{214, 171, 9},
|
||||
2,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
|
||||
// Color: Yellow/Gold
|
||||
// Font: Pricedown
|
||||
// Style: Italic (lowercase only)
|
||||
// Horizontally: Right at x = 620 (from left)
|
||||
// Vertically: Baseline at y = 380 (from top)
|
||||
// Size: 22 Pixel high letters ('S', 'l')
|
||||
case 2:
|
||||
return {
|
||||
str,
|
||||
{620.f, 380.f},
|
||||
1,
|
||||
30,
|
||||
{ 2, 3, 0, 0},
|
||||
{214, 171, 9},
|
||||
2,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
// Color: Light brown
|
||||
// Font: Pricedown
|
||||
// Style: Italic (lowercase only)
|
||||
// Horizontally: Right at x = 620 (from left)
|
||||
// Vertically: Baseline at y = 427 (from top)
|
||||
// Size: 28 Pixel high letters ('S', 'l')
|
||||
case 3:
|
||||
return {str,
|
||||
{320.f, 400.f},
|
||||
1,
|
||||
50,
|
||||
{5, 5, 0, 0},
|
||||
{169, 123, 88}, /// @todo verify
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
|
||||
// Color: Light brown
|
||||
// Font: Pricedown
|
||||
// Style: Italic (lowercase only)
|
||||
// Horizontally: Right at x = 620 (from left)
|
||||
// Vertically: Baseline at y = 427 (from top)
|
||||
// Size: 28 Pixel high letters ('S', 'l')
|
||||
case 3:
|
||||
return {
|
||||
str,
|
||||
{320.f, 400.f},
|
||||
1,
|
||||
50,
|
||||
{ 5, 5, 0, 0},
|
||||
{169, 123, 88}, /// @todo verify
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
// Color: Blue
|
||||
// Font: Arial
|
||||
// Style: Italic
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 176 (from top)
|
||||
// Size: 20 Pixel high letters ('S', 'l')
|
||||
case 4:
|
||||
case 5:
|
||||
return {str,
|
||||
{320.f, 176.f},
|
||||
2,
|
||||
50,
|
||||
((style == 4) ? glm::u8vec4({2, 2, 0, 0})
|
||||
: glm::u8vec4({-2, -2, 0, 0})),
|
||||
{90, 115, 150}, /// @todo verify
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
|
||||
// Color: Blue
|
||||
// Font: Arial
|
||||
// Style: Italic
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 176 (from top)
|
||||
// Size: 20 Pixel high letters ('S', 'l')
|
||||
case 4:
|
||||
case 5:
|
||||
return {
|
||||
str,
|
||||
{320.f, 176.f},
|
||||
2,
|
||||
50,
|
||||
((style == 4) ? glm::u8vec4({ 2, 2, 0, 0}) : glm::u8vec4({ -2, -2, 0, 0 })),
|
||||
{90, 115, 150}, /// @todo verify
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
// Color: Brown
|
||||
// Font: Arial
|
||||
// Style: Italic
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 240 (from top)
|
||||
// Size: 16 Pixel high letters ('S', 'l')
|
||||
case 6:
|
||||
return {str,
|
||||
{320.f, 240.f},
|
||||
2,
|
||||
50,
|
||||
{2, 2, 0, 0},
|
||||
{152, 89, 39},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
|
||||
// Color: Brown
|
||||
// Font: Arial
|
||||
// Style: Italic
|
||||
// Horizontally: Centered
|
||||
// Vertically: Baseline at y = 240 (from top)
|
||||
// Size: 16 Pixel high letters ('S', 'l')
|
||||
case 6:
|
||||
return {
|
||||
str,
|
||||
{320.f, 240.f},
|
||||
2,
|
||||
50,
|
||||
{ 2, 2, 0, 0},
|
||||
{152, 89, 39},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
default:
|
||||
RW_ERROR("Unhandled text style");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
RW_ERROR("Unhandled text style");
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
GameStringUtil::fromString("Error, style " + std::to_string(style)),
|
||||
{320.f, 400.f},
|
||||
2,
|
||||
50,
|
||||
{20, 20, 0, 0},
|
||||
{20, 20, 200},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id
|
||||
};
|
||||
return {GameStringUtil::fromString("Error, style " + std::to_string(style)),
|
||||
{320.f, 400.f},
|
||||
2,
|
||||
50,
|
||||
{20, 20, 0, 0},
|
||||
{20, 20, 200},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
600,
|
||||
id};
|
||||
}
|
||||
|
||||
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,
|
||||
{320.f, 420.f},
|
||||
2,
|
||||
18,
|
||||
{1, 0, 0, 0},
|
||||
{255, 255, 255},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
50,
|
||||
id
|
||||
};
|
||||
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,
|
||||
{320.f, 420.f},
|
||||
2,
|
||||
18,
|
||||
{1, 0, 0, 0},
|
||||
{255, 255, 255},
|
||||
1,
|
||||
durationMS,
|
||||
0,
|
||||
50,
|
||||
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};
|
||||
}
|
||||
|
@ -1,71 +1,69 @@
|
||||
#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
|
||||
{
|
||||
/// Big text will be rendered according to the proscribed style.
|
||||
/// Adding a 2nd big text will cause the first to terminate.
|
||||
Big = 0,
|
||||
/// See Big, will wait for any Big text to finish.
|
||||
BigLowPriority = 1,
|
||||
/// Will be cleared by the clear help opcode
|
||||
Help = 2,
|
||||
/// Automatically cleared after each tick, for generic text.
|
||||
Immediate = 3,
|
||||
/// High priority cutscene text
|
||||
HighPriority = 4,
|
||||
///
|
||||
_Count = 5
|
||||
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,
|
||||
/// See Big, will wait for any Big text to finish.
|
||||
BigLowPriority = 1,
|
||||
/// Will be cleared by the clear help opcode
|
||||
Help = 2,
|
||||
/// Automatically cleared after each tick, for generic text.
|
||||
Immediate = 3,
|
||||
/// High priority cutscene text
|
||||
HighPriority = 4,
|
||||
///
|
||||
_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
|
||||
{
|
||||
/// After processing numbers
|
||||
GameString text;
|
||||
/// in the virtual 640x480 screen space
|
||||
glm::vec2 position;
|
||||
/// Font number
|
||||
int font;
|
||||
/// Font size
|
||||
int size;
|
||||
/// Background colour (or, if a == 0, shadow offset)
|
||||
glm::u8vec4 colourBG;
|
||||
/// Foreground colour
|
||||
glm::u8vec3 colourFG;
|
||||
/// Alignment (left = 0, center = 1, right = 2)
|
||||
unsigned char alignment;
|
||||
/// Onscreen duration
|
||||
int durationMS;
|
||||
/// The amount of time onscreen so far
|
||||
int displayedMS;
|
||||
/// Wrap width
|
||||
int wrapX;
|
||||
/// ID used to reference the text.
|
||||
GameStringKey id;
|
||||
struct ScreenTextEntry {
|
||||
/// After processing numbers
|
||||
GameString text;
|
||||
/// in the virtual 640x480 screen space
|
||||
glm::vec2 position;
|
||||
/// Font number
|
||||
int font;
|
||||
/// Font size
|
||||
int size;
|
||||
/// Background colour (or, if a == 0, shadow offset)
|
||||
glm::u8vec4 colourBG;
|
||||
/// Foreground colour
|
||||
glm::u8vec3 colourFG;
|
||||
/// Alignment (left = 0, center = 1, right = 2)
|
||||
unsigned char alignment;
|
||||
/// Onscreen duration
|
||||
int durationMS;
|
||||
/// The amount of time onscreen so far
|
||||
int displayedMS;
|
||||
/// Wrap width
|
||||
int wrapX;
|
||||
/// ID used to reference the text.
|
||||
GameStringKey id;
|
||||
|
||||
static ScreenTextEntry makeBig(const GameStringKey& id,
|
||||
const GameString& str,
|
||||
int style,
|
||||
int durationMS);
|
||||
static ScreenTextEntry makeBig(const GameStringKey& id,
|
||||
const GameString& str, int style,
|
||||
int durationMS);
|
||||
|
||||
static ScreenTextEntry makeHighPriority(const GameStringKey& id,
|
||||
const GameString& str,
|
||||
int durationMS);
|
||||
static ScreenTextEntry makeHighPriority(const GameStringKey& id,
|
||||
const GameString& str,
|
||||
int durationMS);
|
||||
|
||||
static ScreenTextEntry makeHelp(const GameStringKey& id,
|
||||
const GameString& str);
|
||||
static ScreenTextEntry makeHelp(const GameStringKey& id,
|
||||
const GameString& str);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -88,74 +86,69 @@ 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>;
|
||||
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
|
||||
///
|
||||
void tick(float dt);
|
||||
|
||||
///
|
||||
/// \brief tick Apply display and fading rules to the text
|
||||
/// \param dt
|
||||
///
|
||||
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...));
|
||||
}
|
||||
|
||||
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...));
|
||||
}
|
||||
template <ScreenTextType Q>
|
||||
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>
|
||||
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");
|
||||
m_textQueues[static_cast<size_t>(Q)].clear();
|
||||
}
|
||||
|
||||
template <ScreenTextType Q>
|
||||
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");
|
||||
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());
|
||||
}
|
||||
|
||||
template <ScreenTextType Q>
|
||||
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()
|
||||
);
|
||||
}
|
||||
const EntryQueues& getAllText() const {
|
||||
return m_textQueues;
|
||||
}
|
||||
|
||||
const EntryQueues& getAllText() const
|
||||
{
|
||||
return m_textQueues;
|
||||
}
|
||||
|
||||
template<class...Args>
|
||||
static GameString format(GameString format, Args&&...args)
|
||||
{
|
||||
static auto kReplacementMarker = GameStringUtil::fromString("~1~");
|
||||
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())
|
||||
{
|
||||
format = format.substr(0, x) + vals[val++] + format.substr(x + 3);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
template <class... Args>
|
||||
static GameString format(GameString format, Args&&... args) {
|
||||
static auto kReplacementMarker = GameStringUtil::fromString("~1~");
|
||||
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()) {
|
||||
format = format.substr(0, x) + vals[val++] + format.substr(x + 3);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
private:
|
||||
EntryQueues m_textQueues;
|
||||
EntryQueues m_textQueues;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user