From 49695a2dc6adb159847c5cb338f317881d42bc22 Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Wed, 24 Jun 2015 01:48:26 +0100 Subject: [PATCH] Further game save loading * Give object types individual id namespaces. --- rwengine/include/engine/GameState.hpp | 11 +- rwengine/include/engine/GameWorld.hpp | 51 ++- rwengine/include/engine/SaveGame.hpp | 15 - rwengine/include/script/ScriptTypes.hpp | 19 +- rwengine/src/ai/PlayerController.cpp | 12 +- rwengine/src/ai/TrafficDirector.cpp | 7 +- rwengine/src/engine/GameWorld.cpp | 100 +++--- rwengine/src/engine/SaveGame.cpp | 348 +------------------ rwengine/src/items/WeaponItem.cpp | 3 +- rwengine/src/objects/ProjectileObject.cpp | 4 +- rwengine/src/render/GameRenderer.cpp | 13 +- rwengine/src/render/MapRenderer.cpp | 16 +- rwengine/src/script/ScriptMachine.cpp | 4 + rwengine/src/script/ScriptTypes.cpp | 43 ++- rwengine/src/script/modules/GameModule.cpp | 59 ++-- rwengine/src/script/modules/ObjectModule.cpp | 219 +++++------- rwengine/src/script/modules/VMModule.cpp | 2 +- rwgame/RWGame.cpp | 18 +- rwgame/ingamestate.cpp | 4 +- 19 files changed, 337 insertions(+), 611 deletions(-) diff --git a/rwengine/include/engine/GameState.hpp b/rwengine/include/engine/GameState.hpp index 9a348dbc..df944ef1 100644 --- a/rwengine/include/engine/GameState.hpp +++ b/rwengine/include/engine/GameState.hpp @@ -76,6 +76,15 @@ struct VehicleGenerator struct BlipData { int id; + + enum BlipType + { + Location = 0, + Vehicle = 1, + Pickup = 2, + Character = 3, + }; + BlipType type; GameObjectID target; // If target is null then use coord glm::vec3 coord; @@ -94,7 +103,7 @@ struct BlipData DisplayMode display; BlipData() - : id(-1), target(0), display(Show) + : id(-1), type(Location), target(0), display(Show) { } }; diff --git a/rwengine/include/engine/GameWorld.hpp b/rwengine/include/engine/GameWorld.hpp index 58166acb..a446fe36 100644 --- a/rwengine/include/engine/GameWorld.hpp +++ b/rwengine/include/engine/GameWorld.hpp @@ -2,6 +2,7 @@ #ifndef _GAMEWORLD_HPP_ #define _GAMEWORLD_HPP_ +class PlayerController; class Logger; #include @@ -101,16 +102,6 @@ public: */ CharacterObject* createPlayer(const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0); - /** - * Inserts the given game object into the world. - */ - void insertObject(GameObject* object); - - /** - * Finds the GameObject with the given ID, if not found then nullptr. - */ - GameObject* findObject(GameObjectID id) const; - /** * Destroys an existing Object */ @@ -171,11 +162,45 @@ public: SoundManager sound; /** - * The active GameObjects within the world, mapped to their allocated ID + * Each object type is allocated from a pool. This object helps manage + * the individual pools. */ - std::map objects; + struct ObjectPool + { + std::map objects; + + /** + * Allocates the game object a GameObjectID and inserts it into + * the pool + */ + void insert(GameObject* object); - std::set characters; + /** + * Removes a game object from this pool + */ + void remove(GameObject* object); + + /** + * Finds a game object if it exists in this pool + */ + GameObject* find(GameObjectID id) const; + }; + + /** + * Stores all game objects + */ + std::vector allObjects; + + ObjectPool pedestrianPool; + ObjectPool instancePool; + ObjectPool vehiclePool; + ObjectPool pickupPool; + ObjectPool cutscenePool; + ObjectPool projectilePool; + + ObjectPool& getTypeObjectPool(GameObject* object); + + std::vector players; /** * Stores objects within a grid cell, and their maximum diff --git a/rwengine/include/engine/SaveGame.hpp b/rwengine/include/engine/SaveGame.hpp index 7b81b16f..b8c96641 100644 --- a/rwengine/include/engine/SaveGame.hpp +++ b/rwengine/include/engine/SaveGame.hpp @@ -46,21 +46,6 @@ public: * Returns save game information for all found saves */ static std::vector getAllSaveGameInfo(); - - /** - * Writes the current game state out into a file suitable for loading later. - */ - static void writeState(GameState& state, const std::string& file); - - static bool loadState(GameState& state, const std::string& file); - - static void writeScript(ScriptMachine& sm, const std::string& file); - - static bool loadScript(ScriptMachine&, const std::string& file); - - static void writeObjects(GameWorld& world, const std::string& file); - - static bool loadObjects(GameWorld& world, const std::string& file); }; #endif \ No newline at end of file diff --git a/rwengine/include/script/ScriptTypes.hpp b/rwengine/include/script/ScriptTypes.hpp index 18508bde..f37b1ca8 100644 --- a/rwengine/include/script/ScriptTypes.hpp +++ b/rwengine/include/script/ScriptTypes.hpp @@ -7,6 +7,11 @@ #include #include +class PickupObject; +class CutsceneObject; +class VehicleObject; +class CharacterObject; +class InstanceObject; class GameObject; class ScriptMachine; class ScriptModule; @@ -95,12 +100,18 @@ public: return parameters->at(arg); } - /** - * Returns the GameObject passed at the given argument index - */ - GameObject* getGameObject(unsigned int arg) const; + template + GameObject* getObject(unsigned int arg) const; + + GameObject* getPlayer(unsigned int player) const; }; +template<> GameObject* ScriptArguments::getObject(unsigned int arg) const; +template<> GameObject* ScriptArguments::getObject(unsigned int arg) const; +template<> GameObject* ScriptArguments::getObject(unsigned int arg) const; +template<> GameObject* ScriptArguments::getObject(unsigned int arg) const; +template<> GameObject* ScriptArguments::getObject(unsigned int arg) const; + typedef std::function ScriptFunction; typedef std::function ScriptFunctionBoolean; typedef uint16_t ScriptFunctionID; diff --git a/rwengine/src/ai/PlayerController.cpp b/rwengine/src/ai/PlayerController.cpp index a7adc11d..13b4d743 100644 --- a/rwengine/src/ai/PlayerController.cpp +++ b/rwengine/src/ai/PlayerController.cpp @@ -47,14 +47,12 @@ void PlayerController::enterNearestVehicle() auto world = character->engine; VehicleObject* nearest = nullptr; float d = 10.f; - for( auto& p : world->objects ) { + for( auto& p : world->vehiclePool.objects ) { auto object = p.second; - if( object->type() == GameObject::Vehicle ) { - float vd = glm::length( character->getPosition() - object->getPosition()); - if( vd < d ) { - d = vd; - nearest = static_cast(object); - } + float vd = glm::length( character->getPosition() - object->getPosition()); + if( vd < d ) { + d = vd; + nearest = static_cast(object); } } diff --git a/rwengine/src/ai/TrafficDirector.cpp b/rwengine/src/ai/TrafficDirector.cpp index 4074c57a..1d14fb48 100644 --- a/rwengine/src/ai/TrafficDirector.cpp +++ b/rwengine/src/ai/TrafficDirector.cpp @@ -30,11 +30,10 @@ std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::Nod for ( auto it = available.begin(); it != available.end(); ) { bool blocked = false; - for ( auto obj : world->characters ) + for ( auto obj : world->pedestrianPool.objects ) { // Sanity check - if ( obj->type() != GameObject::Character ) continue; - if ( glm::distance2( (*it)->position, obj->getPosition() ) <= minDist ) + if ( glm::distance2( (*it)->position, obj.second->getPosition() ) <= minDist ) { blocked = true; break; @@ -69,7 +68,7 @@ void TrafficDirector::setDensity(AIGraphNode::NodeType type, float density) std::vector TrafficDirector::populateNearby(const glm::vec3& center, float radius, int maxSpawn) { - int availablePeds = maximumPedestrians - world->characters.size(); + int availablePeds = maximumPedestrians - world->pedestrianPool.objects.size(); std::vector created; diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index c5f63fdc..32a15635 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -95,8 +95,8 @@ GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat) GameWorld::~GameWorld() { - for(auto& p : objects) { - delete p.second; + for(auto& p : allObjects) { + delete p; } delete dynamicsWorld; @@ -110,7 +110,6 @@ GameWorld::~GameWorld() bool GameWorld::placeItems(const std::string& name) { - auto i = data->iplLocations.find(name); std::string path = name; LoaderIPL ipll; @@ -126,15 +125,13 @@ bool GameWorld::placeItems(const std::string& name) } // Attempt to Associate LODs. - for(auto& p: objects) { + for(auto& p: instancePool.objects) { auto object = p.second; - if( object->type() == GameObject::Instance ) { - InstanceObject* instance = static_cast(object); - if( !instance->object->LOD ) { - auto lodInstit = modelInstances.find("LOD" + instance->object->modelName.substr(3)); - if( lodInstit != modelInstances.end() ) { - instance->LODinstance = lodInstit->second; - } + InstanceObject* instance = static_cast(object); + if( !instance->object->LOD ) { + auto lodInstit = modelInstances.find("LOD" + instance->object->modelName.substr(3)); + if( lodInstit != modelInstances.end() ) { + instance->LODinstance = lodInstit->second; } } } @@ -193,7 +190,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po oi, nullptr, dydata ); - insertObject(instance); + instancePool.insert(instance); if( shouldBeOnGrid(instance) ) { @@ -220,7 +217,7 @@ void GameWorld::createTraffic(const glm::vec3& near) void GameWorld::cleanupTraffic(const glm::vec3& focus) { - for ( auto& p : objects ) + for ( auto& p : pedestrianPool.objects ) { if ( p.second->getLifetime() != GameObject::TrafficLifetime ) { @@ -277,7 +274,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve } if( id == 0 ) { - auto playerobj = findObject(state->playerObject); + auto playerobj = pedestrianPool.find(state->playerObject); if( playerobj ) { modelname = playerobj->model->name; @@ -306,7 +303,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve pos, m); - insertObject( instance ); + cutscenePool.insert( instance ); return instance; @@ -371,7 +368,7 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, auto vehicle = new VehicleObject{ this, pos, rot, m, vti, info->second, prim, sec }; vehicle->setGameObjectID(gid); - insertObject( vehicle ); + vehiclePool.insert( vehicle ); return vehicle; } @@ -411,9 +408,8 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3& if(m && m->resource) { auto ped = new CharacterObject( this, pos, rot, m, pt ); ped->setGameObjectID(gid); - insertObject(ped); - characters.insert(ped); new DefaultAIController(ped); + pedestrianPool.insert( ped ); return ped; } } @@ -439,16 +435,15 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos, const glm::quat& auto ped = new CharacterObject( this, pos, rot, m, nullptr ); ped->setGameObjectID(gid); ped->setLifetime(GameObject::PlayerLifetime); - insertObject(ped); - characters.insert(ped); - new PlayerController(ped); + players.push_back(new PlayerController(ped)); + pedestrianPool.insert(ped); return ped; } } return nullptr; } -void GameWorld::insertObject(GameObject* object) +void GameWorld::ObjectPool::insert(GameObject* object) { if( object->getGameObjectID() == 0 ) { @@ -464,12 +459,45 @@ void GameWorld::insertObject(GameObject* object) objects[object->getGameObjectID()] = object; } -GameObject* GameWorld::findObject(GameObjectID id) const +GameObject* GameWorld::ObjectPool::find(GameObjectID id) const { auto it = objects.find( id ); return (it == objects.end())? nullptr : it->second; } +void GameWorld::ObjectPool::remove(GameObject* object) +{ + if( object ) + { + auto it = objects.find(object->getGameObjectID()); + if( it != objects.end() ) { + it = objects.erase(it); + } + } +} + + +GameWorld::ObjectPool& GameWorld::getTypeObjectPool(GameObject* object) +{ + switch( object->type() ) { + case GameObject::Character: + return pedestrianPool; + case GameObject::Vehicle: + return vehiclePool; + case GameObject::Cutscene: + return cutscenePool; + case GameObject::Instance: + return instancePool; + case GameObject::Pickup: + return pickupPool; + case GameObject::Projectile: + return projectilePool; + default: + // error! + return pedestrianPool; + } +} + void GameWorld::destroyObject(GameObject* object) { auto coord = worldToGrid(glm::vec2(object->getPosition())); @@ -480,16 +508,9 @@ void GameWorld::destroyObject(GameObject* object) auto index = (coord.x * WORLD_GRID_WIDTH) + coord.y; worldGrid[index].instances.erase(object); - auto iterator = objects.find(object->getGameObjectID()); - if( iterator != objects.end() ) { - delete object; - objects.erase(iterator); - } - - auto cit = characters.find(object); - if( cit != characters.end() ) { - characters.erase(cit); - } + auto& pool = getTypeObjectPool(object); + pool.remove(object); + delete object; } void GameWorld::destroyObjectQueued(GameObject *object) @@ -715,11 +736,9 @@ void GameWorld::PhysicsTickCallback(btDynamicsWorld *physWorld, btScalar timeSte { GameWorld* world = static_cast(physWorld->getWorldUserInfo()); - for( auto& p : world->objects ) { + for( auto& p : world->vehiclePool.objects ) { GameObject* object = p.second; - if( object->type() == GameObject::Vehicle ) { - static_cast(object)->tickPhysics(timeStep); - } + static_cast(object)->tickPhysics(timeStep); } } @@ -771,11 +790,8 @@ void GameWorld::startCutscene() void GameWorld::clearCutscene() { - for(auto& p : objects) { - auto o = p.second; - if( o->type() == GameObject::Cutscene ) { - destroyObjectQueued(o); - } + for(auto& p : cutscenePool.objects) { + destroyObjectQueued(p.second); } if( cutsceneAudio ) diff --git a/rwengine/src/engine/SaveGame.cpp b/rwengine/src/engine/SaveGame.cpp index 38f8ce2c..8d3cc505 100644 --- a/rwengine/src/engine/SaveGame.cpp +++ b/rwengine/src/engine/SaveGame.cpp @@ -10,323 +10,7 @@ #include