mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-18 16:32:32 +02:00
Merge branch 'rwng-disassembly' into rwng
Conflicts: rwgame/RWGame.hpp rwgame/ingamestate.cpp
This commit is contained in:
commit
8b18712d1f
@ -5,7 +5,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
|
||||
#define ZONE_GANG_COUNT 11
|
||||
#define ZONE_GANG_COUNT 13
|
||||
|
||||
/**
|
||||
* \class Zone
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <objects/ObjectTypes.hpp>
|
||||
|
||||
class GameWorld;
|
||||
class GameObject;
|
||||
@ -73,7 +74,7 @@ struct VehicleGenerator
|
||||
struct BlipData
|
||||
{
|
||||
int id;
|
||||
GameObject* target;
|
||||
GameObjectID target;
|
||||
// If target is null then use coord
|
||||
glm::vec3 coord;
|
||||
|
||||
@ -91,7 +92,7 @@ struct BlipData
|
||||
DisplayMode display;
|
||||
|
||||
BlipData()
|
||||
: id(-1), target(nullptr), display(Show)
|
||||
: id(-1), target(0), display(Show)
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -101,6 +102,10 @@ struct BlipData
|
||||
*/
|
||||
struct GameState
|
||||
{
|
||||
/**
|
||||
* Second since game was started
|
||||
*/
|
||||
float gameTime;
|
||||
unsigned int currentProgress;
|
||||
unsigned int maxProgress;
|
||||
unsigned int numMissions;
|
||||
@ -109,7 +114,7 @@ struct GameState
|
||||
unsigned int numUniqueJumps;
|
||||
unsigned int numRampages;
|
||||
unsigned int maxWantedLevel;
|
||||
PlayerController* player;
|
||||
GameObjectID playerObject;
|
||||
|
||||
unsigned int currentWeather;
|
||||
|
||||
@ -119,7 +124,7 @@ struct GameState
|
||||
unsigned int *scriptOnMissionFlag;
|
||||
|
||||
/** Objects created by the current mission */
|
||||
std::vector<GameObject*> missionObjects;
|
||||
std::vector<GameObjectID> missionObjects;
|
||||
|
||||
bool overrideNextStart;
|
||||
glm::vec4 nextRestartLocation;
|
||||
@ -164,8 +169,8 @@ struct GameState
|
||||
bool cameraFixed;
|
||||
glm::vec3 cameraPosition;
|
||||
glm::quat cameraRotation;
|
||||
|
||||
GameObject* cameraTarget;
|
||||
|
||||
GameObjectID cameraTarget;
|
||||
|
||||
std::vector<VehicleGenerator> vehicleGenerators;
|
||||
|
||||
|
@ -15,6 +15,7 @@ class GameState;
|
||||
|
||||
class CutsceneObject;
|
||||
class WorkContext;
|
||||
#include <objects/ObjectTypes.hpp>
|
||||
|
||||
class GameObject;
|
||||
class CharacterObject;
|
||||
@ -33,7 +34,6 @@ struct WeaponScan;
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <random>
|
||||
#include <array>
|
||||
|
||||
@ -89,13 +89,28 @@ public:
|
||||
/**
|
||||
* Creates a vehicle
|
||||
*/
|
||||
VehicleObject *createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat());
|
||||
VehicleObject *createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
|
||||
|
||||
/**
|
||||
* Creates a pedestrian.
|
||||
*/
|
||||
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat());
|
||||
|
||||
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
|
||||
|
||||
/**
|
||||
* Creates a player
|
||||
*/
|
||||
CharacterObject* createPlayer(const glm::vec3& pos, const glm::quat& rot = glm::quat(), GameObjectID gid = 0);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@ -137,12 +152,9 @@ public:
|
||||
int getMinute();
|
||||
|
||||
glm::vec3 getGroundAtPosition(const glm::vec3& pos) const;
|
||||
|
||||
/**
|
||||
* Game Clock
|
||||
*/
|
||||
float gameTime;
|
||||
|
||||
|
||||
float getGameTime() const;
|
||||
|
||||
/**
|
||||
* Game data
|
||||
*/
|
||||
@ -159,11 +171,9 @@ public:
|
||||
SoundManager sound;
|
||||
|
||||
/**
|
||||
* @brief objects All active GameObjects in the world.
|
||||
* @todo add some mechanism to allow objects to be "locked" preventing deletion.
|
||||
* @todo add deletion queue to allow objects to self delete.
|
||||
* The active GameObjects within the world, mapped to their allocated ID
|
||||
*/
|
||||
std::set<GameObject*> objects;
|
||||
std::map<GameObjectID, GameObject*> objects;
|
||||
|
||||
std::set<GameObject*> characters;
|
||||
|
||||
@ -278,7 +288,7 @@ private:
|
||||
/**
|
||||
* @brief Used by objects to delete themselves during updates.
|
||||
*/
|
||||
std::queue<GameObject*> deletionQueue;
|
||||
std::set<GameObject*> deletionQueue;
|
||||
|
||||
std::vector<AreaIndicatorInfo> areaIndicators;
|
||||
|
||||
|
33
rwengine/include/engine/SaveGame.hpp
Normal file
33
rwengine/include/engine/SaveGame.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#ifndef _SAVEGAME_HPP_
|
||||
#define _SAVEGAME_HPP_
|
||||
|
||||
#include <engine/RWTypes.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
struct GameState;
|
||||
class GameWorld;
|
||||
class ScriptMachine;
|
||||
|
||||
/**
|
||||
* Reads and Writes GameStates to disk, restoring the required state information
|
||||
*/
|
||||
class SaveGame
|
||||
{
|
||||
public:
|
||||
|
||||
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
|
@ -3,6 +3,7 @@
|
||||
#define _GAMEOBJECT_HPP_
|
||||
|
||||
#include <engine/RWTypes.hpp>
|
||||
#include <objects/ObjectTypes.hpp>
|
||||
#include <loaders/LoaderIDE.hpp>
|
||||
#include <loaders/LoaderIPL.hpp>
|
||||
#include <render/Model.hpp>
|
||||
@ -27,7 +28,7 @@ class GameObject
|
||||
{
|
||||
glm::vec3 _lastPosition;
|
||||
glm::quat _lastRotation;
|
||||
|
||||
GameObjectID objectID;
|
||||
public:
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
@ -58,7 +59,7 @@ public:
|
||||
bool visible;
|
||||
|
||||
GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelRef model)
|
||||
: _lastPosition(pos), _lastRotation(rot), position(pos), rotation(rot),
|
||||
: _lastPosition(pos), _lastRotation(rot), objectID(0), position(pos), rotation(rot),
|
||||
model(model), engine(engine), animator(nullptr), skeleton(nullptr), mHealth(0.f),
|
||||
inWater(false), _lastHeight(std::numeric_limits<float>::max()), visible(true),
|
||||
lifetime(GameObject::UnknownLifetime)
|
||||
@ -66,6 +67,12 @@ public:
|
||||
|
||||
virtual ~GameObject();
|
||||
|
||||
GameObjectID getGameObjectID() const { return objectID; }
|
||||
/**
|
||||
* Do not call this, use GameWorld::insertObject
|
||||
*/
|
||||
void setGameObjectID(GameObjectID id) { objectID = id; }
|
||||
|
||||
/**
|
||||
* @brief Enumeration of possible object types.
|
||||
*/
|
||||
|
8
rwengine/include/objects/ObjectTypes.hpp
Normal file
8
rwengine/include/objects/ObjectTypes.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* all wordly GameObjects are associated with a 32-bit identifier
|
||||
*/
|
||||
typedef uint32_t GameObjectID;
|
45
rwengine/include/script/ScriptDisassembly.hpp
Normal file
45
rwengine/include/script/ScriptDisassembly.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#ifndef _SCRIPTDISASSEMBLY_HPP_
|
||||
#define _SCRIPTDISASSEMBLY_HPP_
|
||||
#include <script/ScriptTypes.hpp>
|
||||
|
||||
class SCMFile;
|
||||
|
||||
/**
|
||||
* Extracts instruction level information from a SCM file
|
||||
*/
|
||||
class ScriptDisassembly
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Information about a single call to a single opcode and
|
||||
* it's parameters
|
||||
*/
|
||||
struct InstructionInfo
|
||||
{
|
||||
SCMOpcode opcode;
|
||||
SCMParams parameters;
|
||||
};
|
||||
|
||||
ScriptDisassembly(SCMOpcodes* codes, SCMFile* scm);
|
||||
|
||||
/**
|
||||
* Execute the disassembly routine.
|
||||
*
|
||||
* If there is an error during disassembly, an exeption will be
|
||||
* thrown
|
||||
*/
|
||||
void disassemble(SCMAddress startAddress);
|
||||
|
||||
std::map<SCMAddress, InstructionInfo>& getInstructions() { return instructions; }
|
||||
|
||||
private:
|
||||
|
||||
SCMOpcodes* codes;
|
||||
SCMFile* scm;
|
||||
|
||||
std::map<SCMAddress, InstructionInfo> instructions;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <set>
|
||||
|
||||
@ -12,10 +13,11 @@
|
||||
#define SCM_CONDITIONAL_MASK_PASSED 0xFF
|
||||
#define SCM_THREAD_LOCAL_SIZE 256
|
||||
|
||||
/* as shipped, SCM variables are 4 bytes wide, this isn't enough for 64-bit
|
||||
* pointers, so we re-allocate the global and local space taking into account
|
||||
* the native pointer size */
|
||||
#define SCM_VARIABLE_SIZE sizeof(void*)
|
||||
/* Maxium size value that can be stored in each memory address.
|
||||
* Changing this will break saves.
|
||||
*/
|
||||
#define SCM_VARIABLE_SIZE 4
|
||||
#define SCM_STACK_DEPTH 32
|
||||
|
||||
class GameState;
|
||||
|
||||
@ -109,9 +111,9 @@ static SCMMicrocodeTable knownOps;
|
||||
|
||||
struct SCMThread
|
||||
{
|
||||
typedef unsigned int pc_t;
|
||||
typedef SCMAddress pc_t;
|
||||
|
||||
std::string name;
|
||||
char name[17];
|
||||
pc_t baseAddress;
|
||||
pc_t programCounter;
|
||||
|
||||
@ -122,13 +124,14 @@ struct SCMThread
|
||||
|
||||
/** Number of MS until the thread should be waked (-1 = yeilded) */
|
||||
int wakeCounter;
|
||||
SCMByte locals[SCM_THREAD_LOCAL_SIZE * (SCM_VARIABLE_SIZE)];
|
||||
std::array<SCMByte, SCM_THREAD_LOCAL_SIZE * (SCM_VARIABLE_SIZE)> locals;
|
||||
bool isMission;
|
||||
|
||||
bool finished;
|
||||
|
||||
unsigned int stackDepth;
|
||||
/// Stores the return-addresses for calls.
|
||||
std::stack<pc_t> calls;
|
||||
std::array<pc_t, SCM_STACK_DEPTH> calls;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -143,6 +146,26 @@ struct SCMBreakpoint
|
||||
ScriptArguments* args;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the actual fetch-execute mechanism for the game script virtual machine.
|
||||
*
|
||||
* The unit of functionality is an "instruction", which performs a particular
|
||||
* task such as creating a vehicle, retrieving an object's position or declaring
|
||||
* a new garage.
|
||||
*
|
||||
* The VM executes multiple pseudo-threads that execute in series. Each thread
|
||||
* is represented by SCMThread, which contains the program counter, stack information
|
||||
* the thread name and some thread-local variable space. At startup, a single
|
||||
* thread is created at address 0, which begins execution. From there, the script
|
||||
* may create additional threads.
|
||||
*
|
||||
* Within ScriptMachine, each thread's program counter is used to execute an instruction
|
||||
* by consuming the correct number of arguments, allowing the next instruction to be found,
|
||||
* and then dispatching a call to the opcode's function.
|
||||
*
|
||||
* Breakpoints can be set which will call the breakpoint hander, where it is possible
|
||||
* to halt execution by refusing to return until the handler is ready to continue.
|
||||
*/
|
||||
class ScriptMachine
|
||||
{
|
||||
public:
|
||||
@ -153,7 +176,10 @@ public:
|
||||
|
||||
void startThread(SCMThread::pc_t start, bool mission = false);
|
||||
|
||||
std::vector<SCMThread>& getThreads() { return _activeThreads; }
|
||||
|
||||
SCMByte* getGlobals();
|
||||
std::vector<SCMByte>& getGlobalData() { return globalData; }
|
||||
|
||||
GameState* getState() const { return state; }
|
||||
|
||||
@ -193,7 +219,7 @@ private:
|
||||
|
||||
void executeThread(SCMThread& t, int msPassed);
|
||||
|
||||
SCMByte* _globals;
|
||||
std::vector<SCMByte> globalData;
|
||||
|
||||
BreakpointHandler bpHandler;
|
||||
std::set<SCMThread::pc_t> breakpoints;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class GameObject;
|
||||
class ScriptMachine;
|
||||
class ScriptModule;
|
||||
struct SCMThread;
|
||||
@ -16,6 +17,7 @@ class GameWorld;
|
||||
|
||||
typedef uint16_t SCMOpcode;
|
||||
typedef char SCMByte;
|
||||
typedef unsigned int SCMAddress;
|
||||
|
||||
enum SCMType {
|
||||
EndOfArgList = 0x00,
|
||||
@ -48,17 +50,14 @@ static SCMTypeInfoTable typeData = {
|
||||
struct SCMOpcodeParameter {
|
||||
SCMType type;
|
||||
union {
|
||||
int integer;
|
||||
uint32_t integer;
|
||||
float real;
|
||||
char string[8];
|
||||
void* globalPtr;
|
||||
void** handle;
|
||||
int* globalInteger;
|
||||
uint32_t* globalInteger;
|
||||
float* globalReal;
|
||||
};
|
||||
|
||||
template<class T> T* handleOf() const { return static_cast<T*>(*handle); }
|
||||
|
||||
|
||||
int integerValue() const
|
||||
{
|
||||
if ( type == TGlobal )
|
||||
@ -95,6 +94,11 @@ public:
|
||||
{
|
||||
return parameters->at(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GameObject passed at the given argument index
|
||||
*/
|
||||
GameObject* getGameObject(unsigned int arg) const;
|
||||
};
|
||||
|
||||
typedef std::function<void (const ScriptArguments&)> ScriptFunction;
|
||||
|
@ -47,7 +47,8 @@ void PlayerController::enterNearestVehicle()
|
||||
auto world = character->engine;
|
||||
VehicleObject* nearest = nullptr; float d = 10.f;
|
||||
|
||||
for( GameObject* object : world->objects ) {
|
||||
for( auto& p : world->objects ) {
|
||||
auto object = p.second;
|
||||
if( object->type() == GameObject::Vehicle ) {
|
||||
float vd = glm::length( character->getPosition() - object->getPosition());
|
||||
if( vd < d ) {
|
||||
|
@ -106,6 +106,7 @@ void GameData::load()
|
||||
loadDFF("weapons.dff");
|
||||
loadDFF("arrow.dff");
|
||||
loadTXD("particle.txd");
|
||||
loadTXD("icons.txd");
|
||||
loadTXD("hud.txd");
|
||||
loadTXD("fonts.txd");
|
||||
|
||||
@ -593,7 +594,7 @@ int GameData::getWaterIndexAt(const glm::vec3 &ws) const
|
||||
|
||||
float GameData::getWaveHeightAt(const glm::vec3 &ws) const
|
||||
{
|
||||
return (1+sin(engine->gameTime + (ws.x + ws.y) * WATER_SCALE)) * WATER_HEIGHT;
|
||||
return (1+sin(engine->getGameTime() + (ws.x + ws.y) * WATER_SCALE)) * WATER_HEIGHT;
|
||||
}
|
||||
|
||||
bool GameData::isValidGameDirectory(const std::string& path)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <engine/GameState.hpp>
|
||||
|
||||
GameState::GameState() :
|
||||
gameTime(0.f),
|
||||
currentProgress(0),
|
||||
maxProgress(1),
|
||||
numMissions(0),
|
||||
@ -9,7 +10,6 @@ numHiddenPackagesDiscovered(0),
|
||||
numUniqueJumps(0),
|
||||
numRampages(0),
|
||||
maxWantedLevel(0),
|
||||
player(nullptr),
|
||||
currentWeather(0),
|
||||
scriptOnMissionFlag(nullptr),
|
||||
fadeOut(true),
|
||||
@ -25,7 +25,7 @@ hour(0),
|
||||
minute(0),
|
||||
cameraNear(0.1f),
|
||||
cameraFixed(false),
|
||||
cameraTarget(nullptr),
|
||||
cameraTarget(0),
|
||||
world(nullptr)
|
||||
{
|
||||
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
};
|
||||
|
||||
GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat)
|
||||
: logger(log), gameTime(0.f), data(dat), randomEngine(rand()),
|
||||
: logger(log), data(dat), randomEngine(rand()),
|
||||
_work( work ), cutsceneAudio(nullptr), missionAudio(nullptr),
|
||||
paused(false)
|
||||
{
|
||||
@ -95,8 +95,8 @@ GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat)
|
||||
|
||||
GameWorld::~GameWorld()
|
||||
{
|
||||
for(auto o : objects) {
|
||||
delete o;
|
||||
for(auto& p : objects) {
|
||||
delete p.second;
|
||||
}
|
||||
|
||||
delete dynamicsWorld;
|
||||
@ -126,7 +126,8 @@ bool GameWorld::placeItems(const std::string& name)
|
||||
}
|
||||
|
||||
// Attempt to Associate LODs.
|
||||
for(GameObject* object : objects) {
|
||||
for(auto& p: objects) {
|
||||
auto object = p.second;
|
||||
if( object->type() == GameObject::Instance ) {
|
||||
InstanceObject* instance = static_cast<InstanceObject*>(object);
|
||||
if( !instance->object->LOD ) {
|
||||
@ -192,7 +193,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
|
||||
oi, nullptr, dydata
|
||||
);
|
||||
|
||||
objects.insert(instance);
|
||||
insertObject(instance);
|
||||
|
||||
if( shouldBeOnGrid(instance) )
|
||||
{
|
||||
@ -219,16 +220,16 @@ void GameWorld::createTraffic(const glm::vec3& near)
|
||||
|
||||
void GameWorld::cleanupTraffic(const glm::vec3& focus)
|
||||
{
|
||||
for ( GameObject* object : objects )
|
||||
for ( auto& p : objects )
|
||||
{
|
||||
if ( object->getLifetime() != GameObject::TrafficLifetime )
|
||||
if ( p.second->getLifetime() != GameObject::TrafficLifetime )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( glm::distance( focus, object->getPosition() ) >= 100.f )
|
||||
if ( glm::distance( focus, p.second->getPosition() ) >= 100.f )
|
||||
{
|
||||
destroyObjectQueued( object );
|
||||
destroyObjectQueued( p.second );
|
||||
}
|
||||
}
|
||||
destroyQueuedObjects();
|
||||
@ -276,7 +277,11 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
|
||||
}
|
||||
|
||||
if( id == 0 ) {
|
||||
modelname = state->player->getCharacter()->model->name;
|
||||
auto playerobj = findObject(state->playerObject);
|
||||
if( playerobj )
|
||||
{
|
||||
modelname = playerobj->model->name;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the relevant data is loaded.
|
||||
@ -301,13 +306,13 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
|
||||
pos,
|
||||
m);
|
||||
|
||||
objects.insert(instance);
|
||||
insertObject( instance );
|
||||
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot)
|
||||
VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot, GameObjectID gid)
|
||||
{
|
||||
auto vti = data->findObjectType<VehicleData>(id);
|
||||
if( vti ) {
|
||||
@ -364,15 +369,16 @@ 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);
|
||||
|
||||
objects.insert(vehicle);
|
||||
insertObject( vehicle );
|
||||
|
||||
return vehicle;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3 &pos, const glm::quat& rot)
|
||||
CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3& pos, const glm::quat& rot, GameObjectID gid)
|
||||
{
|
||||
auto pt = data->findObjectType<CharacterData>(id);
|
||||
if( pt ) {
|
||||
@ -404,7 +410,8 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3
|
||||
|
||||
if(m && m->resource) {
|
||||
auto ped = new CharacterObject( this, pos, rot, m, pt );
|
||||
objects.insert(ped);
|
||||
ped->setGameObjectID(gid);
|
||||
insertObject(ped);
|
||||
characters.insert(ped);
|
||||
new DefaultAIController(ped);
|
||||
return ped;
|
||||
@ -413,6 +420,56 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CharacterObject* GameWorld::createPlayer(const glm::vec3& pos, const glm::quat& rot, GameObjectID gid)
|
||||
{
|
||||
// Player object ID is hardcoded to 0.
|
||||
auto pt = data->findObjectType<CharacterData>(0);
|
||||
if( pt ) {
|
||||
// Model name is also hardcoded.
|
||||
std::string modelname = "player";
|
||||
std::string texturename = "player";
|
||||
|
||||
// Ensure the relevant data is loaded.
|
||||
data->loadDFF(modelname + ".dff");
|
||||
data->loadTXD(texturename + ".txd");
|
||||
|
||||
ModelRef m = data->models[modelname];
|
||||
|
||||
if(m && m->resource) {
|
||||
auto ped = new CharacterObject( this, pos, rot, m, nullptr );
|
||||
ped->setGameObjectID(gid);
|
||||
ped->setLifetime(GameObject::PlayerLifetime);
|
||||
insertObject(ped);
|
||||
characters.insert(ped);
|
||||
new PlayerController(ped);
|
||||
return ped;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GameWorld::insertObject(GameObject* object)
|
||||
{
|
||||
if( object->getGameObjectID() == 0 )
|
||||
{
|
||||
// Find the lowest free GameObjectID.
|
||||
GameObjectID availID = 1;
|
||||
for( auto& p : objects )
|
||||
{
|
||||
if( p.first == availID ) availID++;
|
||||
}
|
||||
|
||||
object->setGameObjectID( availID );
|
||||
}
|
||||
objects[object->getGameObjectID()] = object;
|
||||
}
|
||||
|
||||
GameObject* GameWorld::findObject(GameObjectID id) const
|
||||
{
|
||||
auto it = objects.find( id );
|
||||
return (it == objects.end())? nullptr : it->second;
|
||||
}
|
||||
|
||||
void GameWorld::destroyObject(GameObject* object)
|
||||
{
|
||||
auto coord = worldToGrid(glm::vec2(object->getPosition()));
|
||||
@ -423,7 +480,7 @@ void GameWorld::destroyObject(GameObject* object)
|
||||
auto index = (coord.x * WORLD_GRID_WIDTH) + coord.y;
|
||||
worldGrid[index].instances.erase(object);
|
||||
|
||||
auto iterator = objects.find(object);
|
||||
auto iterator = objects.find(object->getGameObjectID());
|
||||
if( iterator != objects.end() ) {
|
||||
delete object;
|
||||
objects.erase(iterator);
|
||||
@ -437,14 +494,14 @@ void GameWorld::destroyObject(GameObject* object)
|
||||
|
||||
void GameWorld::destroyObjectQueued(GameObject *object)
|
||||
{
|
||||
deletionQueue.push(object);
|
||||
deletionQueue.insert(object);
|
||||
}
|
||||
|
||||
void GameWorld::destroyQueuedObjects()
|
||||
{
|
||||
while( !deletionQueue.empty() ) {
|
||||
destroyObject( deletionQueue.front() );
|
||||
deletionQueue.pop();
|
||||
destroyObject( *deletionQueue.begin() );
|
||||
deletionQueue.erase( deletionQueue.begin() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,6 +619,11 @@ glm::vec3 GameWorld::getGroundAtPosition(const glm::vec3 &pos) const
|
||||
return pos;
|
||||
}
|
||||
|
||||
float GameWorld::getGameTime() const
|
||||
{
|
||||
return state->gameTime;
|
||||
}
|
||||
|
||||
void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA)
|
||||
{
|
||||
bool isVehicle = object->type() == GameObject::Vehicle;
|
||||
@ -653,7 +715,8 @@ void GameWorld::PhysicsTickCallback(btDynamicsWorld *physWorld, btScalar timeSte
|
||||
{
|
||||
GameWorld* world = static_cast<GameWorld*>(physWorld->getWorldUserInfo());
|
||||
|
||||
for( GameObject* object : world->objects ) {
|
||||
for( auto& p : world->objects ) {
|
||||
GameObject* object = p.second;
|
||||
if( object->type() == GameObject::Vehicle ) {
|
||||
static_cast<VehicleObject*>(object)->tickPhysics(timeStep);
|
||||
}
|
||||
@ -699,7 +762,7 @@ void GameWorld::loadCutscene(const std::string &name)
|
||||
|
||||
void GameWorld::startCutscene()
|
||||
{
|
||||
state->cutsceneStartTime = gameTime;
|
||||
state->cutsceneStartTime = getGameTime();
|
||||
state->skipCutscene = false;
|
||||
if( cutsceneAudio ) {
|
||||
cutsceneAudio->play();
|
||||
@ -708,7 +771,8 @@ void GameWorld::startCutscene()
|
||||
|
||||
void GameWorld::clearCutscene()
|
||||
{
|
||||
for(auto o : objects) {
|
||||
for(auto& p : objects) {
|
||||
auto o = p.second;
|
||||
if( o->type() == GameObject::Cutscene ) {
|
||||
destroyObjectQueued(o);
|
||||
}
|
||||
@ -730,7 +794,7 @@ void GameWorld::clearCutscene()
|
||||
bool GameWorld::isCutsceneDone()
|
||||
{
|
||||
if( state->currentCutscene ) {
|
||||
float time = gameTime - state->cutsceneStartTime;
|
||||
float time = getGameTime() - state->cutsceneStartTime;
|
||||
if( state->skipCutscene ) {
|
||||
return true;
|
||||
}
|
||||
|
315
rwengine/src/engine/SaveGame.cpp
Normal file
315
rwengine/src/engine/SaveGame.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
#include <engine/SaveGame.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <script/ScriptMachine.hpp>
|
||||
#include <script/SCMFile.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,
|
||||
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;
|
||||
}
|
@ -105,7 +105,7 @@ void WeaponItem::fireProjectile()
|
||||
// Work out the velocity multiplier as a function of how long the player
|
||||
// Was holding down the fire button. If _fireStop < 0.f then the player
|
||||
// is still holding the button down.
|
||||
float throwTime = _character->engine->gameTime - _fireStart;
|
||||
float throwTime = _character->engine->getGameTime() - _fireStart;
|
||||
float forceFactor = throwTime;
|
||||
if( _fireStop > 0.f ) {
|
||||
forceFactor = _fireStop - _fireStart;
|
||||
@ -121,21 +121,21 @@ void WeaponItem::fireProjectile()
|
||||
_wepData
|
||||
});
|
||||
|
||||
_character->engine->objects.insert( projectile );
|
||||
_character->engine->insertObject( projectile );
|
||||
}
|
||||
|
||||
void WeaponItem::primary(bool active)
|
||||
{
|
||||
_firing = active;
|
||||
if( active ) {
|
||||
_fireStart = _character->engine->gameTime;
|
||||
_fireStart = _character->engine->getGameTime();
|
||||
_fireStop = -1.f;
|
||||
|
||||
// ShootWeapon will call ::fire() on us at the appropriate time.
|
||||
_character->controller->setNextActivity(new Activities::ShootWeapon(this));
|
||||
}
|
||||
else {
|
||||
_fireStop = _character->engine->gameTime;
|
||||
_fireStop = _character->engine->getGameTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ void ProjectileObject::explode()
|
||||
const float damage = _info.weapon->damage;
|
||||
|
||||
/// @todo accelerate this with bullet instead of doing this stupid loop.
|
||||
for(auto& o : engine->objects) {
|
||||
for(auto& p : engine->objects) {
|
||||
auto o = p.second;
|
||||
if( o == this ) continue;
|
||||
switch( o->type() ) {
|
||||
case GameObject::Instance:
|
||||
@ -77,7 +78,7 @@ void ProjectileObject::explode()
|
||||
auto explosion = engine->createEffect(VisualFX::Particle);
|
||||
explosion->particle.size = glm::vec2(exp_size);
|
||||
explosion->particle.texture = tex;
|
||||
explosion->particle.starttime = engine->gameTime;
|
||||
explosion->particle.starttime = engine->getGameTime();
|
||||
explosion->particle.lifetime = 0.5f;
|
||||
explosion->particle.orientation = VisualFX::ParticleData::Camera;
|
||||
explosion->particle.colour = glm::vec4(1.0f);
|
||||
|
@ -297,7 +297,8 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
renderer->pushDebugGroup("Objects");
|
||||
renderer->pushDebugGroup("Dynamic");
|
||||
|
||||
for( GameObject* object : world->objects ) {
|
||||
for( auto& p : world->objects ) {
|
||||
auto object = p.second;
|
||||
if(! object->visible )
|
||||
{
|
||||
continue;
|
||||
@ -387,16 +388,20 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
{
|
||||
glm::mat4 model;
|
||||
|
||||
if( blip.second.target )
|
||||
if( blip.second.target > 0 )
|
||||
{
|
||||
model = blip.second.target->getTimeAdjustedTransform( _renderAlpha );
|
||||
auto object = world->findObject(blip.second.target);
|
||||
if( object )
|
||||
{
|
||||
model = object->getTimeAdjustedTransform( _renderAlpha );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
model = glm::translate( model, blip.second.coord );
|
||||
}
|
||||
|
||||
float a = world->gameTime * glm::pi<float>();
|
||||
float a = world->getGameTime() * glm::pi<float>();
|
||||
model = glm::translate( model, glm::vec3(0.f, 0.f, 2.5f + glm::sin( a ) * 0.5f) );
|
||||
model = glm::rotate( model, a, glm::vec3(0.f, 0.f, 1.f) );
|
||||
model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) );
|
||||
@ -469,7 +474,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
renderLetterbox();
|
||||
}
|
||||
|
||||
float fadeTimer = world->gameTime - world->state->fadeStart;
|
||||
float fadeTimer = world->getGameTime() - world->state->fadeStart;
|
||||
if( fadeTimer < world->state->fadeTime || !world->state->fadeOut ) {
|
||||
glUseProgram(ssRectProgram);
|
||||
glUniform2f(ssRectOffset, 0.f, 0.f);
|
||||
@ -705,7 +710,7 @@ void GameRenderer::renderPickup(PickupObject *pickup)
|
||||
if( ! pickup->isEnabled() ) return;
|
||||
|
||||
glm::mat4 modelMatrix = glm::translate(glm::mat4(), pickup->getPosition());
|
||||
modelMatrix = glm::rotate(modelMatrix, _renderWorld->gameTime, glm::vec3(0.f, 0.f, 1.f));
|
||||
modelMatrix = glm::rotate(modelMatrix, _renderWorld->getGameTime(), glm::vec3(0.f, 0.f, 1.f));
|
||||
|
||||
auto odata = data->findObjectType<ObjectData>(pickup->getModelID());
|
||||
|
||||
@ -937,7 +942,7 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info)
|
||||
{
|
||||
glm::mat4 m(1.f);
|
||||
m = glm::translate(m, info->position);
|
||||
glm::vec3 scale = info->radius + 0.15f * glm::sin(_renderWorld->gameTime * 5.f);
|
||||
glm::vec3 scale = info->radius + 0.15f * glm::sin(_renderWorld->getGameTime() * 5.f);
|
||||
|
||||
Renderer::DrawParameters dp;
|
||||
dp.textures = {data->findTexture("cloud1")->getName()};
|
||||
@ -953,7 +958,7 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info)
|
||||
glm::vec3 final = scale * glm::pow(0.9f, i + 1.0f);
|
||||
mt = glm::scale(mt, glm::vec3(final.x, final.y, 1.0f + i * 0.1f));
|
||||
int reverse = (i % 2 ? 1 : -1);
|
||||
mt = glm::rotate(mt, reverse * _renderWorld->gameTime * 0.5f, glm::vec3(0.f, 0.f, 1.f) );
|
||||
mt = glm::rotate(mt, reverse * _renderWorld->getGameTime() * 0.5f, glm::vec3(0.f, 0.f, 1.f) );
|
||||
|
||||
renderer->drawArrays(mt, &cylinderBuffer, dp);
|
||||
}
|
||||
|
@ -149,20 +149,24 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
for(auto& blip : world->state->radarBlips)
|
||||
{
|
||||
glm::vec2 blippos( blip.second.coord );
|
||||
if( blip.second.target )
|
||||
if( blip.second.target > 0 )
|
||||
{
|
||||
blippos = glm::vec2( blip.second.target->getPosition() );
|
||||
auto object = world->findObject(blip.second.target);
|
||||
if( object )
|
||||
{
|
||||
blippos = glm::vec2( object->getPosition() );
|
||||
}
|
||||
}
|
||||
|
||||
drawBlip(blippos, model, mi, "");
|
||||
}
|
||||
|
||||
// Draw the player blip
|
||||
auto player = world->state->player;
|
||||
auto player = world->findObject(world->state->playerObject);
|
||||
if( player )
|
||||
{
|
||||
glm::vec2 plyblip(player->getCharacter()->getPosition());
|
||||
float hdg = glm::roll(player->getCharacter()->getRotation());
|
||||
glm::vec2 plyblip(player->getPosition());
|
||||
float hdg = glm::roll(player->getRotation());
|
||||
drawBlip(plyblip, model, mi, "radar_centre", hdg);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world)
|
||||
buffers[0] = GL_COLOR_ATTACHMENT0;
|
||||
glDrawBuffers(1, buffers);
|
||||
|
||||
r->setUniform(waterProg, "time", world->gameTime);
|
||||
r->setUniform(waterProg, "time", world->getGameTime());
|
||||
r->setUniform(waterProg, "waveParams", glm::vec2(WATER_SCALE, WATER_HEIGHT));
|
||||
auto ivp = glm::inverse(r->getSceneData().projection * r->getSceneData().view);
|
||||
r->setUniform(waterProg, "inverseVP", ivp);
|
||||
|
92
rwengine/src/script/ScriptDisassembly.cpp
Normal file
92
rwengine/src/script/ScriptDisassembly.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <script/ScriptDisassembly.hpp>
|
||||
#include <script/SCMFile.hpp>
|
||||
#include <script/ScriptMachine.hpp>
|
||||
|
||||
ScriptDisassembly::ScriptDisassembly(SCMOpcodes* _codes, SCMFile* _scm)
|
||||
: codes(_codes), scm(_scm)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScriptDisassembly::disassemble(SCMAddress startAddress)
|
||||
{
|
||||
for( SCMAddress a = startAddress; a < scm->getMainSize(); )
|
||||
{
|
||||
auto opcode = scm->read<SCMOpcode>(a);
|
||||
auto opcorg = opcode;
|
||||
|
||||
bool isNegatedConditional = ((opcode & SCM_NEGATE_CONDITIONAL_MASK) == SCM_NEGATE_CONDITIONAL_MASK);
|
||||
opcode = opcode & ~SCM_NEGATE_CONDITIONAL_MASK;
|
||||
|
||||
ScriptFunctionMeta* foundcode;
|
||||
if( ! codes->findOpcode(opcode, &foundcode) )
|
||||
{
|
||||
throw IllegalInstruction(opcode, a, "Disassembler");
|
||||
}
|
||||
ScriptFunctionMeta& code = *foundcode;
|
||||
|
||||
SCMParams parameters;
|
||||
auto instructionAddress = a;
|
||||
a += sizeof(SCMOpcode);
|
||||
|
||||
bool hasExtraParameters = code.arguments < 0;
|
||||
auto requiredParams = std::abs(code.arguments);
|
||||
|
||||
for( int p = 0; p < requiredParams || hasExtraParameters; ++p ) {
|
||||
auto type_r = scm->read<SCMByte>(a);
|
||||
auto type = static_cast<SCMType>(type_r);
|
||||
|
||||
if( type_r > 42 ) {
|
||||
// for implicit strings, we need the byte we just read.
|
||||
type = TString;
|
||||
}
|
||||
else {
|
||||
a += sizeof(SCMByte);
|
||||
}
|
||||
|
||||
parameters.push_back(SCMOpcodeParameter { type, { 0 } });
|
||||
switch(type) {
|
||||
case EndOfArgList:
|
||||
hasExtraParameters = false;
|
||||
break;
|
||||
case TInt8:
|
||||
parameters.back().integer = scm->read<std::uint8_t>(a);
|
||||
a += sizeof(SCMByte);
|
||||
break;
|
||||
case TInt16:
|
||||
parameters.back().integer = scm->read<std::int16_t>(a);
|
||||
a += sizeof(SCMByte) * 2;
|
||||
break;
|
||||
case TGlobal: {
|
||||
auto v = scm->read<std::uint16_t>(a);
|
||||
parameters.back().globalPtr = (void*)v; //* SCM_VARIABLE_SIZE;
|
||||
a += sizeof(SCMByte) * 2;
|
||||
}
|
||||
break;
|
||||
case TLocal: {
|
||||
auto v = scm->read<std::uint16_t>(a);
|
||||
parameters.back().globalPtr = (void*)(v * SCM_VARIABLE_SIZE);
|
||||
a += sizeof(SCMByte) * 2;
|
||||
}
|
||||
break;
|
||||
case TInt32:
|
||||
parameters.back().integer = scm->read<std::uint32_t>(a);
|
||||
a += sizeof(SCMByte) * 4;
|
||||
break;
|
||||
case TString:
|
||||
std::copy(scm->data()+a, scm->data()+a+8,
|
||||
parameters.back().string);
|
||||
a += sizeof(SCMByte) * 8;
|
||||
break;
|
||||
case TFloat16:
|
||||
parameters.back().real = scm->read<std::int16_t>(a) / 16.f;
|
||||
a += sizeof(SCMByte) * 2;
|
||||
break;
|
||||
default:
|
||||
throw UnknownType(type, a, "Disassembler");
|
||||
break;
|
||||
};
|
||||
}
|
||||
instructions[instructionAddress] = InstructionInfo { opcode, parameters };
|
||||
}
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
#include <script/ScriptMachine.hpp>
|
||||
#include <script/SCMFile.hpp>
|
||||
#include <script/ScriptModule.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <core/Logger.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#if SCM_DEBUG_INSTRUCTIONS
|
||||
#include <iostream>
|
||||
@ -86,13 +90,21 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
||||
break;
|
||||
case TGlobal: {
|
||||
auto v = _file->read<std::uint16_t>(t.programCounter);
|
||||
parameters.back().globalPtr = _globals + v * sizeof(SCMByte) * 4;
|
||||
parameters.back().globalPtr = globalData.data() + v; //* SCM_VARIABLE_SIZE;
|
||||
if( v >= _file->getGlobalsSize() )
|
||||
{
|
||||
state->world->logger->error("SCM", "Global Out of bounds! "+ std::to_string(v) + " " + std::to_string(_file->getGlobalsSize()));
|
||||
}
|
||||
t.programCounter += sizeof(SCMByte) * 2;
|
||||
}
|
||||
break;
|
||||
case TLocal: {
|
||||
auto v = _file->read<std::uint16_t>(t.programCounter);
|
||||
parameters.back().globalPtr = t.locals + v * sizeof(SCMByte) * 4;
|
||||
parameters.back().globalPtr = t.locals.data() + v * SCM_VARIABLE_SIZE;
|
||||
if( v >= SCM_THREAD_LOCAL_SIZE )
|
||||
{
|
||||
state->world->logger->error("SCM", "Local Out of bounds!");
|
||||
}
|
||||
t.programCounter += sizeof(SCMByte) * 2;
|
||||
}
|
||||
break;
|
||||
@ -165,9 +177,9 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
||||
}
|
||||
|
||||
SCMOpcodeParameter p;
|
||||
p.globalPtr = (t.locals + 16 * sizeof ( SCMByte ) * 4);
|
||||
p.globalPtr = (t.locals.data() + 16 * sizeof ( SCMByte ) * 4);
|
||||
*p.globalInteger += msPassed;
|
||||
p.globalPtr = (t.locals + 17 * sizeof ( SCMByte ) * 4);
|
||||
p.globalPtr = (t.locals.data() + 17 * sizeof ( SCMByte ) * 4);
|
||||
*p.globalInteger += msPassed;
|
||||
|
||||
if( t.wakeCounter == -1 ) {
|
||||
@ -178,12 +190,11 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
||||
ScriptMachine::ScriptMachine(GameState* _state, SCMFile *file, SCMOpcodes *ops)
|
||||
: _file(file), _ops(ops), state(_state)
|
||||
{
|
||||
startThread(0);
|
||||
auto globals = _file->getGlobalsSize() / 4;
|
||||
_globals = new SCMByte[globals * SCM_VARIABLE_SIZE];
|
||||
for(int i = 0; i < globals * SCM_VARIABLE_SIZE; ++i)
|
||||
auto globals = _file->getGlobalsSize();
|
||||
globalData.resize(globals);
|
||||
for(int i = 0; i < globals; ++i)
|
||||
{
|
||||
_globals[i] = 0;
|
||||
globalData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,16 +202,15 @@ ScriptMachine::~ScriptMachine()
|
||||
{
|
||||
delete _file;
|
||||
delete _ops;
|
||||
delete[] _globals;
|
||||
}
|
||||
|
||||
void ScriptMachine::startThread(SCMThread::pc_t start, bool mission)
|
||||
{
|
||||
SCMThread t;
|
||||
for(int i = 0; i < SCM_THREAD_LOCAL_SIZE; ++i) {
|
||||
for(int i = 0; i < SCM_THREAD_LOCAL_SIZE * SCM_VARIABLE_SIZE; ++i) {
|
||||
t.locals[i] = 0;
|
||||
}
|
||||
t.name = "THREAD";
|
||||
strncpy(t.name, "THREAD", 16);
|
||||
t.conditionResult = false;
|
||||
t.conditionCount = 0;
|
||||
t.conditionAND = false;
|
||||
@ -209,12 +219,13 @@ void ScriptMachine::startThread(SCMThread::pc_t start, bool mission)
|
||||
t.wakeCounter = 0;
|
||||
t.isMission = mission;
|
||||
t.finished = false;
|
||||
t.stackDepth = 0;
|
||||
_activeThreads.push_back(t);
|
||||
}
|
||||
|
||||
SCMByte *ScriptMachine::getGlobals()
|
||||
{
|
||||
return _file->data() + _file->getGlobalSection();
|
||||
return globalData.data();
|
||||
}
|
||||
|
||||
void ScriptMachine::execute(float dt)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <script/ScriptTypes.hpp>
|
||||
#include <script/ScriptMachine.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
|
||||
GameState* ScriptArguments::getState() const
|
||||
{
|
||||
@ -11,3 +12,10 @@ GameWorld* ScriptArguments::getWorld() const
|
||||
{
|
||||
return getVM()->getState()->world;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ void game_print_big(const ScriptArguments& args)
|
||||
args.getWorld()->state->text.push_back({
|
||||
id,
|
||||
str,
|
||||
args.getWorld()->gameTime,
|
||||
args.getWorld()->getGameTime(),
|
||||
args[1].integer / 1000.f,
|
||||
style
|
||||
});
|
||||
@ -47,7 +47,7 @@ void game_print_now(const ScriptArguments& args)
|
||||
args.getWorld()->state->text.push_back({
|
||||
id,
|
||||
str,
|
||||
args.getWorld()->gameTime,
|
||||
args.getWorld()->getGameTime(),
|
||||
args[1].integer / 1000.f,
|
||||
0
|
||||
});
|
||||
@ -126,7 +126,7 @@ void game_set_zone_car_info(const ScriptArguments& args)
|
||||
if( it != args.getWorld()->data->zones.end() )
|
||||
{
|
||||
auto day = args[1].integer == 1;
|
||||
for(int i = 2; i < args.getParameters().size(); ++i)
|
||||
for(int i = 2; i < args.getParameters().size() && i - 2 < ZONE_GANG_COUNT; ++i)
|
||||
{
|
||||
if( day )
|
||||
{
|
||||
@ -142,16 +142,16 @@ void game_set_zone_car_info(const ScriptArguments& args)
|
||||
|
||||
void game_camera_follow_character(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
if( controller != nullptr )
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
if( character != nullptr )
|
||||
{
|
||||
args.getWorld()->state->cameraTarget = controller->getCharacter();
|
||||
args.getWorld()->state->cameraTarget = character->getGameObjectID();
|
||||
}
|
||||
}
|
||||
|
||||
void game_reset_camera(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->cameraTarget = nullptr;
|
||||
args.getWorld()->state->cameraTarget = 0;
|
||||
args.getWorld()->state->cameraFixed = false;
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ void game_fade_screen(const ScriptArguments& args)
|
||||
{
|
||||
args.getWorld()->state->fadeTime = args[0].integer / 1000.f;
|
||||
args.getWorld()->state->fadeOut = !!args[1].integer;
|
||||
args.getWorld()->state->fadeStart = args.getWorld()->gameTime;
|
||||
args.getWorld()->state->fadeStart = args.getWorld()->getGameTime();
|
||||
}
|
||||
bool game_screen_fading(const ScriptArguments& args)
|
||||
{
|
||||
@ -233,7 +233,7 @@ bool game_screen_fading(const ScriptArguments& args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return args.getWorld()->gameTime <
|
||||
return args.getWorld()->getGameTime() <
|
||||
args.getWorld()->state->fadeStart + args.getWorld()->state->fadeTime;
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ void game_link_mission_flag(const ScriptArguments& args)
|
||||
void game_add_vehicle_blip(const ScriptArguments& args)
|
||||
{
|
||||
BlipData data;
|
||||
data.target = static_cast<VehicleObject*>(*args[0].handle);
|
||||
data.target = args.getGameObject(0)->getGameObjectID();
|
||||
data.texture = "";
|
||||
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
|
||||
}
|
||||
@ -266,8 +266,7 @@ void game_add_vehicle_blip(const ScriptArguments& args)
|
||||
void game_add_character_blip(const ScriptArguments& args)
|
||||
{
|
||||
BlipData data;
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
data.target = controller->getCharacter();
|
||||
data.target = args.getGameObject(0)->getGameObjectID();
|
||||
data.texture = "";
|
||||
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
|
||||
}
|
||||
@ -275,7 +274,7 @@ void game_add_character_blip(const ScriptArguments& args)
|
||||
void game_add_pickup_blip(const ScriptArguments& args)
|
||||
{
|
||||
BlipData data;
|
||||
data.target = static_cast<PickupObject*>(*args[0].handle);
|
||||
data.target = args.getGameObject(0)->getGameObjectID();
|
||||
data.texture = "";
|
||||
*args[1].globalInteger = args.getWorld()->state->addRadarBlip(data);
|
||||
}
|
||||
@ -284,7 +283,7 @@ void game_add_pickup_blip(const ScriptArguments& args)
|
||||
void game_add_location_blip(const ScriptArguments& args)
|
||||
{
|
||||
BlipData data;
|
||||
data.target = nullptr;
|
||||
data.target = 0;
|
||||
data.coord = glm::vec3(args[0].real, args[1].real, args[2].real);
|
||||
data.texture = "";
|
||||
*args[3].globalInteger = args.getWorld()->state->addRadarBlip(data);
|
||||
@ -312,8 +311,8 @@ void game_change_blip_mode(const ScriptArguments& args)
|
||||
|
||||
void game_enable_input(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<PlayerController*>(*args[0].handle);
|
||||
controller->setInputEnabled(!!args[1].integer);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
static_cast<PlayerController*>(character->controller)->setInputEnabled(!!args[1].integer);
|
||||
}
|
||||
|
||||
void game_set_weather(const ScriptArguments& args)
|
||||
@ -323,7 +322,7 @@ void game_set_weather(const ScriptArguments& args)
|
||||
|
||||
void game_get_runtime(const ScriptArguments& args)
|
||||
{
|
||||
*args[0].globalInteger = args.getWorld()->gameTime * 1000;
|
||||
*args[0].globalInteger = args.getWorld()->getGameTime() * 1000;
|
||||
}
|
||||
|
||||
void game_print_big_with_number(const ScriptArguments& args)
|
||||
@ -339,7 +338,7 @@ void game_print_big_with_number(const ScriptArguments& args)
|
||||
args.getWorld()->state->text.push_back({
|
||||
id,
|
||||
str,
|
||||
args.getWorld()->gameTime,
|
||||
args.getWorld()->getGameTime(),
|
||||
args[2].integer / 1000.f,
|
||||
style
|
||||
});
|
||||
@ -368,8 +367,8 @@ void game_max_wanted_level(const ScriptArguments& args)
|
||||
// This does nothing for us.
|
||||
void game_get_player(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
*args[1].handle = controller;
|
||||
auto character = args.getGameObject(0);
|
||||
*args[1].globalInteger = character->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_create_garage(const ScriptArguments& args)
|
||||
@ -379,7 +378,8 @@ void game_create_garage(const ScriptArguments& args)
|
||||
|
||||
/// @todo http://www.gtamodding.com/index.php?title=Garage#GTA_III
|
||||
int garageType = args[6].integer;
|
||||
auto garageHandle = args[7].handle;
|
||||
// TODO actually store the garage information and return the handle
|
||||
*args[7].globalInteger = 0;
|
||||
|
||||
args.getWorld()->logger->warning("SCM", "Garages Unimplemented! " + std::to_string(garageType));
|
||||
}
|
||||
@ -442,28 +442,29 @@ 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 controller = args.getWorld()->state->player;
|
||||
auto object = args.getWorld()->findObject(args.getState()->playerObject);
|
||||
auto player = static_cast<CharacterObject*>(object);
|
||||
|
||||
glm::vec3 spawnMagic( 0.f, 0.f, 1.f );
|
||||
|
||||
controller->getCharacter()->setPosition(position + spawnMagic);
|
||||
player->setPosition(position + spawnMagic);
|
||||
|
||||
controller->getCharacter()->setHeading( args[3].real );
|
||||
player->setHeading( args[3].real );
|
||||
|
||||
/// @todo find a nicer way to implement warping out of vehicles.
|
||||
auto cv = controller->getCharacter()->getCurrentVehicle();
|
||||
auto cv = player->getCurrentVehicle();
|
||||
if ( cv != nullptr )
|
||||
{
|
||||
cv->setOccupant( controller->getCharacter()->getCurrentSeat(), nullptr );
|
||||
controller->getCharacter()->setCurrentVehicle(nullptr, 0);
|
||||
cv->setOccupant( player->getCurrentSeat(), nullptr );
|
||||
player->setCurrentVehicle(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// @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 controller = (CharacterController*)(*args[0].handle);
|
||||
return controller != nullptr;
|
||||
auto character = args.getGameObject(0);
|
||||
return character != nullptr;
|
||||
}
|
||||
|
||||
void game_controller_mode(const ScriptArguments& args)
|
||||
@ -514,7 +515,7 @@ void game_add_contact_blip(const ScriptArguments& args)
|
||||
|
||||
BlipData bd;
|
||||
bd.coord = c;
|
||||
bd.target = nullptr;
|
||||
bd.target = 0;
|
||||
bd.texture = spriteName;
|
||||
|
||||
*args[4].globalInteger = args.getWorld()->state->addRadarBlip(bd);
|
||||
@ -534,7 +535,7 @@ void game_add_sprite_blip(const ScriptArguments& args)
|
||||
|
||||
BlipData bd;
|
||||
bd.coord = c;
|
||||
bd.target = nullptr;
|
||||
bd.target = 0;
|
||||
bd.texture = spriteName;
|
||||
|
||||
*args[4].globalInteger = args.getWorld()->state->addRadarBlip(bd);
|
||||
@ -550,15 +551,18 @@ void game_create_cutscene_object(const ScriptArguments& args)
|
||||
auto id = args[0].integer;
|
||||
|
||||
GameObject* object = object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset );
|
||||
*args[1].handle = object;
|
||||
|
||||
if( object == nullptr ) {
|
||||
args.getWorld()->logger->error("SCM", "Could not create cutscene object " + std::to_string(id));
|
||||
}
|
||||
else
|
||||
{
|
||||
*args[1].globalInteger = object->getGameObjectID();
|
||||
}
|
||||
}
|
||||
void game_set_cutscene_anim(const ScriptArguments& args)
|
||||
{
|
||||
GameObject* object = static_cast<GameObject*>(*args[0].handle);
|
||||
GameObject* object = args.getGameObject(0);
|
||||
std::string animName = args[1].string;
|
||||
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
|
||||
Animation* anim = args.getWorld()->data->animations[animName];
|
||||
@ -575,7 +579,7 @@ void game_start_cutscene(const ScriptArguments& args)
|
||||
}
|
||||
void game_get_cutscene_time(const ScriptArguments& args)
|
||||
{
|
||||
float time = args.getWorld()->gameTime - args.getWorld()->state->cutsceneStartTime;
|
||||
float time = args.getWorld()->getGameTime() - args.getWorld()->state->cutsceneStartTime;
|
||||
if( args.getWorld()->state->skipCutscene )
|
||||
{
|
||||
*args[0].globalInteger = args.getWorld()->state->currentCutscene->tracks.duration * 1000;
|
||||
@ -588,7 +592,7 @@ void game_get_cutscene_time(const ScriptArguments& args)
|
||||
bool game_cutscene_finished(const ScriptArguments& args)
|
||||
{
|
||||
if( args.getWorld()->state->currentCutscene ) {
|
||||
float time = args.getWorld()->gameTime - args.getWorld()->state->cutsceneStartTime;
|
||||
float time = args.getWorld()->getGameTime() - args.getWorld()->state->cutsceneStartTime;
|
||||
if( args.getWorld()->state->skipCutscene ) {
|
||||
return true;
|
||||
}
|
||||
@ -613,18 +617,18 @@ void game_load_special_model(const ScriptArguments& args)
|
||||
void game_create_cutscene_head(const ScriptArguments& args)
|
||||
{
|
||||
auto id = args[1].integer;
|
||||
auto actor = static_cast<GameObject*>(*args[0].handle);
|
||||
auto actor = args.getGameObject(0);
|
||||
CutsceneObject* object = args.getWorld()->createCutsceneObject(id, args.getWorld()->state->currentCutscene->meta.sceneOffset );
|
||||
|
||||
auto headframe = actor->model->resource->findFrame("shead");
|
||||
actor->skeleton->setEnabled(headframe, false);
|
||||
object->setParentActor(actor, headframe);
|
||||
|
||||
*args[2].handle = object;
|
||||
*args[2].globalInteger = object->getGameObjectID();
|
||||
}
|
||||
void game_set_head_animation(const ScriptArguments& args)
|
||||
{
|
||||
GameObject* object = static_cast<GameObject*>(*args[0].handle);
|
||||
GameObject* object = args.getGameObject(0);
|
||||
std::string animName = args[1].string;
|
||||
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
|
||||
Animation* anim = args.getWorld()->data->animations[animName];
|
||||
@ -701,8 +705,11 @@ void game_set_background_colour(const ScriptArguments& args)
|
||||
|
||||
void game_set_character_model(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
controller->getCharacter()->changeCharacterModel(args[1].string);
|
||||
auto character = args.getGameObject(0);
|
||||
if( character )
|
||||
{
|
||||
static_cast<CharacterObject*>(character)->changeCharacterModel(args[1].string);
|
||||
}
|
||||
}
|
||||
|
||||
bool game_collision_loaded(const ScriptArguments& args)
|
||||
@ -797,7 +804,7 @@ void game_display_help(const ScriptArguments& args)
|
||||
args.getWorld()->state->text.push_back({
|
||||
id,
|
||||
str,
|
||||
args.getWorld()->gameTime,
|
||||
args.getWorld()->getGameTime(),
|
||||
2.5f,
|
||||
style
|
||||
});
|
||||
@ -812,6 +819,10 @@ void game_clear_help(const ScriptArguments& args)
|
||||
{
|
||||
texts.erase(texts.begin() + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,25 +38,25 @@ void game_create_player(const ScriptArguments& args)
|
||||
position = args.getWorld()->getGroundAtPosition(position);
|
||||
}
|
||||
|
||||
auto pc = args.getWorld()->createPedestrian(1, position + spawnMagic);
|
||||
args.getState()->player = new PlayerController(pc);
|
||||
auto pc = args.getWorld()->createPlayer(position + spawnMagic);
|
||||
args.getState()->playerObject = pc->getGameObjectID();
|
||||
|
||||
*args[4].handle = args.getState()->player;
|
||||
*args[4].globalInteger = pc->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_set_character_position(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = args.getGameObject(0);
|
||||
glm::vec3 position(args[1].real, args[2].real, args[3].real + 1.f);
|
||||
controller->getCharacter()->setPosition(position + spawnMagic);
|
||||
character->setPosition(position + spawnMagic);
|
||||
}
|
||||
|
||||
bool game_player_in_area_2d(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = args.getGameObject(0);
|
||||
glm::vec2 min(args[1].real, args[2].real);
|
||||
glm::vec2 max(args[3].real, args[4].real);
|
||||
auto player = controller->getCharacter()->getPosition();
|
||||
auto player = character->getPosition();
|
||||
if( player.x > min.x && player.y > min.y && player.x < max.x && player.y < max.y ) {
|
||||
return true;
|
||||
}
|
||||
@ -65,10 +65,10 @@ bool game_player_in_area_2d(const ScriptArguments& args)
|
||||
|
||||
bool game_player_in_area_3d(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = args.getGameObject(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 = controller->getCharacter()->getPosition();
|
||||
auto player = character->getPosition();
|
||||
if( player.x > min.x &&
|
||||
player.y > min.y &&
|
||||
player.z > min.z &&
|
||||
@ -76,8 +76,8 @@ bool game_player_in_area_3d(const ScriptArguments& args)
|
||||
player.y < max.y &&
|
||||
player.z < max.z) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void game_create_character(const ScriptArguments& args)
|
||||
@ -98,32 +98,31 @@ void game_create_character(const ScriptArguments& args)
|
||||
for( auto it = args.getWorld()->objects.begin();
|
||||
it != args.getWorld()->objects.end();
|
||||
++it)
|
||||
{
|
||||
if( it->second->type() == GameObject::Character && glm::distance(position, it->second->getPosition()) < replaceThreshold )
|
||||
{
|
||||
if( (*it)->type() == GameObject::Character && glm::distance(position, (*it)->getPosition()) < replaceThreshold )
|
||||
{
|
||||
args.getWorld()->destroyObjectQueued(*it);
|
||||
}
|
||||
args.getWorld()->destroyObjectQueued(it->second);
|
||||
}
|
||||
|
||||
|
||||
auto character = args.getWorld()->createPedestrian(id, position + spawnMagic);
|
||||
auto controller = new DefaultAIController(character);
|
||||
|
||||
if ( args.getThread()->isMission )
|
||||
{
|
||||
args.getState()->missionObjects.push_back(character);
|
||||
}
|
||||
|
||||
*args[5].handle = controller;
|
||||
}
|
||||
|
||||
auto character = args.getWorld()->createPedestrian(id, position + spawnMagic);
|
||||
auto controller = new DefaultAIController(character);
|
||||
|
||||
if ( args.getThread()->isMission )
|
||||
{
|
||||
args.getState()->missionObjects.push_back(character->getGameObjectID());
|
||||
}
|
||||
|
||||
*args[5].globalInteger = character->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_destroy_character(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = args.getGameObject(0);
|
||||
|
||||
if ( controller )
|
||||
if ( character )
|
||||
{
|
||||
args.getWorld()->destroyObjectQueued(controller->getCharacter());
|
||||
args.getWorld()->destroyObjectQueued(character);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,33 +137,33 @@ void game_create_vehicle(const ScriptArguments& args)
|
||||
for( auto it = args.getWorld()->objects.begin();
|
||||
it != args.getWorld()->objects.end();
|
||||
++it)
|
||||
{
|
||||
if( it->second->type() == GameObject::Vehicle && glm::distance(position, it->second->getPosition()) < replaceThreshold )
|
||||
{
|
||||
if( (*it)->type() == GameObject::Vehicle && glm::distance(position, (*it)->getPosition()) < replaceThreshold )
|
||||
{
|
||||
args.getWorld()->destroyObjectQueued(*it);
|
||||
}
|
||||
args.getWorld()->destroyObjectQueued(it->second);
|
||||
}
|
||||
|
||||
auto vehicle = args.getWorld()->createVehicle(id, position);
|
||||
|
||||
if ( args.getThread()->isMission )
|
||||
{
|
||||
args.getState()->missionObjects.push_back(vehicle);
|
||||
}
|
||||
|
||||
*args[4].handle = vehicle;
|
||||
}
|
||||
|
||||
auto vehicle = args.getWorld()->createVehicle(id, position);
|
||||
|
||||
if ( args.getThread()->isMission )
|
||||
{
|
||||
args.getState()->missionObjects.push_back(vehicle->getGameObjectID());
|
||||
}
|
||||
|
||||
*args[4].globalInteger = vehicle->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_destroy_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = args.getGameObject(0);
|
||||
|
||||
args.getWorld()->destroyObjectQueued(vehicle);
|
||||
}
|
||||
|
||||
void game_get_vehicle_position(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = args.getGameObject(0);
|
||||
|
||||
if( vehicle )
|
||||
{
|
||||
@ -177,21 +176,21 @@ void game_get_vehicle_position(const ScriptArguments& args)
|
||||
|
||||
void game_get_character_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
*args[1].handle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
*args[1].globalInteger = character->getCurrentVehicle()->getGameObjectID();
|
||||
}
|
||||
|
||||
bool game_character_in_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[1].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = args.getGameObject(1);
|
||||
|
||||
if( controller == nullptr || vehicle == nullptr )
|
||||
if( character == nullptr || vehicle == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return controller->getCharacter()->getCurrentVehicle() == vehicle;
|
||||
return character->getCurrentVehicle() == vehicle;
|
||||
}
|
||||
|
||||
bool game_character_in_model(const ScriptArguments& args)
|
||||
@ -199,8 +198,7 @@ bool game_character_in_model(const ScriptArguments& args)
|
||||
auto vdata = args.getWorld()->data->findObjectType<VehicleData>(args[1].integer);
|
||||
if( vdata )
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = controller->getCharacter();
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
if ( vehicle ) {
|
||||
|
||||
@ -212,26 +210,26 @@ bool game_character_in_model(const ScriptArguments& args)
|
||||
|
||||
bool game_character_in_any_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
return vehicle != nullptr;
|
||||
}
|
||||
|
||||
bool game_player_in_area_2d_in_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto character = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
glm::vec2 position(args[1].real, args[2].real);
|
||||
glm::vec2 radius(args[3].real, args[4].real);
|
||||
|
||||
bool drawCylinder = args[5].integer;
|
||||
|
||||
if( character->getCharacter()->getCurrentVehicle() == nullptr )
|
||||
if( character->getCurrentVehicle() == nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto vp = character->getCharacter()->getCurrentVehicle()->getPosition();
|
||||
auto vp = character->getCurrentVehicle()->getPosition();
|
||||
glm::vec2 distance = glm::abs(position - glm::vec2(vp));
|
||||
|
||||
if(distance.x <= radius.x && distance.y <= radius.y)
|
||||
@ -250,14 +248,14 @@ bool game_player_in_area_2d_in_vehicle(const ScriptArguments& args)
|
||||
|
||||
bool game_character_near_point_on_foot_3D(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(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;
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
if( ! vehicle ) {
|
||||
auto distance = center - controller->getCharacter()->getPosition();
|
||||
auto distance = center - character->getPosition();
|
||||
distance /= size;
|
||||
if( glm::length( distance ) < 1.f ) return true;
|
||||
}
|
||||
@ -272,14 +270,14 @@ bool game_character_near_point_on_foot_3D(const ScriptArguments& args)
|
||||
|
||||
bool game_character_near_point_in_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(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;
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
if( vehicle ) {
|
||||
auto distance = center - controller->getCharacter()->getPosition();
|
||||
auto distance = center - character->getPosition();
|
||||
distance /= size;
|
||||
if( glm::length( distance ) < 1.f ) return true;
|
||||
}
|
||||
@ -289,13 +287,14 @@ bool game_character_near_point_in_vehicle(const ScriptArguments& args)
|
||||
|
||||
bool game_character_near_character_2D(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto target = static_cast<CharacterController*>(*args[1].handle);
|
||||
glm::vec2 center(target->getCharacter()->getPosition());
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto target = args.getGameObject(1);
|
||||
|
||||
glm::vec2 center(target->getPosition());
|
||||
glm::vec2 size(args[2].real, args[3].real);
|
||||
bool unkown = !!args[4].integer;
|
||||
|
||||
auto distance = center - glm::vec2(controller->getCharacter()->getPosition());
|
||||
auto distance = center - glm::vec2(character->getPosition());
|
||||
distance /= size;
|
||||
return glm::length( distance ) < 1.f;
|
||||
|
||||
@ -304,15 +303,15 @@ bool game_character_near_character_2D(const ScriptArguments& args)
|
||||
|
||||
bool game_character_near_character_in_vehicle_2D(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto target = static_cast<CharacterController*>(*args[1].handle);
|
||||
glm::vec2 center(target->getCharacter()->getPosition());
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto target = args.getGameObject(1);
|
||||
glm::vec2 center(target->getPosition());
|
||||
glm::vec2 size(args[2].real, args[3].real);
|
||||
bool unkown = !!args[4].integer;
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
if( vehicle ) {
|
||||
auto distance = center - glm::vec2(controller->getCharacter()->getPosition());
|
||||
auto distance = center - glm::vec2(character->getPosition());
|
||||
distance /= size;
|
||||
if( glm::length( distance ) < 1.f ) return true;
|
||||
}
|
||||
@ -322,14 +321,14 @@ bool game_character_near_character_in_vehicle_2D(const ScriptArguments& args)
|
||||
|
||||
bool game_character_near_point_on_foot_2D(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
glm::vec2 center(args[1].real, args[2].real);
|
||||
glm::vec2 size(args[3].real, args[4].real);
|
||||
bool unkown = !!args[5].integer;
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
if( !vehicle ) {
|
||||
auto distance = center - glm::vec2(controller->getCharacter()->getPosition());
|
||||
auto distance = center - glm::vec2(character->getPosition());
|
||||
distance /= size;
|
||||
if( glm::length( distance ) < 1.f ) return true;
|
||||
}
|
||||
@ -339,29 +338,30 @@ bool game_character_near_point_on_foot_2D(const ScriptArguments& args)
|
||||
|
||||
bool game_character_dead(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
|
||||
if ( controller )
|
||||
if ( character )
|
||||
{
|
||||
return !controller->getCharacter()->isAlive();
|
||||
return !character->isAlive();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool game_vehicle_dead(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<VehicleObject*>(*args[0].handle);
|
||||
return controller == nullptr;
|
||||
// TODO This won't work until vehicle destruction is finished
|
||||
auto vehicle = args.getGameObject(0);
|
||||
return vehicle == nullptr;
|
||||
}
|
||||
|
||||
bool game_character_in_zone(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
std::string zname(args[1].string);
|
||||
|
||||
auto zfind = args.getWorld()->data->zones.find(zname);
|
||||
if( zfind != args.getWorld()->data->zones.end() ) {
|
||||
auto player = controller->getCharacter()->getPosition();
|
||||
auto player = character->getPosition();
|
||||
auto& min = zfind->second.min;
|
||||
auto& max = zfind->second.max;
|
||||
if( player.x > min.x && player.y > min.y && player.z > min.z &&
|
||||
@ -375,7 +375,7 @@ bool game_character_in_zone(const ScriptArguments& args)
|
||||
|
||||
void game_create_character_in_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
auto type = args[1].integer;
|
||||
auto id = args[2].integer;
|
||||
|
||||
@ -385,40 +385,41 @@ void game_create_character_in_vehicle(const ScriptArguments& args)
|
||||
character->setCurrentVehicle(vehicle, 0);
|
||||
vehicle->setOccupant(0, character);
|
||||
|
||||
*args[3].handle = controller;
|
||||
*args[3].globalInteger = character->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_set_character_heading(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
controller->getCharacter()->setHeading(args[1].real);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
character->setHeading(args[1].real);
|
||||
}
|
||||
|
||||
void game_get_character_heading(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
|
||||
if ( vehicle )
|
||||
if ( character )
|
||||
{
|
||||
// TODO write this
|
||||
*args[1].globalReal = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
void game_set_vehicle_heading(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = (VehicleObject*)(*args[0].handle);
|
||||
vehicle->setHeading(args[1].real);
|
||||
auto object = args.getGameObject(0);
|
||||
object->setHeading(args[1].real);
|
||||
}
|
||||
|
||||
void game_set_object_heading(const ScriptArguments& args)
|
||||
{
|
||||
auto inst = (InstanceObject*)(*args[0].handle);
|
||||
inst->setHeading(args[1].real);
|
||||
auto object = args.getGameObject(0);
|
||||
object->setHeading(args[1].real);
|
||||
}
|
||||
|
||||
bool game_vehicle_stopped(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
|
||||
if( vehicle )
|
||||
{
|
||||
@ -430,7 +431,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 = (GameObject*)(*args[0].handle);
|
||||
auto object = args.getGameObject(0)->getGameObjectID();
|
||||
|
||||
auto& mO = args.getState()->missionObjects;
|
||||
mO.erase(std::remove(mO.begin(), mO.end(), object), mO.end());
|
||||
@ -444,22 +445,22 @@ bool game_character_in_area_on_foot(const ScriptArguments& args)
|
||||
|
||||
bool game_character_stoped_in_volume_in_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
bool drawCylinder = !!args[7].integer;
|
||||
|
||||
if( controller && controller->getCharacter()->getCurrentVehicle() != nullptr )
|
||||
if( character && character->getCurrentVehicle() != nullptr )
|
||||
{
|
||||
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 min = glm::min(vec1, vec2);
|
||||
glm::vec3 max = glm::max(vec1, vec2);
|
||||
|
||||
glm::vec3 pp = controller->getCharacter()->getCurrentVehicle()->getPosition();
|
||||
glm::vec3 pp = character->getCurrentVehicle()->getPosition();
|
||||
|
||||
if( pp.x >= min.x && pp.y >= min.y && pp.z >= min.z &&
|
||||
pp.x <= max.x && pp.y <= max.y && pp.z <= max.z )
|
||||
{
|
||||
return controller->getCharacter()->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
return character->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
}
|
||||
|
||||
// Request the renderer draw a cylinder here.
|
||||
@ -474,7 +475,7 @@ bool game_character_stoped_in_volume_in_vehicle(const ScriptArguments& args)
|
||||
|
||||
bool game_character_stoped_in_volume(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(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);
|
||||
@ -483,18 +484,18 @@ bool game_character_stoped_in_volume(const ScriptArguments& args)
|
||||
glm::vec3 min = glm::min(vec1, vec2);
|
||||
glm::vec3 max = glm::max(vec1, vec2);
|
||||
|
||||
glm::vec3 pp = controller->getCharacter()->getPosition();
|
||||
glm::vec3 pp = character->getPosition();
|
||||
|
||||
if( pp.x >= min.x && pp.y >= min.y && pp.z >= min.z &&
|
||||
pp.x <= max.x && pp.y <= max.y && pp.z <= max.z )
|
||||
{
|
||||
if( controller->getCharacter()->getCurrentVehicle() != nullptr )
|
||||
if( character->getCurrentVehicle() != nullptr )
|
||||
{
|
||||
return controller->getCharacter()->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
return character->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return controller->getCurrentActivity() == nullptr;
|
||||
return character->controller->getCurrentActivity() == nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,11 +510,11 @@ bool game_character_stoped_in_volume(const ScriptArguments& args)
|
||||
|
||||
bool game_is_character_stopped(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
|
||||
if( controller && controller->getCharacter()->getCurrentVehicle() != nullptr )
|
||||
if( character && character->getCurrentVehicle() != nullptr )
|
||||
{
|
||||
return controller->getCharacter()->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
return character->getCurrentVehicle()->physVehicle->getCurrentSpeedKmHour() < 0.75f;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -538,8 +539,9 @@ bool game_objects_in_volume(const ScriptArguments& args)
|
||||
bool objects = args[9].integer;
|
||||
bool particles = args[10].integer;
|
||||
|
||||
for(GameObject* object : args.getWorld()->objects)
|
||||
for(auto& pair : args.getWorld()->objects)
|
||||
{
|
||||
GameObject* object = pair.second;
|
||||
switch( object->type() )
|
||||
{
|
||||
case GameObject::Instance:
|
||||
@ -569,15 +571,15 @@ bool game_objects_in_volume(const ScriptArguments& args)
|
||||
|
||||
bool game_player_in_taxi(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = static_cast<CharacterController*>(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
|
||||
auto vehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto vehicle = character->getCurrentVehicle();
|
||||
return vehicle && (vehicle->vehicle->classType & VehicleData::TAXI) == VehicleData::TAXI;
|
||||
}
|
||||
|
||||
void game_get_speed(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
if( vehicle )
|
||||
{
|
||||
*args[1].globalReal = vehicle->physVehicle->getCurrentSpeedKmHour();
|
||||
@ -586,60 +588,60 @@ void game_get_speed(const ScriptArguments& args)
|
||||
|
||||
void game_enter_as_driver(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto vehicle = (VehicleObject*)(*args[1].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
|
||||
// Cancel whatever we're currently trying to do.
|
||||
controller->skipActivity();
|
||||
controller->setNextActivity(new Activities::EnterVehicle(vehicle,0));
|
||||
character->controller->skipActivity();
|
||||
character->controller->setNextActivity(new Activities::EnterVehicle(vehicle,0));
|
||||
}
|
||||
|
||||
void game_enter_as_passenger(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto vehicle = (VehicleObject*)(*args[1].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
|
||||
|
||||
// Cancel whatever we're currently trying to do.
|
||||
controller->skipActivity();
|
||||
character->controller->skipActivity();
|
||||
/// @todo find next lowest free seat.
|
||||
controller->setNextActivity(new Activities::EnterVehicle(vehicle,Activities::EnterVehicle::ANY_SEAT));
|
||||
character->controller->setNextActivity(new Activities::EnterVehicle(vehicle,Activities::EnterVehicle::ANY_SEAT));
|
||||
}
|
||||
|
||||
void game_character_exit_vehicle(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto vehicle = (VehicleObject*)(*args[1].handle);
|
||||
auto cvehcile = controller->getCharacter()->getCurrentVehicle();
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
|
||||
auto cvehcile = character->getCurrentVehicle();
|
||||
|
||||
if( cvehcile && cvehcile == vehicle )
|
||||
{
|
||||
controller->setNextActivity(new Activities::ExitVehicle());
|
||||
character->controller->setNextActivity(new Activities::ExitVehicle());
|
||||
}
|
||||
}
|
||||
|
||||
void game_character_follow_character(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto leader = (CharacterController*)(*args[1].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto leader = static_cast<CharacterObject*>(args.getGameObject(1));
|
||||
|
||||
controller->setGoal(CharacterController::FollowLeader);
|
||||
controller->setTargetCharacter(leader->getCharacter());
|
||||
character->controller->setGoal(CharacterController::FollowLeader);
|
||||
character->controller->setTargetCharacter(leader);
|
||||
}
|
||||
|
||||
void game_navigate_on_foot(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
glm::vec3 target(args[1].real, args[2].real, 0.f);
|
||||
target = args.getWorld()->getGroundAtPosition(target);
|
||||
|
||||
controller->skipActivity();
|
||||
character->controller->skipActivity();
|
||||
|
||||
if( controller->getCharacter()->getCurrentVehicle() )
|
||||
if( character->getCurrentVehicle() )
|
||||
{
|
||||
// Since we just cleared the Activities, this will become current immediatley.
|
||||
controller->setNextActivity(new Activities::ExitVehicle);
|
||||
character->controller->setNextActivity(new Activities::ExitVehicle);
|
||||
}
|
||||
|
||||
controller->setNextActivity(new Activities::GoTo(target));
|
||||
character->controller->setNextActivity(new Activities::GoTo(target));
|
||||
}
|
||||
|
||||
void game_create_pickup(const ScriptArguments& args)
|
||||
@ -682,14 +684,14 @@ void game_create_pickup(const ScriptArguments& args)
|
||||
|
||||
auto pickup = new GenericPickup(args.getWorld(), pos, id, type);
|
||||
|
||||
args.getWorld()->objects.insert(pickup);
|
||||
args.getWorld()->insertObject( pickup );
|
||||
|
||||
*args[5].handle = pickup;
|
||||
*args[5].globalInteger = pickup->getGameObjectID();
|
||||
}
|
||||
|
||||
bool game_is_pickup_collected(const ScriptArguments& args)
|
||||
{
|
||||
PickupObject* pickup = args[0].handleOf<PickupObject>();
|
||||
PickupObject* pickup = static_cast<PickupObject*>(args.getGameObject(0));
|
||||
|
||||
if ( pickup )
|
||||
{
|
||||
@ -701,7 +703,7 @@ bool game_is_pickup_collected(const ScriptArguments& args)
|
||||
|
||||
void game_destroy_pickup(const ScriptArguments& args)
|
||||
{
|
||||
PickupObject* pickup = args[0].handleOf<PickupObject>();
|
||||
PickupObject* pickup = static_cast<PickupObject*>(args.getGameObject(0));
|
||||
|
||||
if ( pickup )
|
||||
{
|
||||
@ -711,16 +713,16 @@ void game_destroy_pickup(const ScriptArguments& args)
|
||||
|
||||
void game_character_run_to(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
glm::vec3 target(args[1].real, args[2].real, 0.f);
|
||||
target = args.getWorld()->getGroundAtPosition(target);
|
||||
|
||||
controller->setNextActivity(new Activities::GoTo(target));
|
||||
character->controller->setNextActivity(new Activities::GoTo(target));
|
||||
}
|
||||
|
||||
bool game_vehicle_flipped(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
|
||||
if( vehicle )
|
||||
{
|
||||
@ -733,18 +735,18 @@ bool game_vehicle_flipped(const ScriptArguments& args)
|
||||
bool game_vehicle_in_air(const ScriptArguments& args)
|
||||
{
|
||||
/// @todo IS vehicle in air.
|
||||
auto vehicle = (VehicleObject*)(*args[0].handle);
|
||||
return false;
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool game_character_near_car_2d(const ScriptArguments& args)
|
||||
{
|
||||
auto controller = (CharacterController*)(*args[0].handle);
|
||||
auto vehicle = (VehicleObject*)(*args[1].handle);
|
||||
auto character = static_cast<CharacterObject*>(args.getGameObject(0));
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(1));
|
||||
glm::vec2 radius(args[2].real, args[3].real);
|
||||
bool drawMarker = !!args[4].integer;
|
||||
|
||||
auto charVehicle = controller->getCharacter()->getCurrentVehicle();
|
||||
auto charVehicle = character->getCurrentVehicle();
|
||||
if( charVehicle ) {
|
||||
auto dist = charVehicle->getPosition() - vehicle->getPosition();
|
||||
if( dist.x <= radius.x && dist.y <= radius.y ) {
|
||||
@ -757,7 +759,7 @@ bool game_character_near_car_2d(const ScriptArguments& args)
|
||||
|
||||
void game_set_vehicle_colours(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = (VehicleObject*)(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
|
||||
auto& colours = args.getWorld()->data->vehicleColours;
|
||||
vehicle->colourPrimary = colours[args[1].integer];
|
||||
@ -788,12 +790,12 @@ void game_create_object_world(const ScriptArguments& args)
|
||||
|
||||
auto inst = args.getWorld()->createInstance(id, position);
|
||||
|
||||
*args[4].handle = inst;
|
||||
*args[4].globalInteger = inst->getGameObjectID();
|
||||
}
|
||||
|
||||
void game_destroy_object(const ScriptArguments& args)
|
||||
{
|
||||
auto object = static_cast<GameObject*>(*args[0].handle);
|
||||
auto object = args.getGameObject(0);
|
||||
|
||||
args.getWorld()->destroyObjectQueued(object);
|
||||
}
|
||||
@ -842,7 +844,8 @@ void game_set_close_object_visible(const ScriptArguments& args)
|
||||
|
||||
std::transform(model.begin(), model.end(), model.begin(), ::tolower);
|
||||
|
||||
for(auto o : args.getWorld()->objects) {
|
||||
for(auto& p : args.getWorld()->objects) {
|
||||
auto o = p.second;
|
||||
if( o->type() == GameObject::Instance ) {
|
||||
if( !o->model ) continue;
|
||||
if( o->model->name != model ) continue;
|
||||
@ -899,7 +902,8 @@ 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 o : args.getWorld()->objects) {
|
||||
for(auto p : args.getWorld()->objects) {
|
||||
auto o = p.second;
|
||||
if( o->type() == GameObject::Instance ) {
|
||||
if( !o->model ) continue;
|
||||
if( o->model->name != oldmodel ) continue;
|
||||
@ -916,19 +920,22 @@ void game_change_nearest_model(const ScriptArguments& args)
|
||||
|
||||
bool game_rotate_object(const ScriptArguments& args)
|
||||
{
|
||||
auto object = static_cast<GameObject*>(*args[0].handle);
|
||||
float start = args[1].real;
|
||||
float finish = args[2].real;
|
||||
|
||||
// @todo INTERPOLATE instead of just setting the heading.
|
||||
object->setHeading(finish);
|
||||
auto object = args.getGameObject(0);
|
||||
if( object )
|
||||
{
|
||||
float start = args[1].real;
|
||||
float finish = args[2].real;
|
||||
|
||||
// @todo INTERPOLATE instead of just setting the heading.
|
||||
object->setHeading(finish);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void game_get_vehicle_colours(const ScriptArguments& args)
|
||||
{
|
||||
auto vehicle = static_cast<VehicleObject*>(*args[0].handle);
|
||||
auto vehicle = static_cast<VehicleObject*>(args.getGameObject(0));
|
||||
|
||||
if ( vehicle )
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <script/SCMFile.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <cstring>
|
||||
|
||||
SCMThread::pc_t localizeLabel(SCMThread* t, int label)
|
||||
{
|
||||
@ -107,14 +108,13 @@ void vm_halt_thread(const ScriptArguments& args)
|
||||
|
||||
void vm_call(const ScriptArguments& args)
|
||||
{
|
||||
args.getThread()->calls.push(args.getThread()->programCounter);
|
||||
args.getThread()->calls[args.getThread()->stackDepth++] = args.getThread()->programCounter;
|
||||
args.getThread()->programCounter = localizeLabel(args.getThread(), args[0].integer);
|
||||
}
|
||||
|
||||
void vm_return(const ScriptArguments& args)
|
||||
{
|
||||
args.getThread()->programCounter = args.getThread()->calls.top();
|
||||
args.getThread()->calls.pop();
|
||||
args.getThread()->programCounter = args.getThread()->calls[--args.getThread()->stackDepth];
|
||||
}
|
||||
|
||||
void vm_dec_global_int_by_global(const ScriptArguments& args)
|
||||
@ -159,9 +159,13 @@ void vm_new_mission_thread(const ScriptArguments& args)
|
||||
|
||||
void vm_mission_over(const ScriptArguments& args)
|
||||
{
|
||||
for( auto& o : args.getState()->missionObjects )
|
||||
for( auto oid : args.getState()->missionObjects )
|
||||
{
|
||||
args.getWorld()->destroyObjectQueued(o);
|
||||
auto obj = args.getWorld()->findObject(oid);
|
||||
if( obj )
|
||||
{
|
||||
args.getWorld()->destroyObjectQueued(obj);
|
||||
}
|
||||
}
|
||||
|
||||
args.getState()->missionObjects.clear();
|
||||
@ -171,7 +175,7 @@ void vm_mission_over(const ScriptArguments& args)
|
||||
|
||||
void vm_name_thread(const ScriptArguments& args)
|
||||
{
|
||||
args.getThread()->name = args[0].string;
|
||||
strncpy(args.getThread()->name, args[0].string, 16);
|
||||
}
|
||||
|
||||
void vm_start_mission(const ScriptArguments& args)
|
||||
|
19
rwengine/tests/test_GameWorld.cpp
Normal file
19
rwengine/tests/test_GameWorld.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <test_globals.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(GameWorldTests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_gameobject_id)
|
||||
{
|
||||
GameWorld gw(&Global::get().log, &Global::get().work, Global::get().d);
|
||||
|
||||
auto object1 = gw.createInstance(1337, glm::vec3(100.f, 0.f, 0.f));
|
||||
auto object2 = gw.createInstance(1337, glm::vec3(100.f, 0.f, 100.f));
|
||||
|
||||
BOOST_CHECK_NE( object1->getGameObjectID(), object2->getGameObjectID() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
49
rwengine/tests/test_SaveGame.cpp
Normal file
49
rwengine/tests/test_SaveGame.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/SaveGame.hpp>
|
||||
#include <test_globals.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(SaveGameTests)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_write_state)
|
||||
{
|
||||
GameState state;
|
||||
|
||||
// Set some test data
|
||||
state.world = nullptr;
|
||||
state.currentProgress = 10;
|
||||
state.maxProgress = 124;
|
||||
state.numMissions = 12;
|
||||
state.numHiddenPackages = 34;
|
||||
state.numHiddenPackagesDiscovered = 11;
|
||||
state.numUniqueJumps = 14;
|
||||
state.numRampages = 7;
|
||||
state.maxWantedLevel = 5;
|
||||
state.currentWeather = 9;
|
||||
state.overrideNextStart = true;
|
||||
state.hour = 13;
|
||||
state.minute = 32;
|
||||
|
||||
// This may break due to cwd issues
|
||||
SaveGame::writeState(state, "test_savestate.sav");
|
||||
|
||||
GameState loaded;
|
||||
loaded.world = nullptr;
|
||||
|
||||
BOOST_REQUIRE( SaveGame::loadState(loaded, "test_savestate.sav") );
|
||||
BOOST_CHECK( loaded.world == nullptr );
|
||||
BOOST_CHECK_EQUAL( loaded.currentProgress, state.currentProgress );
|
||||
BOOST_CHECK_EQUAL( loaded.maxProgress, state.maxProgress );
|
||||
BOOST_CHECK_EQUAL( loaded.numMissions, state.numMissions );
|
||||
BOOST_CHECK_EQUAL( loaded.numHiddenPackages, state.numHiddenPackages );
|
||||
BOOST_CHECK_EQUAL( loaded.numHiddenPackagesDiscovered, state.numHiddenPackagesDiscovered );
|
||||
BOOST_CHECK_EQUAL( loaded.numUniqueJumps, state.numUniqueJumps );
|
||||
BOOST_CHECK_EQUAL( loaded.numRampages, state.numRampages );
|
||||
BOOST_CHECK_EQUAL( loaded.maxWantedLevel, state.maxWantedLevel );
|
||||
BOOST_CHECK_EQUAL( loaded.currentWeather, state.currentWeather );
|
||||
BOOST_CHECK_EQUAL( loaded.overrideNextStart, state.overrideNextStart );
|
||||
BOOST_CHECK_EQUAL( loaded.hour, state.hour );
|
||||
BOOST_CHECK_EQUAL( loaded.minute, state.minute );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <engine/SaveGame.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
#include <render/DebugDraw.hpp>
|
||||
@ -124,12 +125,10 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
|
||||
data->loadTXD(name + ".txd");
|
||||
}
|
||||
|
||||
newGame();
|
||||
|
||||
auto loading = new LoadingState(this);
|
||||
if( newgame )
|
||||
{
|
||||
loading->setNextState(new IngameState(this,test));
|
||||
loading->setNextState(new IngameState(this,true,test));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -164,13 +163,60 @@ void RWGame::newGame()
|
||||
// Associate the new world with the new state and vice versa
|
||||
state->world = world;
|
||||
world->state = state;
|
||||
|
||||
for(std::map<std::string, std::string>::iterator it = world->data->iplLocations.begin();
|
||||
it != world->data->iplLocations.end();
|
||||
++it) {
|
||||
world->data->loadZone(it->second);
|
||||
world->placeItems(it->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
delete state->world;
|
||||
//delete state;
|
||||
state = nullptr;
|
||||
|
||||
newGame();
|
||||
|
||||
startScript("data/main.scm");
|
||||
|
||||
if(! SaveGame::loadScript(*script, savename+".script") )
|
||||
{
|
||||
log.error("Game", "Failed to restore Script");
|
||||
}
|
||||
if(! SaveGame::loadState(*state, savename+".state") )
|
||||
{
|
||||
log.error("Game", "Failed to restore State");
|
||||
}
|
||||
if(! SaveGame::loadObjects(*world, savename+".world") )
|
||||
{
|
||||
log.error("Game", "Failed to restore World");
|
||||
}
|
||||
// TODO objects.
|
||||
}
|
||||
|
||||
void RWGame::startScript(const std::string& name)
|
||||
{
|
||||
SCMFile* f = world->data->loadSCM(name);
|
||||
if( f ) {
|
||||
if( script ) delete script;
|
||||
if( script )
|
||||
{
|
||||
delete script;
|
||||
}
|
||||
|
||||
SCMOpcodes* opcodes = new SCMOpcodes;
|
||||
opcodes->modules.push_back(new VMModule);
|
||||
@ -206,6 +252,17 @@ void RWGame::startScript(const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
PlayerController *RWGame::getPlayer()
|
||||
{
|
||||
auto object = world->findObject(state->playerObject);
|
||||
if( object )
|
||||
{
|
||||
auto controller = static_cast<CharacterObject*>(object)->controller;
|
||||
return static_cast<PlayerController*>(controller);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int RWGame::run()
|
||||
{
|
||||
clock.restart();
|
||||
@ -283,7 +340,7 @@ void RWGame::tick(float dt)
|
||||
|
||||
static float clockAccumulator = 0.f;
|
||||
if (inFocus && currState->shouldWorldUpdate() ) {
|
||||
world->gameTime += dt;
|
||||
state->gameTime += dt;
|
||||
|
||||
clockAccumulator += dt;
|
||||
while( clockAccumulator >= 1.f ) {
|
||||
@ -306,7 +363,7 @@ void RWGame::tick(float dt)
|
||||
{
|
||||
auto& part = effect->particle;
|
||||
if( part.lifetime < 0.f ) continue;
|
||||
if( world->gameTime >= part.starttime + part.lifetime )
|
||||
if( world->getGameTime() >= part.starttime + part.lifetime )
|
||||
{
|
||||
world->destroyEffect( effect );
|
||||
--i;
|
||||
@ -314,7 +371,8 @@ void RWGame::tick(float dt)
|
||||
}
|
||||
}
|
||||
|
||||
for( GameObject* object : world->objects ) {
|
||||
for( auto& p : world->objects ) {
|
||||
GameObject* object = p.second;
|
||||
object->_updateLastTransform();
|
||||
object->tick(dt);
|
||||
}
|
||||
@ -325,7 +383,7 @@ void RWGame::tick(float dt)
|
||||
for( int i = 0; i < state->text.size(); )
|
||||
{
|
||||
auto& text = state->text[i];
|
||||
if( world->gameTime > text.osTextStart + text.osTextTime )
|
||||
if( world->getGameTime() > text.osTextStart + text.osTextTime )
|
||||
{
|
||||
state->text.erase(state->text.begin() + i);
|
||||
}
|
||||
@ -348,7 +406,7 @@ void RWGame::tick(float dt)
|
||||
}
|
||||
}
|
||||
|
||||
if ( state->player )
|
||||
if ( state->playerObject )
|
||||
{
|
||||
// Use the current camera position to spawn pedestrians.
|
||||
auto p = nextCam.position;
|
||||
@ -376,7 +434,7 @@ void RWGame::render(float alpha, float time)
|
||||
if( state->currentCutscene != nullptr && state->cutsceneStartTime >= 0.f )
|
||||
{
|
||||
auto cutscene = state->currentCutscene;
|
||||
float cutsceneTime = std::min(world->gameTime - state->cutsceneStartTime,
|
||||
float cutsceneTime = std::min(world->getGameTime() - state->cutsceneStartTime,
|
||||
cutscene->tracks.duration);
|
||||
cutsceneTime += GAME_TIMESTEP * alpha;
|
||||
glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
|
||||
@ -502,8 +560,9 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
|
||||
|
||||
// Count the number of interesting objects.
|
||||
int peds = 0, cars = 0;
|
||||
for( GameObject* object : world->objects )
|
||||
for( auto& p : world->objects )
|
||||
{
|
||||
GameObject* object = p.second;
|
||||
switch ( object->type() )
|
||||
{
|
||||
case GameObject::Character: peds++; break;
|
||||
@ -514,10 +573,13 @@ void RWGame::renderDebugStats(float time, Renderer::ProfileInfo& worldRenderTime
|
||||
|
||||
ss << "P " << peds << " V " << cars << "\n";
|
||||
|
||||
if( state->player ) {
|
||||
if( state->playerObject ) {
|
||||
ss << "Player (" << state->playerObject << ")\n";
|
||||
auto object = world->findObject(state->playerObject);
|
||||
auto player = static_cast<CharacterObject*>(object)->controller;
|
||||
ss << "Player Activity: ";
|
||||
if( state->player->getCurrentActivity() ) {
|
||||
ss << state->player->getCurrentActivity()->name();
|
||||
if( player->getCurrentActivity() ) {
|
||||
ss << player->getCurrentActivity()->name();
|
||||
}
|
||||
else {
|
||||
ss << "Idle";
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
class PlayerController;
|
||||
class RWGame
|
||||
{
|
||||
Logger log;
|
||||
@ -53,7 +54,12 @@ public:
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
GameData* getGameData() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
GameRenderer* getRenderer() const
|
||||
{
|
||||
return renderer;
|
||||
@ -103,6 +109,12 @@ public:
|
||||
|
||||
bool hasFocus() const { return inFocus; }
|
||||
|
||||
void saveGame(const std::string& savename);
|
||||
void loadGame(const std::string& savename);
|
||||
|
||||
/** shortcut for getWorld()->state.player->getCharacter() */
|
||||
PlayerController* getPlayer();
|
||||
|
||||
private:
|
||||
void tick(float dt);
|
||||
void render(float alpha, float dt);
|
||||
|
@ -7,19 +7,18 @@
|
||||
#include <sstream>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
void jumpCharacter(RWGame* game, CharacterController* controller, const glm::vec3& target)
|
||||
void jumpCharacter(RWGame* game, CharacterObject* player, const glm::vec3& target)
|
||||
{
|
||||
glm::vec3 ground = game->getWorld()->getGroundAtPosition(target);
|
||||
if( controller )
|
||||
if( player )
|
||||
{
|
||||
auto pl = controller->getCharacter();
|
||||
if( pl->getCurrentVehicle() )
|
||||
if( player->getCurrentVehicle() )
|
||||
{
|
||||
pl->getCurrentVehicle()->setPosition(ground + glm::vec3(0.f, 0.f, 1.f));
|
||||
player->getCurrentVehicle()->setPosition(ground + glm::vec3(0.f, 0.f, 1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
pl->setPosition(ground + glm::vec3(0.f, 0.f, 1.f));
|
||||
player->setPosition(ground + glm::vec3(0.f, 0.f, 1.f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,34 +71,40 @@ DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
|
||||
}, entryHeight));
|
||||
}
|
||||
#endif
|
||||
m->addEntry(Menu::lambda("Quicksave", [=] {
|
||||
game->saveGame("quicksave");
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Quickload", [=] {
|
||||
game->loadGame("quicksave");
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Jump to Garage", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state->player, glm::vec3(270.f, -605.f, 40.f));
|
||||
jumpCharacter(game, game->getPlayer()->getCharacter(), glm::vec3(270.f, -605.f, 40.f));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Jump to Airport", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state->player, glm::vec3(-950.f, -980.f, 12.f));
|
||||
jumpCharacter(game, game->getPlayer()->getCharacter(), glm::vec3(-950.f, -980.f, 12.f));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Jump to Hideout", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state->player, glm::vec3(875.0, -309.0, 100.0));
|
||||
jumpCharacter(game, game->getPlayer()->getCharacter(), glm::vec3(875.0, -309.0, 100.0));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Jump to Luigi's", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state->player, glm::vec3(902.75, -425.56, 100.0));
|
||||
jumpCharacter(game, game->getPlayer()->getCharacter(), glm::vec3(902.75, -425.56, 100.0));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Jump to Hospital", [=] {
|
||||
jumpCharacter(game, game->getWorld()->state->player, glm::vec3(1123.77, -569.15, 100.0));
|
||||
jumpCharacter(game, game->getPlayer()->getCharacter(), glm::vec3(1123.77, -569.15, 100.0));
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Add Follower", [=] {
|
||||
auto spawnPos = game->getWorld()->state->player->getCharacter()->getPosition();
|
||||
spawnPos += game->getWorld()->state->player->getCharacter()->getRotation() * glm::vec3(-1.f, 0.f, 0.f);
|
||||
auto spawnPos = game->getPlayer()->getCharacter()->getPosition();
|
||||
spawnPos += game->getPlayer()->getCharacter()->getRotation() * glm::vec3(-1.f, 0.f, 0.f);
|
||||
auto follower = game->getWorld()->createPedestrian(12, spawnPos);
|
||||
jumpCharacter(game, follower->controller, spawnPos);
|
||||
jumpCharacter(game, follower, spawnPos);
|
||||
follower->controller->setGoal(CharacterController::FollowLeader);
|
||||
follower->controller->setTargetCharacter(game->getWorld()->state->player->getCharacter());
|
||||
follower->controller->setTargetCharacter(game->getPlayer()->getCharacter());
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Set Super Jump", [=] {
|
||||
game->getWorld()->state->player->getCharacter()->setJumpSpeed(20.f);
|
||||
game->getPlayer()->getCharacter()->setJumpSpeed(20.f);
|
||||
}, entryHeight));
|
||||
m->addEntry(Menu::lambda("Set Normal Jump", [=] {
|
||||
game->getWorld()->state->player->getCharacter()->setJumpSpeed(CharacterObject::DefaultJumpSpeed);
|
||||
game->getPlayer()->getCharacter()->setJumpSpeed(CharacterObject::DefaultJumpSpeed);
|
||||
}, entryHeight));
|
||||
|
||||
this->enterMenu(m);
|
||||
@ -237,7 +242,7 @@ void DebugState::handleEvent(const sf::Event &e)
|
||||
|
||||
void DebugState::spawnVehicle(unsigned int id)
|
||||
{
|
||||
auto ch = getWorld()->state->player->getCharacter();
|
||||
auto ch = game->getPlayer()->getCharacter();
|
||||
if(! ch) return;
|
||||
|
||||
glm::vec3 fwd = ch->rotation * glm::vec3(0.f, 1.f, 0.f);
|
||||
|
@ -17,17 +17,17 @@
|
||||
|
||||
#define AUTOLOOK_TIME 2.f
|
||||
|
||||
IngameState::IngameState(RWGame* game, bool test)
|
||||
: State(game), started(false), test(test), autolookTimer(0.f)
|
||||
IngameState::IngameState(RWGame* game, bool newgame, bool test)
|
||||
: State(game), started(false), newgame(newgame), test(test), autolookTimer(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
void IngameState::startTest()
|
||||
{
|
||||
auto playerChar = getWorld()->createPedestrian(1, {270.f, -605.f, 40.f});
|
||||
auto playerChar = getWorld()->createPlayer({270.f, -605.f, 40.f});
|
||||
auto player = new PlayerController(playerChar);
|
||||
|
||||
getWorld()->state->player = player;
|
||||
getWorld()->state->playerObject = playerChar->getGameObjectID();
|
||||
|
||||
/*auto bat = new WeaponItem(getWorld()->data.weaponData["ak47"]);
|
||||
_playerCharacter->addToInventory(bat);
|
||||
@ -36,7 +36,7 @@ void IngameState::startTest()
|
||||
glm::vec3 itemspawn( 276.5f, -609.f, 36.5f);
|
||||
for( auto& w : getWorld()->data->weaponData ) {
|
||||
if( w.first == "unarmed" ) continue;
|
||||
getWorld()->objects.insert(new ItemPickup(getWorld(), itemspawn,
|
||||
getWorld()->insertObject(new ItemPickup(getWorld(), itemspawn,
|
||||
w.second));
|
||||
itemspawn.x += 2.5f;
|
||||
}
|
||||
@ -67,23 +67,22 @@ void IngameState::startTest()
|
||||
void IngameState::startGame()
|
||||
{
|
||||
game->startScript("data/main.scm");
|
||||
game->getScript()->startThread(0);
|
||||
getWorld()->sound.playBackground( getWorld()->data->getDataPath() + "/audio/City.wav" );
|
||||
}
|
||||
|
||||
PlayerController *IngameState::getPlayer()
|
||||
{
|
||||
return getWorld()->state->player;
|
||||
}
|
||||
|
||||
void IngameState::enter()
|
||||
{
|
||||
if( ! started )
|
||||
{
|
||||
if( test ) {
|
||||
startTest();
|
||||
}
|
||||
else {
|
||||
startGame();
|
||||
if( newgame )
|
||||
{
|
||||
if( test ) {
|
||||
startTest();
|
||||
}
|
||||
else {
|
||||
startGame();
|
||||
}
|
||||
}
|
||||
started = true;
|
||||
}
|
||||
@ -97,9 +96,9 @@ void IngameState::exit()
|
||||
void IngameState::tick(float dt)
|
||||
{
|
||||
autolookTimer = std::max(autolookTimer - dt, 0.f);
|
||||
|
||||
auto player = getPlayer();
|
||||
if( player && player->isInputEnabled() && game->hasFocus() )
|
||||
|
||||
auto player = game->getPlayer();
|
||||
if( player && player->isInputEnabled() )
|
||||
{
|
||||
float qpi = glm::half_pi<float>();
|
||||
|
||||
@ -135,7 +134,7 @@ void IngameState::tick(float dt)
|
||||
|
||||
player->updateMovementDirection(angle * _movement, _movement);
|
||||
|
||||
auto target = getWorld()->state->cameraTarget;
|
||||
auto target = getWorld()->findObject(getWorld()->state->cameraTarget);
|
||||
|
||||
if( target == nullptr )
|
||||
{
|
||||
@ -230,7 +229,7 @@ void IngameState::draw(GameRenderer* r)
|
||||
{
|
||||
if( !getWorld()->state->isCinematic && getWorld()->isCutsceneDone() )
|
||||
{
|
||||
drawHUD(getPlayer(), getWorld(), r);
|
||||
drawHUD(game->getPlayer(), getWorld(), r);
|
||||
}
|
||||
|
||||
State::draw(r);
|
||||
@ -238,7 +237,7 @@ void IngameState::draw(GameRenderer* r)
|
||||
|
||||
void IngameState::handleEvent(const sf::Event &event)
|
||||
{
|
||||
auto player = getPlayer();
|
||||
auto player = game->getPlayer();
|
||||
|
||||
switch(event.type) {
|
||||
case sf::Event::KeyPressed:
|
||||
|
@ -9,6 +9,7 @@ class IngameState : public State
|
||||
{
|
||||
bool started;
|
||||
bool test;
|
||||
bool newgame;
|
||||
ViewCamera _look;
|
||||
/** Player input */
|
||||
glm::vec2 _lookAngles;
|
||||
@ -16,14 +17,11 @@ class IngameState : public State
|
||||
/** Timer to reset _lookAngles to forward in vehicles */
|
||||
float autolookTimer;
|
||||
public:
|
||||
IngameState(RWGame* game, bool test = false);
|
||||
IngameState(RWGame* game, bool newgame = true, bool test = false);
|
||||
|
||||
void startTest();
|
||||
void startGame();
|
||||
|
||||
/** shortcut for getWorld()->state.player->getCharacter() */
|
||||
PlayerController* getPlayer();
|
||||
|
||||
virtual void enter();
|
||||
virtual void exit();
|
||||
|
||||
|
@ -9,23 +9,13 @@ LoadingState::LoadingState(RWGame* game)
|
||||
|
||||
void LoadingState::enter()
|
||||
{
|
||||
// Load all of the files waiting to be loaded.
|
||||
auto world = getWorld();
|
||||
|
||||
// Loade all of the IDEs.
|
||||
for(std::map<std::string, std::string>::iterator it = world->data->ideLocations.begin();
|
||||
it != world->data->ideLocations.end();
|
||||
++it) {
|
||||
world->data->loadObjects(it->second);
|
||||
// Load Item definitions
|
||||
for( auto& def : game->getGameData()->ideLocations )
|
||||
{
|
||||
game->getGameData()->loadObjects(def.second);
|
||||
}
|
||||
|
||||
// Load IPLs
|
||||
for(std::map<std::string, std::string>::iterator it = world->data->iplLocations.begin();
|
||||
it != world->data->iplLocations.end();
|
||||
++it) {
|
||||
world->data->loadZone(it->second);
|
||||
world->placeItems(it->second);
|
||||
}
|
||||
game->newGame();
|
||||
}
|
||||
|
||||
void LoadingState::exit()
|
||||
|
@ -10,7 +10,11 @@ MenuState::MenuState(RWGame* game)
|
||||
Menu *m = new Menu(2);
|
||||
m->offset = glm::vec2(200.f, 200.f);
|
||||
m->addEntry(Menu::lambda("Start", [=] { StateManager::get().enter(new IngameState(game)); }));
|
||||
m->addEntry(Menu::lambda("Test", [=] { StateManager::get().enter(new IngameState(game, true)); }));
|
||||
m->addEntry(Menu::lambda("Resume", [=] {
|
||||
StateManager::get().enter(new IngameState(game, false));
|
||||
game->loadGame("quicksave");
|
||||
}));
|
||||
m->addEntry(Menu::lambda("Test", [=] { StateManager::get().enter(new IngameState(game, true, true)); }));
|
||||
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
||||
m->addEntry(Menu::lambda("Exit", [=] { getWindow().close(); }));
|
||||
this->enterMenu(m);
|
||||
|
@ -3,6 +3,13 @@ add_executable(${SCRIPTTOOL} main.cpp)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/rwengine/include)
|
||||
|
||||
target_link_libraries(${SCRIPTTOOL} rwengine)
|
||||
target_link_libraries(${SCRIPTTOOL}
|
||||
rwengine
|
||||
sfml-graphics
|
||||
sfml-window
|
||||
sfml-system
|
||||
${OPENGL_LIBRARIES}
|
||||
GLEW
|
||||
${BULLET_LIBRARIES})
|
||||
|
||||
install(TARGETS ${SCRIPTTOOL} RUNTIME DESTINATION bin)
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
#include <script/SCMFile.hpp>
|
||||
#include <script/ScriptMachine.hpp>
|
||||
#include <script/ScriptDisassembly.hpp>
|
||||
#include <script/modules/VMModule.hpp>
|
||||
#include <script/modules/GameModule.hpp>
|
||||
#include <script/modules/ObjectModule.hpp>
|
||||
|
||||
#define FIELD_DESC_WIDTH 30
|
||||
#define FIELD_PARAM_WIDTH 8
|
||||
@ -37,132 +41,70 @@ void dumpCodeSizes(SCMFile* file)
|
||||
}
|
||||
}
|
||||
|
||||
void dumpOpcodes(SCMFile* scm, unsigned int offset, unsigned int size)
|
||||
void dumpOpcodes(SCMFile* scm, SCMOpcodes* codes, unsigned int offset, unsigned int size)
|
||||
{
|
||||
std::cout << "Offs Opcd " << std::setw(FIELD_DESC_WIDTH) << std::left
|
||||
<< "Description" << "Parameters" << std::endl;
|
||||
|
||||
for( unsigned int i = offset; i < offset+size; ) {
|
||||
SCMOpcode op = scm->read<SCMOpcode>(i) & ~SCM_NEGATE_CONDITIONAL_MASK;
|
||||
ScriptDisassembly disassembly(codes, scm);
|
||||
|
||||
auto opit = knownOps.find( op );
|
||||
try
|
||||
{
|
||||
disassembly.disassemble(offset);
|
||||
}
|
||||
catch( IllegalInstruction& ex )
|
||||
{
|
||||
std::cerr << "Error during disassembly: \n"
|
||||
<< ex.what() << std::endl;
|
||||
}
|
||||
|
||||
// If we don't know the size of the operator's parameters we can't jump over it.
|
||||
if( opit == knownOps.end() ) {
|
||||
throw IllegalInstruction(op, i, "");
|
||||
for( auto& inst : disassembly.getInstructions() )
|
||||
{
|
||||
ScriptFunctionMeta* code;
|
||||
if(! codes->findOpcode(inst.second.opcode, &code) )
|
||||
{
|
||||
std::cerr << "Invalid opcode in disassembly (" << inst.second.opcode << ")" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::hex << std::setfill('0') << std::right <<
|
||||
std::setw(4) << i << ":" <<
|
||||
std::setw(4) << op <<
|
||||
std::setw(FIELD_DESC_WIDTH) << std::setfill(' ') <<
|
||||
std::left << opit->second.name << std::right;
|
||||
std::setw(4) << inst.first << ":" <<
|
||||
std::setw(4) << inst.second.opcode << " " <<
|
||||
std::setw(FIELD_DESC_WIDTH) << std::setfill(' ') <<
|
||||
std::left << code->signature << std::right << "(";
|
||||
|
||||
i += sizeof(SCMOpcode);
|
||||
|
||||
bool hasMoreArgs = opit->second.parameters < 0;
|
||||
for( int p = 0; p < std::abs(opit->second.parameters) || hasMoreArgs; ++p ) {
|
||||
SCMByte datatype = scm->read<SCMByte>(i);
|
||||
|
||||
auto typeit = typeData.find(static_cast<SCMType>(datatype));
|
||||
if( typeit == typeData.end()) {
|
||||
if( datatype < 0x06 ) {
|
||||
throw UnknownType(datatype, i, "");
|
||||
}
|
||||
else {
|
||||
datatype = TString;
|
||||
}
|
||||
}
|
||||
else {
|
||||
i += sizeof(SCMByte);
|
||||
}
|
||||
|
||||
std::cout << " " << std::setfill('0') << std::setw(2) <<
|
||||
static_cast<unsigned int>(datatype) << ": ";
|
||||
std::cout << std::setfill(' ') << std::setw(FIELD_PARAM_WIDTH);
|
||||
|
||||
switch( datatype ) {
|
||||
case TInt32:
|
||||
std::cout << std::dec << scm->read<int32_t>(i);
|
||||
break;
|
||||
case TInt16:
|
||||
std::cout << std::dec << scm->read<int16_t>(i);
|
||||
break;
|
||||
case TGlobal:
|
||||
case TLocal:
|
||||
std::cout << std::hex << scm->read<int16_t>(i);
|
||||
break;
|
||||
case TInt8:
|
||||
std::cout << std::dec << static_cast<int>(scm->read<int8_t>(i));
|
||||
break;
|
||||
case TFloat16:
|
||||
std::cout << (float)scm->read<uint16_t>(i) / 16.f;
|
||||
break;
|
||||
case EndOfArgList:
|
||||
hasMoreArgs = false;
|
||||
break;
|
||||
case TString: {
|
||||
char strbuff[8];
|
||||
for(size_t c = 0; c < 8; ++c) {
|
||||
strbuff[c] = scm->read<char>(i++);
|
||||
}
|
||||
std::cout << strbuff << " ";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::cout << "{unknown}";
|
||||
break;
|
||||
}
|
||||
|
||||
if( typeit != typeData.end() ) {
|
||||
i += typeit->second.size;
|
||||
for( SCMOpcodeParameter& param : inst.second.parameters )
|
||||
{
|
||||
switch( param.type )
|
||||
{
|
||||
case TInt8:
|
||||
std::cout << " i8: " << param.integer;
|
||||
break;
|
||||
case TInt16:
|
||||
std::cout << " i16: " << param.integer;
|
||||
break;
|
||||
case TInt32:
|
||||
std::cout << " i32: " << param.integer;
|
||||
break;
|
||||
case TFloat16:
|
||||
std::cout << " f16: " << param.real;
|
||||
break;
|
||||
case TString:
|
||||
std::cout << " str: " << param.string;
|
||||
break;
|
||||
case TGlobal:
|
||||
std::cout << " g: " << param.globalPtr;
|
||||
break;
|
||||
case TLocal:
|
||||
std::cout << " l: " << param.globalPtr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << " )\n";
|
||||
}
|
||||
}
|
||||
|
||||
void loadKnownOps(const std::string& dbfile)
|
||||
{
|
||||
std::ifstream dbstream(dbfile.c_str());
|
||||
|
||||
if( !dbstream.is_open() ) {
|
||||
std::cerr << "Failed to open " << dbfile << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while( ! dbstream.eof() ) {
|
||||
std::string line;
|
||||
std::getline(dbstream, line);
|
||||
auto fnws = line.find_first_not_of(" ");
|
||||
if( fnws == line.npos || line.at(fnws) == '#' ) continue;
|
||||
|
||||
std::stringstream ss(line);
|
||||
|
||||
std::string sec;
|
||||
|
||||
std::getline(ss, sec, ',');
|
||||
|
||||
SCMMicrocode m;
|
||||
|
||||
uint16_t opcode = std::stoi(sec, 0, 16);
|
||||
|
||||
std::getline(ss, m.name, ',');
|
||||
|
||||
std::getline(ss, sec, ',');
|
||||
m.parameters = std::stoi(sec);
|
||||
|
||||
std::getline(ss, sec, ',');
|
||||
uint16_t flags = std::stoi(sec);
|
||||
|
||||
knownOps.insert({opcode, m});
|
||||
}
|
||||
|
||||
std::cout << knownOps.size() << " known opcodes " << std::endl;
|
||||
}
|
||||
|
||||
void readSCM(const std::string& scmname)
|
||||
void disassemble(const std::string& scmname)
|
||||
{
|
||||
std::ifstream scmfile(scmname.c_str());
|
||||
|
||||
@ -194,8 +136,13 @@ void readSCM(const std::string& scmname)
|
||||
dumpModels(&scm);
|
||||
|
||||
dumpCodeSizes(&scm);
|
||||
|
||||
dumpOpcodes(&scm, scm.getCodeSection(), size);
|
||||
|
||||
SCMOpcodes* opcodes = new SCMOpcodes;
|
||||
opcodes->modules.push_back(new VMModule);
|
||||
opcodes->modules.push_back(new GameModule);
|
||||
opcodes->modules.push_back(new ObjectModule);
|
||||
|
||||
dumpOpcodes(&scm, opcodes, scm.getCodeSection(), size);
|
||||
}
|
||||
catch (SCMException& ex) {
|
||||
std::cerr << ex.what() << std::endl;
|
||||
@ -210,9 +157,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
loadKnownOps("knownops.txt");
|
||||
|
||||
readSCM(std::string(argv[1]));
|
||||
disassemble(std::string(argv[1]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,18 +8,19 @@ BOOST_AUTO_TEST_SUITE(LifetimeTests)
|
||||
BOOST_AUTO_TEST_CASE(test_cleanup)
|
||||
{
|
||||
GameObject* f = Global::get().e->createInstance(1337, glm::vec3(0.f, 0.f, 1000.f));
|
||||
|
||||
auto id = f->getGameObjectID();
|
||||
|
||||
f->setLifetime(GameObject::TrafficLifetime);
|
||||
|
||||
{
|
||||
auto search = Global::get().e->objects.find( f );
|
||||
auto search = Global::get().e->objects.find( id );
|
||||
BOOST_CHECK( search != Global::get().e->objects.end() );
|
||||
}
|
||||
|
||||
Global::get().e->cleanupTraffic(glm::vec3(0.f, 0.f, 0.f));
|
||||
|
||||
{
|
||||
auto search = Global::get().e->objects.find( f );
|
||||
auto search = Global::get().e->objects.find( id );
|
||||
BOOST_CHECK( search == Global::get().e->objects.end() );
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(test_pickup_interaction)
|
||||
|
||||
TestPickup* p = new TestPickup(Global::get().e, { 30.f, 0.f, 0.f } );
|
||||
|
||||
Global::get().e->objects.insert(p);
|
||||
Global::get().e->insertObject(p);
|
||||
|
||||
BOOST_CHECK( ! p->picked_up );
|
||||
|
||||
@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(test_item_pickup)
|
||||
|
||||
ItemPickup* p = new ItemPickup(Global::get().e, { 30.f, 0.f, 0.f }, item );
|
||||
|
||||
Global::get().e->objects.insert(p);
|
||||
Global::get().e->insertObject(p);
|
||||
|
||||
// Check the characters inventory is empty.
|
||||
BOOST_CHECK( character->getInventory().empty() );
|
||||
|
@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile)
|
||||
wepdata
|
||||
});
|
||||
|
||||
Global::get().e->objects.insert( projectile );
|
||||
Global::get().e->insertObject( projectile );
|
||||
|
||||
BOOST_CHECK( character->mHealth == 100.f );
|
||||
|
||||
@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile)
|
||||
wepdata
|
||||
});
|
||||
|
||||
Global::get().e->objects.insert( projectile );
|
||||
Global::get().e->insertObject( projectile );
|
||||
|
||||
BOOST_CHECK( character->mHealth == 100.f );
|
||||
|
||||
@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(TestProjectile)
|
||||
wepdata
|
||||
});
|
||||
|
||||
Global::get().e->objects.insert( projectile );
|
||||
Global::get().e->insertObject( projectile );
|
||||
|
||||
BOOST_CHECK( character->mHealth == 100.f );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user