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:
commit
767f921859
@ -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 ¢er,
|
||||
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) {
|
||||
|
@ -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 <
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -123,6 +123,8 @@ public:
|
||||
return Vehicle;
|
||||
}
|
||||
|
||||
bool canBeRemoved() const override;
|
||||
|
||||
bool isWrecked() const;
|
||||
|
||||
void setHealth(float);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user