From 40226e52747156cbdc5128a416480b226e498fff Mon Sep 17 00:00:00 2001
From: est31 <MTest31@outlook.com>
Date: Sat, 20 Jun 2015 00:30:38 +0200
Subject: [PATCH] Make attached objects visible in 3rd person view

---
 src/content_cao.cpp | 42 ++++++++++++++++++++++++++++--------------
 src/content_cao.h   |  2 ++
 src/environment.cpp |  9 +++++++++
 src/environment.h   |  3 +++
 src/game.cpp        |  1 +
 5 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index 9ee81e63f..4f1336d28 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -727,6 +727,17 @@ scene::IBillboardSceneNode* GenericCAO::getSpriteSceneNode()
 	return m_spritenode;
 }
 
+void GenericCAO::setChildrenVisible(bool toset)
+{
+	for (std::vector<u16>::iterator ci = m_children.begin();
+			ci != m_children.end(); ci++) {
+		GenericCAO *obj = m_env->getGenericCAO(*ci);
+		if (obj) {
+			obj->setVisible(toset);
+		}
+	}
+}
+
 void GenericCAO::setAttachments()
 {
 	updateAttachments();
@@ -1489,16 +1500,7 @@ void GenericCAO::updateBonePosition()
 void GenericCAO::updateAttachments()
 {
 
-	// localplayer itself can't be attached to localplayer
-	if (!m_is_local_player)
-	{
-		m_attached_to_local = getParent() != NULL && getParent()->isLocalPlayer();
-		// Objects attached to the local player should always be hidden
-		m_is_visible = !m_attached_to_local;
-	}
-
-	if(getParent() == NULL || m_attached_to_local) // Detach or don't attach
-	{
+	if (getParent() == NULL) { // Detach or don't attach
 		scene::ISceneNode *node = getSceneNode();
 		if (node) {
 			v3f old_position = node->getAbsolutePosition();
@@ -1667,14 +1669,26 @@ void GenericCAO::processMessage(const std::string &data)
 		m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
 
 		updateBonePosition();
-	}
-	else if(cmd == GENERIC_CMD_SET_ATTACHMENT) {
-		m_env->m_attachements[getId()] = readS16(is);
-		m_children.push_back(m_env->m_attachements[getId()]);
+	} else if (cmd == GENERIC_CMD_SET_ATTACHMENT) {
+		u16 parentID = readS16(is);
+		m_env->m_attachements[getId()] = parentID;
+		GenericCAO *parentobj = m_env->getGenericCAO(parentID);
+
+		if (parentobj) {
+			parentobj->m_children.push_back(getId());
+		}
+
 		m_attachment_bone = deSerializeString(is);
 		m_attachment_position = readV3F1000(is);
 		m_attachment_rotation = readV3F1000(is);
 
+		// localplayer itself can't be attached to localplayer
+		if (!m_is_local_player) {
+			m_attached_to_local = getParent() != NULL && getParent()->isLocalPlayer();
+			// Objects attached to the local player should be hidden by default
+			m_is_visible = !m_attached_to_local;
+		}
+
 		updateAttachments();
 	}
 	else if(cmd == GENERIC_CMD_PUNCHED) {
diff --git a/src/content_cao.h b/src/content_cao.h
index 36245bd3b..813a41259 100644
--- a/src/content_cao.h
+++ b/src/content_cao.h
@@ -162,6 +162,8 @@ class GenericCAO : public ClientActiveObject
 		m_is_visible = toset;
 	}
 
+	void setChildrenVisible(bool toset);
+
 	void setAttachments();
 
 	void removeFromScene(bool permanent);
diff --git a/src/environment.cpp b/src/environment.cpp
index dc18fd58f..7d80619bc 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -2400,6 +2400,15 @@ void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
 	m_simple_objects.push_back(simple);
 }
 
+GenericCAO* ClientEnvironment::getGenericCAO(u16 id)
+{
+	ClientActiveObject *obj = getActiveObject(id);
+	if (obj && obj->getType() == ACTIVEOBJECT_TYPE_GENERIC)
+		return (GenericCAO*) obj;
+	else
+		return NULL;
+}
+
 ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
 {
 	std::map<u16, ClientActiveObject*>::iterator n;
diff --git a/src/environment.h b/src/environment.h
index a25a12db3..983f09409 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -405,6 +405,8 @@ class ServerEnvironment : public Environment
 #ifndef SERVER
 
 #include "clientobject.h"
+#include "content_cao.h"
+
 class ClientSimpleObject;
 
 /*
@@ -467,6 +469,7 @@ class ClientEnvironment : public Environment
 		ActiveObjects
 	*/
 
+	GenericCAO* getGenericCAO(u16 id);
 	ClientActiveObject* getActiveObject(u16 id);
 
 	/*
diff --git a/src/game.cpp b/src/game.cpp
index 903e4f85c..be4897d75 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -3298,6 +3298,7 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time,
 		camera->toggleCameraMode();
 
 		playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
+		playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
 	}
 
 	float full_punch_interval = playeritem_toolcap.full_punch_interval;
-- 
GitLab