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:
commit
989ed36b78
@ -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);
|
||||||
|
@ -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
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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!)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user