1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 18:32:44 +01:00

Merge pull request #477 from husho/fixrestart2

Clear world on player restart
This commit is contained in:
Daniel Evans 2018-05-19 22:51:04 +01:00 committed by GitHub
commit 989ed36b78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 100 additions and 53 deletions

View File

@ -173,6 +173,10 @@ void PlayerController::restart() {
state->hospitalIslandOverride = 0; state->hospitalIslandOverride = 0;
state->policeIslandOverride = 0; state->policeIslandOverride = 0;
// Clear whole world
// Original game uses 4000.f radius
world->clearObjectsWithinArea(character->getPosition(), 10000.f, true);
// Set position and heading for any restart // Set position and heading for any restart
character->setPosition(restartPosition); character->setPosition(restartPosition);
character->setHeading(restartHeading); character->setHeading(restartHeading);

View File

@ -35,7 +35,6 @@
#include <rw_mingw.hpp> #include <rw_mingw.hpp>
#endif #endif
// Behaviour Tuning // Behaviour Tuning
constexpr float kMaxTrafficSpawnRadius = 100.f; constexpr float kMaxTrafficSpawnRadius = 100.f;
constexpr float kMaxTrafficCleanupRadius = kMaxTrafficSpawnRadius * 1.25f; constexpr float kMaxTrafficCleanupRadius = kMaxTrafficSpawnRadius * 1.25f;
@ -86,7 +85,7 @@ bool GameWorld::placeItems(const std::string& name) {
if (ipll.load(path)) { if (ipll.load(path)) {
// Find the object. // Find the object.
for (const auto &inst : ipll.m_instances) { for (const auto& inst : ipll.m_instances) {
if (!createInstance(inst->id, inst->pos, inst->rot)) { if (!createInstance(inst->id, inst->pos, inst->rot)) {
logger->error("World", "No object data for instance " + logger->error("World", "No object data for instance " +
std::to_string(inst->id) + " in " + std::to_string(inst->id) + " in " +
@ -245,7 +244,7 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
auto model = vti->getModel(); auto model = vti->getModel();
auto info = data->vehicleInfo.find(vti->handling_); auto info = data->vehicleInfo.find(vti->handling_);
if (model && info != data->vehicleInfo.end() && if (model && info != data->vehicleInfo.end() &&
info->second->wheels.empty() && info->second->seats.empty()) { info->second->wheels.empty() && info->second->seats.empty()) {
auto root = model->getFrame(); auto root = model->getFrame();
for (const auto& frame : root->getChildren()) { for (const auto& frame : root->getChildren()) {
const std::string& name = frame->getName(); const std::string& name = frame->getName();
@ -261,18 +260,21 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
auto backseat = frame->findDescendant("ped_backseat"); auto backseat = frame->findDescendant("ped_backseat");
if (frontseat) { if (frontseat) {
addSeats(info->second->seats.front, frontseat->getDefaultTranslation()); addSeats(info->second->seats.front,
frontseat->getDefaultTranslation());
} }
if (backseat) { if (backseat) {
// @todo how does this work for the barracks, ambulance // @todo how does this work for the barracks, ambulance
// or coach? // or coach?
addSeats(info->second->seats.back, backseat->getDefaultTranslation()); addSeats(info->second->seats.back,
backseat->getDefaultTranslation());
} }
} else if (name == "ped_frontseat") { } else if (name == "ped_frontseat") {
// The speeder boat does not have a chassis_dummy but has the // The speeder boat does not have a chassis_dummy but has the
// frontseat directly in the root frame. // frontseat directly in the root frame.
addSeats(info->second->seats.front, frame->getDefaultTranslation()); addSeats(info->second->seats.front,
frame->getDefaultTranslation());
} }
} }
} }
@ -560,7 +562,7 @@ float GameWorld::getGameTime() const {
} }
namespace { namespace {
void handleVehicleResponse(GameObject *object, btManifoldPoint &mp, bool isA) { void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA) {
bool isVehicle = object->type() == GameObject::Vehicle; bool isVehicle = object->type() == GameObject::Vehicle;
if (!isVehicle) return; if (!isVehicle) return;
if (mp.getAppliedImpulse() <= 100.f) return; if (mp.getAppliedImpulse() <= 100.f) return;
@ -581,7 +583,8 @@ void handleVehicleResponse(GameObject *object, btManifoldPoint &mp, bool isA) {
mp.getAppliedImpulse()}); mp.getAppliedImpulse()});
} }
void handleInstanceResponse(InstanceObject *instance, const btManifoldPoint &mp, bool isA) { void handleInstanceResponse(InstanceObject* instance, const btManifoldPoint& mp,
bool isA) {
if (!instance->dynamics) { if (!instance->dynamics) {
return; return;
} }
@ -600,7 +603,7 @@ void handleInstanceResponse(InstanceObject *instance, const btManifoldPoint &mp,
impulse}); impulse});
} }
} }
} } // namespace
bool GameWorld::ContactProcessedCallback(btManifoldPoint& mp, void* body0, bool GameWorld::ContactProcessedCallback(btManifoldPoint& mp, void* body0,
void* body1) { void* body1) {
@ -868,6 +871,69 @@ VehicleObject* GameWorld::tryToSpawnVehicle(VehicleGenerator& gen) {
} }
bool GameWorld::isRaining() const { bool GameWorld::isRaining() const {
return WeatherCondition (state->basic.nextWeather) == return WeatherCondition(state->basic.nextWeather) ==
WeatherCondition::Rainy; WeatherCondition::Rainy;
} }
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)->seatOccupants) {
auto character = static_cast<CharacterObject*>(seat.second);
if (character->getLifetime() == GameObject::PlayerLifetime ||
character->getLifetime() == GameObject::MissionLifetime) {
skipFlag = true;
}
}
if (skipFlag) {
continue;
}
if (glm::distance(center, obj.second->getPosition()) < radius) {
destroyObjectQueued(obj.second);
}
}
// 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) {
continue;
}
if (glm::distance(center, obj.second->getPosition()) < radius) {
destroyObjectQueued(obj.second);
}
}
/// @todo Do we also have to clear all projectiles + particles *in this
/// area*, even if the bool is false?
if (clearParticles) {
RW_UNUSED(clearParticles);
RW_UNIMPLEMENTED(
"should clear all particles and projectiles (not limited to "
"area!)");
}
// @todo Remove all temp objects, extinguish all fires, remove all
// explosions, remove all projectiles
}

