1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-10-06 09:07:19 +02:00

Merge pull request #709 from danhedron/feat-script-object-cleanup

Remove existing vehicles & peds when creating script objects
This commit is contained in:
Daniel Evans 2019-05-06 04:08:49 +01:00 committed by GitHub
commit 767f921859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 36 deletions

View File

@ -1006,31 +1006,9 @@ bool GameWorld::isRaining() const {
void GameWorld::clearObjectsWithinArea(const glm::vec3 center,
const float radius,
const bool clearParticles) {
bool skipFlag = false;
// Vehicles
for (auto& obj : vehiclePool.objects) {
skipFlag = false;
// Skip if it's the player or owned by player or owned by mission
if (obj.second->getLifetime() == GameObject::PlayerLifetime ||
obj.second->getLifetime() == GameObject::MissionLifetime) {
continue;
}
// Check if we have any important objects in a vehicle, if we do - don't
// erase it
for (auto& seat :
static_cast<VehicleObject*>(obj.second.get())->seatOccupants) {
auto character = static_cast<CharacterObject*>(seat.second);
if (character->getLifetime() == GameObject::PlayerLifetime ||
character->getLifetime() == GameObject::MissionLifetime) {
skipFlag = true;
}
}
if (skipFlag) {
if (!obj.second->canBeRemoved()) {
continue;
}
@ -1041,9 +1019,7 @@ void GameWorld::clearObjectsWithinArea(const glm::vec3 center,
// Peds
for (auto& obj : pedestrianPool.objects) {
// Skip if it's the player or owned by player or owned by mission
if (obj.second->getLifetime() == GameObject::PlayerLifetime ||
obj.second->getLifetime() == GameObject::MissionLifetime) {
if (!obj.second->canBeRemoved()) {
continue;
}
@ -1066,6 +1042,28 @@ void GameWorld::clearObjectsWithinArea(const glm::vec3 center,
// explosions, remove all projectiles
}
std::vector<GameObject *>
GameWorld::findOverlappingObjects(const glm::vec3 &center,
float radius) const {
std::vector<GameObject*> overlapping;
auto checkObjects = [&](const auto& objects) {
for (auto& p : objects) {
const auto& object = p.second.get();
auto objectBounds = object->getModel()->getBoundingRadius();
if (glm::distance(center, object->getPosition()) <
radius + objectBounds) {
overlapping.push_back(object);
}
}
};
checkObjects(vehiclePool.objects);
checkObjects(pedestrianPool.objects);
return overlapping;
}
ai::PlayerController* GameWorld::getPlayer() {
auto object = pedestrianPool.find(state->playerObject);
if (object) {

View File

@ -397,6 +397,9 @@ public:
void clearObjectsWithinArea(const glm::vec3 center, const float radius,
const bool clearParticles);
std::vector<GameObject*> findOverlappingObjects(const glm::vec3& center,
float radius) const;
ai::PlayerController* getPlayer();
template <

View File

@ -238,10 +238,22 @@ public:
void setLifetime(ObjectLifetime ol) {
lifetime = ol;
}
ObjectLifetime getLifetime() const {
return lifetime;
}
/// Returns true if the object is not referenced by a script or player
virtual bool canBeRemoved() const {
switch (lifetime) {
case MissionLifetime:
case PlayerLifetime:
return false;
default:
return true;
}
}
virtual void updateTransform(const glm::vec3& pos, const glm::quat& rot) {
_lastPosition = position;
_lastRotation = rotation;

View File

@ -643,6 +643,12 @@ float VehicleObject::getVelocity() const {
return 0.f;
}
bool VehicleObject::canBeRemoved() const {
return GameObject::canBeRemoved() &&
all_of(seatOccupants.begin(), seatOccupants.end(),
[](const auto& p) { return p.second->canBeRemoved(); });
}
bool VehicleObject::isWrecked() const {
return health < 250.f;
}

View File

@ -123,6 +123,8 @@ public:
return Vehicle;
}
bool canBeRemoved() const override;
bool isWrecked() const;
void setHealth(float);

View File

@ -217,6 +217,23 @@ inline BlipData createObjectBlipSprite(const ScriptArguments& args,
ScriptModel getModel(const ScriptArguments& args, ScriptModel model);
inline void clearSpaceForObject(const ScriptArguments& args,
GameObject* object) {
RW_ASSERT(object->getModel());
auto radius = object->getModel()->getBoundingRadius();
const auto& overlapping = args.getWorld()->findOverlappingObjects(
object->getPosition(), radius);
for (const auto& found : overlapping) {
if (found->canBeRemoved())
args.getWorld()->destroyObjectQueued(found);
// @todo check collision meshes for real intersection
}
}
inline void addObjectToMissionCleanup(const ScriptArguments& args,
GameObject* object) {
if (args.getThread()->isMission) {

View File

@ -916,6 +916,7 @@ void opcode_0053(const ScriptArguments& args, const ScriptInt index, ScriptVec3
character->applyOffset();
player = static_cast<ai::PlayerController*>(character->controller);
args.getState()->playerObject = character->getGameObjectID();
script::clearSpaceForObject(args, character);
}
/**
@ -940,9 +941,9 @@ void opcode_0054(const ScriptArguments& args, const ScriptPlayer player, ScriptF
@arg coord Coordinates
*/
void opcode_0055(const ScriptArguments& args, const ScriptPlayer player, ScriptVec3 coord) {
RW_UNUSED(args);
player->getCharacter()->setPosition(coord);
player->getCharacter()->applyOffset();
script::clearSpaceForObject(args, player->getCharacter());
}
/**
@ -1797,11 +1798,11 @@ void opcode_009a(const ScriptArguments& args, const ScriptPedType pedType, const
character->applyOffset();
character->setLifetime(GameObject::MissionLifetime);
script::clearSpaceForObject(args, character);
if (args.getThread()->isMission) {
script::addObjectToMissionCleanup(args, character);
}
/// @todo track object mission status
}
/**
@ -1889,7 +1890,7 @@ void opcode_00a0(const ScriptArguments& args, const ScriptCharacter character, S
*/
void opcode_00a1(const ScriptArguments& args, const ScriptCharacter character, ScriptVec3 coord) {
script::setObjectPosition(character, coord);
RW_UNUSED(args);
script::clearSpaceForObject(args, character);
}
/**
@ -1947,6 +1948,8 @@ void opcode_00a5(const ScriptArguments& args, const ScriptModelID model, ScriptV
vehicle->applyOffset();
vehicle->setLifetime(GameObject::MissionLifetime);
script::clearSpaceForObject(args, vehicle);
if (args.getThread()->isMission) {
script::addObjectToMissionCleanup(args, vehicle);
}
@ -2022,8 +2025,8 @@ void opcode_00aa(const ScriptArguments& args, const ScriptVehicle vehicle, Scrip
@arg coord Coordinates
*/
void opcode_00ab(const ScriptArguments& args, const ScriptVehicle vehicle, ScriptVec3 coord) {
RW_UNUSED(args);
script::setObjectPosition(vehicle, coord);
script::clearSpaceForObject(args, vehicle);
}
/**
@ -4917,8 +4920,8 @@ void opcode_01bb(const ScriptArguments& args, const ScriptObject object, ScriptF
@arg coord Coordinates
*/
void opcode_01bc(const ScriptArguments& args, const ScriptObject object, ScriptVec3 coord) {
RW_UNUSED(args);
script::setObjectPosition(object, coord);
script::clearSpaceForObject(args, object);
}
/**
@ -5035,7 +5038,6 @@ void opcode_01c4(const ScriptArguments& args, const ScriptObject object) {
@arg character Character/ped
*/
void opcode_01c5(const ScriptArguments& args, const ScriptCharacter character) {
RW_UNUSED(args);
script::removeObjectFromMissionCleanup(args, character);
}
@ -5046,7 +5048,6 @@ void opcode_01c5(const ScriptArguments& args, const ScriptCharacter character) {
@arg vehicle Car/vehicle
*/
void opcode_01c6(const ScriptArguments& args, const ScriptVehicle vehicle) {
RW_UNUSED(args);
script::removeObjectFromMissionCleanup(args, vehicle);
}
@ -5057,7 +5058,6 @@ void opcode_01c6(const ScriptArguments& args, const ScriptVehicle vehicle) {
@arg object Object
*/
void opcode_01c7(const ScriptArguments& args, const ScriptObject object) {
RW_UNUSED(args);
script::removeObjectFromMissionCleanup(args, object);
}
@ -9610,9 +9610,9 @@ void opcode_0361(const ScriptArguments& args, const ScriptGarage garage) {
*/
void opcode_0362(const ScriptArguments& args, const ScriptCharacter character,
ScriptVec3 coord) {
RW_UNUSED(args);
character->setCurrentVehicle(nullptr, 0);
character->setPosition(coord);
script::clearSpaceForObject(args, character);
}
/**
@ -9964,6 +9964,7 @@ void opcode_0376(const ScriptArguments& args, ScriptVec3 coord,
pedGroup.at(args.getWorld()->getRandomNumber(0u, pedGroup.size() - 1));
character = world->createPedestrian(model, coord);
character->applyOffset();
script::clearSpaceForObject(args, character);
}
/**