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