diff --git a/rwengine/src/ai/CharacterController.cpp b/rwengine/src/ai/CharacterController.cpp index aa9b5afb..9e243395 100644 --- a/rwengine/src/ai/CharacterController.cpp +++ b/rwengine/src/ai/CharacterController.cpp @@ -179,7 +179,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, RW_UNUSED(controller); // Boats don't have any kind of entry animation unless you're onboard. - if (vehicle->vehicle->type == VehicleData::BOAT) { + if (vehicle->getVehicle()->vehicletype_ == VehicleModelInfo::BOAT) { character->enterVehicle(vehicle, seat); return true; } @@ -344,7 +344,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, anm_exit = character->animations.car_getout_rhs; } - if (vehicle->vehicle->type == VehicleData::BOAT) { + if (vehicle->getVehicle()->vehicletype_ == VehicleModelInfo::BOAT) { auto ppos = character->getPosition(); character->enterVehicle(nullptr, seat); character->setPosition(ppos); diff --git a/rwengine/src/data/ModelData.cpp b/rwengine/src/data/ModelData.cpp index 77dc3d8a..278d0001 100644 --- a/rwengine/src/data/ModelData.cpp +++ b/rwengine/src/data/ModelData.cpp @@ -1,10 +1 @@ -#include "data/ObjectData.hpp" - -const ObjectInformation::ObjectClass ObjectData::class_id = - ObjectInformation::_class("OBJS"); -const ObjectInformation::ObjectClass VehicleData::class_id = - ObjectInformation::_class("CARS"); -const ObjectInformation::ObjectClass CharacterData::class_id = - ObjectInformation::_class("PEDS"); -const ObjectInformation::ObjectClass CutsceneObjectData::class_id = - ObjectInformation::_class("HIER"); +#include "data/ModelData.hpp" diff --git a/rwengine/src/data/ModelData.hpp b/rwengine/src/data/ModelData.hpp index 632053d7..d3a60363 100644 --- a/rwengine/src/data/ModelData.hpp +++ b/rwengine/src/data/ModelData.hpp @@ -4,109 +4,227 @@ #include #include #include +#include #include +#include #include +#include #ifdef RW_WINDOWS #include #endif -typedef uint16_t ObjectID; - /** - * Stores basic information about an Object and it's real type. + * 16-bit model ID identifier (from .ide) */ -struct ObjectInformation { - typedef size_t ObjectClass; - static ObjectClass _class(const std::string& name) { - return std::hash()(name); - } +using ModelID = uint16_t; - ObjectID ID; - const ObjectClass class_type; - - ObjectInformation(const ObjectClass type) : class_type(type) { - } - - virtual ~ObjectInformation() { - } +enum class ModelDataType { + SimpleInfo = 1, + /** Unknown */ + MLoModelInfo = 2, + /** Currently unused; data in SimpleInfo instead */ + TimeModelInfo = 3, + ClumpInfo = 4, + VehicleInfo = 5, + PedInfo = 6 }; -typedef std::shared_ptr ObjectInformationPtr; - /** - * Data used by Normal Objects + * Base type for all model information + * + * @todo reference counting + * @todo store collision model */ -struct ObjectData : public ObjectInformation { - static const ObjectClass class_id; +class BaseModelInfo { +public: + std::string name; + std::string textureslot; - ObjectData() : ObjectInformation(_class("OBJS")) { + BaseModelInfo(ModelDataType type) : type_(type) { } - std::string modelName; - std::string textureName; - uint8_t numClumps; - float drawDistance[3]; - int32_t flags; - bool LOD; + virtual ~BaseModelInfo() { + } - short timeOn; - short timeOff; + ModelID id() const { + return modelid_; + } + + void setModelID(ModelID id) { + modelid_ = id; + } + + ModelDataType type() const { + return type_; + } + + void addReference() { + refcount_++; + } + + void removeReference() { + refcount_--; + } + + int getReferenceCount() const { + return refcount_; + } + + /// @todo replace with proper streaming implementation + virtual bool isLoaded() const = 0; + + static std::string getTypeName(ModelDataType type) { + switch (type) { + case ModelDataType::SimpleInfo: + return "Simple"; + case ModelDataType::VehicleInfo: + return "Vehicle"; + case ModelDataType::PedInfo: + return "Pedestrian"; + case ModelDataType::ClumpInfo: + return "Cutscene"; + default: + break; + } + return "Unknown"; + } + +private: + ModelID modelid_ = 0; + ModelDataType type_; + int refcount_ = 0; +}; + +/** + * Model data for simple types + * + * @todo replace Model* with librw types + */ +class SimpleModelInfo : public BaseModelInfo { +public: + static constexpr ModelDataType kType = ModelDataType::SimpleInfo; + + /// @todo Use TimeModelInfo instead of hacking this in here + int timeOn = 0; + int timeOff = 24; + int flags; + /// @todo Remove this? + bool LOD = false; + /// Information loaded from PATH sections + /// @todo remove this from here too :) + std::vector paths; + + SimpleModelInfo() : BaseModelInfo(kType) { + } + SimpleModelInfo(ModelDataType type) : BaseModelInfo(type) { + } + + /// @todo change with librw + void setAtomic(Model* model, int n, ModelFrame* atomic) { + model_ = model; + atomics_[n] = atomic; + } + + ModelFrame* getAtomic(int n) const { + return atomics_[n]; + } + + void setLodDistance(int n, float d) { + RW_CHECK(n < 3, "Lod Index out of range"); + loddistances_[n] = d; + } + + float getLodDistance(int n) { + RW_CHECK(n < 3, "Lod Index out of range"); + return loddistances_[n]; + } + + void setNumAtomics(int num) { + numatomics_ = num; + } + + int getNumAtomics() const { + return numatomics_; + } enum { - NORMAL_CULL = - 1, /// Cull model if player doesn't look at it. Ignored in GTA 3. - DO_NOT_FADE = 1 << 1, /// Do not fade the object when it is being - /// loaded into or out of view. - DRAW_LAST = 1 << 2, /// Model is transparent. Render this object after - /// all opaque objects, allowing transparencies of - /// other objects to be visible through this - /// object. - ADDITIVE = 1 << 3, /// Render with additive blending. Previous flag - /// must be enabled too. - IS_SUBWAY = 1 << 4, /// Model is a tunnel, i.e. set the object as - /// invisible unless the player enters cull zone - /// flag 128. This flag works only with static - /// models. - IGNORE_LIGHTING = 1 << 5, /// Don't use static lighting, we want - /// dynamic if it's possible. - NO_ZBUFFER_WRITE = - 1 << 6, /// Model is a shadow. Disable writing to z-buffer when - /// rendering it, allowing transparencies of other objects, - /// shadows, and lights to be visible through this object. - /// (Not implemented in the PS2 version) + /// Cull model if player doesn't look at it. Ignored in GTA 3. + NORMAL_CULL = 1, + /// Do not fade the object when it is being + /// loaded into or out of view. + DO_NOT_FADE = 1 << 1, + /// Model is transparent. Render this object after + /// all opaque objects, allowing transparencies of + /// other objects to be visible through this + /// object. + DRAW_LAST = 1 << 2, + /// Render with additive blending. Previous flag + /// must be enabled too. + ADDITIVE = 1 << 3, + /// Model is a tunnel, i.e. set the object as + /// invisible unless the player enters cull zone + /// flag 128. This flag works only with static + /// models. + IS_SUBWAY = 1 << 4, + /// Don't use static lighting, we want + /// dynamic if it's possible. + IGNORE_LIGHTING = 1 << 5, + /// Model is a shadow. Disable writing to z-buffer when + /// rendering it, allowing transparencies of other objects, + /// shadows, and lights to be visible through this object. + /// (Not implemented in the PS2 version) + NO_ZBUFFER_WRITE = 1 << 6, }; - // Information loaded from PATH sections - std::vector paths; +private: + Model* model_ = nullptr; + ModelFrame* atomics_[3] = {}; + float loddistances_[3] = {}; + uint8_t numatomics_ = 0; + uint8_t alpha_ = 0; /// @todo ask aap why }; -typedef std::shared_ptr ObjectDataPtr; +/** + * @todo this + */ +class TimeModelInfo : public SimpleModelInfo { + TimeModelInfo() : SimpleModelInfo(ModelDataType::TimeModelInfo) { + } +}; /** - * Data used by peds + * @todo document me */ -struct CharacterData : public ObjectInformation { - static const ObjectClass class_id; +class ClumpModelInfo : public BaseModelInfo { +public: + static constexpr ModelDataType kType = ModelDataType::ClumpInfo; - CharacterData() : ObjectInformation(_class("PEDS")) { + ClumpModelInfo() : BaseModelInfo(kType) { + } + ClumpModelInfo(ModelDataType type) : BaseModelInfo(type) { } - std::string modelName; - std::string textureName; - std::string type; - std::string behaviour; - std::string animGroup; - uint8_t driveMask; + void setModel(Model* model) { + model_ = model; + } + + Model* getModel() const { + return model_; + } + +private: + Model* model_ = nullptr; }; /** - * @brief Stores vehicle data loaded from item definition files. + * Data for a vehicle model type */ -struct VehicleData : public ObjectInformation { - static const ObjectClass class_id; +class VehicleModelInfo : public ClumpModelInfo { +public: + static constexpr ModelDataType kType = ModelDataType::VehicleInfo; - VehicleData() : ObjectInformation(_class("CARS")) { + VehicleModelInfo() : ClumpModelInfo(kType) { } enum VehicleClass { @@ -124,6 +242,8 @@ struct VehicleData : public ObjectInformation { WORKERBOAT = 1 << 10, BICYCLE = 1 << 11, ONFOOT = 1 << 12, + /// @todo verify that this is the correct bit + SPECIAL = 1 << 13, }; enum VehicleType { @@ -134,32 +254,120 @@ struct VehicleData : public ObjectInformation { HELI, }; - std::string modelName; - std::string textureName; - VehicleType type; - std::string handlingID; - std::string gameName; - VehicleClass classType; - uint8_t frequency; // big enough int type? - uint8_t lvl; // big enough int type? - uint16_t comprules; - union { // big enough int types? - uint16_t wheelModelID; // used only when type == CAR - int16_t modelLOD; // used only when type == PLANE - }; - float wheelScale; // used only when type == CAR -}; + VehicleType vehicletype_; + ModelID wheelmodel_; + float wheelscale_; + int numdoors_; + std::string handling_; + VehicleClass vehicleclass_; + int frequency_; + int level_; + int componentrules_; + std::string vehiclename_; -typedef std::shared_ptr VehicleDataHandle; - -struct CutsceneObjectData : public ObjectInformation { - static const ObjectClass class_id; - - CutsceneObjectData() : ObjectInformation(_class("HIER")) { + static VehicleType findVehicleType(const std::string& name) { + static const std::unordered_map vehicleTypes{ + {"car", CAR}, + {"boat", BOAT}, + {"train", TRAIN}, + {"plane", PLANE}, + {"heli", HELI}}; + return vehicleTypes.at(name); } - std::string modelName; - std::string textureName; + static VehicleClass findVehicleClass(const std::string& name) { + static const std::unordered_map classTypes{ + // III, VC, SA + {"ignore", IGNORE}, + {"normal", NORMAL}, + {"poorfamily", POORFAMILY}, + {"richfamily", RICHFAMILY}, + {"executive", EXECUTIVE}, + {"worker", WORKER}, + {"big", BIG}, + {"taxi", TAXI}, + {"special", SPECIAL}, + // VC, SA + {"moped", MOPED}, + {"motorbike", MOTORBIKE}, + {"leisureboat", LEISUREBOAT}, + {"workerboat", WORKERBOAT}, + {"bicycle", BICYCLE}, + {"onfoot", ONFOOT}, + }; + return classTypes.at(name); + } +}; + +class PedModelInfo : public ClumpModelInfo { +public: + static constexpr ModelDataType kType = ModelDataType::PedInfo; + + PedModelInfo() : ClumpModelInfo(kType) { + } + + enum PedType { + // III + PLAYER1 = 0, + PLAYER2, + PLAYER3, + PLAYER_4, + CIVMALE, + CIVFEMALE, + COP, + GANG1, + GANG2, + GANG3, + GANG4, + GANG5, + GANG6, + GANG7, + GANG8, + GANG9, + EMERGENCY, + FIREMAN, + CRIMINAL, + _UNNAMED, + PROSTITUTE, + SPECIAL, + }; + + PedType pedtype_ = PLAYER1; + /// @todo this should be an index + std::string behaviour_; + /// @todo this should be an index + std::string animgroup_; + /// The mask of vehicle classes this ped can drive + int carsmask_ = 0; + + static PedType findPedType(const std::string& name) { + static const std::unordered_map pedTypes{ + // III + {"PLAYER1", PLAYER1}, + {"PLAYER2", PLAYER2}, + {"PLAYER3", PLAYER3}, + {"PLAYER_4", PLAYER_4}, + {"CIVMALE", CIVMALE}, + {"CIVFEMALE", CIVFEMALE}, + {"COP", COP}, + {"GANG1", GANG1}, + {"GANG2", GANG2}, + {"GANG3", GANG3}, + {"GANG4", GANG4}, + {"GANG5", GANG5}, + {"GANG6", GANG6}, + {"GANG7", GANG7}, + {"GANG8", GANG8}, + {"GANG9", GANG9}, + {"EMERGENCY", EMERGENCY}, + {"FIREMAN", FIREMAN}, + {"CRIMINAL", CRIMINAL}, + {"_UNNAMED", _UNNAMED}, + {"PROSTITUTE", PROSTITUTE}, + {"SPECIAL", SPECIAL}, + }; + return pedTypes.at(name); + } }; /** diff --git a/rwengine/src/engine/GameData.cpp b/rwengine/src/engine/GameData.cpp index 98bd12e2..1396c3d1 100644 --- a/rwengine/src/engine/GameData.cpp +++ b/rwengine/src/engine/GameData.cpp @@ -109,23 +109,19 @@ void GameData::loadIDE(const std::string& path) { LoaderIDE idel; if (idel.load(systempath)) { - objectTypes.insert(idel.objects.begin(), idel.objects.end()); + std::move(idel.objects.begin(), idel.objects.end(), + std::inserter(modelinfo, modelinfo.end())); } else { logger->error("Data", "Failed to load IDE " + path); } } uint16_t GameData::findModelObject(const std::string model) { - auto defit = std::find_if( - objectTypes.begin(), objectTypes.end(), - [&](const decltype(objectTypes)::value_type& d) { - if (d.second->class_type == ObjectInformation::_class("OBJS")) { - auto dat = static_cast(d.second.get()); - return boost::iequals(dat->modelName, model); - } - return false; - }); - if (defit != objectTypes.end()) return defit->first; + auto defit = std::find_if(modelinfo.begin(), modelinfo.end(), + [&](const decltype(modelinfo)::value_type& d) { + return boost::iequals(d.second->name, model); + }); + if (defit != modelinfo.end()) return defit->first; return -1; } diff --git a/rwengine/src/engine/GameData.hpp b/rwengine/src/engine/GameData.hpp index b33508d5..e692ec55 100644 --- a/rwengine/src/engine/GameData.hpp +++ b/rwengine/src/engine/GameData.hpp @@ -170,20 +170,15 @@ public: */ std::map zones; - /** - * Object Definitions - */ - std::map objectTypes; + std::unordered_map> modelinfo; uint16_t findModelObject(const std::string model); template - std::shared_ptr findObjectType(ObjectID id) { - auto f = objectTypes.find(id); - /// @TODO don't instanciate an object here just to read .type - T tmp; - if (f != objectTypes.end() && f->second->class_type == tmp.class_type) { - return std::static_pointer_cast(f->second); + T* findModelInfo(ModelID id) { + auto f = modelinfo.find(id); + if (f != modelinfo.end() && f->second->type() == T::kType) { + return static_cast(f->second.get()); } return nullptr; } diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index 256b9e20..f03bcec5 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -140,10 +140,10 @@ bool GameWorld::placeItems(const std::string& name) { for (auto& p : instancePool.objects) { auto object = p.second; InstanceObject* instance = static_cast(object); - if (!instance->object->LOD && - instance->object->modelName.length() > 3) { - auto lodInstit = modelInstances.find( - "LOD" + instance->object->modelName.substr(3)); + auto modelinfo = instance->getModelInfo(); + if (!modelinfo->LOD && modelinfo->name.length() > 3) { + auto lodInstit = + modelInstances.find("LOD" + modelinfo->name.substr(3)); if (lodInstit != modelInstances.end()) { instance->LODinstance = lodInstit->second; } @@ -162,10 +162,10 @@ bool GameWorld::placeItems(const std::string& name) { InstanceObject* GameWorld::createInstance(const uint16_t id, const glm::vec3& pos, const glm::quat& rot) { - auto oi = data->findObjectType(id); + auto oi = data->findModelInfo(id); if (oi) { - std::string modelname = oi->modelName; - std::string texturename = oi->textureName; + std::string modelname = oi->name; + std::string texturename = oi->textureslot; std::transform(std::begin(modelname), std::end(modelname), std::begin(modelname), tolower); @@ -173,7 +173,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id, std::begin(texturename), tolower); // Ensure the relevant data is loaded. - if (!oi->modelName.empty()) { + if (!modelname.empty()) { if (modelname != "null") { data->loadDFF(modelname + ".dff", false); } @@ -185,7 +185,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id, ModelRef m = data->models[modelname]; // Check for dynamic data. - auto dyit = data->dynamicObjectData.find(oi->modelName); + auto dyit = data->dynamicObjectData.find(oi->name); std::shared_ptr dydata; if (dyit != data->dynamicObjectData.end()) { dydata = dyit->second; @@ -202,7 +202,7 @@ InstanceObject* GameWorld::createInstance(const uint16_t id, instancePool.insert(instance); allObjects.push_back(instance); - modelInstances.insert({oi->modelName, instance}); + modelInstances.insert({oi->name, instance}); return instance; } @@ -250,34 +250,33 @@ void GameWorld::cleanupTraffic(const ViewCamera& focus) { CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id, const glm::vec3& pos, const glm::quat& rot) { + auto modelinfo = data->modelinfo[id].get(); std::string modelname; std::string texturename; - auto type = data->objectTypes.find(id); - if (type != data->objectTypes.end()) { - if (type->second->class_type == ObjectInformation::_class("HIER")) { - modelname = state->specialModels[id]; - texturename = state->specialModels[id]; - } else { - if (type->second->class_type == ObjectInformation::_class("OBJS")) { - auto v = static_cast(type->second.get()); - modelname = v->modelName; - texturename = v->textureName; - } else if (type->second->class_type == - ObjectInformation::_class("PEDS")) { - auto v = static_cast(type->second.get()); - modelname = v->modelName; - texturename = v->textureName; + if (modelinfo) { + modelname = modelinfo->name; + texturename = modelinfo->textureslot; - static std::string specialPrefix("special"); + /// @todo Store loaded models directly + switch (modelinfo->type()) { + case ModelDataType::ClumpInfo: + // Re-direct the hier objects to the special object ids + modelname = state->specialModels[id]; + texturename = state->specialModels[id]; + break; + case ModelDataType::PedInfo: + static const std::string specialPrefix("special"); if (!modelname.compare(0, specialPrefix.size(), specialPrefix)) { auto sid = modelname.substr(specialPrefix.size()); unsigned short specialID = std::atoi(sid.c_str()); modelname = state->specialCharacters[specialID]; texturename = state->specialCharacters[specialID]; + break; } - } + default: + break; } } @@ -305,7 +304,7 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id, ModelRef m = data->models[modelname]; - auto instance = new CutsceneObject(this, pos, rot, m); + auto instance = new CutsceneObject(this, pos, rot, m, modelinfo); cutscenePool.insert(instance); allObjects.push_back(instance); @@ -316,21 +315,21 @@ CutsceneObject* GameWorld::createCutsceneObject(const uint16_t id, VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot, GameObjectID gid) { - auto vti = data->findObjectType(id); + auto vti = data->findModelInfo(id); if (vti) { logger->info("World", "Creating Vehicle ID " + std::to_string(id) + - " (" + vti->gameName + ")"); + " (" + vti->vehiclename_ + ")"); - if (!vti->modelName.empty()) { - data->loadDFF(vti->modelName + ".dff"); + if (!vti->name.empty()) { + data->loadDFF(vti->name + ".dff"); } - if (!vti->textureName.empty()) { - data->loadTXD(vti->textureName + ".txd"); + if (!vti->textureslot.empty()) { + data->loadTXD(vti->textureslot + ".txd"); } glm::u8vec3 prim(255), sec(128); auto palit = data->vehiclePalettes.find( - vti->modelName); // modelname is conveniently lowercase (usually) + vti->name); // modelname is conveniently lowercase (usually) if (palit != data->vehiclePalettes.end() && palit->second.size() > 0) { std::uniform_int_distribution uniform( 0, palit->second.size() - 1); @@ -339,19 +338,12 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, sec = data->vehicleColours[palit->second[set].second]; } else { logger->warning("World", - "No colour palette for vehicle " + vti->modelName); + "No colour palette for vehicle " + vti->name); } - auto wi = data->findObjectType(vti->wheelModelID); - if (wi) { - if (!wi->textureName.empty()) { - data->loadTXD(wi->textureName + ".txd"); - } - } - - ModelRef& m = data->models[vti->modelName]; + ModelRef& m = data->models[vti->name]; auto model = m->resource; - auto info = data->vehicleInfo.find(vti->handlingID); + auto info = data->vehicleInfo.find(vti->handling_); if (model && info != data->vehicleInfo.end()) { if (info->second->wheels.size() == 0 && info->second->seats.size() == 0) { @@ -403,13 +395,13 @@ CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3& pos, const glm::quat& rot, GameObjectID gid) { - auto pt = data->findObjectType(id); + auto pt = data->findModelInfo(id); if (pt) { - std::string modelname = pt->modelName; - std::string texturename = pt->textureName; + std::string modelname = pt->name; + std::string texturename = pt->textureslot; // Ensure the relevant data is loaded. - if (!pt->modelName.empty()) { + if (!modelname.empty()) { // Some model names have special meanings. /// @todo Should CharacterObjects handle this? static std::string specialPrefix("special"); @@ -446,7 +438,7 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos, const glm::quat& rot, GameObjectID gid) { // Player object ID is hardcoded to 0. - auto pt = data->findObjectType(0); + auto pt = data->findModelInfo(0); if (pt) { // Model name is also hardcoded. std::string modelname = "player"; @@ -472,15 +464,15 @@ CharacterObject* GameWorld::createPlayer(const glm::vec3& pos, } PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) { - auto modelInfo = data->findObjectType(id); + auto modelInfo = data->modelinfo[id].get(); RW_CHECK(modelInfo != nullptr, "Pickup Object Data is not found"); if (modelInfo == nullptr) { return nullptr; } - data->loadDFF(modelInfo->modelName + ".dff"); - data->loadTXD(modelInfo->textureName + ".txd"); + data->loadDFF(modelInfo->name + ".dff"); + data->loadTXD(modelInfo->textureslot + ".txd"); PickupObject* pickup = nullptr; auto pickuptype = (PickupObject::PickupType)type; @@ -492,10 +484,10 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) { // If nothing, create a generic pickup instead of an item pickup if (it != inventoryItems.end()) { - pickup = new ItemPickup(this, pos, pickuptype, *it); + pickup = new ItemPickup(this, pos, modelInfo, pickuptype, *it); } else { RW_UNIMPLEMENTED("Non-weapon pickups"); - pickup = new PickupObject(this, pos, id, pickuptype); + pickup = new PickupObject(this, pos, modelInfo, pickuptype); } pickupPool.insert(pickup); diff --git a/rwengine/src/loaders/LoaderIDE.cpp b/rwengine/src/loaders/LoaderIDE.cpp index 9a83fa11..26b00e8f 100644 --- a/rwengine/src/loaders/LoaderIDE.cpp +++ b/rwengine/src/loaders/LoaderIDE.cpp @@ -48,34 +48,35 @@ bool LoaderIDE::load(const std::string &filename) { line.end()); std::stringstream strstream(line); + std::string buff; switch (section) { default: break; case OBJS: case TOBJ: { // Supports Type 1, 2 and 3 - std::shared_ptr objs(new ObjectData); + auto objs = + std::unique_ptr(new SimpleModelInfo); - std::string id, numClumps, flags, modelName, textureName; + getline(strstream, buff, ','); + objs->setModelID(atoi(buff.c_str())); - // Read the content of the line - getline(strstream, id, ','); - getline(strstream, modelName, ','); - getline(strstream, textureName, ','); - getline(strstream, numClumps, ','); + getline(strstream, objs->name, ','); + getline(strstream, objs->textureslot, ','); - objs->numClumps = atoi(numClumps.c_str()); - for (size_t i = 0; i < objs->numClumps; i++) { - std::string drawDistance; - getline(strstream, drawDistance, ','); - objs->drawDistance[i] = atoi(drawDistance.c_str()); + getline(strstream, buff, ','); + objs->setNumAtomics(atoi(buff.c_str())); + + for (int i = 0; i < objs->getNumAtomics(); i++) { + getline(strstream, buff, ','); + objs->setLodDistance(i, atof(buff.c_str())); } - getline(strstream, flags, ','); + getline(strstream, buff, ','); + objs->flags = atoi(buff.c_str()); // Keep reading TOBJ data if (section == LoaderIDE::TOBJ) { - std::string buff; getline(strstream, buff, ','); objs->timeOn = atoi(buff.c_str()); getline(strstream, buff, ','); @@ -85,104 +86,82 @@ bool LoaderIDE::load(const std::string &filename) { objs->timeOff = 24; } - // Put stuff in our struct - objs->ID = atoi(id.c_str()); - objs->flags = atoi(flags.c_str()); - objs->modelName = modelName; - objs->textureName = textureName; - objs->LOD = false; - - if (modelName.find("LOD", 0, 3) != modelName.npos && - modelName != "LODistancoast01") { + /// @todo Figure out how LOD stuff is intended to work + if (objs->name.find("LOD", 0, 3) != std::string::npos && + objs->name != "LODistancoast01") { objs->LOD = true; } - objects.insert({objs->ID, objs}); + objects.emplace(objs->id(), std::move(objs)); break; } case CARS: { - std::shared_ptr cars(new VehicleData); + auto cars = + std::unique_ptr(new VehicleModelInfo); - std::string id, type, classType, frequency, lvl, comprules, - wheelModelID, wheelScale; + getline(strstream, buff, ','); + cars->setModelID(std::atoi(buff.c_str())); - getline(strstream, id, ','); - getline(strstream, cars->modelName, ','); - getline(strstream, cars->textureName, ','); - getline(strstream, type, ','); - getline(strstream, cars->handlingID, ','); - getline(strstream, cars->gameName, ','); - getline(strstream, classType, ','); - getline(strstream, frequency, ','); - getline(strstream, lvl, ','); - getline(strstream, comprules, ','); - getline(strstream, wheelModelID, ','); - getline(strstream, wheelScale, ','); + getline(strstream, cars->name, ','); + getline(strstream, cars->textureslot, ','); - cars->ID = atoi(id.c_str()); - cars->frequency = atoi(frequency.c_str()); - cars->lvl = atoi(lvl.c_str()); - cars->comprules = atoi(comprules.c_str()); + getline(strstream, buff, ','); + cars->vehicletype_ = + VehicleModelInfo::findVehicleType(buff); - if (type == "car") { - cars->type = VehicleData::CAR; - cars->wheelModelID = atoi(wheelModelID.c_str()); - cars->wheelScale = atof(wheelScale.c_str()); - } else if (type == "boat") { - cars->type = VehicleData::BOAT; - } else if (type == "train") { - cars->type = VehicleData::TRAIN; - cars->modelLOD = atoi(wheelModelID.c_str()); - } else if (type == "plane") { - cars->type = VehicleData::PLANE; - } else if (type == "heli") { - cars->type = VehicleData::HELI; - } + getline(strstream, cars->handling_, ','); + getline(strstream, cars->vehiclename_, ','); + getline(strstream, buff, ','); + cars->vehicleclass_ = + VehicleModelInfo::findVehicleClass(buff); - const std::map - classTypes{ - {VehicleData::IGNORE, "ignore"}, - {VehicleData::NORMAL, "normal"}, - {VehicleData::POORFAMILY, "poorfamily"}, - {VehicleData::RICHFAMILY, "richfamily"}, - {VehicleData::EXECUTIVE, "executive"}, - {VehicleData::WORKER, "worker"}, - {VehicleData::BIG, "big"}, - {VehicleData::TAXI, "taxi"}, - {VehicleData::MOPED, "moped"}, - {VehicleData::MOTORBIKE, "motorbike"}, - {VehicleData::LEISUREBOAT, "leisureboat"}, - {VehicleData::WORKERBOAT, "workerboat"}, - {VehicleData::BICYCLE, "bicycle"}, - {VehicleData::ONFOOT, "onfoot"}, - }; - for (auto &a : classTypes) { - if (classType == a.second) { - cars->classType = a.first; + getline(strstream, buff, ','); + cars->frequency_ = std::atoi(buff.c_str()); + + getline(strstream, buff, ','); + cars->level_ = std::atoi(buff.c_str()); + + getline(strstream, buff, ','); + cars->componentrules_ = std::atoi(buff.c_str()); + + switch (cars->vehicletype_) { + case VehicleModelInfo::CAR: + getline(strstream, buff, ','); + cars->wheelmodel_ = std::atoi(buff.c_str()); + getline(strstream, buff, ','); + cars->wheelscale_ = std::atof(buff.c_str()); + break; + case VehicleModelInfo::PLANE: + /// @todo load LOD + getline(strstream, buff, ','); + // cars->planeLOD_ = std::atoi(buff.c_str()); + break; + default: break; - } } - objects.insert({cars->ID, cars}); + objects.emplace(cars->id(), std::move(cars)); break; } case PEDS: { - std::shared_ptr peds(new CharacterData); + auto peds = std::unique_ptr(new PedModelInfo); - std::string id, driveMask; + getline(strstream, buff, ','); + peds->setModelID(std::atoi(buff.c_str())); - getline(strstream, id, ','); - getline(strstream, peds->modelName, ','); - getline(strstream, peds->textureName, ','); - getline(strstream, peds->type, ','); - getline(strstream, peds->behaviour, ','); - getline(strstream, peds->animGroup, ','); - getline(strstream, driveMask, ','); + getline(strstream, peds->name, ','); + getline(strstream, peds->textureslot, ','); - peds->ID = atoi(id.c_str()); - peds->driveMask = atoi(driveMask.c_str()); + getline(strstream, buff, ','); + peds->pedtype_ = PedModelInfo::findPedType(buff); - objects.insert({peds->ID, peds}); + getline(strstream, peds->behaviour_, ','); + getline(strstream, peds->animgroup_, ','); + + getline(strstream, buff, ','); + peds->carsmask_ = std::atoi(buff.c_str()); + + objects.emplace(peds->id(), std::move(peds)); break; } case PATH: { @@ -253,25 +232,22 @@ bool LoaderIDE::load(const std::string &filename) { } auto &object = objects[path.ID]; - auto instance = - std::dynamic_pointer_cast(object); - instance->paths.push_back(path); + auto simple = dynamic_cast(object.get()); + simple->paths.push_back(path); break; } case HIER: { - std::shared_ptr cut( - new CutsceneObjectData); + auto hier = + std::unique_ptr(new ClumpModelInfo); - std::string id; + getline(strstream, buff, ','); + hier->setModelID(std::atoi(buff.c_str())); - getline(strstream, id, ','); - getline(strstream, cut->modelName, ','); - getline(strstream, cut->textureName, ','); + getline(strstream, hier->name, ','); + getline(strstream, hier->textureslot, ','); - cut->ID = atoi(id.c_str()); - - objects.insert({cut->ID, cut}); + objects.emplace(hier->id(), std::move(hier)); break; } } diff --git a/rwengine/src/loaders/LoaderIDE.hpp b/rwengine/src/loaders/LoaderIDE.hpp index c0a814ce..f6a44195 100644 --- a/rwengine/src/loaders/LoaderIDE.hpp +++ b/rwengine/src/loaders/LoaderIDE.hpp @@ -27,13 +27,7 @@ public: /** * @brief objects loaded during the call to load() */ - std::map objects; - - /*std::vector> OBJSs; - std::vector> CARSs; - std::vector> PEDSs; - std::vector> HIERs; - std::vector> PATHs;*/ + std::map> objects; }; #endif diff --git a/rwengine/src/objects/CharacterObject.cpp b/rwengine/src/objects/CharacterObject.cpp index ef27ddf9..16845627 100644 --- a/rwengine/src/objects/CharacterObject.cpp +++ b/rwengine/src/objects/CharacterObject.cpp @@ -15,8 +15,8 @@ const float CharacterObject::DefaultJumpSpeed = 2.f; CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, - std::shared_ptr data) - : GameObject(engine, pos, rot, model) + BaseModelInfo *modelinfo) + : GameObject(engine, pos, rot, modelinfo, model) , currentState({}) , currentVehicle(nullptr) , currentSeat(0) @@ -24,7 +24,6 @@ CharacterObject::CharacterObject(GameWorld* engine, const glm::vec3& pos, , jumped(false) , jumpSpeed(DefaultJumpSpeed) , motionBlockedByActivity(false) - , ped(data) , physCharacter(nullptr) , physObject(nullptr) , physShape(nullptr) diff --git a/rwengine/src/objects/CharacterObject.hpp b/rwengine/src/objects/CharacterObject.hpp index 29fb6ba0..e26da4a8 100644 --- a/rwengine/src/objects/CharacterObject.hpp +++ b/rwengine/src/objects/CharacterObject.hpp @@ -125,8 +125,6 @@ private: public: static const float DefaultJumpSpeed; - std::shared_ptr ped; - btKinematicCharacterController* physCharacter; btPairCachingGhostObject* physObject; btCapsuleShapeZ* physShape; @@ -143,7 +141,7 @@ public: */ CharacterObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, - std::shared_ptr data); + BaseModelInfo* modelinfo); ~CharacterObject(); @@ -151,6 +149,7 @@ public: return Character; } + void tick(float dt); const CharacterState& getCurrentState() const { diff --git a/rwengine/src/objects/CutsceneObject.cpp b/rwengine/src/objects/CutsceneObject.cpp index 9e317094..3d2e0a2a 100644 --- a/rwengine/src/objects/CutsceneObject.cpp +++ b/rwengine/src/objects/CutsceneObject.cpp @@ -3,8 +3,11 @@ #include CutsceneObject::CutsceneObject(GameWorld *engine, const glm::vec3 &pos, - const glm::quat &rot, const ModelRef &model) - : GameObject(engine, pos, rot, model), _parent(nullptr), _bone(nullptr) { + const glm::quat &rot, + const ModelRef &model, BaseModelInfo *modelinfo) + : GameObject(engine, pos, rot, modelinfo, model) + , _parent(nullptr) + , _bone(nullptr) { skeleton = new Skeleton; animator = new Animator(model->resource, skeleton); } diff --git a/rwengine/src/objects/CutsceneObject.hpp b/rwengine/src/objects/CutsceneObject.hpp index 181f50e7..fda619d6 100644 --- a/rwengine/src/objects/CutsceneObject.hpp +++ b/rwengine/src/objects/CutsceneObject.hpp @@ -12,7 +12,7 @@ class CutsceneObject : public GameObject { public: CutsceneObject(GameWorld* engine, const glm::vec3& pos, - const glm::quat& rot, const ModelRef& model); + const glm::quat& rot, const ModelRef& model, BaseModelInfo *modelinfo); ~CutsceneObject(); Type type() { diff --git a/rwengine/src/objects/GameObject.cpp b/rwengine/src/objects/GameObject.cpp index 81c37962..08f6741a 100644 --- a/rwengine/src/objects/GameObject.cpp +++ b/rwengine/src/objects/GameObject.cpp @@ -12,6 +12,10 @@ GameObject::~GameObject() { if (skeleton) { delete skeleton; } + + if (modelinfo_) { + modelinfo_->removeReference(); + } } void GameObject::setPosition(const glm::vec3& pos) { diff --git a/rwengine/src/objects/GameObject.hpp b/rwengine/src/objects/GameObject.hpp index a606ddbd..78a80e2d 100644 --- a/rwengine/src/objects/GameObject.hpp +++ b/rwengine/src/objects/GameObject.hpp @@ -28,6 +28,8 @@ class GameObject { glm::quat _lastRotation; GameObjectID objectID; + BaseModelInfo* modelinfo_; + public: glm::vec3 position; glm::quat rotation; @@ -53,10 +55,11 @@ public: bool visible; GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, - ModelRef model) + BaseModelInfo* modelinfo, ModelRef model) : _lastPosition(pos) , _lastRotation(rot) , objectID(0) + , modelinfo_(modelinfo) , position(pos) , rotation(rot) , model(model) @@ -67,6 +70,9 @@ public: , _lastHeight(std::numeric_limits::max()) , visible(true) , lifetime(GameObject::UnknownLifetime) { + if (modelinfo_) { + modelinfo_->addReference(); + } } virtual ~GameObject(); @@ -85,6 +91,11 @@ public: return getGameObjectID(); } + template + T* getModelInfo() const { + return static_cast(modelinfo_); + } + /** * @brief Enumeration of possible object types. */ diff --git a/rwengine/src/objects/InstanceObject.cpp b/rwengine/src/objects/InstanceObject.cpp index edaa209d..2a0ce5ff 100644 --- a/rwengine/src/objects/InstanceObject.cpp +++ b/rwengine/src/objects/InstanceObject.cpp @@ -8,22 +8,25 @@ InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, const glm::vec3& scale, - std::shared_ptr obj, + BaseModelInfo *modelinfo, InstanceObject* lod, std::shared_ptr dyn) - : GameObject(engine, pos, rot, model) + : GameObject(engine, pos, rot, modelinfo, model) , health(100.f) , scale(scale) , body(nullptr) - , object(obj) , LODinstance(lod) , dynamics(dyn) , _enablePhysics(false) { - if (obj) { - changeModel(obj); + if (modelinfo) { + changeModel(modelinfo); - for (auto& path : obj->paths) { - engine->aigraph.createPathNodes(position, rot, path); + /// @todo store path information properly + if (modelinfo->type() == ModelDataType::SimpleInfo) { + auto simpledata = static_cast(modelinfo); + for (auto& path : simpledata->paths) { + engine->aigraph.createPathNodes(position, rot, path); + } } } } @@ -120,18 +123,18 @@ void InstanceObject::tick(float dt) { if (animator) animator->tick(dt); } -void InstanceObject::changeModel(std::shared_ptr incoming) { +void InstanceObject::changeModel(BaseModelInfo *incoming) { if (body) { delete body; body = nullptr; } - object = incoming; + /// @todo store the new object if (incoming) { auto bod = new CollisionInstance; - if (bod->createPhysicsBody(this, object->modelName, dynamics.get())) { + if (bod->createPhysicsBody(this, incoming->name, dynamics.get())) { bod->getBulletBody()->setActivationState(ISLAND_SLEEPING); body = bod; } diff --git a/rwengine/src/objects/InstanceObject.hpp b/rwengine/src/objects/InstanceObject.hpp index fa50fbd3..e7c92838 100644 --- a/rwengine/src/objects/InstanceObject.hpp +++ b/rwengine/src/objects/InstanceObject.hpp @@ -17,14 +17,13 @@ class InstanceObject : public GameObject { public: glm::vec3 scale; CollisionInstance* body; - std::shared_ptr object; InstanceObject* LODinstance; std::shared_ptr dynamics; bool _enablePhysics; InstanceObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, - const glm::vec3& scale, std::shared_ptr obj, + const glm::vec3& scale, BaseModelInfo* modelinfo, InstanceObject* lod, std::shared_ptr dyn); ~InstanceObject(); @@ -34,7 +33,7 @@ public: void tick(float dt); - void changeModel(std::shared_ptr incoming); + void changeModel(BaseModelInfo* incoming); virtual void setRotation(const glm::quat& r); diff --git a/rwengine/src/objects/ItemPickup.cpp b/rwengine/src/objects/ItemPickup.cpp index cedea85a..4f64dcb2 100644 --- a/rwengine/src/objects/ItemPickup.cpp +++ b/rwengine/src/objects/ItemPickup.cpp @@ -5,8 +5,9 @@ #include ItemPickup::ItemPickup(GameWorld *world, const glm::vec3 &position, - PickupType type, InventoryItem *item) - : PickupObject(world, position, item->getModelID(), type), item(item) { + BaseModelInfo *modelinfo, PickupType type, + InventoryItem *item) + : PickupObject(world, position, modelinfo, type), item(item) { RW_CHECK(item != nullptr, "Pickup created with null item"); } diff --git a/rwengine/src/objects/ItemPickup.hpp b/rwengine/src/objects/ItemPickup.hpp index 9181f42c..90dccb69 100644 --- a/rwengine/src/objects/ItemPickup.hpp +++ b/rwengine/src/objects/ItemPickup.hpp @@ -14,7 +14,7 @@ class ItemPickup : public PickupObject { InventoryItem* item; public: - ItemPickup(GameWorld* world, const glm::vec3& position, PickupType type, + ItemPickup(GameWorld* world, const glm::vec3& position, BaseModelInfo *modelinfo, PickupType type, InventoryItem* item); bool onCharacterTouch(CharacterObject* character); diff --git a/rwengine/src/objects/PickupObject.cpp b/rwengine/src/objects/PickupObject.cpp index 34b4a618..3015ef67 100644 --- a/rwengine/src/objects/PickupObject.cpp +++ b/rwengine/src/objects/PickupObject.cpp @@ -59,13 +59,12 @@ uint32_t PickupObject::behaviourFlags(PickupType type) { } PickupObject::PickupObject(GameWorld* world, const glm::vec3& position, - int modelID, PickupType type) - : GameObject(world, position, glm::quat(), nullptr) + BaseModelInfo* modelinfo, PickupType type) + : GameObject(world, position, glm::quat(), modelinfo, nullptr) , m_ghost(nullptr) , m_shape(nullptr) , m_enabled(false) , m_collected(false) - , m_model(modelID) , m_type(type) { btTransform tf; tf.setIdentity(); diff --git a/rwengine/src/objects/PickupObject.hpp b/rwengine/src/objects/PickupObject.hpp index 2e2f6c22..ddf346eb 100644 --- a/rwengine/src/objects/PickupObject.hpp +++ b/rwengine/src/objects/PickupObject.hpp @@ -37,15 +37,11 @@ public: static float respawnTime(PickupType type); static uint32_t behaviourFlags(PickupType type); - PickupObject(GameWorld* world, const glm::vec3& position, int modelID, + PickupObject(GameWorld* world, const glm::vec3& position, BaseModelInfo *modelinfo, PickupType type); ~PickupObject(); - int getModelID() const { - return m_model; - } - Type type() { return Pickup; } @@ -76,7 +72,6 @@ private: bool m_enabled; float m_enableTimer; bool m_collected; - int m_model; VisualFX* m_corona; PickupType m_type; diff --git a/rwengine/src/objects/ProjectileObject.cpp b/rwengine/src/objects/ProjectileObject.cpp index 2150c9c3..c99960cc 100644 --- a/rwengine/src/objects/ProjectileObject.cpp +++ b/rwengine/src/objects/ProjectileObject.cpp @@ -107,7 +107,7 @@ void ProjectileObject::cleanup() { ProjectileObject::ProjectileObject(GameWorld* world, const glm::vec3& position, const ProjectileObject::ProjectileInfo& info) - : GameObject(world, position, glm::quat(), nullptr) + : GameObject(world, position, glm::quat(), nullptr, nullptr) , _info(info) , _body(nullptr) , _ghostBody(nullptr) diff --git a/rwengine/src/objects/VehicleInfo.hpp b/rwengine/src/objects/VehicleInfo.hpp index a47b3437..adead690 100644 --- a/rwengine/src/objects/VehicleInfo.hpp +++ b/rwengine/src/objects/VehicleInfo.hpp @@ -6,8 +6,6 @@ #include #include -struct VehicleData; - /** * @brief Stores data loaded from handling.cfg */ diff --git a/rwengine/src/objects/VehicleObject.cpp b/rwengine/src/objects/VehicleObject.cpp index 19cfd2d5..d43403a4 100644 --- a/rwengine/src/objects/VehicleObject.cpp +++ b/rwengine/src/objects/VehicleObject.cpp @@ -84,14 +84,13 @@ private: VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, const ModelRef& model, - VehicleDataHandle data, VehicleInfoHandle info, + BaseModelInfo *modelinfo, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec) - : GameObject(engine, pos, rot, model) + : GameObject(engine, pos, rot, modelinfo, model) , steerAngle(0.f) , throttle(0.f) , brake(0.f) , handbrake(true) - , vehicle(data) , info(info) , colourPrimary(prim) , colourSecondary(sec) @@ -99,7 +98,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, , physRaycaster(nullptr) , physVehicle(nullptr) { collision = new CollisionInstance; - if (collision->createPhysicsBody(this, data->modelName, nullptr, + if (collision->createPhysicsBody(this, modelinfo->name, nullptr, &info->handling)) { physRaycaster = new VehicleRaycaster(this, engine->dynamicsWorld); btRaycastVehicle::btVehicleTuning tuning; @@ -127,7 +126,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, bool front = connection.y() > 0; btWheelInfo& wi = physVehicle->addWheel( connection, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f), - restLength, data->wheelScale / 2.f, tuning, front); + restLength, getVehicle()->wheelscale_ / 2.f, tuning, front); wi.m_suspensionRestLength1 = restLength; wi.m_raycastInfo.m_suspensionLength = 0.f; @@ -282,7 +281,7 @@ void VehicleObject::tickPhysics(float dt) { seat.second->updateTransform(passPosition, getRotation()); } - if (vehicle->type == VehicleData::BOAT) { + if (getVehicle()->vehicletype_ == VehicleModelInfo::BOAT) { if (isInWater()) { float sign = std::signbit(steerAngle) ? -1.f : 1.f; float steer = @@ -356,6 +355,7 @@ void VehicleObject::tickPhysics(float dt) { } } + auto isBoat = getVehicle()->vehicletype_ == VehicleModelInfo::BOAT; if (inWater) { // Ensure that vehicles don't fall asleep at the top of a wave. if (!collision->getBulletBody()->isActive()) { @@ -367,15 +367,13 @@ void VehicleObject::tickPhysics(float dt) { float oZ = 0.f; oZ = -bbZ / 2.f + (bbZ * (info->handling.percentSubmerged / 120.f)); - if (vehicle->type != VehicleData::BOAT) { + if (isBoat) { + oZ = 0.f; + } else { // Damper motion collision->getBulletBody()->setDamping(0.95f, 0.9f); } - if (vehicle->type == VehicleData::BOAT) { - oZ = 0.f; - } - // Boats, Buoyancy offset is affected by the orientation of the // chassis. // Vehicles, it isn't. @@ -399,7 +397,7 @@ void VehicleObject::tickPhysics(float dt) { applyWaterFloat(vRt); applyWaterFloat(vLeft); } else { - if (vehicle->type == VehicleData::BOAT) { + if (isBoat) { collision->getBulletBody()->setDamping(0.1f, 0.8f); } else { collision->getBulletBody()->setDamping(0.05f, 0.0f); diff --git a/rwengine/src/objects/VehicleObject.hpp b/rwengine/src/objects/VehicleObject.hpp index 34b2be8c..46edb696 100644 --- a/rwengine/src/objects/VehicleObject.hpp +++ b/rwengine/src/objects/VehicleObject.hpp @@ -24,7 +24,6 @@ private: bool handbrake; public: - VehicleDataHandle vehicle; VehicleInfoHandle info; glm::u8vec3 colourPrimary; glm::u8vec3 colourSecondary; @@ -50,7 +49,7 @@ public: std::map dynamicParts; VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, - const ModelRef& model, VehicleDataHandle data, + const ModelRef& model, BaseModelInfo* modelinfo, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec); @@ -60,6 +59,10 @@ public: void setRotation(const glm::quat& orientation); + VehicleModelInfo* getVehicle() const { + return getModelInfo(); + } + Type type() { return Vehicle; } diff --git a/rwengine/src/render/ObjectRenderer.cpp b/rwengine/src/render/ObjectRenderer.cpp index e9e7d6b6..3b672287 100644 --- a/rwengine/src/render/ObjectRenderer.cpp +++ b/rwengine/src/render/ObjectRenderer.cpp @@ -51,9 +51,9 @@ void ObjectRenderer::renderGeometry(Model* model, size_t g, dp.visibility = 1.f; if (object && object->type() == GameObject::Instance) { - auto instance = static_cast(object); + auto modelinfo = object->getModelInfo(); dp.depthWrite = - !(instance->object->flags & ObjectData::NO_ZBUFFER_WRITE); + !(modelinfo->flags & SimpleModelInfo::NO_ZBUFFER_WRITE); } if (model->geometries[g]->materials.size() > subgeom.material) { @@ -163,11 +163,10 @@ void ObjectRenderer::renderItem(InventoryItem* item, return; // No model for this item } - std::shared_ptr odata = - m_world->data->findObjectType(item->getModelID()); + auto odata = m_world->data->modelinfo[item->getModelID()].get(); auto weapons = m_world->data->models["weapons"]; if (weapons && weapons->resource) { - auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); + auto itemModel = weapons->resource->findFrame(odata->name + "_l0"); auto matrix = glm::inverse(itemModel->getTransform()); if (itemModel) { renderFrame(weapons->resource, itemModel, modelMatrix * matrix, @@ -187,15 +186,17 @@ void ObjectRenderer::renderInstance(InstanceObject* instance, return; } + auto modelinfo = instance->getModelInfo(); + // Handles times provided by TOBJ data const auto currentHour = m_world->getHour(); - if (instance->object->timeOff < instance->object->timeOn) { - if (currentHour >= instance->object->timeOff && - currentHour < instance->object->timeOn) + if (modelinfo->timeOff < modelinfo->timeOn) { + if (currentHour >= modelinfo->timeOff && + currentHour < modelinfo->timeOn) return; } else { - if (currentHour >= instance->object->timeOff || - currentHour < instance->object->timeOn) + if (currentHour >= modelinfo->timeOff || + currentHour < modelinfo->timeOn) return; } @@ -216,17 +217,20 @@ void ObjectRenderer::renderInstance(InstanceObject* instance, float opacity = 0.f; constexpr float fadeRange = 50.f; - if (instance->object->numClumps == 1) { + /// @todo replace this block with the correct logic + if (modelinfo->getNumAtomics() == 1) { // Is closest point greater than the *object* draw distance - float objectRange = instance->object->drawDistance[0]; + float objectRange = modelinfo->getLodDistance(0); float overlap = (mindist - objectRange); if (mindist > objectRange) { // Check for LOD instances if (instance->LODinstance) { // Is the closest point greater than the *LOD* draw distance - float LODrange = instance->LODinstance->object->drawDistance[0]; - if (mindist > LODrange) { - } else if (instance->LODinstance->model->resource) { + auto lodmodelinfo = + instance->LODinstance->getModelInfo(); + float LODrange = lodmodelinfo->getLodDistance(0); + if (mindist <= LODrange && + instance->LODinstance->model->resource) { // The model matrix needs to be for the LOD instead matrixModel = instance->LODinstance->getTimeAdjustedTransform( @@ -249,7 +253,7 @@ void ObjectRenderer::renderInstance(InstanceObject* instance, } } // Otherwise, if we aren't marked as a LOD model, we can render - else if (!instance->object->LOD) { + else if (!modelinfo->LOD) { model = instance->model->resource; } } else { @@ -260,9 +264,9 @@ void ObjectRenderer::renderInstance(InstanceObject* instance, matrixModel *= root->getTransform(); - for (int i = 0; i < instance->object->numClumps - 1; ++i) { - auto ind = (instance->object->numClumps - 1) - i; - float lodDistance = instance->object->drawDistance[i]; + for (int i = 0; i < modelinfo->getNumAtomics() - 1; ++i) { + auto ind = (modelinfo->getNumAtomics() - 1) - i; + float lodDistance = modelinfo->getLodDistance(i); if (mindist > lodDistance) { fadingFrame = root->getChildren()[ind]; fadingModel = objectModel; @@ -372,10 +376,11 @@ void ObjectRenderer::renderVehicle(VehicleObject* vehicle, renderFrame(vehicle->model->resource, vehicle->model->resource->frames[0], matrixModel, vehicle, 1.f, outList); + auto modelinfo = vehicle->getVehicle(); // Draw wheels n' stuff for (size_t w = 0; w < vehicle->info->wheels.size(); ++w) { - auto woi = m_world->data->findObjectType( - vehicle->vehicle->wheelModelID); + auto woi = m_world->data->findModelInfo( + modelinfo->wheelmodel_); if (woi) { Model* wheelModel = m_world->data->models["wheels"]->resource; auto& wi = vehicle->physVehicle->getWheelInfo(w); @@ -406,12 +411,12 @@ void ObjectRenderer::renderVehicle(VehicleObject* vehicle, wheelM = matrixModel * wheelM; wheelM = - glm::scale(wheelM, glm::vec3(vehicle->vehicle->wheelScale)); + glm::scale(wheelM, glm::vec3(modelinfo->wheelscale_)); if (wi.m_chassisConnectionPointCS.x() < 0.f) { wheelM = glm::scale(wheelM, glm::vec3(-1.f, 1.f, 1.f)); } - renderWheel(vehicle, wheelModel, wheelM, woi->modelName, + renderWheel(vehicle, wheelModel, wheelM, woi->name, outList); } } @@ -425,25 +430,24 @@ void ObjectRenderer::renderPickup(PickupObject* pickup, RenderList& outList) { modelMatrix = glm::rotate(modelMatrix, m_world->getGameTime(), glm::vec3(0.f, 0.f, 1.f)); - auto odata = - m_world->data->findObjectType(pickup->getModelID()); + auto odata = pickup->getModelInfo(); Model* model = nullptr; ModelFrame* itemModel = nullptr; /// @todo Better determination of is this object a weapon. - if (odata->ID >= 170 && odata->ID <= 184) { + if (odata->id() >= 170 && odata->id() <= 184) { auto weapons = m_world->data->models["weapons"]; if (weapons && weapons->resource && odata) { model = weapons->resource; - itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); + itemModel = weapons->resource->findFrame(odata->name + "_l0"); RW_CHECK(itemModel, "Weapon Frame not present int weapon model"); if (!itemModel) { return; } } } else { - auto handle = m_world->data->models[odata->modelName]; + auto handle = m_world->data->models[odata->name]; RW_CHECK(handle && handle->resource, "Pickup has no model"); if (handle && handle->resource) { model = handle->resource; @@ -505,14 +509,14 @@ void ObjectRenderer::renderProjectile(ProjectileObject* projectile, RenderList& outList) { glm::mat4 modelMatrix = projectile->getTimeAdjustedTransform(m_renderAlpha); - auto odata = m_world->data->findObjectType( + auto odata = m_world->data->findModelInfo( projectile->getProjectileInfo().weapon->modelID); auto weapons = m_world->data->models["weapons"]; RW_CHECK(weapons, "Weapons model not loaded"); if (weapons && weapons->resource) { - auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); + auto itemModel = weapons->resource->findFrame(odata->name + "_l0"); auto matrix = glm::inverse(itemModel->getTransform()); RW_CHECK(itemModel, "Weapon frame not in model"); if (itemModel) { diff --git a/rwengine/src/script/ScriptFunctions.hpp b/rwengine/src/script/ScriptFunctions.hpp index 1b1c0ca7..b20226d9 100644 --- a/rwengine/src/script/ScriptFunctions.hpp +++ b/rwengine/src/script/ScriptFunctions.hpp @@ -31,11 +31,11 @@ inline VehicleObject* getCharacterVehicle(CharacterObject* character) { } inline bool isInModel(const ScriptArguments& args, CharacterObject* character, int model) { - auto data = args.getWorld()->data->findObjectType(model); + auto data = args.getWorld()->data->findModelInfo(model); if (data) { auto vehicle = getCharacterVehicle(character); if (vehicle) { - return vehicle->model ? vehicle->model->name == data->modelName + return vehicle->model ? vehicle->model->name == data->name : false; } } diff --git a/rwengine/src/script/modules/GTA3ModuleImpl.inl b/rwengine/src/script/modules/GTA3ModuleImpl.inl index 7f1b92ab..d5eeb808 100644 --- a/rwengine/src/script/modules/GTA3ModuleImpl.inl +++ b/rwengine/src/script/modules/GTA3ModuleImpl.inl @@ -3546,12 +3546,8 @@ void opcode_0136(const ScriptArguments& args, const ScriptInt arg1, const Script @arg model Model ID */ bool opcode_0137(const ScriptArguments& args, const ScriptVehicle vehicle, const ScriptModelID model) { - auto data = args.getWorld()->data->findObjectType(model); - RW_CHECK(data, "non-vehicle model ID"); - if (data) { - return vehicle->model->name == data->modelName; - } - return false; + RW_UNUSED(args); + return vehicle->getVehicle()->id() == model; } /** @@ -8156,7 +8152,11 @@ void opcode_02dd(const ScriptArguments& args, const ScriptString areaName, Scrip bool opcode_02de(const ScriptArguments& args, const ScriptPlayer player) { RW_UNUSED(args); auto vehicle = player->getCharacter()->getCurrentVehicle(); - return (vehicle && (vehicle->vehicle->classType & VehicleData::TAXI) == VehicleData::TAXI); + if (!vehicle) { + return false; + } + auto type = vehicle->getVehicle()->vehicleclass_; + return (type & VehicleModelInfo::TAXI) == VehicleModelInfo::TAXI; } /** @@ -10063,7 +10063,8 @@ void opcode_0363(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa InstanceObject* object = static_cast(i.second); // Check if this instance has the correct model id, early out if it isn't - if (!boost::iequals(object->object->modelName, modelName)) { + auto modelinfo = object->getModelInfo(); + if (!boost::iequals(modelinfo->name, modelName)) { continue; } @@ -11343,7 +11344,7 @@ void opcode_03b6(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloa std::transform(oldmodel.begin(), oldmodel.end(), oldmodel.begin(), ::tolower); auto newobjectid = args.getWorld()->data->findModelObject(newmodel); - auto nobj = args.getWorld()->data->findObjectType(newobjectid); + auto nobj = args.getWorld()->data->findModelInfo(newobjectid); /// @todo Objects need to adopt the new object ID, not just the model. for(auto p : args.getWorld()->instancePool.objects) { diff --git a/rwgame/DrawUI.cpp b/rwgame/DrawUI.cpp index 7994bd39..ede27471 100644 --- a/rwgame/DrawUI.cpp +++ b/rwgame/DrawUI.cpp @@ -157,10 +157,10 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, if (current) { uint16_t model = current->getModelID(); if (model > 0) { - ObjectDataPtr weaponData = - world->data->findObjectType(model); + auto weaponData = + world->data->findModelInfo(model); if (weaponData != nullptr) { - itemTextureName = weaponData->modelName; + itemTextureName = weaponData->name; } } } diff --git a/rwgame/states/IngameState.cpp b/rwgame/states/IngameState.cpp index 88c22b1d..cd4cf76a 100644 --- a/rwgame/states/IngameState.cpp +++ b/rwgame/states/IngameState.cpp @@ -116,16 +116,15 @@ void IngameState::startTest() { auto carRot = glm::angleAxis(glm::radians(90.f), glm::vec3(0.f, 0.f, 1.f)); // auto boatPos = glm::vec3( -1000.f, -1040.f, 5.f ); int i = 0; - for (auto& vi : getWorld()->data->objectTypes) { + for (auto& vi : getWorld()->data->modelinfo) { switch (vi.first) { case 140: continue; case 141: continue; } - if (vi.second->class_type == ObjectInformation::_class("CARS")) { + if (vi.second->type() == ModelDataType::VehicleInfo) { if (i++ > 20) break; - auto vehicle = std::static_pointer_cast(vi.second); auto& sp = carPos; auto& sr = carRot; diff --git a/rwviewer/ItemListModel.cpp b/rwviewer/ItemListModel.cpp index bff04e88..0aab0530 100644 --- a/rwviewer/ItemListModel.cpp +++ b/rwviewer/ItemListModel.cpp @@ -2,7 +2,7 @@ #include qint16 ItemListModel::getIDOf(unsigned int row) const { - if (row < world()->data->objectTypes.size()) { + if (row < world()->data->modelinfo.size()) { return row; } @@ -14,7 +14,7 @@ ItemListModel::ItemListModel(GameWorld *world, QObject *parent) } int ItemListModel::rowCount(const QModelIndex &parent) const { - return _world->data->objectTypes.size(); + return _world->data->modelinfo.size(); } int ItemListModel::columnCount(const QModelIndex &parent) const { diff --git a/rwviewer/ViewerWidget.cpp b/rwviewer/ViewerWidget.cpp index a2d9d8f6..57b3a69d 100644 --- a/rwviewer/ViewerWidget.cpp +++ b/rwviewer/ViewerWidget.cpp @@ -177,16 +177,21 @@ void ViewerWidget::showObject(qint16 item) { if (dummyObject) gworld->destroyObject(dummyObject); - auto def = world()->data->objectTypes[item]; + auto def = world()->data->modelinfo[item].get(); if (def) { - if (def->class_type == ObjectData::class_id) { - dummyObject = gworld->createInstance(item, {}); - } else if (def->class_type == CharacterData::class_id) { - dummyObject = gworld->createPedestrian(item, {}); - } else if (def->class_type == VehicleData::class_id) { - dummyObject = gworld->createVehicle(item, {}); + switch (def->type()) { + default: + dummyObject = gworld->createInstance(item, {}); + break; + case ModelDataType::PedInfo: + dummyObject = gworld->createPedestrian(item, {}); + break; + case ModelDataType::VehicleInfo: + dummyObject = gworld->createVehicle(item, {}); + break; } + RW_CHECK(dummyObject != nullptr, "Dummy Object is null"); if (dummyObject != nullptr) { activeModel = dummyObject->model->resource; diff --git a/rwviewer/models/ObjectListModel.cpp b/rwviewer/models/ObjectListModel.cpp index f8bb4749..6c14d36b 100644 --- a/rwviewer/models/ObjectListModel.cpp +++ b/rwviewer/models/ObjectListModel.cpp @@ -5,19 +5,13 @@ ObjectListModel::ObjectListModel(GameData *dat, QObject *parent) } int ObjectListModel::rowCount(const QModelIndex &parent) const { - return _gameData->objectTypes.size(); + return _gameData->modelinfo.size(); } int ObjectListModel::columnCount(const QModelIndex &parent) const { return 3; } -static std::map gDataType = { - {ObjectInformation::_class("OBJS"), "Object"}, - {ObjectInformation::_class("CARS"), "Vehicle"}, - {ObjectInformation::_class("PEDS"), "Pedestrian"}, - {ObjectInformation::_class("HIER"), "Cutscene"}}; - QVariant ObjectListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { auto id = index.internalId(); @@ -25,23 +19,12 @@ QVariant ObjectListModel::data(const QModelIndex &index, int role) const { if (index.column() == 0) { return id; } else if (index.column() == 1) { - auto object = _gameData->objectTypes[id]; - if (gDataType[object->class_type].isEmpty()) { - return QString("Unknown"); - } - return gDataType[object->class_type]; + auto object = _gameData->modelinfo[id].get(); + return QString::fromStdString( + BaseModelInfo::getTypeName(object->type())); } else if (index.column() == 2) { - auto object = _gameData->objectTypes[id]; - if (object->class_type == ObjectData::class_id) { - auto v = std::static_pointer_cast(object); - return QString::fromStdString(v->modelName); - } else if (object->class_type == VehicleData::class_id) { - auto v = std::static_pointer_cast(object); - return QString::fromStdString(v->modelName); - } else if (object->class_type == CharacterData::class_id) { - auto v = std::static_pointer_cast(object); - return QString::fromStdString(v->modelName); - } + auto object = _gameData->modelinfo[id].get(); + return QString::fromStdString(object->name); } } return QVariant::Invalid; @@ -64,9 +47,9 @@ QVariant ObjectListModel::headerData(int section, Qt::Orientation orientation, QModelIndex ObjectListModel::index(int row, int column, const QModelIndex &parent) const { - auto it = _gameData->objectTypes.begin(); + auto it = _gameData->modelinfo.begin(); for (int i = 0; i < row; i++) it++; - auto id = it->second->ID; + auto id = it->second->id(); return hasIndex(row, column, parent) ? createIndex(row, column, id) : QModelIndex(); diff --git a/rwviewer/views/ObjectViewer.cpp b/rwviewer/views/ObjectViewer.cpp index 8d2fe912..0e81dae3 100644 --- a/rwviewer/views/ObjectViewer.cpp +++ b/rwviewer/views/ObjectViewer.cpp @@ -60,30 +60,14 @@ void ObjectViewer::worldChanged() { SLOT(showItem(QModelIndex))); } -static std::map gDataType = { - {ObjectInformation::_class("OBJS"), "Object"}, - {ObjectInformation::_class("CARS"), "Vehicle"}, - {ObjectInformation::_class("PEDS"), "Pedestrian"}, - {ObjectInformation::_class("HIER"), "Cutscene"}}; - void ObjectViewer::showItem(qint16 item) { - auto def = world()->data->objectTypes[item]; + auto def = world()->data->modelinfo[item].get(); if (def) { - previewID->setText(QString::number(def->ID)); - previewClass->setText(gDataType[def->class_type]); - - if (def->class_type == ObjectData::class_id) { - auto v = std::static_pointer_cast(def); - previewModel->setText(QString::fromStdString(v->modelName)); - } else if (def->class_type == VehicleData::class_id) { - auto v = std::static_pointer_cast(def); - previewModel->setText(QString::fromStdString(v->modelName)); - } else if (def->class_type == CharacterData::class_id) { - auto v = std::static_pointer_cast(def); - previewModel->setText(QString::fromStdString(v->modelName)); - } - + previewID->setText(QString::number(def->id())); + previewClass->setText( + QString::fromStdString(BaseModelInfo::getTypeName(def->type()))); + previewModel->setText(QString::fromStdString(def->name)); previewWidget->showObject(item); } } diff --git a/tests/test_GameData.cpp b/tests/test_GameData.cpp index ba7a56b5..0d02edb7 100644 --- a/tests/test_GameData.cpp +++ b/tests/test_GameData.cpp @@ -12,16 +12,16 @@ BOOST_AUTO_TEST_CASE(test_object_data) { gd.load(); { - auto def = gd.findObjectType(1100); + auto def = gd.findModelInfo(1100); BOOST_REQUIRE(def); - BOOST_ASSERT(def->class_type == ObjectInformation::_class("OBJS")); + BOOST_ASSERT(def->type() == ModelDataType::SimpleInfo); - BOOST_CHECK_EQUAL(def->modelName, "rd_Corner1"); - BOOST_CHECK_EQUAL(def->textureName, "generic"); - BOOST_CHECK_EQUAL(def->numClumps, 1); - BOOST_CHECK_EQUAL(def->drawDistance[0], 220); + BOOST_CHECK_EQUAL(def->name, "rd_Corner1"); + BOOST_CHECK_EQUAL(def->textureslot, "generic"); + BOOST_CHECK_EQUAL(def->getNumAtomics(), 1); + BOOST_CHECK_EQUAL(def->getLodDistance(0), 220); BOOST_CHECK_EQUAL(def->flags, 0); } } diff --git a/tests/test_buoyancy.cpp b/tests/test_buoyancy.cpp index 180b82d7..0839f7e3 100644 --- a/tests/test_buoyancy.cpp +++ b/tests/test_buoyancy.cpp @@ -14,7 +14,7 @@ BOOST_AUTO_TEST_CASE(test_vehicle_buoyancy) { BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle->info != nullptr); - BOOST_REQUIRE(vehicle->vehicle != nullptr); + BOOST_REQUIRE(vehicle->getVehicle() != nullptr); // Relies on tile 0,0 being watered... diff --git a/tests/test_object_data.cpp b/tests/test_object_data.cpp index a70b2584..91c6a448 100644 --- a/tests/test_object_data.cpp +++ b/tests/test_object_data.cpp @@ -13,16 +13,16 @@ BOOST_AUTO_TEST_CASE(test_object_data) { BOOST_ASSERT(l.objects.find(1100) != l.objects.end()); - auto obj = l.objects[1100]; + auto obj = l.objects[1100].get(); - auto def = std::dynamic_pointer_cast(obj); + auto def = dynamic_cast(obj); - BOOST_ASSERT(def->class_type == ObjectInformation::_class("OBJS")); + BOOST_ASSERT(def->type() == ModelDataType::SimpleInfo); - BOOST_CHECK_EQUAL(def->modelName, "rd_Corner1"); - BOOST_CHECK_EQUAL(def->textureName, "generic"); - BOOST_CHECK_EQUAL(def->numClumps, 1); - BOOST_CHECK_EQUAL(def->drawDistance[0], 220); + BOOST_CHECK_EQUAL(def->name, "rd_Corner1"); + BOOST_CHECK_EQUAL(def->textureslot, "generic"); + BOOST_CHECK_EQUAL(def->getNumAtomics(), 1); + BOOST_CHECK_EQUAL(def->getLodDistance(0), 220); BOOST_CHECK_EQUAL(def->flags, 0); } { @@ -32,21 +32,21 @@ BOOST_AUTO_TEST_CASE(test_object_data) { BOOST_ASSERT(l.objects.find(90) != l.objects.end()); - auto obj = l.objects[90]; + auto obj = l.objects[90].get(); - auto def = std::dynamic_pointer_cast(obj); + auto def = dynamic_cast(obj); - BOOST_ASSERT(def->class_type == ObjectInformation::_class("CARS")); + BOOST_ASSERT(def->type() == ModelDataType::VehicleInfo); - BOOST_CHECK_EQUAL(def->modelName, "landstal"); - BOOST_CHECK_EQUAL(def->textureName, "landstal"); - BOOST_CHECK_EQUAL(def->type, VehicleData::CAR); - BOOST_CHECK_EQUAL(def->handlingID, "LANDSTAL"); - BOOST_CHECK_EQUAL(def->gameName, "LANDSTK"); - BOOST_CHECK_EQUAL(def->classType, VehicleData::RICHFAMILY); - BOOST_CHECK_EQUAL(def->frequency, 10); - BOOST_CHECK_EQUAL(def->wheelModelID, 164); - BOOST_CHECK_CLOSE(def->wheelScale, 0.8f, 0.01f); + BOOST_CHECK_EQUAL(def->name, "landstal"); + BOOST_CHECK_EQUAL(def->textureslot, "landstal"); + BOOST_CHECK_EQUAL(def->vehicletype_, VehicleModelInfo::CAR); + BOOST_CHECK_EQUAL(def->handling_, "LANDSTAL"); + BOOST_CHECK_EQUAL(def->vehiclename_, "LANDSTK"); + BOOST_CHECK_EQUAL(def->vehicleclass_, VehicleModelInfo::RICHFAMILY); + BOOST_CHECK_EQUAL(def->frequency_, 10); + BOOST_CHECK_EQUAL(def->wheelmodel_, 164); + BOOST_CHECK_CLOSE(def->wheelscale_, 0.8f, 0.01f); } } diff --git a/tests/test_pickup.cpp b/tests/test_pickup.cpp index 88202a51..aeca2253 100644 --- a/tests/test_pickup.cpp +++ b/tests/test_pickup.cpp @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(test_item_pickup) { BOOST_REQUIRE(item != nullptr); ItemPickup* p = new ItemPickup(Global::get().e, {30.f, 0.f, 0.f}, - PickupObject::OnStreet, item); + nullptr, PickupObject::OnStreet, item); Global::get().e->allObjects.push_back(p); diff --git a/tests/test_vehicle.cpp b/tests/test_vehicle.cpp index 503826da..b5cb8dfa 100644 --- a/tests/test_vehicle.cpp +++ b/tests/test_vehicle.cpp @@ -14,10 +14,11 @@ BOOST_AUTO_TEST_CASE(test_create_vehicle) { BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle->info != nullptr); - BOOST_REQUIRE(vehicle->vehicle != nullptr); + BOOST_REQUIRE(vehicle->getVehicle() != nullptr); // Hardcoded values for the moment - BOOST_CHECK_EQUAL(vehicle->vehicle->type, VehicleData::CAR); + BOOST_CHECK_EQUAL(vehicle->getVehicle()->vehicletype_, + VehicleModelInfo::CAR); BOOST_CHECK_EQUAL(vehicle->info->wheels.size(), 4); @@ -76,7 +77,7 @@ BOOST_AUTO_TEST_CASE(test_door_position) { BOOST_REQUIRE(vehicle != nullptr); BOOST_REQUIRE(vehicle->info != nullptr); - BOOST_REQUIRE(vehicle->vehicle != nullptr); + BOOST_REQUIRE(vehicle->getVehicle() != nullptr); BOOST_CHECK(vehicle->getSeatEntryPositionWorld(0).x > 5.f);