forked from Mirrorlandia_minetest/minetest
Prevent objects from colliding with own child attachments (#7610)
Also, use a better distance calculation for 'collide with objects'. Fixes the issue of a vehicle occasionally colliding with its own driver, causing one of the velocity components to be set to zero.
This commit is contained in:
parent
88efebdf86
commit
ee63b94f2c
@ -51,6 +51,7 @@ public:
|
|||||||
virtual scene::ISceneNode *getSceneNode() { return NULL; }
|
virtual scene::ISceneNode *getSceneNode() { return NULL; }
|
||||||
virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() { return NULL; }
|
virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() { return NULL; }
|
||||||
virtual bool isLocalPlayer() const {return false;}
|
virtual bool isLocalPlayer() const {return false;}
|
||||||
|
virtual ClientActiveObject *getParent() const { return nullptr; };
|
||||||
virtual void setAttachments() {}
|
virtual void setAttachments() {}
|
||||||
virtual bool doShowSelectionBox(){return true;}
|
virtual bool doShowSelectionBox(){return true;}
|
||||||
|
|
||||||
|
@ -360,11 +360,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
|
||||||
if (c_env != 0) {
|
if (c_env != 0) {
|
||||||
f32 distance = speed_f->getLength();
|
// Calculate distance by speed, add own extent and 1.5m of tolerance
|
||||||
|
f32 distance = speed_f->getLength() * dtime +
|
||||||
|
box_0.getExtent().getLength() + 1.5f * BS;
|
||||||
std::vector<DistanceSortedActiveObject> clientobjects;
|
std::vector<DistanceSortedActiveObject> clientobjects;
|
||||||
c_env->getActiveObjects(*pos_f, distance * 1.5f, clientobjects);
|
c_env->getActiveObjects(*pos_f, distance, clientobjects);
|
||||||
|
|
||||||
for (auto &clientobject : clientobjects) {
|
for (auto &clientobject : clientobjects) {
|
||||||
if (!self || (self != clientobject.obj)) {
|
// Do collide with everything but itself and the parent CAO
|
||||||
|
if (!self || (self != clientobject.obj &&
|
||||||
|
self != clientobject.obj->getParent())) {
|
||||||
objects.push_back((ActiveObject*) clientobject.obj);
|
objects.push_back((ActiveObject*) clientobject.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,12 +379,17 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
|
|||||||
{
|
{
|
||||||
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
|
||||||
if (s_env != NULL) {
|
if (s_env != NULL) {
|
||||||
f32 distance = speed_f->getLength();
|
// Calculate distance by speed, add own extent and 1.5m of tolerance
|
||||||
|
f32 distance = speed_f->getLength() * dtime +
|
||||||
|
box_0.getExtent().getLength() + 1.5f * BS;
|
||||||
std::vector<u16> s_objects;
|
std::vector<u16> s_objects;
|
||||||
s_env->getObjectsInsideRadius(s_objects, *pos_f, distance * 1.5f);
|
s_env->getObjectsInsideRadius(s_objects, *pos_f, distance);
|
||||||
|
|
||||||
for (u16 obj_id : s_objects) {
|
for (u16 obj_id : s_objects) {
|
||||||
ServerActiveObject *current = s_env->getActiveObject(obj_id);
|
ServerActiveObject *current = s_env->getActiveObject(obj_id);
|
||||||
if (!self || (self != current)) {
|
|
||||||
|
if (!self || (self != current &&
|
||||||
|
self != current->getParent())) {
|
||||||
objects.push_back((ActiveObject*)current);
|
objects.push_back((ActiveObject*)current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,8 +139,6 @@ public:
|
|||||||
|
|
||||||
void processInitData(const std::string &data);
|
void processInitData(const std::string &data);
|
||||||
|
|
||||||
ClientActiveObject *getParent() const;
|
|
||||||
|
|
||||||
bool getCollisionBox(aabb3f *toset) const;
|
bool getCollisionBox(aabb3f *toset) const;
|
||||||
|
|
||||||
bool collideWithObjects() const;
|
bool collideWithObjects() const;
|
||||||
@ -181,6 +179,8 @@ public:
|
|||||||
|
|
||||||
void setChildrenVisible(bool toset);
|
void setChildrenVisible(bool toset);
|
||||||
|
|
||||||
|
ClientActiveObject *getParent() const;
|
||||||
|
|
||||||
void setAttachments();
|
void setAttachments();
|
||||||
|
|
||||||
void removeFromScene(bool permanent);
|
void removeFromScene(bool permanent);
|
||||||
|
@ -118,15 +118,14 @@ UnitSAO::UnitSAO(ServerEnvironment *env, v3f pos):
|
|||||||
m_armor_groups["fleshy"] = 100;
|
m_armor_groups["fleshy"] = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnitSAO::isAttached() const
|
ServerActiveObject *UnitSAO::getParent() const
|
||||||
{
|
{
|
||||||
if (!m_attachment_parent_id)
|
if (!m_attachment_parent_id)
|
||||||
return false;
|
return nullptr;
|
||||||
// Check if the parent still exists
|
// Check if the parent still exists
|
||||||
ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
|
ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
|
||||||
if (obj)
|
|
||||||
return true;
|
return obj;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitSAO::setArmorGroups(const ItemGroupList &armor_groups)
|
void UnitSAO::setArmorGroups(const ItemGroupList &armor_groups)
|
||||||
|
@ -42,7 +42,9 @@ public:
|
|||||||
// Use a function, if isDead can be defined by other conditions
|
// Use a function, if isDead can be defined by other conditions
|
||||||
bool isDead() const { return m_hp == 0; }
|
bool isDead() const { return m_hp == 0; }
|
||||||
|
|
||||||
bool isAttached() const;
|
inline bool isAttached() const
|
||||||
|
{ return getParent(); }
|
||||||
|
|
||||||
void setArmorGroups(const ItemGroupList &armor_groups);
|
void setArmorGroups(const ItemGroupList &armor_groups);
|
||||||
const ItemGroupList &getArmorGroups();
|
const ItemGroupList &getArmorGroups();
|
||||||
void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop);
|
void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop);
|
||||||
@ -57,6 +59,7 @@ public:
|
|||||||
void addAttachmentChild(int child_id);
|
void addAttachmentChild(int child_id);
|
||||||
void removeAttachmentChild(int child_id);
|
void removeAttachmentChild(int child_id);
|
||||||
const std::unordered_set<int> &getAttachmentChildIds();
|
const std::unordered_set<int> &getAttachmentChildIds();
|
||||||
|
ServerActiveObject *getParent() const;
|
||||||
ObjectProperties* accessObjectProperties();
|
ObjectProperties* accessObjectProperties();
|
||||||
void notifyObjectPropertiesModified();
|
void notifyObjectPropertiesModified();
|
||||||
protected:
|
protected:
|
||||||
|
@ -173,6 +173,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual const std::unordered_set<int> &getAttachmentChildIds()
|
virtual const std::unordered_set<int> &getAttachmentChildIds()
|
||||||
{ static const std::unordered_set<int> rv; return rv; }
|
{ static const std::unordered_set<int> rv; return rv; }
|
||||||
|
virtual ServerActiveObject *getParent() const { return nullptr; }
|
||||||
virtual ObjectProperties* accessObjectProperties()
|
virtual ObjectProperties* accessObjectProperties()
|
||||||
{ return NULL; }
|
{ return NULL; }
|
||||||
virtual void notifyObjectPropertiesModified()
|
virtual void notifyObjectPropertiesModified()
|
||||||
|
Loading…
Reference in New Issue
Block a user