1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 10:22:52 +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->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
character->setPosition(restartPosition);
character->setHeading(restartHeading);

View File

@ -35,7 +35,6 @@
#include <rw_mingw.hpp>
#endif
// Behaviour Tuning
constexpr float kMaxTrafficSpawnRadius = 100.f;
constexpr float kMaxTrafficCleanupRadius = kMaxTrafficSpawnRadius * 1.25f;
@ -86,7 +85,7 @@ bool GameWorld::placeItems(const std::string& name) {
if (ipll.load(path)) {
// 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)) {
logger->error("World", "No object data for instance " +
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 info = data->vehicleInfo.find(vti->handling_);
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();
for (const auto& frame : root->getChildren()) {
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");
if (frontseat) {
addSeats(info->second->seats.front, frontseat->getDefaultTranslation());
addSeats(info->second->seats.front,
frontseat->getDefaultTranslation());
}
if (backseat) {
// @todo how does this work for the barracks, ambulance
// or coach?
addSeats(info->second->seats.back, backseat->getDefaultTranslation());
addSeats(info->second->seats.back,
backseat->getDefaultTranslation());
}
} else if (name == "ped_frontseat") {
// The speeder boat does not have a chassis_dummy but has the
// 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 {
void handleVehicleResponse(GameObject *object, btManifoldPoint &mp, bool isA) {
void handleVehicleResponse(GameObject* object, btManifoldPoint& mp, bool isA) {
bool isVehicle = object->type() == GameObject::Vehicle;
if (!isVehicle) return;
if (mp.getAppliedImpulse() <= 100.f) return;
@ -581,7 +583,8 @@ void handleVehicleResponse(GameObject *object, btManifoldPoint &mp, bool isA) {
mp.getAppliedImpulse()});
}
void handleInstanceResponse(InstanceObject *instance, const btManifoldPoint &mp, bool isA) {
void handleInstanceResponse(InstanceObject* instance, const btManifoldPoint& mp,
bool isA) {
if (!instance->dynamics) {
return;
}
@ -600,7 +603,7 @@ void handleInstanceResponse(InstanceObject *instance, const btManifoldPoint &mp,
impulse});
}
}
}
} // namespace
bool GameWorld::ContactProcessedCallback(btManifoldPoint& mp, void* body0,
void* body1) {
@ -868,6 +871,69 @@ VehicleObject* GameWorld::tryToSpawnVehicle(VehicleGenerator& gen) {
}
bool GameWorld::isRaining() const {
return WeatherCondition (state->basic.nextWeather) ==
WeatherCondition::Rainy;
return WeatherCondition(state->basic.nextWeather) ==
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 <vector>
#include <LinearMath/btScalar.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <LinearMath/btScalar.h>
#include <ai/AIGraph.hpp>
#include <ai/AIGraphNode.hpp>
@ -102,34 +102,39 @@ public:
* Creates an instance
*/
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.
*/
CutsceneObject* createCutsceneObject(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});
/**
* Creates a vehicle
*/
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);
/**
* Creates a pedestrian.
*/
CharacterObject* createPedestrian(const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f,0.0f,0.0f,0.0f},
GameObjectID gid = 0);
CharacterObject* createPedestrian(
const uint16_t id, const glm::vec3& pos,
const glm::quat& rot = glm::quat{1.0f, 0.0f, 0.0f, 0.0f},
GameObjectID gid = 0);
/**
* Creates a player
*/
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);
/**
@ -344,6 +349,9 @@ public:
*/
VehicleObject* tryToSpawnVehicle(VehicleGenerator& gen);
void clearObjectsWithinArea(const glm::vec3 center, const float radius,
const bool clearParticles);
private:
/**
* @brief Used by objects to delete themselves during updates.
@ -360,7 +368,7 @@ private:
/**
* Private data
*/
std::unique_ptr<btOverlappingPairCallback> _overlappingPairCallback;
std::unique_ptr<btOverlappingPairCallback> _overlappingPairCallback;
};
#endif

View File

@ -10549,39 +10549,8 @@ void opcode_0394(const ScriptArguments& args, const ScriptInt arg1) {
@arg clearParticles Boolean true/false
*/
void opcode_0395(const ScriptArguments& args, ScriptVec3 coord, const ScriptFloat radius, const ScriptBoolean clearParticles) {
GameWorld* gw = args.getWorld();
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!)");
}
coord = script::getGround(args, coord);
args.getWorld()->clearObjectsWithinArea(coord, radius, clearParticles);
}
/**