1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 15:02:34 +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
{
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)
{ }
};

View File

@ -2,6 +2,7 @@
#ifndef _GAMEWORLD_HPP_
#define _GAMEWORLD_HPP_
class PlayerController;
class Logger;
#include <GL/glew.h>
@ -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<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

View File

@ -46,21 +46,6 @@ public:
* Returns save game information for all found saves
*/
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

View File

@ -7,6 +7,11 @@
#include <vector>
#include <functional>
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 <class T>
GameObject* getObject(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<bool (const ScriptArguments&)> ScriptFunctionBoolean;
typedef uint16_t ScriptFunctionID;

View File

@ -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<VehicleObject*>(object);
}
float vd = glm::length( character->getPosition() - object->getPosition());
if( vd < d ) {
d = vd;
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(); )
{
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<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;

View File

@ -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<InstanceObject*>(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<InstanceObject*>(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<GameWorld*>(physWorld->getWorldUserInfo());
for( auto& p : world->objects ) {
for( auto& p : world->vehiclePool.objects ) {
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()
{
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 )

View File

@ -10,323 +10,7 @@
#include <script/SCMFile.hpp>
#include <ai/PlayerController.hpp>
#include <items/WeaponItem.hpp>
#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;
}
#include <cstring>
// Original save game file data structures
typedef uint16_t BlockWord;
@ -402,7 +86,7 @@ struct Block0RunningScript {
BlockDword unknown1;
BlockWord stackCounter;
BlockWord unknown2;
BlockDword scriptVariables[16];
SCMByte variables[16*4];
BlockDword timerA;
BlockDword timerB;
uint8_t ifFlag;
@ -628,8 +312,8 @@ void SaveGame::writeGame(GameState& state, const std::string& file)
script.stack[i] = thread.calls[i];
}
script.stackCounter = thread.stackDepth;
for(int i = 0; i < 16; i++) {
script.scriptVariables[i] = *(((BlockDword*)thread.locals.data())+i);
for(int i = 0; i < sizeof(Block0RunningScript::variables); i++) {
script.variables[i] = thread.locals[i];
}
script.timerA = *(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.currentWeather = block0Data.nextWeather;
state.cameraPosition = block0Data.cameraPosition;
std::cout << scriptVars << " / " << state.script->getFile()->getGlobalsSize() << std::endl;
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;
@ -742,10 +426,14 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
}
/* TODO not hardcode +33 ms */
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 ) {
auto& ply = players[0];
std::cout << ply.reference << std::endl;
auto player = state.world->createPlayer(players[0].info.position);
player->mHealth = players[0].info.health;
state.playerObject = player->getGameObjectID();
@ -774,15 +462,13 @@ bool SaveGame::loadGame(GameState& state, const std::string& file)
// Find the nearest dynamic instance?
float distance = std::numeric_limits<float>::max();
GameObject* nearinst = nullptr;
for(std::pair<GameObjectID, GameObject*> object : state.world->objects) {
if( object.second->type() == GameObject::Instance ) {
auto instance = static_cast<InstanceObject*>(object.second);
if( instance->dynamics ) {
float idist = glm::distance(center, instance->getPosition());
if( idist < distance ) {
distance = idist;
nearinst = instance;
}
for(std::pair<GameObjectID, GameObject*> object : state.world->instancePool.objects) {
auto instance = static_cast<InstanceObject*>(object.second);
if( instance->dynamics ) {
float idist = glm::distance(center, instance->getPosition());
if( idist < distance ) {
distance = idist;
nearinst = instance;
}
}
}

View File

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

View File

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

View File

@ -297,8 +297,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
renderer->pushDebugGroup("Objects");
renderer->pushDebugGroup("Dynamic");
for( auto& p : world->objects ) {
auto object = p.second;
for( auto& object : world->allObjects ) {
if(! object->visible )
{
continue;
@ -390,11 +389,13 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
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 )
{
model = object->getTimeAdjustedTransform( _renderAlpha );
}
}*/
}
else
{
@ -475,7 +476,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
}
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);
glUniform2f(ssRectOffset, 0.f, 0.f);
glUniform2f(ssRectSize, 1.f, 1.f);
@ -503,7 +504,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
glBindVertexArray( ssRectDraw.getVAOName() );
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}*/
if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) {
renderLetterbox();

View File

@ -151,7 +151,19 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
glm::vec2 blippos( blip.second.coord );
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 )
{
blippos = glm::vec2( object->getPosition() );
@ -162,7 +174,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
}
// Draw the player blip
auto player = world->findObject(world->state->playerObject);
auto player = world->pedestrianPool.find(world->state->playerObject);
if( player )
{
glm::vec2 plyblip(player->getPosition());

View File

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

View File

@ -2,6 +2,8 @@
#include <script/ScriptMachine.hpp>
#include <engine/GameState.hpp>
#include <engine/GameWorld.hpp>
#include <objects/CharacterObject.hpp>
#include <ai/PlayerController.hpp>
GameState* ScriptArguments::getState() const
{
@ -13,9 +15,46 @@ GameWorld* ScriptArguments::getWorld() const
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 it = getWorld()->objects.find( gameObjectID );
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if( character != nullptr )
{
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;
}
void game_add_vehicle_blip(const ScriptArguments& args)
template <class Tobject>
void game_add_object_blip(const ScriptArguments& args)
{
BlipData data;
data.target = args.getGameObject(0)->getGameObjectID();
data.target = args.getObject<Tobject>(0)->getGameObjectID();
data.texture = "";
*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)
{
BlipData data;
@ -311,8 +295,8 @@ void game_change_blip_mode(const ScriptArguments& args)
void game_enable_input(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
static_cast<PlayerController*>(character->controller)->setInputEnabled(!!args[1].integer);
auto player = static_cast<CharacterObject*>(args.getPlayer(0));
static_cast<PlayerController*>(player->controller)->setInputEnabled(!!args[1].integer);
}
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;
}
// This does nothing for us.
void game_get_player(const ScriptArguments& args)
{
auto character = args.getGameObject(0);
auto character = args.getPlayer(0);
*args[1].globalInteger = character->getGameObjectID();
}
@ -444,7 +427,7 @@ void game_restart_critical_mission(const ScriptArguments& args)
// Reset player state.
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);
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)
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 args.getWorld()->findObject(args.getState()->playerObject) != nullptr;
}
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)
{
GameObject* object = args.getGameObject(0);
GameObject* object = args.getObject<CutsceneObject>(0);
std::string animName = args[1].string;
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
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)
{
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 );
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)
{
GameObject* object = args.getGameObject(0);
GameObject* object = args.getObject<CutsceneObject>(0);
std::string animName = args[1].string;
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
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)
{
auto character = args.getGameObject(0);
auto character = args.getObject<CharacterObject>(0);
if( character )
{
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)
{
*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( 0x0182, game_unknown, 2, "Unknown Character Opcode" );
bindFunction(0x0186, game_add_vehicle_blip, 2, "Add Blip for Vehicle");
bindFunction(0x0187, game_add_character_blip, 2, "Add Blip for Character");
bindFunction(0x0186, game_add_object_blip<VehicleObject>, 2, "Add Blip for Vehicle");
bindFunction(0x0187, game_add_object_blip<CharacterObject>, 2, "Add Blip for Character");
bindFunction(0x018A, game_add_location_blip, 4, "Add Blip for Coord");
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" );
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" );
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" );

View File

@ -44,16 +44,17 @@ void game_create_player(const ScriptArguments& args)
*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);
character->setPosition(position + spawnMagic);
}
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 max(args[3].real, args[4].real);
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)
{
auto character = args.getGameObject(0);
auto character = args.getPlayer(0);
glm::vec3 min(args[1].real, args[2].real, args[3].real);
glm::vec3 max(args[4].real, args[5].real, args[6].real);
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.
const float replaceThreshold = 2.f;
for( auto it = args.getWorld()->objects.begin();
it != args.getWorld()->objects.end();
++it)
for(auto& p : args.getWorld()->pedestrianPool.objects)
{
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();
}
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)
{
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.
const float replaceThreshold = 1.f;
for( auto it = args.getWorld()->objects.begin();
it != args.getWorld()->objects.end();
++it)
for(auto& p : args.getWorld()->vehiclePool.objects)
{
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();
}
void game_destroy_vehicle(const ScriptArguments& args)
{
auto vehicle = args.getGameObject(0);
args.getWorld()->destroyObjectQueued(vehicle);
}
void game_get_vehicle_position(const ScriptArguments& args)
{
auto vehicle = args.getGameObject(0);
auto vehicle = args.getObject<VehicleObject>(0);
if( vehicle )
{
@ -176,14 +156,14 @@ void game_get_vehicle_position(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();
}
bool game_character_in_vehicle(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto vehicle = args.getGameObject(1);
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = args.getObject<VehicleObject>(1);
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);
if( vdata )
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = character->getCurrentVehicle();
if ( vehicle ) {
@ -210,7 +190,7 @@ bool game_character_in_model(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();
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)
{
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 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)
{
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 size(args[4].real, args[5].real, args[6].real);
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)
{
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 size(args[4].real, args[5].real, args[6].real);
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto target = args.getGameObject(1);
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto target = args.getObject<CharacterObject>(1);
glm::vec2 center(target->getPosition());
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto target = args.getGameObject(1);
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto target = args.getObject<CharacterObject>(1);
glm::vec2 center(target->getPosition());
glm::vec2 size(args[2].real, args[3].real);
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)
{
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 size(args[3].real, args[4].real);
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if ( character )
{
@ -350,13 +330,13 @@ bool game_character_dead(const ScriptArguments& args)
bool game_vehicle_dead(const ScriptArguments& args)
{
// TODO This won't work until vehicle destruction is finished
auto vehicle = args.getGameObject(0);
auto vehicle = args.getObject<VehicleObject>(0);
return vehicle == nullptr;
}
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);
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)
{
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
auto type = args[1].integer;
auto id = args[2].integer;
@ -388,38 +368,22 @@ void game_create_character_in_vehicle(const ScriptArguments& args)
*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));
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);
auto object = args.getPlayer(0);
object->setHeading(args[1].real);
}
template <class Tobject>
void game_set_object_heading(const ScriptArguments& args)
{
auto object = args.getGameObject(0);
auto object = args.getObject<Tobject>(0);
object->setHeading(args[1].real);
}
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 )
{
@ -431,7 +395,7 @@ bool game_vehicle_stopped(const ScriptArguments& args)
/// Remove object from cleanup at end of missions.
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;
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
bool drawCylinder = !!args[7].integer;
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)
{
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 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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
if( character && character->getCurrentVehicle() != nullptr )
{
@ -539,9 +503,8 @@ bool game_objects_in_volume(const ScriptArguments& args)
bool objects = args[9].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() )
{
case GameObject::Instance:
@ -571,15 +534,15 @@ bool game_objects_in_volume(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();
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)
{
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
if( vehicle )
{
*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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
// Cancel whatever we're currently trying to do.
character->controller->skipActivity();
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)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
// Cancel whatever we're currently trying to do.
character->controller->skipActivity();
@ -608,8 +571,8 @@ void game_enter_as_passenger(const ScriptArguments& args)
void game_character_exit_vehicle(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
auto cvehcile = character->getCurrentVehicle();
if( cvehcile && cvehcile == vehicle )
@ -620,8 +583,8 @@ void game_character_exit_vehicle(const ScriptArguments& args)
void game_character_follow_character(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto leader = static_cast<CharacterObject*>(args.getGameObject(1));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto leader = static_cast<CharacterObject*>(args.getObject<CharacterObject>(1));
character->controller->setGoal(CharacterController::FollowLeader);
character->controller->setTargetCharacter(leader);
@ -629,7 +592,7 @@ void game_character_follow_character(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);
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);
args.getWorld()->insertObject( pickup );
args.getWorld()->pickupPool.insert( pickup );
*args[5].globalInteger = pickup->getGameObjectID();
}
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 )
{
@ -703,7 +666,7 @@ bool game_is_pickup_collected(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 )
{
@ -713,7 +676,7 @@ void game_destroy_pickup(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);
target = args.getWorld()->getGroundAtPosition(target);
@ -722,7 +685,7 @@ void game_character_run_to(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 )
{
@ -735,14 +698,14 @@ bool game_vehicle_flipped(const ScriptArguments& args)
bool game_vehicle_in_air(const ScriptArguments& args)
{
/// @todo IS vehicle in air.
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
return false;
}
bool game_character_near_car_2d(const ScriptArguments& args)
{
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
auto character = static_cast<CharacterObject*>(args.getObject<CharacterObject>(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(1));
glm::vec2 radius(args[2].real, args[3].real);
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)
{
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
auto vehicle = static_cast<VehicleObject*>(args.getObject<VehicleObject>(0));
auto& colours = args.getWorld()->data->vehicleColours;
vehicle->colourPrimary = colours[args[1].integer];
@ -793,9 +756,10 @@ void game_create_object_world(const ScriptArguments& args)
*args[4].globalInteger = inst->getGameObjectID();
}
template <class Tobject>
void game_destroy_object(const ScriptArguments& args)
{
auto object = args.getGameObject(0);
auto object = args.getObject<Tobject>(0);
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);
for(auto& p : args.getWorld()->objects) {
for(auto& p : args.getWorld()->instancePool.objects) {
auto o = p.second;
if( o->type() == GameObject::Instance ) {
if( !o->model ) continue;
if( o->model->name != model ) continue;
float d = glm::distance(position, o->getPosition());
if( d < radius ) {
o->visible = !!args[5].integer;
}
if( !o->model ) continue;
if( o->model->name != model ) continue;
float d = glm::distance(position, o->getPosition());
if( d < radius ) {
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);
/// @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;
if( o->type() == GameObject::Instance ) {
if( !o->model ) continue;
if( o->model->name != oldmodel ) continue;
float d = glm::distance(position, o->getPosition());
if( d < radius ) {
args.getWorld()->data->loadDFF(newmodel + ".dff", false);
InstanceObject* inst = static_cast<InstanceObject*>(o);
inst->changeModel(nobj);
inst->model = args.getWorld()->data->models[newmodel];
}
if( !o->model ) continue;
if( o->model->name != oldmodel ) continue;
float d = glm::distance(position, o->getPosition());
if( d < radius ) {
args.getWorld()->data->loadDFF(newmodel + ".dff", false);
InstanceObject* inst = static_cast<InstanceObject*>(o);
inst->changeModel(nobj);
inst->model = args.getWorld()->data->models[newmodel];
}
}
}
bool game_rotate_object(const ScriptArguments& args)
{
auto object = args.getGameObject(0);
auto object = args.getObject<InstanceObject>(0);
if( object )
{
float start = args[2].real;
@ -935,7 +895,7 @@ bool game_rotate_object(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 )
{
@ -951,19 +911,19 @@ ObjectModule::ObjectModule()
{
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(0x0057, game_player_in_area_3d, 8, "Is Player In Area 3D" );
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" );
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(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" );
@ -992,7 +952,7 @@ ObjectModule::ObjectModule()
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(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");
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(0x0174, game_get_character_heading, 2, "Get Vehicle Heading" );
bindFunction(0x0173, game_set_object_heading<CharacterObject>, 2, "Set Character 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, 2, "Set Object heading" );
bindFunction(0x0177, game_set_object_heading<InstanceObject>, 2, "Set Object heading" );
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 )
{
auto obj = args.getWorld()->findObject(oid);
auto obj = args.getWorld()->vehiclePool.find(oid);
if( obj )
{
args.getWorld()->destroyObjectQueued(obj);

View File

@ -175,13 +175,7 @@ void RWGame::newGame()
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)
@ -246,7 +240,7 @@ void RWGame::startScript(const std::string& name)
PlayerController *RWGame::getPlayer()
{
auto object = world->findObject(state->playerObject);
auto object = world->pedestrianPool.find(state->playerObject);
if( object )
{
auto controller = static_cast<CharacterObject*>(object)->controller;
@ -364,8 +358,7 @@ void RWGame::tick(float dt)
}
}
for( auto& p : world->objects ) {
GameObject* object = p.second;
for( auto& object : world->allObjects ) {
object->_updateLastTransform();
object->tick(dt);
}
@ -553,9 +546,8 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
// Count the number of interesting objects.
int peds = 0, cars = 0;
for( auto& p : world->objects )
for( auto& object : world->allObjects )
{
GameObject* object = p.second;
switch ( object->type() )
{
case GameObject::Character: peds++; break;
@ -568,7 +560,7 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
if( state->playerObject ) {
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;
ss << "Player Activity: ";
if( player->getCurrentActivity() ) {

View File

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