1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-18 16:32:32 +02:00

Further game save loading

* Give object types individual id namespaces.
This commit is contained in:
Daniel Evans 2015-06-24 01:48:26 +01:00
parent 7ceaac370c
commit 49695a2dc6
19 changed files with 337 additions and 611 deletions

View File

@ -76,6 +76,15 @@ struct VehicleGenerator
struct BlipData struct BlipData
{ {
int id; int id;
enum BlipType
{
Location = 0,
Vehicle = 1,
Pickup = 2,
Character = 3,
};
BlipType type;
GameObjectID target; GameObjectID target;
// If target is null then use coord // If target is null then use coord
glm::vec3 coord; glm::vec3 coord;
@ -94,7 +103,7 @@ struct BlipData
DisplayMode display; DisplayMode display;
BlipData() BlipData()
: id(-1), target(0), display(Show) : id(-1), type(Location), target(0), display(Show)
{ } { }
}; };

View File

@ -2,6 +2,7 @@
#ifndef _GAMEWORLD_HPP_ #ifndef _GAMEWORLD_HPP_
#define _GAMEWORLD_HPP_ #define _GAMEWORLD_HPP_
class PlayerController;
class Logger; class Logger;
#include <GL/glew.h> #include <GL/glew.h>
@ -101,16 +102,6 @@ public:
*/ */
CharacterObject* createPlayer(const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0); CharacterObject* createPlayer(const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
/**
* 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 * Destroys an existing Object
*/ */
@ -171,11 +162,45 @@ public:
SoundManager sound; 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<GameObjectID, GameObject*> objects; struct ObjectPool
{
std::map<GameObjectID, GameObject*> objects;
/**
* Allocates the game object a GameObjectID and inserts it into
* the pool
*/
void insert(GameObject* object);
std::set<GameObject*> 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<GameObject*> allObjects;
ObjectPool pedestrianPool;
ObjectPool instancePool;
ObjectPool vehiclePool;
ObjectPool pickupPool;
ObjectPool cutscenePool;
ObjectPool projectilePool;
ObjectPool& getTypeObjectPool(GameObject* object);
std::vector<PlayerController*> players;
/** /**
* Stores objects within a grid cell, and their maximum * Stores objects within a grid cell, and their maximum

View File

@ -46,21 +46,6 @@ public:
* Returns save game information for all found saves * Returns save game information for all found saves
*/ */
static std::vector<SaveGameInfo> getAllSaveGameInfo(); static std::vector<SaveGameInfo> 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 #endif

View File

@ -7,6 +7,11 @@
#include <vector> #include <vector>
#include <functional> #include <functional>
class PickupObject;
class CutsceneObject;
class VehicleObject;
class CharacterObject;
class InstanceObject;
class GameObject; class GameObject;
class ScriptMachine; class ScriptMachine;
class ScriptModule; class ScriptModule;
@ -95,12 +100,18 @@ public:
return parameters->at(arg); return parameters->at(arg);
} }
/** template <class T>
* Returns the GameObject passed at the given argument index GameObject* getObject(unsigned int arg) const;
*/
GameObject* getGameObject(unsigned int arg) const; GameObject* getPlayer(unsigned int player) const;
}; };
template<> GameObject* ScriptArguments::getObject<InstanceObject>(unsigned int arg) const;
template<> GameObject* ScriptArguments::getObject<CharacterObject>(unsigned int arg) const;
template<> GameObject* ScriptArguments::getObject<VehicleObject>(unsigned int arg) const;
template<> GameObject* ScriptArguments::getObject<CutsceneObject>(unsigned int arg) const;
template<> GameObject* ScriptArguments::getObject<PickupObject>(unsigned int arg) const;
typedef std::function<void (const ScriptArguments&)> ScriptFunction; typedef std::function<void (const ScriptArguments&)> ScriptFunction;
typedef std::function<bool (const ScriptArguments&)> ScriptFunctionBoolean; typedef std::function<bool (const ScriptArguments&)> ScriptFunctionBoolean;
typedef uint16_t ScriptFunctionID; typedef uint16_t ScriptFunctionID;

View File

@ -47,14 +47,12 @@ void PlayerController::enterNearestVehicle()
auto world = character->engine; auto world = character->engine;
VehicleObject* nearest = nullptr; float d = 10.f; VehicleObject* nearest = nullptr; float d = 10.f;
for( auto& p : world->objects ) { for( auto& p : world->vehiclePool.objects ) {
auto object = p.second; auto object = p.second;
if( object->type() == GameObject::Vehicle ) { float vd = glm::length( character->getPosition() - object->getPosition());
float vd = glm::length( character->getPosition() - object->getPosition()); if( vd < d ) {
if( vd < d ) { d = vd;
d = vd; nearest = static_cast<VehicleObject*>(object);
nearest = static_cast<VehicleObject*>(object);
}
} }
} }

View File