View File

@ -9,9 +9,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <LinearMath/btScalar.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <LinearMath/btScalar.h>
#include <ai/AIGraph.hpp> #include <ai/AIGraph.hpp>
#include <ai/AIGraphNode.hpp> #include <ai/AIGraphNode.hpp>
@ -102,34 +102,39 @@ public:
* Creates an instance * Creates an instance
*/ */
InstanceObject* createInstance(const uint16_t id, const glm::vec3& pos, InstanceObject* createInstance(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f}); const glm::quat& rot = glm::quat{
1.0f, 0.0f, 0.0f, 0.0f});
/** /**
* @brief Creates an InstanceObject for use in the current Cutscene. * @brief Creates an InstanceObject for use in the current Cutscene.
*/ */
CutsceneObject* createCutsceneObject(const uint16_t id, CutsceneObject* createCutsceneObject(const uint16_t id,
const glm::vec3& pos, const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f}); const glm::quat& rot = glm::quat{
1.0f, 0.0f, 0.0f, 0.0f});
/** /**
* Creates a vehicle * Creates a vehicle
*/ */
VehicleObject* createVehicle(const uint16_t id, const glm::vec3& pos, VehicleObject* createVehicle(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f}, const glm::quat& rot = glm::quat{1.0f, 0.0f,
0.0f, 0.0f},
GameObjectID gid = 0); GameObjectID gid = 0);
/** /**
* Creates a pedestrian. * Creates a pedestrian.
*/ */
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos, CharacterObject* createPedestrian(
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f}, const uint16_t id, const glm::vec3& pos,
GameObjectID gid = 0); const glm::quat& rot = glm::quat{1.0f, 0.0f, 0.0f, 0.0f},
GameObjectID gid = 0);
/** /**
* Creates a player * Creates a player
*/ */
CharacterObject* createPlayer(const glm::vec3& pos, CharacterObject* createPlayer(const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f}, const glm::quat& rot = glm::quat{1.0f, 0.0f,
0.0f, 0.0f},
GameObjectID gid = 0); GameObjectID gid = 0);
/** /**
@ -344,6 +349,9 @@ public:
*/ */
VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen); VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen);
void clearObjectsWithinArea(const glm::vec3 center, const float radius,
const bool clearParticles);
private: private:
/** /**
* @brief Used by objects to delete themselves during updates. * @brief Used by objects to delete themselves during updates.
@ -360,7 +368,7 @@ private:
/** /**
* Private data * Private data
*/ */
std::unique_ptr<btOverlappingPairCallback> _overlappingPairCallback; std::unique_ptr<btOverlappingPairCallback> _overlappingPairCallback;
}; };
#endif #endif

View File

@ -10549,39 +10549,8 @@ void opcode_0394(const ScriptArguments& args, const ScriptInt arg1) {
@arg clearParticles Boolean true/false @arg clearParticles Boolean true/false
*/ */
void opcode_0395(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat radius, const ScriptBoolean clearParticles) { void opcode_0395(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat radius, const ScriptBoolean clearParticles) {
GameWorld* gw = args.getWorld(); coord = script::getGround(args, coord);
args.getWorld()->clearObjectsWithinArea(coord, radius, clearParticles);
for (auto& v : gw->vehiclePool.objects)
{
if (v.second->getLifetime() != GameObject::MissionLifetime) {
continue;
}
if (glm::distance(coord, v.second->getPosition()) < radius)
{
gw->destroyObjectQueued(v.second);
}
}
for (auto& p : gw->pedestrianPool.objects)
{
if (p.second->getLifetime() == GameObject::PlayerLifetime || p.second->getLifetime() != GameObject::MissionLifetime) {
continue;
}
if (glm::distance(coord, p.second->getPosition()) < radius)
{
gw->destroyObjectQueued(p.second);
}
}
/// @todo Do we also have to clear all projectiles + particles *in this area*, even if the bool is false?
if (clearParticles)
{
RW_UNUSED(clearParticles);
RW_UNIMPLEMENTED("should clear all particles and projectiles (not limited to area!)");
}
} }
/** /**