aboutsummaryrefslogtreecommitdiff
path: root/src/client/content_cao.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/content_cao.cpp')
-rw-r--r--src/client/content_cao.cpp56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index c1715a289..fae06554a 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -456,7 +456,8 @@ void GenericCAO::setChildrenVisible(bool toset)
for (u16 cao_id : m_attachment_child_ids) {
GenericCAO *obj = m_env->getGenericCAO(cao_id);
if (obj) {
- obj->setVisible(toset);
+ // Check if the entity is forced to appear in first person.
+ obj->setVisible(obj->isForcedVisible() ? true : toset);
}
}
}
@@ -477,8 +478,6 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit
if (parent)
parent->addAttachmentChild(m_id);
}
-
-
updateAttachments();
}
@@ -498,7 +497,7 @@ void GenericCAO::clearChildAttachments()
int child_id = *m_attachment_child_ids.begin();
if (ClientActiveObject *child = m_env->getActiveObject(child_id))
- child->setAttachment(0, "", v3f(), v3f());
+ child->setAttachment(0, "", v3f(), v3f(), false);
removeAttachmentChild(child_id);
}
@@ -800,6 +799,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
updateBonePosition();
updateAttachments();
setNodeLight(m_last_light);
+ updateMeshCulling();
}
void GenericCAO::updateLight(u32 day_night_ratio)
@@ -1411,6 +1411,9 @@ void GenericCAO::updateTextures(std::string mod)
setMeshColor(mesh, m_prop.colors[0]);
}
}
+ // Prevent showing the player after changing texture
+ if (m_is_local_player)
+ updateMeshCulling();
}
void GenericCAO::updateAnimation()
@@ -1739,12 +1742,25 @@ void GenericCAO::processMessage(const std::string &data)
std::string bone = deSerializeString16(is);
v3f position = readV3F32(is);
v3f rotation = readV3F32(is);
+ m_force_visible = readU8(is); // Returns false for EOF
setAttachment(parent_id, bone, position, rotation);
+ // Forcibly show attachments if required by set_attach
+ if (m_force_visible)
+ m_is_visible = true;
// localplayer itself can't be attached to localplayer
- if (!m_is_local_player)
- m_is_visible = !m_attached_to_local;
+ else if (!m_is_local_player) {
+ // Objects attached to the local player should be hidden in first
+ // person provided the forced boolean isn't set.
+ m_is_visible = !m_attached_to_local ||
+ m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST;
+ m_force_visible = false;
+ } else {
+ // Local players need to have this set,
+ // otherwise first person attachments fail.
+ m_is_visible = true;
+ }
} else if (cmd == AO_CMD_PUNCHED) {
u16 result_hp = readU16(is);
@@ -1858,5 +1874,33 @@ std::string GenericCAO::debugInfoText()
return os.str();
}
+void GenericCAO::updateMeshCulling()
+{
+ if (!m_is_local_player)
+ return;
+
+ // Grab the active player scene node so we know there's
+ // at least a mesh to occlude from the camera.
+ irr::scene::ISceneNode *node = getSceneNode();
+ if (!node)
+ return;
+
+ if (m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST) {
+ // Hide the mesh by culling both front and
+ // back faces. Serious hackyness but it works for our
+ // purposes. This also preserves the skeletal armature.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ true);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ true);
+ } else {
+ // Restore mesh visibility.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ m_prop.backface_culling);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ false);
+ }
+}
+
// Prototype
GenericCAO proto_GenericCAO(NULL, NULL);