mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-23 19:02:39 +01:00
Garages continuation
This commit is contained in:
parent
10ef3448aa
commit
92d2a614b7
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ documentation/
|
|||||||
*swp
|
*swp
|
||||||
*.user*
|
*.user*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode/
|
||||||
|
@ -61,8 +61,8 @@ set(RWENGINE_SOURCES
|
|||||||
src/engine/GameState.hpp
|
src/engine/GameState.hpp
|
||||||
src/engine/GameWorld.cpp
|
src/engine/GameWorld.cpp
|
||||||
src/engine/GameWorld.hpp
|
src/engine/GameWorld.hpp
|
||||||
src/engine/GarageController.cpp
|
src/engine/Garage.cpp
|
||||||
src/engine/GarageController.hpp
|
src/engine/Garage.hpp
|
||||||
src/engine/Payphone.cpp
|
src/engine/Payphone.cpp
|
||||||
src/engine/Payphone.hpp
|
src/engine/Payphone.hpp
|
||||||
src/engine/SaveGame.cpp
|
src/engine/SaveGame.cpp
|
||||||
|
@ -211,56 +211,6 @@ struct BlipData {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GarageType {
|
|
||||||
Mission = 1,
|
|
||||||
BombShop1 = 2,
|
|
||||||
BombShop2 = 3,
|
|
||||||
BombShop3 = 4,
|
|
||||||
Respray = 5,
|
|
||||||
CollectCars1 = 8,
|
|
||||||
CollectCars2 = 9,
|
|
||||||
MissionForCarToComeOut = 11,
|
|
||||||
Crusher = 13,
|
|
||||||
MissionKeepCar = 14,
|
|
||||||
Hideout1 = 16,
|
|
||||||
Hideout2 = 17,
|
|
||||||
Hideout3 = 18,
|
|
||||||
MissionToOpenAndClose = 19,
|
|
||||||
MissionForSpecificCar = 20,
|
|
||||||
MissionKeepCarAndRemainClosed = 21,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class GarageState { Closed, Closing, Opening, Opened };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data for garages
|
|
||||||
*/
|
|
||||||
struct GarageInfo {
|
|
||||||
GarageType type;
|
|
||||||
|
|
||||||
int id;
|
|
||||||
glm::vec3 min;
|
|
||||||
glm::vec3 max;
|
|
||||||
|
|
||||||
GameObject* target;
|
|
||||||
|
|
||||||
GarageState state;
|
|
||||||
|
|
||||||
GarageInfo(int id_, const glm::vec3 min_, const glm::vec3 max_,
|
|
||||||
GarageType type_)
|
|
||||||
: type(type_)
|
|
||||||
, id(id_)
|
|
||||||
, min(min_)
|
|
||||||
, max(max_)
|
|
||||||
, target(nullptr)
|
|
||||||
, state(GarageState::Closed) {
|
|
||||||
}
|
|
||||||
|
|
||||||
int getScriptObjectID() const {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HudFlash {
|
enum class HudFlash {
|
||||||
Disabled = -1,
|
Disabled = -1,
|
||||||
FlashArmor = 3,
|
FlashArmor = 3,
|
||||||
@ -406,8 +356,6 @@ public:
|
|||||||
|
|
||||||
std::map<int, BlipData> radarBlips;
|
std::map<int, BlipData> radarBlips;
|
||||||
|
|
||||||
std::vector<GarageInfo> garages;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bitsets for the car import / export list mission
|
* Bitsets for the car import / export list mission
|
||||||
*/
|
*/
|
||||||
|
@ -386,77 +386,11 @@ PickupObject* GameWorld::createPickup(const glm::vec3& pos, int id, int type) {
|
|||||||
return pickup;
|
return pickup;
|
||||||
}
|
}
|
||||||
|
|
||||||
GarageInfo* GameWorld::createGarage(const glm::vec3 coord0,
|
Garage* GameWorld::createGarage(const glm::vec3 coord0, const glm::vec3 coord1,
|
||||||
const glm::vec3 coord1, const int type) {
|
Garage::Type type) {
|
||||||
glm::vec3 min;
|
const int id = garages.size();
|
||||||
glm::vec3 max;
|
garages.emplace_back(std::make_unique<Garage>(this, id, coord0, coord1, type));
|
||||||
glm::vec3 midpoint;
|
return garages.back().get();
|
||||||
|
|
||||||
min.x = std::min(coord0.x, coord1.x);
|
|
||||||
min.y = std::min(coord0.y, coord1.y);
|
|
||||||
min.z = std::min(coord0.z, coord1.z);
|
|
||||||
|
|
||||||
max.x = std::max(coord0.x, coord1.x);
|
|
||||||
max.y = std::max(coord0.y, coord1.y);
|
|
||||||
max.z = std::max(coord0.z, coord1.z);
|
|
||||||
|
|
||||||
midpoint.x = (min.x + max.x) / 2;
|
|
||||||
midpoint.y = (min.y + max.y) / 2;
|
|
||||||
midpoint.z = (min.z + max.z) / 2;
|
|
||||||
|
|
||||||
// Find door object for this garage
|
|
||||||
InstanceObject* door = nullptr;
|
|
||||||
|
|
||||||
for (auto p : instancePool.objects) {
|
|
||||||
auto o = p.second;
|
|
||||||
if (!o->getModel()) continue;
|
|
||||||
if (!SimpleModelInfo::isDoorModel(
|
|
||||||
o->getModelInfo<BaseModelInfo>()->name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Is this how the game finds door object?
|
|
||||||
if (glm::distance(midpoint, o->getPosition()) < 20.f) {
|
|
||||||
door = static_cast<InstanceObject*>(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create garage
|
|
||||||
int id = state->garages.size();
|
|
||||||
GarageInfo* info =
|
|
||||||
new GarageInfo{id, min, max, static_cast<GarageType>(type)};
|
|
||||||
state->garages.push_back(*info);
|
|
||||||
|
|
||||||
switch (static_cast<GarageType>(type)) {
|
|
||||||
case GarageType::Mission:
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2:
|
|
||||||
case GarageType::MissionForCarToComeOut:
|
|
||||||
case GarageType::MissionKeepCar:
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3:
|
|
||||||
case GarageType::MissionToOpenAndClose:
|
|
||||||
case GarageType::MissionForSpecificCar:
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
info->state = GarageState::Closed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray:
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
info->state = GarageState::Opened;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create controller
|
|
||||||
garageControllers.push_back(
|
|
||||||
std::make_unique<GarageController>(GarageController(this, info, door)));
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Payphone* GameWorld::createPayphone(const glm::vec2 coord) {
|
Payphone* GameWorld::createPayphone(const glm::vec2 coord) {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <ai/AIGraphNode.hpp>
|
#include <ai/AIGraphNode.hpp>
|
||||||
#include <audio/SoundManager.hpp>
|
#include <audio/SoundManager.hpp>
|
||||||
|
|
||||||
#include <engine/GarageController.hpp>
|
#include <engine/Garage.hpp>
|
||||||
#include <engine/Payphone.hpp>
|
#include <engine/Payphone.hpp>
|
||||||
#include <objects/ObjectTypes.hpp>
|
#include <objects/ObjectTypes.hpp>
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ class btSequentialImpulseConstraintSolver;
|
|||||||
struct btDbvtBroadphase;
|
struct btDbvtBroadphase;
|
||||||
|
|
||||||
class GameState;
|
class GameState;
|
||||||
class GarageController;
|
class Garage;
|
||||||
class Payphone;
|
class Payphone;
|
||||||
|
|
||||||
class PlayerController;
|
class PlayerController;
|
||||||
@ -150,8 +150,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Creates a garage
|
* Creates a garage
|
||||||
*/
|
*/
|
||||||
GarageInfo* createGarage(const glm::vec3 coord0, const glm::vec3 coord1,
|
Garage* createGarage(const glm::vec3 coord0, const glm::vec3 coord1,
|
||||||
const int type);
|
Garage::Type type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a payphone
|
* Creates a payphone
|
||||||
@ -271,7 +271,7 @@ public:
|
|||||||
|
|
||||||
std::vector<PlayerController*> players;
|
std::vector<PlayerController*> players;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<GarageController>> garageControllers;
|
std::vector<std::unique_ptr<Garage>> garages;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Payphone>> payphones;
|
std::vector<std::unique_ptr<Payphone>> payphones;
|
||||||
|
|
||||||
|
886
rwengine/src/engine/Garage.cpp
Normal file
886
rwengine/src/engine/Garage.cpp
Normal file
@ -0,0 +1,886 @@
|
|||||||
|
#include "Garage.hpp"
|
||||||
|
|
||||||
|
#include <btBulletDynamicsCommon.h>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
|
#include "dynamics/CollisionInstance.hpp"
|
||||||
|
|
||||||
|
#include "ai/PlayerController.hpp"
|
||||||
|
|
||||||
|
#include "engine/GameState.hpp"
|
||||||
|
|
||||||
|
#include "objects/CharacterObject.hpp"
|
||||||
|
#include "objects/GameObject.hpp"
|
||||||
|
#include "objects/InstanceObject.hpp"
|
||||||
|
#include "objects/VehicleObject.hpp"
|
||||||
|
|
||||||
|
Garage::Garage(GameWorld* engine_, const int id_, const glm::vec3 coord0,
|
||||||
|
const glm::vec3 coord1, const Type type_)
|
||||||
|
: engine(engine_), id(id_), type(type_) {
|
||||||
|
min.x = std::min(coord0.x, coord1.x);
|
||||||
|
min.y = std::min(coord0.y, coord1.y);
|
||||||
|
min.z = std::min(coord0.z, coord1.z);
|
||||||
|
|
||||||
|
max.x = std::max(coord0.x, coord1.x);
|
||||||
|
max.y = std::max(coord0.y, coord1.y);
|
||||||
|
max.z = std::max(coord0.z, coord1.z);
|
||||||
|
|
||||||
|
glm::vec2 midpoint;
|
||||||
|
midpoint.x = (min.x + max.x) / 2;
|
||||||
|
midpoint.y = (min.y + max.y) / 2;
|
||||||
|
|
||||||
|
// Find door objects for this garage
|
||||||
|
for (const auto p : engine->instancePool.objects) {
|
||||||
|
const auto inst = static_cast<InstanceObject*>(p.second);
|
||||||
|
|
||||||
|
if (!inst->getModel()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SimpleModelInfo::isDoorModel(
|
||||||
|
inst->getModelInfo<BaseModelInfo>()->name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto instPos = inst->getPosition();
|
||||||
|
const auto xDist = std::abs(instPos.x - midpoint.x);
|
||||||
|
const auto yDist = std::abs(instPos.y - midpoint.y);
|
||||||
|
|
||||||
|
if (xDist < 20.f && yDist < 20.f) {
|
||||||
|
if (!doorObject) {
|
||||||
|
doorObject = inst;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
secondDoorObject = inst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doorObject) {
|
||||||
|
startPosition = doorObject->getPosition();
|
||||||
|
|
||||||
|
// Setup door height based on model's bounding box
|
||||||
|
auto doorModel = doorObject->getModelInfo<BaseModelInfo>();
|
||||||
|
auto collision = doorModel->getCollision();
|
||||||
|
// Original behavior - game actually subtracts 0.1f
|
||||||
|
doorHeight =
|
||||||
|
collision->boundingBox.max.z - collision->boundingBox.min.z - 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondDoorObject) {
|
||||||
|
startPositionSecondDoor = secondDoorObject->getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
step /= doorHeight;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Garage::Type::Mission:
|
||||||
|
case Garage::Type::CollectCars1:
|
||||||
|
case Garage::Type::CollectCars2:
|
||||||
|
case Garage::Type::MissionForCarToComeOut:
|
||||||
|
case Garage::Type::MissionKeepCar:
|
||||||
|
case Garage::Type::Hideout1:
|
||||||
|
case Garage::Type::Hideout2:
|
||||||
|
case Garage::Type::Hideout3:
|
||||||
|
case Garage::Type::MissionToOpenAndClose:
|
||||||
|
case Garage::Type::MissionForSpecificCar:
|
||||||
|
case Garage::Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
state = State::Closed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Garage::Type::BombShop1:
|
||||||
|
case Garage::Type::BombShop2:
|
||||||
|
case Garage::Type::BombShop3:
|
||||||
|
case Garage::Type::Respray:
|
||||||
|
case Garage::Type::Crusher: {
|
||||||
|
state = State::Opened;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == State::Closed) {
|
||||||
|
fraction = 0.f;
|
||||||
|
} else {
|
||||||
|
fraction = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doorObject) {
|
||||||
|
updateDoor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::makeDoorSwing() {
|
||||||
|
// This is permanent, you can't restore it
|
||||||
|
// back to non swing just like in original game
|
||||||
|
// Values are from original game
|
||||||
|
if (!swingType) {
|
||||||
|
swingType = true;
|
||||||
|
doorHeight /= 2.0f;
|
||||||
|
doorHeight -= 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::isTargetInsideGarage() const {
|
||||||
|
return state == State::Closed && isObjectInsideGarage(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::activate() {
|
||||||
|
active = true;
|
||||||
|
|
||||||
|
if (type == Type::MissionForCarToComeOut && state == State::Closed) {
|
||||||
|
state = State::Opening;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::deactivate() {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::open() {
|
||||||
|
if (state == State::Closed || state == State::Closing) {
|
||||||
|
state = State::Opening;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::close() {
|
||||||
|
if (state == State::Opened || state == State::Opening) {
|
||||||
|
state = State::Closing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float Garage::getDistanceToGarage(const glm::vec3 point) {
|
||||||
|
// Seems like original game ignores z axis
|
||||||
|
float dx = std::max({min.x - point.x, 0.f, point.x - max.x});
|
||||||
|
float dy = std::max({min.y - point.y, 0.f, point.y - max.y});
|
||||||
|
|
||||||
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::isObjectInsideGarage(GameObject* object) const {
|
||||||
|
auto p = object->getPosition();
|
||||||
|
|
||||||
|
// Do basic check first
|
||||||
|
if (p.x < min.x) return false;
|
||||||
|
if (p.y < min.y) return false;
|
||||||
|
if (p.z < min.z) return false;
|
||||||
|
if (p.x > max.x) return false;
|
||||||
|
if (p.y > max.y) return false;
|
||||||
|
if (p.z > max.z) return false;
|
||||||
|
|
||||||
|
// Now check if all collision spheres are inside
|
||||||
|
// garage's bounding box
|
||||||
|
auto objectModel = object->getModelInfo<BaseModelInfo>();
|
||||||
|
auto collision = objectModel->getCollision();
|
||||||
|
// Peds don't have collisions currently?
|
||||||
|
if (collision) {
|
||||||
|
for (auto& sphere : collision->spheres) {
|
||||||
|
auto c = p + sphere.center;
|
||||||
|
auto r = sphere.radius;
|
||||||
|
if (c.x + r < min.x) return false;
|
||||||
|
if (c.y + r < min.y) return false;
|
||||||
|
if (c.z + r < min.z) return false;
|
||||||
|
if (c.x - r > max.x) return false;
|
||||||
|
if (c.y - r > max.y) return false;
|
||||||
|
if (c.z - r > max.z) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::shouldClose() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission: {
|
||||||
|
if (!isObjectInsideGarage(static_cast<GameObject*>(plyChar)) &&
|
||||||
|
isObjectInsideGarage(target) && !playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) >= 2.f) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3: {
|
||||||
|
if (playerIsInVehicle) {
|
||||||
|
if (isObjectInsideGarage(
|
||||||
|
static_cast<GameObject*>(playerVehicle)) &&
|
||||||
|
playerVehicle->isStopped()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Respray: {
|
||||||
|
if (playerIsInVehicle) {
|
||||||
|
if (isObjectInsideGarage(
|
||||||
|
static_cast<GameObject*>(playerVehicle)) &&
|
||||||
|
playerVehicle->isStopped() && !resprayDone) {
|
||||||
|
return true;
|
||||||
|
} else if (!isObjectInsideGarage(
|
||||||
|
static_cast<GameObject*>(playerVehicle)) &&
|
||||||
|
getDistanceToGarage(playerVehicle->getPosition()) >=
|
||||||
|
2.f &&
|
||||||
|
resprayDone) {
|
||||||
|
resprayDone = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
if (playerIsInVehicle) {
|
||||||
|
if (isObjectInsideGarage(
|
||||||
|
static_cast<GameObject*>(playerVehicle))) {
|
||||||
|
if (playerVehicle->getLifetime() !=
|
||||||
|
GameObject::MissionLifetime) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// @todo show message "come back when youre not busy"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
// Not sure about these values
|
||||||
|
if ((!playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) >= 5.f) ||
|
||||||
|
(playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) >= 10.f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::shouldOpen() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission: {
|
||||||
|
// Not sure about these values
|
||||||
|
if (playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) < 8.f &&
|
||||||
|
playerVehicle == target) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3:
|
||||||
|
case Type::Respray: {
|
||||||
|
if (garageTimer < engine->getGameTime()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
// Not sure about these values
|
||||||
|
if ((!playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) < 5.f) ||
|
||||||
|
(playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) < 10.f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::shouldStopClosing() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission:
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3:
|
||||||
|
case Type::Respray:
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
// Not sure about these values
|
||||||
|
if ((!playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) < 5.f) ||
|
||||||
|
(playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) < 10.f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Garage::shouldStopOpening() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission:
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3:
|
||||||
|
case Type::Respray:
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
// Not sure about these values
|
||||||
|
if ((!playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) >= 5.f) ||
|
||||||
|
(playerIsInVehicle &&
|
||||||
|
getDistanceToGarage(playerPosition) >= 10.f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
// @todo unimplemented
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::doOnOpenEvent() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
RW_UNUSED(playerPosition);
|
||||||
|
RW_UNUSED(playerIsInVehicle);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop2: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop3: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Respray: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::doOnCloseEvent() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
RW_UNUSED(playerPosition);
|
||||||
|
RW_UNUSED(playerIsInVehicle);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission: {
|
||||||
|
player->setInputEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3: {
|
||||||
|
// Find out real value
|
||||||
|
garageTimer = engine->getGameTime() + 1.5f;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Respray: {
|
||||||
|
// Find out real value
|
||||||
|
garageTimer = engine->getGameTime() + 2.f;
|
||||||
|
playerVehicle->setHealth(1000.f);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::doOnStartOpeningEvent() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
RW_UNUSED(playerPosition);
|
||||||
|
RW_UNUSED(playerIsInVehicle);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
player->setInputEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3: {
|
||||||
|
player->setInputEnabled(true);
|
||||||
|
playerVehicle->setHandbraking(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Respray: {
|
||||||
|
player->setInputEnabled(true);
|
||||||
|
playerVehicle->setHandbraking(false);
|
||||||
|
resprayDone = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Hideout1:
|
||||||
|
case Type::Hideout2:
|
||||||
|
case Type::Hideout3: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::doOnStartClosingEvent() {
|
||||||
|
auto player = engine->getPlayer();
|
||||||
|
auto plyChar = player->getCharacter();
|
||||||
|
auto playerPosition = plyChar->getPosition();
|
||||||
|
auto playerVehicle = plyChar->getCurrentVehicle();
|
||||||
|
bool playerIsInVehicle = playerVehicle != nullptr;
|
||||||
|
RW_UNUSED(playerPosition);
|
||||||
|
RW_UNUSED(playerIsInVehicle);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Type::Mission:
|
||||||
|
case Type::CollectCars1:
|
||||||
|
case Type::CollectCars2: {
|
||||||
|
player->setInputEnabled(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::BombShop1:
|
||||||
|
case Type::BombShop2:
|
||||||
|
case Type::BombShop3:
|
||||||
|
case Type::Respray: {
|
||||||
|
player->setInputEnabled(false);
|
||||||
|
playerVehicle->setHandbraking(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForCarToComeOut: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::Crusher: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionToOpenAndClose: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionForSpecificCar: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Type::MissionKeepCarAndRemainClosed: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::tick(float dt) {
|
||||||
|
if (!doorObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
needsToUpdate = false;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case State::Opened: {
|
||||||
|
if (shouldClose()) {
|
||||||
|
state = State::Closing;
|
||||||
|
doOnStartClosingEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::Closed: {
|
||||||
|
if (shouldOpen()) {
|
||||||
|
state = State::Opening;
|
||||||
|
doOnStartOpeningEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::Opening: {
|
||||||
|
if (shouldStopOpening()) {
|
||||||
|
state = State::Closing;
|
||||||
|
} else {
|
||||||
|
fraction += dt * step;
|
||||||
|
|
||||||
|
if (fraction >= 1.0f) {
|
||||||
|
state = State::Opened;
|
||||||
|
fraction = 1.f;
|
||||||
|
doOnOpenEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
needsToUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case State::Closing: {
|
||||||
|
if (shouldStopClosing()) {
|
||||||
|
state = State::Opening;
|
||||||
|
} else {
|
||||||
|
fraction -= dt * step;
|
||||||
|
|
||||||
|
if (fraction <= 0.f) {
|
||||||
|
state = State::Closed;
|
||||||
|
fraction = 0.f;
|
||||||
|
doOnCloseEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
needsToUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsToUpdate) {
|
||||||
|
updateDoor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Garage::updateDoor() {
|
||||||
|
if (swingType) {
|
||||||
|
doorObject->setRotation(glm::angleAxis(fraction * glm::radians(90.f),
|
||||||
|
glm::vec3(0.f, 1.f, 0.f)));
|
||||||
|
|
||||||
|
if (secondDoorObject) {
|
||||||
|
secondDoorObject->setRotation(glm::angleAxis(
|
||||||
|
fraction * glm::radians(90.f), glm::vec3(0.f, 1.f, 0.f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doorObject->setPosition(startPosition +
|
||||||
|
glm::vec3(0.f, 0.f, fraction * doorHeight));
|
||||||
|
|
||||||
|
if (secondDoorObject) {
|
||||||
|
secondDoorObject->setPosition(
|
||||||
|
startPositionSecondDoor +
|
||||||
|
glm::vec3(0.f, 0.f, fraction * doorHeight));
|
||||||
|
}
|
||||||
|
}
|
112
rwengine/src/engine/Garage.hpp
Normal file
112
rwengine/src/engine/Garage.hpp
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#ifndef _RWENGINE_Garage_HPP_
|
||||||
|
#define _RWENGINE_Garage_HPP_
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
#include <rw/defines.hpp>
|
||||||
|
|
||||||
|
class PlayerController;
|
||||||
|
|
||||||
|
class GameWorld;
|
||||||
|
|
||||||
|
class CharacterObject;
|
||||||
|
class InstanceObject;
|
||||||
|
class GameObject;
|
||||||
|
|
||||||
|
class Garage {
|
||||||
|
private:
|
||||||
|
InstanceObject* doorObject = nullptr;
|
||||||
|
InstanceObject* secondDoorObject = nullptr;
|
||||||
|
|
||||||
|
bool active = true;
|
||||||
|
|
||||||
|
float garageTimer = 0.f;
|
||||||
|
|
||||||
|
bool swingType = false;
|
||||||
|
|
||||||
|
glm::vec3 startPosition;
|
||||||
|
glm::vec3 startPositionSecondDoor;
|
||||||
|
|
||||||
|
bool needsToUpdate = false;
|
||||||
|
|
||||||
|
float fraction = 0.f;
|
||||||
|
float step = 3.f; // this should be adjusted somehow
|
||||||
|
// to look similar to original game
|
||||||
|
float doorHeight = 4.f;
|
||||||
|
|
||||||
|
float getDistanceToGarage(glm::vec3 point);
|
||||||
|
|
||||||
|
bool shouldOpen();
|
||||||
|
bool shouldClose();
|
||||||
|
bool shouldStopOpening();
|
||||||
|
bool shouldStopClosing();
|
||||||
|
|
||||||
|
void doOnOpenEvent();
|
||||||
|
void doOnCloseEvent();
|
||||||
|
void doOnStartOpeningEvent();
|
||||||
|
void doOnStartClosingEvent();
|
||||||
|
|
||||||
|
void updateDoor();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Garage types are from original game
|
||||||
|
enum class Type {
|
||||||
|
Mission = 1,
|
||||||
|
BombShop1 = 2,
|
||||||
|
BombShop2 = 3,
|
||||||
|
BombShop3 = 4,
|
||||||
|
Respray = 5,
|
||||||
|
CollectCars1 = 8,
|
||||||
|
CollectCars2 = 9,
|
||||||
|
MissionForCarToComeOut = 11,
|
||||||
|
Crusher = 13,
|
||||||
|
MissionKeepCar = 14,
|
||||||
|
Hideout1 = 16,
|
||||||
|
Hideout2 = 17,
|
||||||
|
Hideout3 = 18,
|
||||||
|
MissionToOpenAndClose = 19,
|
||||||
|
MissionForSpecificCar = 20,
|
||||||
|
MissionKeepCarAndRemainClosed = 21,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class State { Closed, Closing, Opening, Opened };
|
||||||
|
|
||||||
|
GameWorld* engine;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
int getScriptObjectID() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 min;
|
||||||
|
glm::vec3 max;
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
GameObject* target = nullptr;
|
||||||
|
// @todo use model type
|
||||||
|
int targetModel = 0;
|
||||||
|
|
||||||
|
State state = State::Closed;
|
||||||
|
|
||||||
|
bool resprayDone = false;
|
||||||
|
|
||||||
|
Garage(GameWorld* engine_, const int id_, const glm::vec3 coord0,
|
||||||
|
const glm::vec3 coord1, const Type type_);
|
||||||
|
~Garage() = default;
|
||||||
|
|
||||||
|
void makeDoorSwing();
|
||||||
|
|
||||||
|
bool isObjectInsideGarage(GameObject* object) const;
|
||||||
|
bool isTargetInsideGarage() const;
|
||||||
|
|
||||||
|
void activate();
|
||||||
|
void deactivate();
|
||||||
|
|
||||||
|
void open();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void tick(float dt);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,702 +0,0 @@
|
|||||||
#include "GarageController.hpp"
|
|
||||||
|
|
||||||
#include <btBulletDynamicsCommon.h>
|
|
||||||
#include <glm/gtx/quaternion.hpp>
|
|
||||||
|
|
||||||
#include "dynamics/CollisionInstance.hpp"
|
|
||||||
|
|
||||||
#include "ai/PlayerController.hpp"
|
|
||||||
|
|
||||||
#include "engine/GameState.hpp"
|
|
||||||
|
|
||||||
#include "objects/CharacterObject.hpp"
|
|
||||||
#include "objects/GameObject.hpp"
|
|
||||||
#include "objects/InstanceObject.hpp"
|
|
||||||
#include "objects/VehicleObject.hpp"
|
|
||||||
|
|
||||||
GarageController::GarageController(GameWorld* engine, GarageInfo* info,
|
|
||||||
InstanceObject* door)
|
|
||||||
|
|
||||||
: swingType(false)
|
|
||||||
, needsToUpdate(false)
|
|
||||||
, fraction(0.f)
|
|
||||||
, step(0.5f)
|
|
||||||
, doorHeight(4.0f)
|
|
||||||
, engine(engine)
|
|
||||||
, garageInfo(info)
|
|
||||||
, doorObject(door) {
|
|
||||||
if (doorObject) {
|
|
||||||
startPosition = doorObject->getPosition();
|
|
||||||
startRotation = doorObject->getRotation();
|
|
||||||
}
|
|
||||||
if (garageInfo) {
|
|
||||||
if (garageInfo->state == GarageState::Closed) {
|
|
||||||
fraction = 0.f;
|
|
||||||
} else {
|
|
||||||
fraction = 1.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo set door height according to model size
|
|
||||||
|
|
||||||
updateDoor();
|
|
||||||
}
|
|
||||||
|
|
||||||
GarageController::~GarageController() {
|
|
||||||
}
|
|
||||||
|
|
||||||
float GarageController::getDistanceToGarage(glm::vec3 point) {
|
|
||||||
float dx = std::max(
|
|
||||||
{garageInfo->min.x - point.x, 0.f, point.x - garageInfo->max.x});
|
|
||||||
float dy = std::max(
|
|
||||||
{garageInfo->min.y - point.y, 0.f, point.y - garageInfo->max.y});
|
|
||||||
|
|
||||||
// Seems like original game ignores z axis, bug or feature?
|
|
||||||
// float dz = std::max(
|
|
||||||
// {garageInfo->min.z - point.z, 0.f, point.z - garageInfo->max.z});
|
|
||||||
|
|
||||||
// return std::sqrt(dx * dx + dy * dy + dz * dz);
|
|
||||||
|
|
||||||
return std::sqrt(dx * dx + dy * dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GarageController::isObjectInsideGarage(GameObject* object) {
|
|
||||||
// This is not that trivial, we need to check if full vehicle body is inside
|
|
||||||
auto p = object->getPosition();
|
|
||||||
|
|
||||||
if (p.x >= (garageInfo->min.x) && p.y >= (garageInfo->min.y) &&
|
|
||||||
p.z >= (garageInfo->min.z) && p.x <= (garageInfo->max.x) &&
|
|
||||||
p.y <= (garageInfo->max.y) && p.z <= (garageInfo->max.z)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GarageController::shouldClose() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission: {
|
|
||||||
if (!isObjectInsideGarage(static_cast<GameObject*>(plyChar)) &&
|
|
||||||
isObjectInsideGarage(garageInfo->target)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray: {
|
|
||||||
if (playerIsInVehicle) {
|
|
||||||
if (isObjectInsideGarage(
|
|
||||||
static_cast<GameObject*>(playerVehicle)) &&
|
|
||||||
playerVehicle->isStopped()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
if (playerIsInVehicle) {
|
|
||||||
if (isObjectInsideGarage(
|
|
||||||
static_cast<GameObject*>(playerVehicle))) {
|
|
||||||
if (playerVehicle->getLifetime() !=
|
|
||||||
GameObject::MissionLifetime) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// @todo show message "come back when youre not busy"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
// Not sure about these values
|
|
||||||
if ((!playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) >= 5.f) ||
|
|
||||||
(playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) >= 10.f)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GarageController::shouldOpen() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission: {
|
|
||||||
// Not sure about these values
|
|
||||||
if (playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) < 8.f &&
|
|
||||||
playerVehicle == garageInfo->target) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray: {
|
|
||||||
if (garageTimer < engine->getGameTime()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
// Not sure about these values
|
|
||||||
if ((!playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) < 5.f) ||
|
|
||||||
(playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) < 10.f)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GarageController::shouldStopClosing() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission:
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray:
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
// Not sure about these values
|
|
||||||
if ((!playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) < 5.f) ||
|
|
||||||
(playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) < 10.f)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GarageController::shouldStopOpening() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission:
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray:
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
// Not sure about these values
|
|
||||||
if ((!playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) >= 5.f) ||
|
|
||||||
(playerIsInVehicle &&
|
|
||||||
getDistanceToGarage(playerPosition) >= 10.f)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
// @todo unimplemented
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::doOnOpenEvent() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop2: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop3: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Respray: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::doOnCloseEvent() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3: {
|
|
||||||
// Find out real value
|
|
||||||
garageTimer = engine->getGameTime() + 1.5f;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Respray: {
|
|
||||||
// Find out real value
|
|
||||||
garageTimer = engine->getGameTime() + 2.f;
|
|
||||||
playerVehicle->setHealth(1000.f);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::doOnStartOpeningEvent() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission:
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
controller->setInputEnabled(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray: {
|
|
||||||
controller->setInputEnabled(true);
|
|
||||||
playerVehicle->setHandbraking(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Hideout1:
|
|
||||||
case GarageType::Hideout2:
|
|
||||||
case GarageType::Hideout3: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::doOnStartClosingEvent() {
|
|
||||||
auto controller = engine->players.at(0);
|
|
||||||
auto plyChar = controller->getCharacter();
|
|
||||||
auto playerPosition = plyChar->getPosition();
|
|
||||||
auto playerVehicle = plyChar->getCurrentVehicle();
|
|
||||||
bool playerIsInVehicle = playerVehicle != nullptr;
|
|
||||||
|
|
||||||
switch (garageInfo->type) {
|
|
||||||
case GarageType::Mission:
|
|
||||||
case GarageType::CollectCars1:
|
|
||||||
case GarageType::CollectCars2: {
|
|
||||||
controller->setInputEnabled(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::BombShop1:
|
|
||||||
case GarageType::BombShop2:
|
|
||||||
case GarageType::BombShop3:
|
|
||||||
case GarageType::Respray: {
|
|
||||||
controller->setInputEnabled(false);
|
|
||||||
playerVehicle->setHandbraking(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForCarToComeOut: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::Crusher: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionToOpenAndClose: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionForSpecificCar: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageType::MissionKeepCarAndRemainClosed: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::tick(float dt) {
|
|
||||||
if (!garageInfo) return;
|
|
||||||
if (!doorObject) return;
|
|
||||||
|
|
||||||
needsToUpdate = false;
|
|
||||||
|
|
||||||
switch (garageInfo->state) {
|
|
||||||
case GarageState::Opened: {
|
|
||||||
if (shouldClose()) {
|
|
||||||
garageInfo->state = GarageState::Closing;
|
|
||||||
doOnStartClosingEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageState::Closed: {
|
|
||||||
if (shouldOpen()) {
|
|
||||||
garageInfo->state = GarageState::Opening;
|
|
||||||
doOnStartOpeningEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageState::Opening: {
|
|
||||||
if (shouldStopOpening()) {
|
|
||||||
garageInfo->state = GarageState::Closing;
|
|
||||||
} else {
|
|
||||||
fraction += dt * step;
|
|
||||||
|
|
||||||
if (fraction >= 1.0f) {
|
|
||||||
garageInfo->state = GarageState::Opened;
|
|
||||||
fraction = 1.f;
|
|
||||||
doOnOpenEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
needsToUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GarageState::Closing: {
|
|
||||||
if (shouldStopClosing()) {
|
|
||||||
garageInfo->state = GarageState::Opening;
|
|
||||||
} else {
|
|
||||||
fraction -= dt * step;
|
|
||||||
|
|
||||||
if (fraction <= 0.f) {
|
|
||||||
garageInfo->state = GarageState::Closed;
|
|
||||||
fraction = 0.f;
|
|
||||||
doOnCloseEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
needsToUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsToUpdate) {
|
|
||||||
updateDoor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GarageController::updateDoor() {
|
|
||||||
if (swingType) {
|
|
||||||
// @todo incomplete
|
|
||||||
doorObject->setRotation(
|
|
||||||
glm::angleAxis(fraction * 1.57079632679f, glm::vec3(0, 1, 0)));
|
|
||||||
} else {
|
|
||||||
doorObject->setPosition(startPosition +
|
|
||||||
glm::vec3(0.f, 0.f, fraction * doorHeight));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
#ifndef _RWENGINE_GARAGECONTROLLER_HPP_
|
|
||||||
#define _RWENGINE_GARAGECONTROLLER_HPP_
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
#include <rw/defines.hpp>
|
|
||||||
|
|
||||||
class PlayerController;
|
|
||||||
|
|
||||||
struct GarageInfo;
|
|
||||||
|
|
||||||
class GameWorld;
|
|
||||||
|
|
||||||
class CharacterObject;
|
|
||||||
class InstanceObject;
|
|
||||||
class GameObject;
|
|
||||||
|
|
||||||
class GarageController {
|
|
||||||
private:
|
|
||||||
float garageTimer = 0.f;
|
|
||||||
|
|
||||||
bool swingType;
|
|
||||||
|
|
||||||
glm::vec3 startPosition;
|
|
||||||
glm::quat startRotation;
|
|
||||||
|
|
||||||
bool needsToUpdate;
|
|
||||||
|
|
||||||
float fraction;
|
|
||||||
float step;
|
|
||||||
float doorHeight;
|
|
||||||
|
|
||||||
float getDistanceToGarage(glm::vec3 point);
|
|
||||||
bool isObjectInsideGarage(GameObject* object);
|
|
||||||
|
|
||||||
bool shouldOpen();
|
|
||||||
bool shouldClose();
|
|
||||||
bool shouldStopOpening();
|
|
||||||
bool shouldStopClosing();
|
|
||||||
|
|
||||||
void doOnOpenEvent();
|
|
||||||
void doOnCloseEvent();
|
|
||||||
void doOnStartOpeningEvent();
|
|
||||||
void doOnStartClosingEvent();
|
|
||||||
|
|
||||||
void updateDoor();
|
|
||||||
|
|
||||||
public:
|
|
||||||
GameWorld* engine;
|
|
||||||
GarageInfo* garageInfo;
|
|
||||||
InstanceObject* doorObject;
|
|
||||||
|
|
||||||
GarageController(GameWorld* engine, GarageInfo* info, InstanceObject* door);
|
|
||||||
~GarageController();
|
|
||||||
|
|
||||||
void tick(float dt);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1264,9 +1264,9 @@ bool SaveGame::loadGame(GameState& state, const std::string& file) {
|
|||||||
// http://gtaforums.com/topic/758692-gta-iii-save-file-documentation/
|
// http://gtaforums.com/topic/758692-gta-iii-save-file-documentation/
|
||||||
for (size_t g = 0; g < garageData.garageCount; ++g) {
|
for (size_t g = 0; g < garageData.garageCount; ++g) {
|
||||||
auto& garage = garages[g];
|
auto& garage = garages[g];
|
||||||
state.garages.emplace_back(
|
state.world->createGarage(glm::vec3(garage.x1, garage.y1, garage.z1),
|
||||||
(int)g, glm::vec3(garage.x1, garage.y1, garage.z1),
|
glm::vec3(garage.x2, garage.y2, garage.z2),
|
||||||
glm::vec3(garage.x2, garage.y2, garage.z2), static_cast<GarageType>(garage.type));
|
static_cast<Garage::Type>(garage.type));
|
||||||
}
|
}
|
||||||
for (auto &c : garageData.cars) {
|
for (auto &c : garageData.cars) {
|
||||||
if (c.modelId == 0) continue;
|
if (c.modelId == 0) continue;
|
||||||
|
@ -140,7 +140,7 @@ void do_unpacked_call(Tret (*const& func)(Targs...),
|
|||||||
const ScriptArguments& args) {
|
const ScriptArguments& args) {
|
||||||
script_bind::binder<Tret, Targs...>::call(func, args);
|
script_bind::binder<Tret, Targs...>::call(func, args);
|
||||||
}
|
}
|
||||||
}
|
} // namespace script_bind
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for a collection of functions that can be exported to a game script
|
* Interface for a collection of functions that can be exported to a game script
|
||||||
@ -154,8 +154,7 @@ void do_unpacked_call(Tret (*const& func)(Targs...),
|
|||||||
class ScriptModule {
|
class ScriptModule {
|
||||||
public:
|
public:
|
||||||
template <class String>
|
template <class String>
|
||||||
ScriptModule(String&& _name)
|
ScriptModule(String&& _name) : name(std::forward<String>(_name)) {
|
||||||
: name(std::forward<String>(_name)) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& getName() const {
|
const std::string& getName() const {
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include "objects/InstanceObject.hpp"
|
#include "objects/InstanceObject.hpp"
|
||||||
#include "objects/PickupObject.hpp"
|
#include "objects/PickupObject.hpp"
|
||||||
#include "objects/VehicleObject.hpp"
|
#include "objects/VehicleObject.hpp"
|
||||||
#include "script/ScriptMachine.hpp"
|
|
||||||
#include "script/SCMFile.hpp"
|
#include "script/SCMFile.hpp"
|
||||||
|
#include "script/ScriptMachine.hpp"
|
||||||
|
|
||||||
GameState* ScriptArguments::getState() const {
|
GameState* ScriptArguments::getState() const {
|
||||||
return getVM()->getState();
|
return getVM()->getState();
|
||||||
@ -47,6 +47,12 @@ GameObject* ScriptArguments::getPlayerCharacter(unsigned int player) const {
|
|||||||
return controller->getCharacter();
|
return controller->getCharacter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo figure out original cast
|
||||||
|
template <>
|
||||||
|
ScriptGarageType ScriptArguments::getParameter<ScriptGarageType>(unsigned int arg) const {
|
||||||
|
return static_cast<Garage::Type>(getParameters().at(arg).integerValue());
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
GameObject* ScriptArguments::getObject<PlayerController>(
|
GameObject* ScriptArguments::getObject<PlayerController>(
|
||||||
unsigned int arg) const {
|
unsigned int arg) const {
|
||||||
@ -208,14 +214,14 @@ ScriptObjectType<VehicleGenerator> ScriptArguments::getScriptObject(
|
|||||||
return {param.handleValue(), generator};
|
return {param.handleValue(), generator};
|
||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
ScriptObjectType<GarageInfo> ScriptArguments::getScriptObject(
|
ScriptObjectType<Garage> ScriptArguments::getScriptObject(
|
||||||
unsigned int arg) const {
|
unsigned int arg) const {
|
||||||
auto& param = (*this)[arg];
|
auto& param = (*this)[arg];
|
||||||
RW_CHECK(param.isLvalue(), "Non lvalue passed as object");
|
RW_CHECK(param.isLvalue(), "Non lvalue passed as object");
|
||||||
auto& garages = getWorld()->state->garages;
|
auto& garages = getWorld()->garages;
|
||||||
GarageInfo* garage = nullptr;
|
Garage* garage = nullptr;
|
||||||
if (size_t(*param.handleValue()) < garages.size()) {
|
if (size_t(*param.handleValue()) < garages.size()) {
|
||||||
garage = &garages[*param.handleValue()];
|
garage = garages[*param.handleValue()].get();
|
||||||
}
|
}
|
||||||
return {param.handleValue(), garage};
|
return {param.handleValue(), garage};
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <rw/defines.hpp>
|
#include <rw/defines.hpp>
|
||||||
|
|
||||||
|
#include "engine/Garage.hpp"
|
||||||
|
|
||||||
class CharacterObject;
|
class CharacterObject;
|
||||||
class CutsceneObject;
|
class CutsceneObject;
|
||||||
class GameObject;
|
class GameObject;
|
||||||
@ -24,6 +26,7 @@ struct SCMThread;
|
|||||||
class GameState;
|
class GameState;
|
||||||
class GameWorld;
|
class GameWorld;
|
||||||
class Payphone;
|
class Payphone;
|
||||||
|
class Garage;
|
||||||
|
|
||||||
typedef uint16_t SCMOpcode;
|
typedef uint16_t SCMOpcode;
|
||||||
typedef char SCMByte;
|
typedef char SCMByte;
|
||||||
@ -98,14 +101,13 @@ using ScriptPlayer = ScriptObjectType<PlayerController>;
|
|||||||
using ScriptVehicle = ScriptObjectType<VehicleObject>;
|
using ScriptVehicle = ScriptObjectType<VehicleObject>;
|
||||||
using ScriptCharacter = ScriptObjectType<CharacterObject>;
|
using ScriptCharacter = ScriptObjectType<CharacterObject>;
|
||||||
using ScriptPickup = ScriptObjectType<PickupObject>;
|
using ScriptPickup = ScriptObjectType<PickupObject>;
|
||||||
|
using ScriptGarage = ScriptObjectType<Garage>;
|
||||||
|
|
||||||
struct VehicleGenerator;
|
struct VehicleGenerator;
|
||||||
struct BlipData;
|
struct BlipData;
|
||||||
struct GarageInfo;
|
|
||||||
|
|
||||||
using ScriptVehicleGenerator = ScriptObjectType<VehicleGenerator>;
|
using ScriptVehicleGenerator = ScriptObjectType<VehicleGenerator>;
|
||||||
using ScriptBlip = ScriptObjectType<BlipData>;
|
using ScriptBlip = ScriptObjectType<BlipData>;
|
||||||
using ScriptGarage = ScriptObjectType<GarageInfo>;
|
|
||||||
using ScriptPayphone = ScriptObjectType<Payphone>;
|
using ScriptPayphone = ScriptObjectType<Payphone>;
|
||||||
|
|
||||||
/// @todo replace these with real types for sounds etc.
|
/// @todo replace these with real types for sounds etc.
|
||||||
@ -159,7 +161,7 @@ using ScriptParticle = int;
|
|||||||
using ScriptTempact = int;
|
using ScriptTempact = int;
|
||||||
using ScriptSoundType = int;
|
using ScriptSoundType = int;
|
||||||
using ScriptPickupType = int;
|
using ScriptPickupType = int;
|
||||||
using ScriptGarageType = int;
|
using ScriptGarageType = Garage::Type;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Script Bytecode Types
|
// Script Bytecode Types
|
||||||
@ -345,7 +347,7 @@ template <>
|
|||||||
ScriptObjectType<VehicleGenerator> ScriptArguments::getScriptObject(
|
ScriptObjectType<VehicleGenerator> ScriptArguments::getScriptObject(
|
||||||
unsigned int arg) const;
|
unsigned int arg) const;
|
||||||
template <>
|
template <>
|
||||||
ScriptObjectType<GarageInfo> ScriptArguments::getScriptObject(
|
ScriptObjectType<Garage> ScriptArguments::getScriptObject(
|
||||||
unsigned int arg) const;
|
unsigned int arg) const;
|
||||||
|
|
||||||
typedef std::function<void(const ScriptArguments&)> ScriptFunction;
|
typedef std::function<void(const ScriptArguments&)> ScriptFunction;
|
||||||
|
@ -6103,8 +6103,8 @@ void opcode_0218(const ScriptArguments& args, const ScriptString gxtEntry, const
|
|||||||
@arg arg7
|
@arg arg7
|
||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_0219(const ScriptArguments& args, ScriptVec3 coord0,
|
void opcode_0219(const ScriptArguments& args, const ScriptVec3 coord0,
|
||||||
ScriptVec3 coord1, const ScriptInt type,
|
const ScriptVec3 coord1, const ScriptGarageType type,
|
||||||
ScriptGarage& garage) {
|
ScriptGarage& garage) {
|
||||||
garage = args.getWorld()->createGarage(coord0, coord1, type);
|
garage = args.getWorld()->createGarage(coord0, coord1, type);
|
||||||
}
|
}
|
||||||
@ -6117,10 +6117,8 @@ void opcode_0219(const ScriptArguments& args, ScriptVec3 coord0,
|
|||||||
@arg vehicle Car/vehicle
|
@arg vehicle Car/vehicle
|
||||||
*/
|
*/
|
||||||
void opcode_021b(const ScriptArguments& args, const ScriptGarage garage, const ScriptVehicle vehicle) {
|
void opcode_021b(const ScriptArguments& args, const ScriptGarage garage, const ScriptVehicle vehicle) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x021b);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(vehicle);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->target = vehicle.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6130,16 +6128,8 @@ void opcode_021b(const ScriptArguments& args, const ScriptGarage garage, const S
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
bool opcode_021c(const ScriptArguments& args, const ScriptGarage garage) {
|
bool opcode_021c(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
auto& objects = args.getWorld()->vehiclePool.objects;
|
RW_UNUSED(args);
|
||||||
for(auto& v : objects) {
|
return garage->isTargetInsideGarage();
|
||||||
// @todo if this car only accepts mission cars we probably have to filter here / only check for one specific car
|
|
||||||
auto vp = v.second->getPosition();
|
|
||||||
if (vp.x >= garage->min.x && vp.y >= garage->min.y && vp.z >= garage->min.z &&
|
|
||||||
vp.x <= garage->max.x && vp.y <= garage->max.y && vp.z <= garage->max.z) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6843,9 +6833,8 @@ void opcode_0298(const ScriptArguments& args, const ScriptModelID model0, Script
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_0299(const ScriptArguments& args, const ScriptGarage garage) {
|
void opcode_0299(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0299);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7342,9 +7331,8 @@ bool opcode_02b8(const ScriptArguments& args, const ScriptPlayer player, ScriptV
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_02b9(const ScriptArguments& args, const ScriptGarage garage) {
|
void opcode_02b9(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x02b9);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8163,11 +8151,9 @@ void opcode_02f9(const ScriptArguments& args, const ScriptVehicle vehicle, Scrip
|
|||||||
@arg garage0
|
@arg garage0
|
||||||
@arg garage1
|
@arg garage1
|
||||||
*/
|
*/
|
||||||
void opcode_02fa(const ScriptArguments& args, const ScriptGarage garage0, const ScriptGarageType garage1) {
|
void opcode_02fa(const ScriptArguments& args, const ScriptGarage garage, const ScriptGarageType garageType) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x02fa);
|
|
||||||
RW_UNUSED(garage0);
|
|
||||||
RW_UNUSED(garage1);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->type = garageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8894,18 +8880,8 @@ void opcode_0327(const ScriptArguments& args, ScriptVec2 coord0, ScriptVec2 coor
|
|||||||
@arg garage Handle
|
@arg garage Handle
|
||||||
*/
|
*/
|
||||||
bool opcode_0329(const ScriptArguments& args, const ScriptGarage garage) {
|
bool opcode_0329(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
if (garage->type != GarageType::Respray) {
|
RW_UNUSED(args);
|
||||||
return false;
|
return garage->resprayDone;
|
||||||
}
|
|
||||||
|
|
||||||
auto playerobj = args.getWorld()->pedestrianPool.find(args.getState()->playerObject);
|
|
||||||
auto pp = playerobj->getPosition();
|
|
||||||
if (pp.x >= garage->min.x && pp.y >= garage->min.y && pp.z >= garage->min.z &&
|
|
||||||
pp.x <= garage->max.x && pp.y <= garage->max.y && pp.z <= garage->max.z) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9584,9 +9560,8 @@ void opcode_035f(const ScriptArguments& args, const ScriptCharacter character, c
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_0360(const ScriptArguments& args, const ScriptGarage garage) {
|
void opcode_0360(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0360);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9596,9 +9571,8 @@ void opcode_0360(const ScriptArguments& args, const ScriptGarage garage) {
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_0361(const ScriptArguments& args, const ScriptGarage garage) {
|
void opcode_0361(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x0361);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10698,12 +10672,11 @@ void opcode_03a4(const ScriptArguments& args, const ScriptString name) {
|
|||||||
@arg garage1
|
@arg garage1
|
||||||
@arg model
|
@arg model
|
||||||
*/
|
*/
|
||||||
void opcode_03a5(const ScriptArguments& args, const ScriptGarage garage0, const ScriptGarageType garage1, const ScriptModelID model) {
|
void opcode_03a5(const ScriptArguments& args, const ScriptGarage garage, const ScriptGarageType garageType, const ScriptModelID model) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x03a5);
|
|
||||||
RW_UNUSED(garage0);
|
|
||||||
RW_UNUSED(garage1);
|
|
||||||
RW_UNUSED(model);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->type = garageType;
|
||||||
|
garage->targetModel = model;
|
||||||
|
garage->state = Garage::State::Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10826,10 +10799,8 @@ bool opcode_03b0(const ScriptArguments& args, const ScriptGarage garage) {
|
|||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
bool opcode_03b1(const ScriptArguments& args, const ScriptGarage garage) {
|
bool opcode_03b1(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x03b1);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
return false;
|
return garage->state == Garage::State::Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10964,12 +10935,11 @@ void opcode_03ba(const ScriptArguments& args, ScriptVec3 coord0, ScriptVec3 coor
|
|||||||
@brief set_garage %1d% door_type_to_swing_open
|
@brief set_garage %1d% door_type_to_swing_open
|
||||||
|
|
||||||
opcode 03bb
|
opcode 03bb
|
||||||
@arg garage
|
@arg garage
|
||||||
*/
|
*/
|
||||||
void opcode_03bb(const ScriptArguments& args, const ScriptGarage garage) {
|
void opcode_03bb(const ScriptArguments& args, const ScriptGarage garage) {
|
||||||
RW_UNIMPLEMENTED_OPCODE(0x03bb);
|
|
||||||
RW_UNUSED(garage);
|
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
|
garage->makeDoorSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11302,21 +11272,18 @@ void opcode_03d3(const ScriptArguments& args, ScriptVec3 coord, ScriptFloat& xCo
|
|||||||
@arg garage Handle
|
@arg garage Handle
|
||||||
@arg arg2
|
@arg arg2
|
||||||
*/
|
*/
|
||||||
bool opcode_03d4(const ScriptArguments& args, const ScriptGarage garage, const ScriptInt arg2) {
|
bool opcode_03d4(const ScriptArguments& args, const ScriptGarage garage, const ScriptInt index) {
|
||||||
int entryIndex = arg2;
|
int entryIndex = index;
|
||||||
RW_CHECK(entryIndex >= 0, "Entry index too low");
|
RW_CHECK(entryIndex >= 0, "Entry index too low");
|
||||||
RW_CHECK(entryIndex < 32, "Entry index too high");
|
RW_CHECK(entryIndex < 32, "Entry index too high");
|
||||||
|
|
||||||
// @todo reimplement
|
// @todo reimplement
|
||||||
if (garage->type == GarageType::CollectCars1) {
|
if (garage->type == Garage::Type::CollectCars1) {
|
||||||
return args.getState()->importExportPortland[entryIndex];
|
return args.getState()->importExportPortland[entryIndex];
|
||||||
}
|
}
|
||||||
if (garage->type == GarageType::CollectCars2) {
|
if (garage->type == Garage::Type::CollectCars2) {
|
||||||
return args.getState()->importExportShoreside[entryIndex];
|
return args.getState()->importExportShoreside[entryIndex];
|
||||||
}
|
}
|
||||||
// if (garage->type == GarageType::CollectCars3) {
|
|
||||||
// return args.getState()->importExportUnused[entryIndex];
|
|
||||||
// }
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -12179,18 +12146,7 @@ void opcode_0421(const ScriptArguments& args, const ScriptBoolean arg1) {
|
|||||||
*/
|
*/
|
||||||
bool opcode_0422(const ScriptArguments& args, const ScriptGarage garage, const ScriptVehicle vehicle) {
|
bool opcode_0422(const ScriptArguments& args, const ScriptGarage garage, const ScriptVehicle vehicle) {
|
||||||
RW_UNUSED(args);
|
RW_UNUSED(args);
|
||||||
/// @todo move to garage code
|
return garage->isObjectInsideGarage(vehicle.get());
|
||||||
|
|
||||||
if (vehicle) {
|
|
||||||
/// @todo if this car only accepts mission cars we probably have to filter here / only check for one specific car
|
|
||||||
auto vp = vehicle->getPosition();
|
|
||||||
if(vp.x >= garage->min.x && vp.y >= garage->min.y && vp.z >= garage->min.z &&
|
|
||||||
vp.x <= garage->max.x && vp.y <= garage->max.y && vp.z <= garage->max.z) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,8 +537,8 @@ void RWGame::tick(float dt) {
|
|||||||
object->tick(dt);
|
object->tick(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& gc : world->garageControllers) {
|
for (auto& g : world->garages) {
|
||||||
gc->tick(dt);
|
g->tick(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& p : world->payphones) {
|
for (auto& p : world->payphones) {
|
||||||
@ -717,11 +717,11 @@ void RWGame::renderDebugPaths(float time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw Garage bounds
|
// Draw Garage bounds
|
||||||
for (const auto& garage : state.garages) {
|
for (const auto& garage : world->garages) {
|
||||||
btVector3 minColor(1.f, 0.f, 0.f);
|
btVector3 minColor(1.f, 0.f, 0.f);
|
||||||
btVector3 maxColor(0.f, 1.f, 0.f);
|
btVector3 maxColor(0.f, 1.f, 0.f);
|
||||||
btVector3 min(garage.min.x, garage.min.y, garage.min.z);
|
btVector3 min(garage->min.x, garage->min.y, garage->min.z);
|
||||||
btVector3 max(garage.max.x, garage.max.y, garage.max.z);
|
btVector3 max(garage->max.x, garage->max.y, garage->max.z);
|
||||||
debug.drawLine(min, min + btVector3(0.5f, 0.f, 0.f), minColor);
|
debug.drawLine(min, min + btVector3(0.5f, 0.f, 0.f), minColor);
|
||||||
debug.drawLine(min, min + btVector3(0.f, 0.5f, 0.f), minColor);
|
debug.drawLine(min, min + btVector3(0.f, 0.5f, 0.f), minColor);
|
||||||
debug.drawLine(min, min + btVector3(0.f, 0.f, 0.5f), minColor);
|
debug.drawLine(min, min + btVector3(0.f, 0.f, 0.5f), minColor);
|
||||||
|
@ -16,6 +16,7 @@ set(TESTS
|
|||||||
FileIndex
|
FileIndex
|
||||||
GameData
|
GameData
|
||||||
GameWorld
|
GameWorld
|
||||||
|
Garage
|
||||||
Input
|
Input
|
||||||
Items
|
Items
|
||||||
Lifetime
|
Lifetime
|
||||||
|
18
tests/test_Garage.cpp
Normal file
18
tests/test_Garage.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <engine/Garage.hpp>
|
||||||
|
#include "test_Globals.hpp"
|
||||||
|
#if RW_TEST_WITH_DATA
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(GarageTests)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_garage_interaction) {
|
||||||
|
{
|
||||||
|
auto garage = Global::get().e->createGarage(
|
||||||
|
{0.f, 0.f, 0.f}, {3.f, 3.f, 3.f}, Garage::Type::Respray);
|
||||||
|
BOOST_REQUIRE(garage != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user