@ -30,11 +30,10 @@ std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::Nod
for ( auto it = available.begin(); it != available.end(); ) for ( auto it = available.begin(); it != available.end(); )
{ {
bool blocked = false; bool blocked = false;
for ( auto obj : world->characters ) for ( auto obj : world->pedestrianPool.objects )
{ {
// Sanity check // Sanity check
if ( obj->type() != GameObject::Character ) continue; if ( glm::distance2( (*it)->position, obj.second->getPosition() ) <= minDist )
if ( glm::distance2( (*it)->position, obj->getPosition() ) <= minDist )
{ {
blocked = true; blocked = true;
break; break;
@ -69,7 +68,7 @@ void TrafficDirector::setDensity(AIGraphNode::NodeType type, float density)
std::vector<GameObject*> TrafficDirector::populateNearby(const glm::vec3& center, float radius, int maxSpawn) std::vector<GameObject*> 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<GameObject*> created; std::vector<GameObject*> created;

View File

@ -95,8 +95,8 @@ GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat)
GameWorld::~GameWorld() GameWorld::~GameWorld()
{ {
for(auto& p : objects) { for(auto& p : allObjects) {
delete p.second; delete p;
} }
delete dynamicsWorld; delete dynamicsWorld;
@ -110,7 +110,6 @@ GameWorld::~GameWorld()
bool GameWorld::placeItems(const std::string& name) bool GameWorld::placeItems(const std::string& name)
{ {
auto i = data->iplLocations.find(name);
std::string path = name; std::string path = name;
LoaderIPL ipll; LoaderIPL ipll;
@ -126,15 +125,13 @@ bool GameWorld::placeItems(const std::string& name)
} }
// Attempt to Associate LODs. // Attempt to Associate LODs.
for(auto& p: objects) { for(auto& p: instancePool.objects) {
auto object = p.second; auto object = p.second;
if( object->type() == GameObject::Instance ) { InstanceObject* instance = static_cast<InstanceObject*>(object);
InstanceObject* instance = static_cast<InstanceObject*>(object); if( !instance->object->LOD ) {
if( !instance->object->LOD ) { auto lodInstit = modelInstances.find("LOD" + instance->object->modelName.substr(3));
auto lodInstit = modelInstances.find("LOD" + instance->object->modelName.substr(3)); if( lodInstit != modelInstances.end() ) {
if( lodInstit != modelInstances.end() ) { instance->LODinstance = lodInstit->second;
instance->LODinstance = lodInstit->second;
}
} }
} }
} }
@ -193,7 +190,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
oi, nullptr, dydata oi, nullptr, dydata
); );
insertObject(instance); instancePool.insert(instance);
if( shouldBeOnGrid(instance) ) if( shouldBeOnGrid(instance) )
{ {
@ -220,7 +217,7 @@ void GameWorld::createTraffic(const glm::vec3& near)
void GameWorld::cleanupTraffic(const glm::vec3& focus) void GameWorld::cleanupTraffic(const glm::vec3& focus)
{ {
for ( auto& p : objects ) for ( auto& p : pedestrianPool.objects )
{ {
if ( p.second->getLifetime() != GameObject::TrafficLifetime ) if ( p.second->getLifetime() != GameObject::TrafficLifetime )
{ {
@ -277,7 +274,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
} }
if( id == 0 ) { if( id == 0 ) {
auto playerobj = findObject(state->playerObject); auto playerobj = pedestrianPool.find(state->playerObject);
if( playerobj ) if( playerobj )
{ {
modelname = playerobj->model->name; modelname = playerobj->model->name;
@ -306,7 +303,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
pos, pos,
m); m);
insertObject( instance ); cutscenePool.insert( instance );
return 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 }; auto vehicle = new VehicleObject{ this, pos, rot, m, vti, info->second, prim, sec };
vehicle->setGameObjectID(gid); vehicle->setGameObjectID(gid);
insertObject( vehicle ); vehiclePool.insert( vehicle );
return vehicle; return vehicle;
} }
@ -411,9 +408,8 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3&
if(m && m->resource) { if(m && m->resource) {
auto ped = new CharacterObject( this, pos, rot, m, pt ); auto ped = new CharacterObject( this, pos, rot, m, pt );
ped->setGameObjectID(gid); ped->setGameObjectID(gid);
insertObject(ped);
characters.insert(ped);
new DefaultAIController(ped); new DefaultAIController(ped);
pedestrianPool.insert( ped );
return 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 ); auto ped = new CharacterObject( this, pos, rot, m, nullptr );
ped->setGameObjectID(gid); ped->setGameObjectID(gid);
ped->setLifetime(GameObject::PlayerLifetime); ped->setLifetime(GameObject::PlayerLifetime);
insertObject(ped); players.push_back(new PlayerController(ped));
characters.insert(ped); pedestrianPool.insert(ped);
new PlayerController(ped);
return ped; return ped;
} }
} }
return nullptr; return nullptr;
} }
void GameWorld::insertObject(GameObject* object) void GameWorld::ObjectPool::insert(GameObject* object)
{ {
if( object->getGameObjectID() == 0 ) if( object->getGameObjectID() == 0 )
{ {
@ -464,12 +459,45 @@ void GameWorld::insertObject(GameObject* object)
objects[object->getGameObjectID()] = object; objects[object->getGameObjectID()] = object;
} }
GameObject* GameWorld::findObject(GameObjectID id) const GameObject* GameWorld::ObjectPool::find(GameObjectID id) const
{ {
auto it = objects.find( id ); auto it = objects.find( id );
return (it == objects.end())? nullptr : it->second; 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) void GameWorld::destroyObject(GameObject* object)
{ {
auto coord = worldToGrid(glm::vec2(object->getPosition())); 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; auto index = (coord.x * WORLD_GRID_WIDTH) + coord.y;
worldGrid[index].instances.erase(object); worldGrid[index].instances.erase(object);
auto iterator = objects.find(object->getGameObjectID()); auto& pool = getTypeObjectPool(object);
if( iterator != objects.end() ) { pool.remove(object);
delete object; delete object;
objects.erase(iterator);
}
auto cit = characters.find(object);
if( cit != characters.end() ) {
characters.erase(cit);
}
} }
void GameWorld::destroyObjectQueued(GameObject *object) void GameWorld::destroyObjectQueued(GameObject *object)
@ -715,11 +736,9 @@ void GameWorld::PhysicsTickCallback(btDynamicsWorld *physWorld, btScalar timeSte
{ {
GameWorld* world = static_cast<GameWorld*>(physWorld->getWorldUserInfo()); GameWorld* world = static_cast<GameWorld*>(physWorld->getWorldUserInfo());
for( auto& p : world->objects ) { for( auto& p : world->vehiclePool.objects ) {
GameObject* object = p.second; GameObject* object = p.second;
if( object->type() == GameObject::Vehicle ) { static_cast<VehicleObject*>(object)->tickPhysics(timeStep);
static_cast<VehicleObject*>(object)->tickPhysics(timeStep);
}
} }
} }
@ -771,11 +790,8 @@ void GameWorld::startCutscene()
void GameWorld::clearCutscene() void GameWorld::clearCutscene()
{ {
for(auto& p : objects) { for(auto& p : cutscenePool.objects) {
auto o = p.second; destroyObjectQueued(p.second);
if( o->type() == GameObject::Cutscene ) {
destroyObjectQueued(o);
}
} }
if( cutsceneAudio ) if( cutsceneAudio )

View File

@ -10,323 +10,7 @@
#include <script/SCMFile.hpp> #include <script/SCMFile.hpp>
#include <ai/PlayerController.hpp> #include <ai/PlayerController.hpp>
#include <items/WeaponItem.hpp> #include <items/WeaponItem.hpp>
#include <cstring>
#include <fstream>
#include <cereal/cereal.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/array.hpp>
#include <cereal/types/map.hpp>
namespace cereal
{
template<class Archive>
void serialize(Archive& archive,
glm::vec3& s)
{
archive(s.x, s.y, s.z);
}
template<class Archive>
void serialize(Archive& archive,
glm::vec4& s)
{
archive(s.x, s.y, s.z, s.w);
}
template<class Archive>
void serialize(Archive& archive,
glm::u16vec3& s)
{
archive(s.x, s.y, s.z);
}
template<class Archive>
void serialize(Archive& archive,
glm::quat& s)
{
archive(s.x, s.y, s.z, s.w);
}
template<class Archive>
void serialize(Archive& archive,
OnscreenText& t)
{
archive(
t.id,
t.osTextString,
t.osTextStart,
t.osTextTime,
t.osTextStyle);
}
template<class Archive>
void serialize(Archive& archive,
VehicleGenerator& s)
{
archive(
s.position,
s.heading,
s.vehicleID,
s.colourFG,
s.colourBG,
s.alwaysSpawn,
s.alarmThreshold,
s.lockedThreshold,
s.minDelay,
s.maxDelay,
s.lastSpawnTime,
s.remainingSpawns);
}
template<class Archive>
void serialize(Archive& archive,
BlipData& s)
{
archive(
s.id,
s.target,
s.coord,
s.texture,
s.display);
}
template<class Archive>
void serialize(Archive& archive,
GarageInfo& s)
{
archive(
s.min,
s.max,
s.type);
}
template<class Archive>
void serialize(Archive& archive,
GameState& s)
{
archive(
s.gameTime,
s.currentProgress,
s.maxProgress,
s.numMissions,
s.numHiddenPackages,
s.numHiddenPackagesDiscovered,
s.numUniqueJumps,
s.numRampages,
s.maxWantedLevel,
s.playerObject,
s.currentWeather,
s.missionObjects,
s.overrideNextStart,
s.nextRestartLocation,
s.fadeOut,
s.fadeStart,
s.fadeTime,
s.fadeSound,
s.fadeColour,
s.currentSplash,
s.skipCutscene,
s.isIntroPlaying,
s.isCinematic,
s.hour,
s.minute,
s.lastMissionName,
s.specialCharacters,
s.specialModels,
s.text,
s.cameraNear,
s.cameraFixed,
s.cameraPosition,
s.cameraRotation,
s.cameraTarget,
s.vehicleGenerators,
s.radarBlips);
}
template<class Archive>
void serialize(Archive& archive,
SCMThread& s)
{
archive(
s.name,
s.baseAddress,
s.programCounter,
s.conditionCount,
s.conditionResult,
s.conditionMask,
s.conditionAND,
s.wakeCounter,
s.locals,
s.isMission,
s.finished,
s.stackDepth,
s.calls);
}
template<class Archive>
void serialize(Archive& archive,
ScriptMachine& s)
{
archive(
s.getThreads(),
s.getGlobalData());
}
}
void SaveGame::writeState(GameState& state, const std::string& file)
{
std::ofstream os(file.c_str());
{
cereal::JSONOutputArchive oa(os);
oa(state);
}
}
bool SaveGame::loadState(GameState& state, const std::string& file)
{
std::ifstream is(file.c_str());
{
cereal::JSONInputArchive ia(is);
ia(state);
}
return true;
}
void SaveGame::writeScript(ScriptMachine& sm, const std::string& file)
{
std::ofstream os(file.c_str());
{
cereal::JSONOutputArchive oa(os);
oa(sm);
}
}
bool SaveGame::loadScript(ScriptMachine& sm, const std::string& file)
{
std::ifstream is(file.c_str());
{
cereal::JSONInputArchive ia(is);
ia(sm);
}
return true;
}
void SaveGame::writeObjects(GameWorld& world, const std::string& file)
{
std::ofstream os(file.c_str());
{
cereal::JSONOutputArchive oa(os);
std::vector<GameObject*> writeable;
for( auto& p : world.objects )
{
switch( p.second->type() )
{
case GameObject::Vehicle:
case GameObject::Character:
break;
default:
continue;
}
if( p.second->getLifetime() == GameObject::TrafficLifetime )
{
continue;
}
writeable.push_back(p.second);
}
// Write object count.
oa(writeable.size());
for( GameObject* saved : writeable )
{
oa(saved->getGameObjectID());
oa(saved->type());
oa(saved->getLifetime());
oa(saved->getPosition());
oa(saved->getRotation());
switch( saved->type() )
{
case GameObject::Vehicle:
{
auto vehicle = static_cast<VehicleObject*>(saved);
oa(vehicle->vehicle->ID);
} break;
case GameObject::Character:
{
auto character = static_cast<CharacterObject*>(saved);
oa(character->ped->ID);
} break;
}
}
}
}
bool SaveGame::loadObjects(GameWorld& world, const std::string& file)
{
std::ifstream is(file.c_str());
{
cereal::JSONInputArchive ia(is);
std::size_t num;
ia(num);
for(int i = 0; i < num; i++)
{
GameObjectID gameID;
GameObject::Type type;
GameObject::ObjectLifetime lifetime;
glm::vec3 translation;
glm::quat orientation;
ia(gameID);
ia(type);
ia(lifetime);
ia(translation);
ia(orientation);
switch( type )
{
case GameObject::Vehicle:
{
ObjectID id;
ia(id);
auto vehicle = world.createVehicle(id, translation, orientation, gameID);
vehicle->setLifetime(lifetime);
} break;
case GameObject::Character:
{
ObjectID id;
ia(id);
CharacterObject* character;
if( lifetime == GameObject::PlayerLifetime )
{
character = world.createPlayer(translation, orientation, gameID);
}
else
{
character = world.createPedestrian(id, translation, orientation, gameID);
}
} break;
}
}
}
return true;
}
// Original save game file data structures // Original save game file data structures
typedef uint16_t BlockWord; typedef uint16_t BlockWord;
@ -402,7 +86,7 @@ struct Block0RunningScript {
BlockDword unknown1; BlockDword unknown1;
BlockWord stackCounter; BlockWord stackCounter;
BlockWord unknown2; BlockWord unknown2;
BlockDword scriptVariables[16]; SCMByte variables[16*4];
BlockDword timerA; BlockDword timerA;
BlockDword timerB; BlockDword timerB;
uint8_t ifFlag; uint8_t ifFlag;
@ -628,8 +312,8 @@ void SaveGame::writeGame(GameState& state, const std::string& file)
script.stack[i] = thread.calls[i]; script.stack[i] = thread.calls[i];
} }
script.stackCounter = thread.stackDepth; script.stackCounter = thread.stackDepth;
for(int i = 0; i < 16; i++) { for(int i = 0; i < sizeof(Block0RunningScript::variables); i++) {
script.scriptVariables[i] = *(((BlockDword*)thread.locals.data())+i); script.variables[i] = thread.locals[i];
} }
script.timerA = *(BlockDword*)(thread.locals.data() + 16 * sizeof ( SCMByte ) * 4); script.timerA = *(BlockDword*)(thread.locals.data() + 16 * sizeof ( SCMByte ) * 4);
script.timerB = *(BlockDword*)(thread.locals.data() + 16 * sizeof ( SCMByte ) * 4); script.timerB = *(BlockDword*)(thread.locals.data() + 16 * sizeof ( SCMByte ) * 4);
@ -722,9 +406,9 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
state.gameTime = block0Data.timeMS / 1000.f; state.gameTime = block0Data.timeMS / 1000.f;
state.currentWeather = block0Data.nextWeather; state.currentWeather = block0Data.nextWeather;
state.cameraPosition = block0Data.cameraPosition; state.cameraPosition = block0Data.cameraPosition;
std::cout << scriptVars << " / " << state.script->getFile()->getGlobalsSize() << std::endl;
for(int v = 0; v < scriptVars; ++v) { for(int v = 0; v < scriptVars; ++v) {
state.script->getGlobals()[v] = bytes[v]; state.script->getGlobalData()[v] = bytes[v];
} }
state.scriptOnMissionFlag = (unsigned int*)state.script->getGlobals() + (size_t)scriptData.onMissionOffset; state.scriptOnMissionFlag = (unsigned int*)state.script->getGlobals() + (size_t)scriptData.onMissionOffset;
@ -742,10 +426,14 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
} }
/* TODO not hardcode +33 ms */ /* TODO not hardcode +33 ms */
thread.wakeCounter = scripts[s].wakeTimer - block0Data.lastTick + 33; thread.wakeCounter = scripts[s].wakeTimer - block0Data.lastTick + 33;
for(int i = 0; i < sizeof(Block0RunningScript::variables); ++i) {
thread.locals[i] = scripts[s].variables[i];
}
} }
if( playerCount > 0 ) { if( playerCount > 0 ) {
auto& ply = players[0]; auto& ply = players[0];
std::cout << ply.reference << std::endl;
auto player = state.world->createPlayer(players[0].info.position); auto player = state.world->createPlayer(players[0].info.position);
player->mHealth = players[0].info.health; player->mHealth = players[0].info.health;
state.playerObject = player->getGameObjectID(); state.playerObject = player->getGameObjectID();
@ -774,15 +462,13 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
// Find the nearest dynamic instance? // Find the nearest dynamic instance?
float distance = std::numeric_limits<float>::max(); float distance = std::numeric_limits<float>::max();
GameObject* nearinst = nullptr; GameObject* nearinst = nullptr;
for(std::pair<GameObjectID, GameObject*> object : state.world->objects) { for(std::pair<GameObjectID, GameObject*> object : state.world->instancePool.objects) {
if( object.second->type() == GameObject::Instance ) { auto instance = static_cast<InstanceObject*>(object.second);
auto instance = static_cast<InstanceObject*>(object.second); if( instance->dynamics ) {
if( instance->dynamics ) { float idist = glm::distance(center, instance->getPosition());
float idist = glm::distance(center, instance->getPosition()); if( idist < distance ) {
if( idist < distance ) { distance = idist;
distance = idist; nearinst = instance;
nearinst = instance;
}
} }
} }
} }

View File

@ -121,7 +121,8 @@ void WeaponItem::fireProjectile()
_wepData _wepData
}); });
_character->engine->insertObject( projectile ); auto& pool = _character->engine->getTypeObjectPool( projectile );
pool.insert(projectile);
} }
void WeaponItem::primary(bool active) void WeaponItem::primary(bool active)

View File

@ -48,9 +48,7 @@ void ProjectileObject::explode()
const float damageSize = 5.f; const float damageSize = 5.f;
const float damage = _info.weapon->damage; const float damage = _info.weapon->damage;
/// @todo accelerate this with bullet instead of doing this stupid loop. for(auto& o : engine->allObjects) {
for(auto& p : engine->objects) {
auto o = p.second;
if( o == this ) continue; if( o == this ) continue;
switch( o->type() ) { switch( o->type() ) {
case GameObject::Instance: case GameObject::Instance:

View File

@ -297,8 +297,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
renderer->pushDebugGroup("Objects"); renderer->pushDebugGroup("Objects");
renderer->pushDebugGroup("Dynamic"); renderer->pushDebugGroup("Dynamic");
for( auto& p : world->objects ) { for( auto& object : world->allObjects ) {
auto object = p.second;
if(! object->visible ) if(! object->visible )
{ {
continue; continue;
@ -390,11 +389,13 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
if( blip.second.target > 0 ) if( blip.second.target > 0 )
{ {
auto object = world->findObject(blip.second.target); // TODO restore arrows
/*auto& pool = world->getTypeObjectPool(blip.second.target);
auto object = pool.find(blip.second.target);
if( object ) if( object )
{ {
model = object->getTimeAdjustedTransform( _renderAlpha ); model = object->getTimeAdjustedTransform( _renderAlpha );
} }*/
} }
else else
{ {
@ -475,7 +476,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
} }
float fadeTimer = world->getGameTime() - world->state->fadeStart; float fadeTimer = world->getGameTime() - world->state->fadeStart;
if( fadeTimer < world->state->fadeTime || !world->state->fadeOut ) { /*if( fadeTimer < world->state->fadeTime || !world->state->fadeOut ) {
glUseProgram(ssRectProgram); glUseProgram(ssRectProgram);
glUniform2f(ssRectOffset, 0.f, 0.f); glUniform2f(ssRectOffset, 0.f, 0.f);
glUniform2f(ssRectSize, 1.f, 1.f); glUniform2f(ssRectSize, 1.f, 1.f);
@ -503,7 +504,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
glBindVertexArray( ssRectDraw.getVAOName() ); glBindVertexArray( ssRectDraw.getVAOName() );
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }*/
if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) { if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) {
renderLetterbox(); renderLetterbox();

View File

@ -151,7 +151,19 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
glm::vec2 blippos( blip.second.coord ); glm::vec2 blippos( blip.second.coord );
if( blip.second.target > 0 ) if( blip.second.target > 0 )
{ {
auto object = world->findObject(blip.second.target); GameObject* object = nullptr;
switch( blip.second.type ) {
case BlipData::Vehicle:
object = world->vehiclePool.find(blip.second.target);
break;
case BlipData::Character:
object = world->pedestrianPool.find(blip.second.target);
break;
case BlipData::Pickup:
object = world->pickupPool.find(blip.second.target);
break;
default: break;
}
if( object ) if( object )
{ {
blippos = glm::vec2( object->getPosition() ); blippos = glm::vec2( object->getPosition() );
@ -162,7 +174,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
} }
// Draw the player blip // Draw the player blip
auto player = world->findObject(world->state->playerObject); auto player = world->pedestrianPool.find(world->state->playerObject);
if( player ) if( player )
{ {
glm::vec2 plyblip(player->getPosition()); glm::vec2 plyblip(player->getPosition());

View File

@ -31,6 +31,7 @@ bool SCMOpcodes::findOpcode(ScriptFunctionID id, ScriptFunctionMeta** out)
return false; return false;
} }
#include <iostream>
void ScriptMachine::executeThread(SCMThread &t, int msPassed) void ScriptMachine::executeThread(SCMThread &t, int msPassed)
{ {
if( t.wakeCounter > 0 ) { if( t.wakeCounter > 0 ) {
@ -53,6 +54,9 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
throw IllegalInstruction(opcode, t.programCounter, t.name); throw IllegalInstruction(opcode, t.programCounter, t.name);
} }
ScriptFunctionMeta& code = *foundcode; ScriptFunctionMeta& code = *foundcode;
if(t.baseAddress == 60824) {
std::cout << opcode << ": " << code.signature << std::endl;
}
// Keep the pc for the debugger // Keep the pc for the debugger
auto pc = t.programCounter; auto pc = t.programCounter;

View File

@ -2,6 +2,8 @@
#include <script/ScriptMachine.hpp> #include <script/ScriptMachine.hpp>
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <engine/GameWorld.hpp> #include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
#include <ai/PlayerController.hpp>
GameState* ScriptArguments::getState() const GameState* ScriptArguments::getState() const
{ {
@ -13,9 +15,46 @@ GameWorld* ScriptArguments::getWorld() const
return getVM()->getState()->world; return getVM()->getState()->world;
} }
GameObject* ScriptArguments::getGameObject(unsigned int arg) const GameObject* ScriptArguments::getPlayer(unsigned int player) const
{
auto playerId = parameters->at(player).integerValue();
PlayerController* controller = getWorld()->players.at( playerId );
return controller->getCharacter();
}
template<> GameObject* ScriptArguments::getObject< CharacterObject >(unsigned int arg) const
{
auto gameObjectID = parameters->at(arg).integerValue();
return getWorld()->pedestrianPool.find( gameObjectID );
}
template<> GameObject* ScriptArguments::getObject< CutsceneObject >(unsigned int arg) const
{
auto gameObjectID = parameters->at(arg).integerValue();
return getWorld()->cutscenePool.find( gameObjectID );
}
template<> GameObject* ScriptArguments::getObject< InstanceObject >(unsigned int arg) const
{
auto gameObjectID = parameters->at(arg).integerValue();
return getWorld()->instancePool.find( gameObjectID );
}
template<> GameObject* ScriptArguments::getObject< PickupObject >(unsigned int arg) const
{
auto gameObjectID = parameters->at(arg).integerValue();
return getWorld()->pickupPool.find( gameObjectID );
}
template<> GameObject* ScriptArguments::getObject< VehicleObject >(unsigned int arg) const
{
auto gameObjectID = parameters->at(arg).integerValue();
return getWorld()->vehiclePool.find( gameObjectID );
}
/*GameObject* ScriptArguments::getGameObject(unsigned int arg) const
{ {
auto gameObjectID = parameters->at(arg).integerValue(); auto gameObjectID = parameters->at(arg).integerValue();
auto it = getWorld()->objects.find( gameObjectID ); auto it = getWorld()->objects.find( gameObjectID );
return (it == getWorld()->objects.end())? nullptr : it->second; return (it == getWorld()->objects.end())? nullptr : it->second;
} }*/

View File

@ -142,7 +142,7 @@ void game_set_zone_car_info(const ScriptArguments& args)
void game_camera_follow_character(const ScriptArguments& args) void game_camera_follow_character(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if( character != nullptr ) if( character != nullptr )
{ {
args.getWorld()->state->cameraTarget = character->getGameObjectID(); args.getWorld()->state->cameraTarget = character->getGameObjectID();
@ -255,31 +255,15 @@ void game_link_mission_flag(const ScriptArguments& args)
args.getWorld()->state->scriptOnMissionFlag = (unsigned int*)args[0].globalInteger; args.getWorld()->state->scriptOnMissionFlag = (unsigned int*)args[0].globalInteger;
} }
void game_add_vehicle_blip(const ScriptArguments& args) template <class Tobject>
void game_add_object_blip(const ScriptArguments& args)
{ {
BlipData data; BlipData data;
data.target = args.getGameObject(0)->getGameObjectID(); data.target = args.getObject<Tobject>(0)->getGameObjectID();
data.texture = ""; data.texture = "";
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data); *args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
} }
void game_add_character_blip(const ScriptArguments& args)
{
BlipData data;
data.target = args.getGameObject(0)->getGameObjectID();
data.texture = "";
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
}
void game_add_pickup_blip(const ScriptArguments& args)
{
BlipData data;
data.target = args.getGameObject(0)->getGameObjectID();
data.texture = "";
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
}
void game_add_location_blip(const ScriptArguments& args) void game_add_location_blip(const ScriptArguments& args)
{ {
BlipData data; BlipData data;
@ -311,8 +295,8 @@ void game_change_blip_mode(const ScriptArguments& args)
void game_enable_input(const ScriptArguments& args) void game_enable_input(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto player = static_cast<CharacterObject*>(args.getPlayer(0));
static_cast<PlayerController*>(character->controller)->setInputEnabled(!!args[1].integer); static_cast<PlayerController*>(player->controller)->setInputEnabled(!!args[1].integer);
} }
void game_set_weather(const ScriptArguments& args) void game_set_weather(const ScriptArguments& args)
@ -364,10 +348,9 @@ void game_max_wanted_level(const ScriptArguments& args)
args.getWorld()->state->maxWantedLevel = args[0].integer; args.getWorld()->state->maxWantedLevel = args[0].integer;
} }
// This does nothing for us.
void game_get_player(const ScriptArguments& args) void game_get_player(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getPlayer(0);
*args[1].globalInteger = character->getGameObjectID(); *args[1].globalInteger = character->getGameObjectID();
} }
@ -444,7 +427,7 @@ void game_restart_critical_mission(const ScriptArguments& args)
// Reset player state. // Reset player state.
glm::vec3 position(args[0].real, args[1].real, args[2].real + 1.f); glm::vec3 position(args[0].real, args[1].real, args[2].real + 1.f);
auto object = args.getWorld()->findObject(args.getState()->playerObject); auto object = args.getWorld()->pedestrianPool.find(args.getState()->playerObject);
auto player = static_cast<CharacterObject*>(object); auto player = static_cast<CharacterObject*>(object);
glm::vec3 spawnMagic( 0.f, 0.f, 1.f ); glm::vec3 spawnMagic( 0.f, 0.f, 1.f );
@ -465,8 +448,10 @@ void game_restart_critical_mission(const ScriptArguments& args)
/// @todo http://www.gtamodding.com/index.php?title=0256 (e.g. check if dead or busted) /// @todo http://www.gtamodding.com/index.php?title=0256 (e.g. check if dead or busted)
bool game_is_player_playing(const ScriptArguments& args) bool game_is_player_playing(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getPlayer(0);
std::cout << args.getPlayer(0) << std::endl;
return character != nullptr; return character != nullptr;
//return args.getWorld()->findObject(args.getState()->playerObject) != nullptr;
} }
void game_controller_mode(const ScriptArguments& args) void game_controller_mode(const ScriptArguments& args)
@ -564,7 +549,7 @@ void game_create_cutscene_object(const ScriptArguments& args)
} }
void game_set_cutscene_anim(const ScriptArguments& args) void game_set_cutscene_anim(const ScriptArguments& args)
{ {
GameObject* object = args.getGameObject(0); GameObject* object = args.getObject<CutsceneObject>(0);
std::string animName = args[1].string; std::string animName = args[1].string;
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower); std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
Animation* anim = args.getWorld()->data->animations[animName]; Animation* anim = args.getWorld()->data->animations[animName];
@ -619,7 +604,7 @@ void game_load_special_model(const ScriptArguments& args)
void game_create_cutscene_head(const ScriptArguments& args) void game_create_cutscene_head(const ScriptArguments& args)
{ {
auto id = args[1].integer; auto id = args[1].integer;
auto actor = args.getGameObject(0); auto actor = args.getObject<CutsceneObject>(0);
CutsceneObject* object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset ); CutsceneObject* object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset );
auto headframe = actor->model->resource->findFrame("shead"); auto headframe = actor->model->resource->findFrame("shead");
@ -630,7 +615,7 @@ void game_create_cutscene_head(const ScriptArguments& args)
} }
void game_set_head_animation(const ScriptArguments& args) void game_set_head_animation(const ScriptArguments& args)
{ {
GameObject* object = args.getGameObject(0); GameObject* object = args.getObject<CutsceneObject>(0);
std::string animName = args[1].string; std::string animName = args[1].string;
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower); std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
Animation* anim = args.getWorld()->data->animations[animName]; Animation* anim = args.getWorld()->data->animations[animName];
@ -707,7 +692,7 @@ void game_set_background_colour(const ScriptArguments& args)
void game_set_character_model(const ScriptArguments& args) void game_set_character_model(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getObject<CharacterObject>(0);
if( character ) if( character )
{ {
static_cast<CharacterObject*>(character)->changeCharacterModel(args[1].string); static_cast<CharacterObject*>(character)->changeCharacterModel(args[1].string);
@ -793,6 +778,12 @@ void game_clear_print(const ScriptArguments& args)
} }
} }
bool game_did_game_save(const ScriptArguments& args)
{
// TODO not sure what could be false about this.
return true;
}
void game_get_found_hidden_packages(const ScriptArguments& args) void game_get_found_hidden_packages(const ScriptArguments& args)
{ {
*args[0].globalInteger = args.getWorld()->state->numHiddenPackagesDiscovered; *args[0].globalInteger = args.getWorld()->state->numHiddenPackagesDiscovered;
@ -930,8 +921,8 @@ GameModule::GameModule()
bindUnimplemented( 0x0181, game_link_character_mission_flag, 2, "Link Character Mission Flag" ); bindUnimplemented( 0x0181, game_link_character_mission_flag, 2, "Link Character Mission Flag" );
bindUnimplemented( 0x0182, game_unknown, 2, "Unknown Character Opcode" ); bindUnimplemented( 0x0182, game_unknown, 2, "Unknown Character Opcode" );
bindFunction(0x0186, game_add_vehicle_blip, 2, "Add Blip for Vehicle"); bindFunction(0x0186, game_add_object_blip<VehicleObject>, 2, "Add Blip for Vehicle");
bindFunction(0x0187, game_add_character_blip, 2, "Add Blip for Character"); bindFunction(0x0187, game_add_object_blip<CharacterObject>, 2, "Add Blip for Character");
bindFunction(0x018A, game_add_location_blip, 4, "Add Blip for Coord"); bindFunction(0x018A, game_add_location_blip, 4, "Add Blip for Coord");
bindFunction(0x018B, game_change_blip_mode, 2, "Change Blip Display Mode"); bindFunction(0x018B, game_change_blip_mode, 2, "Change Blip Display Mode");
@ -1103,10 +1094,10 @@ GameModule::GameModule()
bindFunction(0x03D5, game_clear_print, 1, "Clear This Print" ); bindFunction(0x03D5, game_clear_print, 1, "Clear This Print" );
bindUnimplemented( 0x03D6, game_clear_this_print, 1, "Clear This Big Print" ); bindUnimplemented( 0x03D6, game_clear_this_print, 1, "Clear This Big Print" );
bindFunction(0x03D9, game_did_game_save, 0, "Did game save" );
bindUnimplemented( 0x03DA, game_set_garage_follow_player, 1, "Set Garage Camera Follows Player" ); bindUnimplemented( 0x03DA, game_set_garage_follow_player, 1, "Set Garage Camera Follows Player" );
bindFunction(0x03DC, game_add_pickup_blip, 2, "Add blip for pickup"); bindFunction(0x03DC, game_add_object_blip<PickupObject>, 2, "Add blip for pickup");
bindUnimplemented( 0x03DE, game_set_pedestrian_density, 1, "Set Pedestrian density" ); bindUnimplemented( 0x03DE, game_set_pedestrian_density, 1, "Set Pedestrian density" );

View File

@ -44,16 +44,17 @@ void game_create_player(const ScriptArguments& args)
*args[4].globalInteger = pc->getGameObjectID(); *args[4].globalInteger = pc->getGameObjectID();
} }
void game_set_character_position(const ScriptArguments& args) template<class Tobject>
void game_set_object_position(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getObject<Tobject>(0);
glm::vec3 position(args[1].real, args[2].real, args[3].real + 1.f); glm::vec3 position(args[1].real, args[2].real, args[3].real + 1.f);
character->setPosition(position + spawnMagic); character->setPosition(position + spawnMagic);
} }
bool game_player_in_area_2d(const ScriptArguments& args) bool game_player_in_area_2d(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getPlayer(0);
glm::vec2 min(args[1].real, args[2].real); glm::vec2 min(args[1].real, args[2].real);
glm::vec2 max(args[3].real, args[4].real); glm::vec2 max(args[3].real, args[4].real);
auto player = character->getPosition(); auto player = character->getPosition();
@ -65,7 +66,7 @@ bool game_player_in_area_2d(const ScriptArguments& args)
bool game_player_in_area_3d(const ScriptArguments& args) bool game_player_in_area_3d(const ScriptArguments& args)
{ {
auto character = args.getGameObject(0); auto character = args.getPlayer(0);
glm::vec3 min(args[1].real, args[2].real, args[3].real); glm::vec3 min(args[1].real, args[2].real, args[3].real);
glm::vec3 max(args[4].real, args[5].real, args[6].real); glm::vec3 max(args[4].real, args[5].real, args[6].real);
auto player = character->getPosition(); auto player = character->getPosition();
@ -95,13 +96,11 @@ void game_create_character(const ScriptArguments& args)
// If there is already a chracter less than this distance away, it will be destroyed. // If there is already a chracter less than this distance away, it will be destroyed.
const float replaceThreshold = 2.f; const float replaceThreshold = 2.f;
for( auto it = args.getWorld()->objects.begin(); for(auto& p : args.getWorld()->pedestrianPool.objects)
it != args.getWorld()->objects.end();
++it)
{ {
if( it->second->type() == GameObject::Character && glm::distance(position, it->second->getPosition()) < replaceThreshold ) if( glm::distance(position, p.second->getPosition()) < replaceThreshold )
{ {
args.getWorld()->destroyObjectQueued(it->second); args.getWorld()->destroyObjectQueued(p.second);
} }
} }
@ -116,16 +115,6 @@ void game_create_character(const ScriptArguments& args)
*args[5].globalInteger = character->getGameObjectID(); *args[5].globalInteger = character->getGameObjectID();
} }
void game_destroy_character(const ScriptArguments& args)
{
auto character = args.getGameObject(0);
if ( character )
{
args.getWorld()->destroyObjectQueued(character);
}
}
void game_create_vehicle(const ScriptArguments& args) void game_create_vehicle(const ScriptArguments& args)
{ {
auto id = args[0].integer; auto id = args[0].integer;
@ -134,13 +123,11 @@ void game_create_vehicle(const ScriptArguments& args)
// If there is already a vehicle less than this distance away, it will be destroyed. // If there is already a vehicle less than this distance away, it will be destroyed.
const float replaceThreshold = 1.f; const float replaceThreshold = 1.f;
for( auto it = args.getWorld()->objects.begin(); for(auto& p : args.getWorld()->vehiclePool.objects)
it != args.getWorld()->objects.end();
++it)
{ {
if( it->second->type() == GameObject::Vehicle && glm::distance(position, it->second->getPosition()) < replaceThreshold ) if( glm::distance(position, p.second->getPosition()) < replaceThreshold )
{ {
args.getWorld()->destroyObjectQueued(it->second); args.getWorld()->destroyObjectQueued(p.second);
} }
} }
@ -154,16 +141,9 @@ void game_create_vehicle(const ScriptArguments& args)
*args[4].globalInteger = vehicle->getGameObjectID(); *args[4].globalInteger = vehicle->getGameObjectID();
} }
void game_destroy_vehicle(const ScriptArguments& args)
{
auto vehicle = args.getGameObject(0);
args.getWorld()->destroyObjectQueued(vehicle);
}
void game_get_vehicle_position(const ScriptArguments& args) void game_get_vehicle_position(const ScriptArguments& args)
{ {
auto vehicle = args.getGameObject(0); auto vehicle = args.getObject<VehicleObject>(0);
if( vehicle ) if( vehicle )
{ {
@ -176,14 +156,14 @@ void game_get_vehicle_position(const ScriptArguments& args)
void game_get_character_vehicle(const ScriptArguments& args) void game_get_character_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
*args[1].globalInteger = character->getCurrentVehicle()->getGameObjectID(); *args[1].globalInteger = character->getCurrentVehicle()->getGameObjectID();
} }
bool game_character_in_vehicle(const ScriptArguments& args) bool game_character_in_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = args.getGameObject(1); auto vehicle = args.getObject<VehicleObject>(1);
if( character == nullptr || vehicle == nullptr ) if( character == nullptr || vehicle == nullptr )
{ {
@ -198,7 +178,7 @@ bool game_character_in_model(const ScriptArguments& args)
auto vdata = args.getWorld()->data->findObjectType<VehicleData>(args[1].integer); auto vdata = args.getWorld()->data->findObjectType<VehicleData>(args[1].integer);
if( vdata ) if( vdata )
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = character->getCurrentVehicle(); auto vehicle = character->getCurrentVehicle();
if ( vehicle ) { if ( vehicle ) {
@ -210,7 +190,7 @@ bool game_character_in_model(const ScriptArguments& args)
bool game_character_in_any_vehicle(const ScriptArguments& args) bool game_character_in_any_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = character->getCurrentVehicle(); auto vehicle = character->getCurrentVehicle();
return vehicle != nullptr; return vehicle != nullptr;
@ -218,7 +198,7 @@ bool game_character_in_any_vehicle(const ScriptArguments& args)
bool game_player_in_area_2d_in_vehicle(const ScriptArguments& args) bool game_player_in_area_2d_in_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getPlayer(0));
glm::vec2 position(args[1].real, args[2].real); glm::vec2 position(args[1].real, args[2].real);
glm::vec2 radius(args[3].real, args[4].real); glm::vec2 radius(args[3].real, args[4].real);
@ -248,7 +228,7 @@ bool game_player_in_area_2d_in_vehicle(const ScriptArguments& args)
bool game_character_near_point_on_foot_3D(const ScriptArguments& args) bool game_character_near_point_on_foot_3D(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec3 center(args[1].real, args[2].real, args[3].real); glm::vec3 center(args[1].real, args[2].real, args[3].real);
glm::vec3 size(args[4].real, args[5].real, args[6].real); glm::vec3 size(args[4].real, args[5].real, args[6].real);
bool drawCylinder = !!args[7].integer; bool drawCylinder = !!args[7].integer;
@ -270,7 +250,7 @@ bool game_character_near_point_on_foot_3D(const ScriptArguments& args)
bool game_character_near_point_in_vehicle(const ScriptArguments& args) bool game_character_near_point_in_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec3 center(args[1].real, args[2].real, args[3].real); glm::vec3 center(args[1].real, args[2].real, args[3].real);
glm::vec3 size(args[4].real, args[5].real, args[6].real); glm::vec3 size(args[4].real, args[5].real, args[6].real);
bool unkown = !!args[7].integer; bool unkown = !!args[7].integer;
@ -287,8 +267,8 @@ bool game_character_near_point_in_vehicle(const ScriptArguments& args)
bool game_character_near_character_2D(const ScriptArguments& args) bool game_character_near_character_2D(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto target = args.getGameObject(1); auto target = args.getObject<CharacterObject>(1);
glm::vec2 center(target->getPosition()); glm::vec2 center(target->getPosition());
glm::vec2 size(args[2].real, args[3].real); glm::vec2 size(args[2].real, args[3].real);
@ -303,8 +283,8 @@ bool game_character_near_character_2D(const ScriptArguments& args)
bool game_character_near_character_in_vehicle_2D(const ScriptArguments& args) bool game_character_near_character_in_vehicle_2D(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto target = args.getGameObject(1); auto target = args.getObject<CharacterObject>(1);
glm::vec2 center(target->getPosition()); glm::vec2 center(target->getPosition());
glm::vec2 size(args[2].real, args[3].real); glm::vec2 size(args[2].real, args[3].real);
bool unkown = !!args[4].integer; bool unkown = !!args[4].integer;
@ -321,7 +301,7 @@ bool game_character_near_character_in_vehicle_2D(const ScriptArguments& args)
bool game_character_near_point_on_foot_2D(const ScriptArguments& args) bool game_character_near_point_on_foot_2D(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec2 center(args[1].real, args[2].real); glm::vec2 center(args[1].real, args[2].real);
glm::vec2 size(args[3].real, args[4].real); glm::vec2 size(args[3].real, args[4].real);
bool unkown = !!args[5].integer; bool unkown = !!args[5].integer;
@ -338,7 +318,7 @@ bool game_character_near_point_on_foot_2D(const ScriptArguments& args)
bool game_character_dead(const ScriptArguments& args) bool game_character_dead(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if ( character ) if ( character )
{ {
@ -350,13 +330,13 @@ bool game_character_dead(const ScriptArguments& args)
bool game_vehicle_dead(const ScriptArguments& args) bool game_vehicle_dead(const ScriptArguments& args)
{ {
// TODO This won't work until vehicle destruction is finished // TODO This won't work until vehicle destruction is finished
auto vehicle = args.getGameObject(0); auto vehicle = args.getObject<VehicleObject>(0);
return vehicle == nullptr; return vehicle == nullptr;
} }
bool game_character_in_zone(const ScriptArguments& args) bool game_character_in_zone(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
std::string zname(args[1].string); std::string zname(args[1].string);
auto zfind = args.getWorld()->data->zones.find(zname); auto zfind = args.getWorld()->data->zones.find(zname);
@ -375,7 +355,7 @@ bool game_character_in_zone(const ScriptArguments& args)
void game_create_character_in_vehicle(const ScriptArguments& args) void game_create_character_in_vehicle(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
auto type = args[1].integer; auto type = args[1].integer;
auto id = args[2].integer; auto id = args[2].integer;
@ -388,38 +368,22 @@ void game_create_character_in_vehicle(const ScriptArguments& args)
*args[3].globalInteger = character->getGameObjectID(); *args[3].globalInteger = character->getGameObjectID();
} }
void game_set_character_heading(const ScriptArguments& args) void game_set_player_heading(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto object = args.getPlayer(0);
character->setHeading(args[1].real);
}
void game_get_character_heading(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
if ( character )
{
// TODO write this
*args[1].globalReal = 0.f;
}
}
void game_set_vehicle_heading(const ScriptArguments& args)
{
auto object = args.getGameObject(0);
object->setHeading(args[1].real); object->setHeading(args[1].real);
} }
template <class Tobject>
void game_set_object_heading(const ScriptArguments& args) void game_set_object_heading(const ScriptArguments& args)
{ {
auto object = args.getGameObject(0); auto object = args.getObject<Tobject>(0);
object->setHeading(args[1].real); object->setHeading(args[1].real);
} }
bool game_vehicle_stopped(const ScriptArguments& args) bool game_vehicle_stopped(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
if( vehicle ) if( vehicle )
{ {
@ -431,7 +395,7 @@ bool game_vehicle_stopped(const ScriptArguments& args)
/// Remove object from cleanup at end of missions. /// Remove object from cleanup at end of missions.
void game_dont_remove_object(const ScriptArguments& args) void game_dont_remove_object(const ScriptArguments& args)
{ {
auto object = args.getGameObject(0)->getGameObjectID(); auto object = args.getObject<VehicleObject>(0)->getGameObjectID();
auto& mO = args.getState()->missionObjects; auto& mO = args.getState()->missionObjects;
mO.erase(std::remove(mO.begin(), mO.end(), object), mO.end()); mO.erase(std::remove(mO.begin(), mO.end(), object), mO.end());
@ -445,7 +409,7 @@ bool game_character_in_area_on_foot(const ScriptArguments& args)
bool game_character_stoped_in_volume_in_vehicle(const ScriptArguments& args) bool game_character_stoped_in_volume_in_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
bool drawCylinder = !!args[7].integer; bool drawCylinder = !!args[7].integer;
if( character && character->getCurrentVehicle() != nullptr ) if( character && character->getCurrentVehicle() != nullptr )
@ -475,7 +439,7 @@ bool game_character_stoped_in_volume_in_vehicle(const ScriptArguments& args)
bool game_character_stoped_in_volume(const ScriptArguments& args) bool game_character_stoped_in_volume(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec3 vec1(args[1].real, args[2].real, args[3].real); glm::vec3 vec1(args[1].real, args[2].real, args[3].real);
glm::vec3 vec2(args[4].real, args[5].real, args[6].real); glm::vec3 vec2(args[4].real, args[5].real, args[6].real);
@ -510,7 +474,7 @@ bool game_character_stoped_in_volume(const ScriptArguments& args)
bool game_is_character_stopped(const ScriptArguments& args) bool game_is_character_stopped(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if( character && character->getCurrentVehicle() != nullptr ) if( character && character->getCurrentVehicle() != nullptr )
{ {
@ -539,9 +503,8 @@ bool game_objects_in_volume(const ScriptArguments& args)
bool objects = args[9].integer; bool objects = args[9].integer;
bool particles = args[10].integer; bool particles = args[10].integer;
for(auto& pair : args.getWorld()->objects) for(auto& object : args.getWorld()->allObjects)
{ {
GameObject* object = pair.second;
switch( object->type() ) switch( object->type() )
{ {
case GameObject::Instance: case GameObject::Instance:
@ -571,15 +534,15 @@ bool game_objects_in_volume(const ScriptArguments& args)
bool game_player_in_taxi(const ScriptArguments& args) bool game_player_in_taxi(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getPlayer(0));
auto vehicle = character->getCurrentVehicle(); auto vehicle = character->getCurrentVehicle();
return vehicle && (vehicle->vehicle->classType & VehicleData::TAXI) == VehicleData::TAXI; return (vehicle && (vehicle->vehicle->classType & VehicleData::TAXI) == VehicleData::TAXI);
} }
void game_get_speed(const ScriptArguments& args) void game_get_speed(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
if( vehicle ) if( vehicle )
{ {
*args[1].globalReal = vehicle->physVehicle->getCurrentSpeedKmHour(); *args[1].globalReal = vehicle->physVehicle->getCurrentSpeedKmHour();
@ -588,8 +551,8 @@ void game_get_speed(const ScriptArguments& args)
void game_enter_as_driver(const ScriptArguments& args) void game_enter_as_driver(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
// Cancel whatever we're currently trying to do. // Cancel whatever we're currently trying to do.
character->controller->skipActivity(); character->controller->skipActivity();
character->controller->setNextActivity(new Activities::EnterVehicle(vehicle,0)); character->controller->setNextActivity(new Activities::EnterVehicle(vehicle,0));
@ -597,8 +560,8 @@ void game_enter_as_driver(const ScriptArguments& args)
void game_enter_as_passenger(const ScriptArguments& args) void game_enter_as_passenger(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
// Cancel whatever we're currently trying to do. // Cancel whatever we're currently trying to do.
character->controller->skipActivity(); character->controller->skipActivity();
@ -608,8 +571,8 @@ void game_enter_as_passenger(const ScriptArguments& args)
void game_character_exit_vehicle(const ScriptArguments& args) void game_character_exit_vehicle(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
auto cvehcile = character->getCurrentVehicle(); auto cvehcile = character->getCurrentVehicle();
if( cvehcile && cvehcile == vehicle ) if( cvehcile && cvehcile == vehicle )
@ -620,8 +583,8 @@ void game_character_exit_vehicle(const ScriptArguments& args)
void game_character_follow_character(const ScriptArguments& args) void game_character_follow_character(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto leader = static_cast<CharacterObject*>(args.getGameObject(1)); auto leader = static_cast<CharacterObject*>(args.getObject<CharacterObject>(1));
character->controller->setGoal(CharacterController::FollowLeader); character->controller->setGoal(CharacterController::FollowLeader);
character->controller->setTargetCharacter(leader); character->controller->setTargetCharacter(leader);
@ -629,7 +592,7 @@ void game_character_follow_character(const ScriptArguments& args)
void game_navigate_on_foot(const ScriptArguments& args) void game_navigate_on_foot(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec3 target(args[1].real, args[2].real, 0.f); glm::vec3 target(args[1].real, args[2].real, 0.f);
target = args.getWorld()->getGroundAtPosition(target); target = args.getWorld()->getGroundAtPosition(target);
@ -684,14 +647,14 @@ void game_create_pickup(const ScriptArguments& args)
auto pickup = new GenericPickup(args.getWorld(), pos, id, type); auto pickup = new GenericPickup(args.getWorld(), pos, id, type);
args.getWorld()->insertObject( pickup ); args.getWorld()->pickupPool.insert( pickup );
*args[5].globalInteger = pickup->getGameObjectID(); *args[5].globalInteger = pickup->getGameObjectID();
} }
bool game_is_pickup_collected(const ScriptArguments& args) bool game_is_pickup_collected(const ScriptArguments& args)
{ {
PickupObject* pickup = static_cast<PickupObject*>(args.getGameObject(0)); PickupObject* pickup = static_cast<PickupObject*>(args.getObject<PickupObject>(0));
if ( pickup ) if ( pickup )
{ {
@ -703,7 +666,7 @@ bool game_is_pickup_collected(const ScriptArguments& args)
void game_destroy_pickup(const ScriptArguments& args) void game_destroy_pickup(const ScriptArguments& args)
{ {
PickupObject* pickup = static_cast<PickupObject*>(args.getGameObject(0)); PickupObject* pickup = static_cast<PickupObject*>(args.getObject<PickupObject>(0));
if ( pickup ) if ( pickup )
{ {
@ -713,7 +676,7 @@ void game_destroy_pickup(const ScriptArguments& args)
void game_character_run_to(const ScriptArguments& args) void game_character_run_to(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
glm::vec3 target(args[1].real, args[2].real, 0.f); glm::vec3 target(args[1].real, args[2].real, 0.f);
target = args.getWorld()->getGroundAtPosition(target); target = args.getWorld()->getGroundAtPosition(target);
@ -722,7 +685,7 @@ void game_character_run_to(const ScriptArguments& args)
bool game_vehicle_flipped(const ScriptArguments& args) bool game_vehicle_flipped(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
if( vehicle ) if( vehicle )
{ {
@ -735,14 +698,14 @@ bool game_vehicle_flipped(const ScriptArguments& args)
bool game_vehicle_in_air(const ScriptArguments& args) bool game_vehicle_in_air(const ScriptArguments& args)
{ {
/// @todo IS vehicle in air. /// @todo IS vehicle in air.
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
return false; return false;
} }
bool game_character_near_car_2d(const ScriptArguments& args) bool game_character_near_car_2d(const ScriptArguments& args)
{ {
auto character = static_cast<CharacterObject*>(args.getGameObject(0)); auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
glm::vec2 radius(args[2].real, args[3].real); glm::vec2 radius(args[2].real, args[3].real);
bool drawMarker = !!args[4].integer; bool drawMarker = !!args[4].integer;
@ -759,7 +722,7 @@ bool game_character_near_car_2d(const ScriptArguments& args)
void game_set_vehicle_colours(const ScriptArguments& args) void game_set_vehicle_colours(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
auto& colours = args.getWorld()->data->vehicleColours; auto& colours = args.getWorld()->data->vehicleColours;
vehicle->colourPrimary = colours[args[1].integer]; vehicle->colourPrimary = colours[args[1].integer];
@ -793,9 +756,10 @@ void game_create_object_world(const ScriptArguments& args)
*args[4].globalInteger = inst->getGameObjectID(); *args[4].globalInteger = inst->getGameObjectID();
} }
template <class Tobject>
void game_destroy_object(const ScriptArguments& args) void game_destroy_object(const ScriptArguments& args)
{ {
auto object = args.getGameObject(0); auto object = args.getObject<Tobject>(0);
args.getWorld()->destroyObjectQueued(object); args.getWorld()->destroyObjectQueued(object);
} }
@ -844,15 +808,13 @@ void game_set_close_object_visible(const ScriptArguments& args)
std::transform(model.begin(), model.end(), model.begin(), ::tolower); std::transform(model.begin(), model.end(), model.begin(), ::tolower);
for(auto& p : args.getWorld()->objects) { for(auto& p : args.getWorld()->instancePool.objects) {
auto o = p.second; auto o = p.second;
if( o->type() == GameObject::Instance ) { if( !o->model ) continue;
if( !o->model ) continue; if( o->model->name != model ) continue;
if( o->model->name != model ) continue; float d = glm::distance(position, o->getPosition());
float d = glm::distance(position, o->getPosition()); if( d < radius ) {
if( d < radius ) { o->visible = !!args[5].integer;
o->visible = !!args[5].integer;
}
} }
} }
} }
@ -902,25 +864,23 @@ void game_change_nearest_model(const ScriptArguments& args)
auto nobj = args.getWorld()->data->findObjectType<ObjectData>(newobjectid); auto nobj = args.getWorld()->data->findObjectType<ObjectData>(newobjectid);
/// @todo Objects need to adopt the new object ID, not just the model. /// @todo Objects need to adopt the new object ID, not just the model.
for(auto p : args.getWorld()->objects) { for(auto p : args.getWorld()->instancePool.objects) {
auto o = p.second; auto o = p.second;
if( o->type() == GameObject::Instance ) { if( !o->model ) continue;
if( !o->model ) continue; if( o->model->name != oldmodel ) continue;
if( o->model->name != oldmodel ) continue; float d = glm::distance(position, o->getPosition());
float d = glm::distance(position, o->getPosition()); if( d < radius ) {
if( d < radius ) { args.getWorld()->data->loadDFF(newmodel + ".dff", false);
args.getWorld()->data->loadDFF(newmodel + ".dff", false); InstanceObject* inst = static_cast<InstanceObject*>(o);
InstanceObject* inst = static_cast<InstanceObject*>(o); inst->changeModel(nobj);
inst->changeModel(nobj); inst->model = args.getWorld()->data->models[newmodel];
inst->model = args.getWorld()->data->models[newmodel];
}
} }
} }
} }
bool game_rotate_object(const ScriptArguments& args) bool game_rotate_object(const ScriptArguments& args)
{ {
auto object = args.getGameObject(0); auto object = args.getObject<InstanceObject>(0);
if( object ) if( object )
{ {
float start = args[2].real; float start = args[2].real;
@ -935,7 +895,7 @@ bool game_rotate_object(const ScriptArguments& args)
void game_get_vehicle_colours(const ScriptArguments& args) void game_get_vehicle_colours(const ScriptArguments& args)
{ {
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0)); auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
if ( vehicle ) if ( vehicle )
{ {
@ -951,19 +911,19 @@ ObjectModule::ObjectModule()
{ {
bindFunction(0x0053, game_create_player, 5, "Create Player" ); bindFunction(0x0053, game_create_player, 5, "Create Player" );
bindFunction(0x0055, game_set_character_position, 4, "Set Player Position" ); bindFunction(0x0055, game_set_object_position<CharacterObject>, 4, "Set Player Position" );
bindFunction(0x0056, game_player_in_area_2d, 6, "Is Player In Area 2D" ); bindFunction(0x0056, game_player_in_area_2d, 6, "Is Player In Area 2D" );
bindFunction(0x0057, game_player_in_area_3d, 8, "Is Player In Area 3D" ); bindFunction(0x0057, game_player_in_area_3d, 8, "Is Player In Area 3D" );
bindFunction(0x009A, game_create_character, 6, "Create Character" ); bindFunction(0x009A, game_create_character, 6, "Create Character" );
bindFunction(0x009B, game_destroy_character, 1, "Destroy Character" ); bindFunction(0x009B, game_destroy_object<CharacterObject>, 1, "Destroy Character" );
bindUnimplemented( 0x009F, game_character_make_idle, 1, "Set Character to Idle" ); bindUnimplemented( 0x009F, game_character_make_idle, 1, "Set Character to Idle" );
bindFunction(0x00A1, game_set_character_position, 4, "Set Character Position" ); bindFunction(0x00A1, game_set_object_position<CharacterObject>, 4, "Set Character Position" );
bindFunction(0x00A5, game_create_vehicle, 5, "Create Vehicle" ); bindFunction(0x00A5, game_create_vehicle, 5, "Create Vehicle" );
bindFunction(0x00A6, game_destroy_vehicle, 1, "Destroy Vehicle" ); bindFunction(0x00A6, game_destroy_object<VehicleObject>, 1, "Destroy Vehicle" );
bindFunction(0x00AA, game_get_vehicle_position, 4, "Get Vehicle Position" ); bindFunction(0x00AA, game_get_vehicle_position, 4, "Get Vehicle Position" );
@ -992,7 +952,7 @@ ObjectModule::ObjectModule()
bindFunction(0x0100, game_character_near_point_in_vehicle, 8, "Is Character near point in car" ); bindFunction(0x0100, game_character_near_point_in_vehicle, 8, "Is Character near point in car" );
bindFunction(0x0108, game_destroy_object, 1, "Destroy Object" ); bindFunction(0x0108, game_destroy_object<InstanceObject>, 1, "Destroy Object" );
bindFunction(0x0118, game_character_dead, 1, "Is Character Dead" ); bindFunction(0x0118, game_character_dead, 1, "Is Character Dead" );
bindFunction(0x0119, game_vehicle_dead, 1, "Is Vehicle Dead" ); bindFunction(0x0119, game_vehicle_dead, 1, "Is Vehicle Dead" );
@ -1005,14 +965,13 @@ ObjectModule::ObjectModule()
bindUnimplemented(0x0135, game_set_vehicle_locked, 2, "Set Vehicle locked state"); bindUnimplemented(0x0135, game_set_vehicle_locked, 2, "Set Vehicle locked state");
bindFunction(0x0171, game_set_character_heading, 2, "Set Player Heading" ); bindFunction(0x0171, game_set_player_heading, 2, "Set Player Heading" );
bindFunction(0x0173, game_set_character_heading, 2, "Set Character Heading" ); bindFunction(0x0173, game_set_object_heading<CharacterObject>, 2, "Set Character Heading" );
bindFunction(0x0174, game_get_character_heading, 2, "Get Vehicle Heading" ); bindUnimplemented(0x0174, game_get_character_heading, 2, "Get Vehicle Heading" );
bindFunction(0x0175, game_set_object_heading<VehicleObject>, 2, "Set Vehicle heading" );
bindFunction(0x0175, game_set_vehicle_heading, 2, "Set Vehicle heading" ); bindFunction(0x0177, game_set_object_heading<InstanceObject>, 2, "Set Object heading" );
bindFunction(0x0177, game_set_object_heading, 2, "Set Object heading" );
bindUnimplemented( 0x0192, game_character_stand_still, 1, "Make character stand still" ); bindUnimplemented( 0x0192, game_character_stand_still, 1, "Make character stand still" );

View File

@ -161,7 +161,7 @@ void vm_mission_over(const ScriptArguments& args)
{ {
for( auto oid : args.getState()->missionObjects ) for( auto oid : args.getState()->missionObjects )
{ {
auto obj = args.getWorld()->findObject(oid); auto obj = args.getWorld()->vehiclePool.find(oid);
if( obj ) if( obj )
{ {
args.getWorld()->destroyObjectQueued(obj); args.getWorld()->destroyObjectQueued(obj);

View File

@ -175,13 +175,7 @@ void RWGame::newGame()
void RWGame::saveGame(const std::string& savename) void RWGame::saveGame(const std::string& savename)
{ {
// Save games without a script don't make much sense at the moment
if( script )
{
SaveGame::writeScript(*script, savename+".script");
SaveGame::writeState(*state, savename+".state");
SaveGame::writeObjects(*world, savename+".world");
}
} }
void RWGame::loadGame(const std::string& savename) void RWGame::loadGame(const std::string& savename)
@ -246,7 +240,7 @@ void RWGame::startScript(const std::string& name)
PlayerController *RWGame::getPlayer() PlayerController *RWGame::getPlayer()
{ {
auto object = world->findObject(state->playerObject); auto object = world->pedestrianPool.find(state->playerObject);
if( object ) if( object )
{ {
auto controller = static_cast<CharacterObject*>(object)->controller; auto controller = static_cast<CharacterObject*>(object)->controller;
@ -364,8 +358,7 @@ void RWGame::tick(float dt)
} }
} }
for( auto& p : world->objects ) { for( auto& object : world->allObjects ) {
GameObject* object = p.second;
object->_updateLastTransform(); object->_updateLastTransform();
object->tick(dt); object->tick(dt);
} }
@ -553,9 +546,8 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
// Count the number of interesting objects. // Count the number of interesting objects.
int peds = 0, cars = 0; int peds = 0, cars = 0;
for( auto& p : world->objects ) for( auto& object : world->allObjects )
{ {
GameObject* object = p.second;
switch ( object->type() ) switch ( object->type() )
{ {
case GameObject::Character: peds++; break; case GameObject::Character: peds++; break;
@ -568,7 +560,7 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
if( state->playerObject ) { if( state->playerObject ) {
ss << "Player (" << state->playerObject << ")\n"; ss << "Player (" << state->playerObject << ")\n";
auto object = world->findObject(state->playerObject); auto object = world->pedestrianPool.find(state->playerObject);
auto player = static_cast<CharacterObject*>(object)->controller; auto player = static_cast<CharacterObject*>(object)->controller;
ss << "Player Activity: "; ss << "Player Activity: ";
if( player->getCurrentActivity() ) { if( player->getCurrentActivity() ) {

View File

@ -37,7 +37,7 @@ void IngameState::startTest()
glm::vec3 itemspawn( 276.5f, -609.f, 36.5f); glm::vec3 itemspawn( 276.5f, -609.f, 36.5f);
for( auto& w : getWorld()->data->weaponData ) { for( auto& w : getWorld()->data->weaponData ) {
if( w->name == "unarmed" ) continue; if( w->name == "unarmed" ) continue;
getWorld()->insertObject(new ItemPickup(getWorld(), itemspawn, getWorld()->pickupPool.insert(new ItemPickup(getWorld(), itemspawn,
w)); w));
itemspawn.x += 2.5f; itemspawn.x += 2.5f;
} }
@ -134,7 +134,7 @@ void IngameState::tick(float dt)
viewDistance = 4.f; viewDistance = 4.f;
} }
auto target = getWorld()->findObject(getWorld()->state->cameraTarget); auto target = getWorld()->pedestrianPool.find(getWorld()->state->cameraTarget);
if( target == nullptr ) if( target == nullptr )
{ {