Prevent objects from colliding with own child attachments (#7610)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Sun, 5 Aug 2018 20:28:41 +0000 (22:28 +0200)
committerParamat <paramat@users.noreply.github.com>
Sun, 5 Aug 2018 20:28:41 +0000 (21:28 +0100)
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.

src/clientobject.h
src/collision.cpp
src/content_cao.h
src/content_sao.cpp
src/content_sao.h
src/serverobject.h

index c85e1ec916ebffcc2996855f85e9adb7e3f60493..9377d1e678927b48ded0440a0490f89047df457a 100644 (file)
@@ -51,6 +51,7 @@ public:
        virtual scene::ISceneNode *getSceneNode() { return NULL; }
        virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() { return NULL; }
        virtual bool isLocalPlayer() const {return false;}
+       virtual ClientActiveObject *getParent() const { return nullptr; };
        virtual void setAttachments() {}
        virtual bool doShowSelectionBox(){return true;}
 
index 99874dbfd8c1337d71e9fb440687573ad446d00c..48a681dca543f0e699dd2a1d6e59dc24f31e165e 100644 (file)
@@ -360,11 +360,16 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
 #ifndef SERVER
                ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
                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;
-                       c_env->getActiveObjects(*pos_f, distance * 1.5f, clientobjects);
+                       c_env->getActiveObjects(*pos_f, distance, 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);
                                }
                        }
@@ -374,12 +379,17 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
                {
                        ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
                        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;
-                               s_env->getObjectsInsideRadius(s_objects, *pos_f, distance * 1.5f);
+                               s_env->getObjectsInsideRadius(s_objects, *pos_f, distance);
+
                                for (u16 obj_id : s_objects) {
                                        ServerActiveObject *current = s_env->getActiveObject(obj_id);
-                                       if (!self || (self != current)) {
+
+                                       if (!self || (self != current &&
+                                                       self != current->getParent())) {
                                                objects.push_back((ActiveObject*)current);
                                        }
                                }
index cd58681bb1c4b7cc44e5d975d100912219eb174f..9e688d78d99c337145e16281b4ae370cfcc58c5b 100644 (file)
@@ -139,8 +139,6 @@ public:
 
        void processInitData(const std::string &data);
 
-       ClientActiveObject *getParent() const;
-
        bool getCollisionBox(aabb3f *toset) const;
 
        bool collideWithObjects() const;
@@ -181,6 +179,8 @@ public:
 
        void setChildrenVisible(bool toset);
 
+       ClientActiveObject *getParent() const;
+
        void setAttachments();
 
        void removeFromScene(bool permanent);
index 4ef52c7f29c2ac46826fce9245135141c5692d67..f322941910f344725238bef6149b0ac7eca8cdca 100644 (file)
@@ -118,15 +118,14 @@ UnitSAO::UnitSAO(ServerEnvironment *env, v3f pos):
        m_armor_groups["fleshy"] = 100;
 }
 
-bool UnitSAO::isAttached() const
+ServerActiveObject *UnitSAO::getParent() const
 {
        if (!m_attachment_parent_id)
-               return false;
+               return nullptr;
        // Check if the parent still exists
        ServerActiveObject *obj = m_env->getActiveObject(m_attachment_parent_id);
-       if (obj)
-               return true;
-       return false;
+
+       return obj;
 }
 
 void UnitSAO::setArmorGroups(const ItemGroupList &armor_groups)
index 8510015c562846b96a0a55ce69437448d62a2988..e45a4028ed73d9d068071e6680520ea0a6897627 100644 (file)
@@ -42,7 +42,9 @@ public:
        // Use a function, if isDead can be defined by other conditions
        bool isDead() const { return m_hp == 0; }
 
-       bool isAttached() const;
+       inline bool isAttached() const
+       { return getParent(); }
+
        void setArmorGroups(const ItemGroupList &armor_groups);
        const ItemGroupList &getArmorGroups();
        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 removeAttachmentChild(int child_id);
        const std::unordered_set<int> &getAttachmentChildIds();
+       ServerActiveObject *getParent() const;
        ObjectProperties* accessObjectProperties();
        void notifyObjectPropertiesModified();
 protected:
index ba205f6a5762849ba5110a08e4309b9a2f673a29..04d52425de451ce830b65bb632add7c8b3d878c9 100644 (file)
@@ -173,6 +173,7 @@ public:
        {}
        virtual const std::unordered_set<int> &getAttachmentChildIds()
        { static const std::unordered_set<int> rv; return rv; }
+       virtual ServerActiveObject *getParent() const { return nullptr; }
        virtual ObjectProperties* accessObjectProperties()
        { return NULL; }
        virtual void notifyObjectPropertiesModified()