X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcontent_cao.cpp;h=f414b2b9beae7a4dc52464e6395df81fdbeb926c;hb=d1df09841d0eac7a88f638676b80ec848522cca5;hp=671ddd4b1afc241667b734229b4c49b176f3b349;hpb=10e0cf8b2c27917a3fd45e73a5d835af4313db3b;p=dragonfireclient.git diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 671ddd4b1..f414b2b9b 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -27,14 +27,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" // For IntervalLimiter #include "util/serialize.h" #include "util/mathconstants.h" -#include "tile.h" +#include "client/tile.h" #include "environment.h" #include "collision.h" #include "settings.h" #include "serialization.h" // For decompressZlib #include "gamedef.h" #include "clientobject.h" -#include "content_object.h" #include "mesh.h" #include "itemdef.h" #include "tool.h" @@ -43,7 +42,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "localplayer.h" #include "map.h" -#include "main.h" // g_settings #include "camera.h" // CameraModes #include "wieldmesh.h" #include "log.h" @@ -144,12 +142,12 @@ class TestCAO : public ClientActiveObject public: TestCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~TestCAO(); - - u8 getType() const + + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; } - + static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, @@ -194,9 +192,9 @@ void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, { if(m_node != NULL) return; - + //video::IVideoDriver* driver = smgr->getVideoDriver(); - + scene::SMesh *mesh = new scene::SMesh(); scene::IMeshBuffer *buf = new scene::SMeshBuffer(); video::SColor c(255,255,255,255); @@ -212,7 +210,7 @@ void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, // Set material buf->getMaterial().setFlag(video::EMF_LIGHTING, false); buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, tsrc->getTexture("rat.png")); + buf->getMaterial().setTexture(0, tsrc->getTextureForMesh("rat.png")); buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; @@ -288,12 +286,12 @@ class ItemCAO : public ClientActiveObject public: ItemCAO(IGameDef *gamedef, ClientEnvironment *env); virtual ~ItemCAO(); - - u8 getType() const + + ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_ITEM; } - + static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, @@ -310,18 +308,18 @@ class ItemCAO : public ClientActiveObject void processMessage(const std::string &data); void initialize(const std::string &data); - - core::aabbox3d* getSelectionBox() + + aabb3f *getSelectionBox() {return &m_selection_box;} v3f getPosition() {return m_position;} - + std::string infoText() {return m_infotext;} bool getCollisionBox(aabb3f *toset) { return false; } private: - core::aabbox3d m_selection_box; + aabb3f m_selection_box; scene::IMeshSceneNode *m_node; v3f m_position; std::string m_itemstring; @@ -359,9 +357,9 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, { if(m_node != NULL) return; - + //video::IVideoDriver* driver = smgr->getVideoDriver(); - + scene::SMesh *mesh = new scene::SMesh(); scene::IMeshBuffer *buf = new scene::SMeshBuffer(); video::SColor c(255,255,255,255); @@ -467,11 +465,11 @@ void ItemCAO::updateTexture() } catch(SerializationError &e) { - infostream<<"WARNING: "<<__FUNCTION_NAME + warningstream<getMaterial(0).setTexture(0, texture); } @@ -516,7 +514,7 @@ void ItemCAO::processMessage(const std::string &data) void ItemCAO::initialize(const std::string &data) { infostream<<"ItemCAO: Got init data"< >()), m_attachment_bone(""), m_attachment_position(v3f(0,0,0)), @@ -582,8 +581,11 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env): m_last_light(255), m_is_visible(false) { - if(gamedef == NULL) + if (gamedef == NULL) { ClientActiveObject::registerType(getType(), create); + } else { + m_gamedef = gamedef; + } } bool GenericCAO::getCollisionBox(aabb3f *toset) @@ -669,14 +671,13 @@ void GenericCAO::initialize(const std::string &data) GenericCAO::~GenericCAO() { - if(m_is_player) - { + if (m_is_player) { m_env->removePlayerName(m_name.c_str()); } removeFromScene(true); } -core::aabbox3d* GenericCAO::getSelectionBox() +aabb3f *GenericCAO::getSelectionBox() { if(!m_prop.is_visible || !m_is_visible || m_is_local_player || getParent() != NULL) return NULL; @@ -697,14 +698,15 @@ v3f GenericCAO::getPosition() scene::ISceneNode* GenericCAO::getSceneNode() { - if (m_meshnode) + if (m_meshnode) { return m_meshnode; - if (m_animated_meshnode) + } else if (m_animated_meshnode) { return m_animated_meshnode; - if (m_wield_meshnode) + } else if (m_wield_meshnode) { return m_wield_meshnode; - if (m_spritenode) + } else if (m_spritenode) { return m_spritenode; + } return NULL; } @@ -728,6 +730,16 @@ scene::IBillboardSceneNode* GenericCAO::getSpriteSceneNode() return m_spritenode; } +void GenericCAO::setChildrenVisible(bool toset) +{ + for (std::vector::size_type i = 0; i < m_children.size(); i++) { + GenericCAO *obj = m_env->getGenericCAO(m_children[i]); + if (obj) { + obj->setVisible(toset); + } + } +} + void GenericCAO::setAttachments() { updateAttachments(); @@ -737,7 +749,7 @@ ClientActiveObject* GenericCAO::getParent() { ClientActiveObject *obj = NULL; - u16 attached_id = m_env->m_attachements[getId()]; + u16 attached_id = m_env->attachement_parent_ids[getId()]; if ((attached_id != 0) && (attached_id != getId())) { @@ -749,18 +761,17 @@ ClientActiveObject* GenericCAO::getParent() void GenericCAO::removeFromScene(bool permanent) { // Should be true when removing the object permanently and false when refreshing (eg: updating visuals) - if((m_env != NULL) && (permanent)) + if((m_env != NULL) && (permanent)) { - for(std::vector::iterator ci = m_children.begin(); - ci != m_children.end(); ci++) - { - if (m_env->m_attachements[*ci] == getId()) { - m_env->m_attachements[*ci] = 0; + for (std::vector::size_type i = 0; i < m_children.size(); i++) { + u16 ci = m_children[i]; + if (m_env->attachement_parent_ids[ci] == getId()) { + m_env->attachement_parent_ids[ci] = 0; } } - m_env->m_attachements[getId()] = 0; - + m_env->attachement_parent_ids[getId()] = 0; + LocalPlayer* player = m_env->getLocalPlayer(); if (this == player->parent) { player->parent = NULL; @@ -768,62 +779,53 @@ void GenericCAO::removeFromScene(bool permanent) } } - if(m_meshnode) - { + if (m_meshnode) { m_meshnode->remove(); m_meshnode->drop(); m_meshnode = NULL; - } - if(m_animated_meshnode) - { + } else if (m_animated_meshnode) { m_animated_meshnode->remove(); m_animated_meshnode->drop(); m_animated_meshnode = NULL; - } - if(m_wield_meshnode) - { + } else if (m_wield_meshnode) { m_wield_meshnode->remove(); m_wield_meshnode->drop(); m_wield_meshnode = NULL; - } - if(m_spritenode) - { + } else if (m_spritenode) { m_spritenode->remove(); m_spritenode->drop(); m_spritenode = NULL; } - if (m_textnode) - { - m_textnode->remove(); - m_textnode->drop(); - m_textnode = NULL; + + if (m_nametag) { + m_gamedef->getCamera()->removeNametag(m_nametag); + m_nametag = NULL; } } -void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) +void GenericCAO::addToScene(scene::ISceneManager *smgr, + ITextureSource *tsrc, IrrlichtDevice *irr) { m_smgr = smgr; m_irr = irr; - if (getSceneNode() != NULL) + if (getSceneNode() != NULL) { return; + } m_visuals_expired = false; - if(!m_prop.is_visible) + if (!m_prop.is_visible) { return; + } - //video::IVideoDriver* driver = smgr->getVideoDriver(); - - if(m_prop.visual == "sprite") - { + if (m_prop.visual == "sprite") { infostream<<"GenericCAO::addToScene(): single_sprite"<addBillboardSceneNode( NULL, v2f(1, 1), v3f(0,0,0), -1); m_spritenode->grab(); m_spritenode->setMaterialTexture(0, - tsrc->getTexture("unknown_node.png")); + tsrc->getTextureForMesh("unknown_node.png")); m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false); m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); @@ -837,54 +839,50 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, setBillboardTextureMatrix(m_spritenode, txs, tys, 0, 0); } - } - else if(m_prop.visual == "upright_sprite") { + } else if (m_prop.visual == "upright_sprite") { scene::SMesh *mesh = new scene::SMesh(); - double dx = BS*m_prop.visual_size.X/2; - double dy = BS*m_prop.visual_size.Y/2; - { // Front - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + double dx = BS * m_prop.visual_size.X / 2; + double dy = BS * m_prop.visual_size.Y / 2; u8 li = m_last_light; - video::SColor c(255,li,li,li); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-dx,-dy,0, 0,0,0, c, 0,1), - video::S3DVertex(dx,-dy,0, 0,0,0, c, 1,1), - video::S3DVertex(dx,dy,0, 0,0,0, c, 1,0), - video::S3DVertex(-dx,dy,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); + video::SColor c(255, li, li, li); + + { // Front + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::S3DVertex vertices[4] = { + video::S3DVertex(-dx, -dy, 0, 0,0,0, c, 1,1), + video::S3DVertex( dx, -dy, 0, 0,0,0, c, 0,1), + video::S3DVertex( dx, dy, 0, 0,0,0, c, 0,0), + video::S3DVertex(-dx, dy, 0, 0,0,0, c, 1,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); } { // Back - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - u8 li = m_last_light; - video::SColor c(255,li,li,li); - video::S3DVertex vertices[4] = - { - video::S3DVertex(dx,-dy,0, 0,0,0, c, 1,1), - video::S3DVertex(-dx,-dy,0, 0,0,0, c, 0,1), - video::S3DVertex(-dx,dy,0, 0,0,0, c, 0,0), - video::S3DVertex(dx,dy,0, 0,0,0, c, 1,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::S3DVertex vertices[4] = { + video::S3DVertex( dx,-dy, 0, 0,0,0, c, 1,1), + video::S3DVertex(-dx,-dy, 0, 0,0,0, c, 0,1), + video::S3DVertex(-dx, dy, 0, 0,0,0, c, 0,0), + video::S3DVertex( dx, dy, 0, 0,0,0, c, 1,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); } m_meshnode = smgr->addMeshSceneNode(mesh, NULL); m_meshnode->grab(); @@ -899,7 +897,7 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, m_meshnode = smgr->addMeshSceneNode(mesh, NULL); m_meshnode->grab(); mesh->drop(); - + m_meshnode->setScale(v3f(m_prop.visual_size.X, m_prop.visual_size.Y, m_prop.visual_size.X)); @@ -926,10 +924,15 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, u8 li = m_last_light; setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li)); + bool backface_culling = m_prop.backface_culling; + if (m_is_player) + backface_culling = false; + m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false); m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true); + m_animated_meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, backface_culling); } else errorstream<<"GenericCAO::addToScene(): Could not load mesh "<getRootSceneNode(), smgr, -1); m_wield_meshnode->setItem(item, m_gamedef); - m_wield_meshnode->grab(); - + m_wield_meshnode->setScale(v3f(m_prop.visual_size.X/2, m_prop.visual_size.Y/2, m_prop.visual_size.X/2)); @@ -960,14 +962,10 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, updateTextures(""); scene::ISceneNode *node = getSceneNode(); - if (node && m_is_player && !m_is_local_player) { - // Add a text node for showing the name - gui::IGUIEnvironment* gui = irr->getGUIEnvironment(); - std::wstring wname = narrow_to_wide(m_name); - m_textnode = smgr->addTextSceneNode(gui->getBuiltInFont(), - wname.c_str(), video::SColor(255,255,255,255), node); - m_textnode->grab(); - m_textnode->setPosition(v3f(0, BS*1.1, 0)); + if (node && m_prop.nametag != "" && !m_is_local_player) { + // Add nametag + m_nametag = m_gamedef->getCamera()->addNametag(node, + m_prop.nametag, m_prop.nametag_color); } updateNodePos(); @@ -975,22 +973,40 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, updateBonePosition(); updateAttachments(); } - + void GenericCAO::updateLight(u8 light_at_pos) +{ + // Don't update light of attached one + if (getParent() != NULL) { + return; + } + + updateLightNoCheck(light_at_pos); + + // Update light of all children + for (std::vector::size_type i = 0; i < m_children.size(); i++) { + ClientActiveObject *obj = m_env->getActiveObject(m_children[i]); + if (obj) { + obj->updateLightNoCheck(light_at_pos); + } + } +} + +void GenericCAO::updateLightNoCheck(u8 light_at_pos) { u8 li = decode_light(light_at_pos); - if(li != m_last_light) - { + if (li != m_last_light) { m_last_light = li; video::SColor color(255,li,li,li); - if(m_meshnode) + if (m_meshnode) { setMeshColor(m_meshnode->getMesh(), color); - if(m_animated_meshnode) + } else if (m_animated_meshnode) { setMeshColor(m_animated_meshnode->getMesh(), color); - if(m_wield_meshnode) + } else if (m_wield_meshnode) { m_wield_meshnode->setColor(color); - if(m_spritenode) + } else if (m_spritenode) { m_spritenode->setColor(color); + } } } @@ -1016,7 +1032,7 @@ void GenericCAO::updateNodePos() } } } - + void GenericCAO::step(float dtime, ClientEnvironment *env) { // Handel model of local player instantly to prevent lags @@ -1036,7 +1052,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) PlayerControl controls = player->getPlayerControl(); bool walking = false; - if(controls.up || controls.down || controls.left || controls.right) + if (controls.up || controls.down || controls.left || controls.right || + controls.forw_move_joystick_axis != 0.f || + controls.sidew_move_joystick_axis != 0.f) walking = true; f32 new_speed = player->local_animation_speed; @@ -1102,7 +1120,7 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) for(std::vector::iterator ci = m_children.begin(); ci != m_children.end();) { - if (m_env->m_attachements[*ci] != getId()) { + if (m_env->attachement_parent_ids[*ci] != getId()) { ci = m_children.erase(ci); continue; } @@ -1119,11 +1137,9 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) addToScene(m_smgr, m_gamedef->tsrc(), m_irr); // Attachments, part 2: Now that the parent has been refreshed, put its attachments back - for(std::vector::iterator ci = m_children.begin(); - ci != m_children.end(); ci++) - { + for (std::vector::size_type i = 0; i < m_children.size(); i++) { // Get the object of the child - ClientActiveObject *obj = m_env->getActiveObject(*ci); + ClientActiveObject *obj = m_env->getActiveObject(m_children[i]); if (obj) obj->setAttachments(); } @@ -1153,22 +1169,20 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) if(m_prop.physical) { - core::aabbox3d box = m_prop.collisionbox; + aabb3f box = m_prop.collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.125; // Distance per iteration v3f p_pos = m_position; v3f p_velocity = m_velocity; - v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(env,env->getGameDef(), pos_max_d, box, m_prop.stepheight, dtime, - p_pos, p_velocity, p_acceleration, + &p_pos, &p_velocity, m_acceleration, this, m_prop.collideWithObjects); // Apply results m_position = p_pos; m_velocity = p_velocity; - m_acceleration = p_acceleration; bool is_end_position = moveresult.collides; pos_translator.update(m_position, is_end_position, dtime); @@ -1228,8 +1242,18 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) if (getParent() == NULL && m_prop.automatic_face_movement_dir && (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) { - m_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + float optimal_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI + m_prop.automatic_face_movement_dir_offset; + float max_rotation_delta = + dtime * m_prop.automatic_face_movement_max_rotation_per_sec; + + if ((m_prop.automatic_face_movement_max_rotation_per_sec > 0) && + (fabs(m_yaw - optimal_yaw) > max_rotation_delta)) { + + m_yaw = optimal_yaw < m_yaw ? m_yaw - max_rotation_delta : m_yaw + max_rotation_delta; + } else { + m_yaw = optimal_yaw; + } updateNodePos(); } } @@ -1301,7 +1325,7 @@ void GenericCAO::updateTextures(const std::string &mod) texturestring = m_prop.textures[0]; texturestring += mod; m_spritenode->setMaterialTexture(0, - tsrc->getTexture(texturestring)); + tsrc->getTextureForMesh(texturestring)); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest @@ -1329,7 +1353,7 @@ void GenericCAO::updateTextures(const std::string &mod) if(texturestring == "") continue; // Empty texture string means don't modify that material texturestring += mod; - video::ITexture* texture = tsrc->getTexture(texturestring); + video::ITexture* texture = tsrc->getTextureForMesh(texturestring); if(!texture) { errorstream<<"GenericCAO::updateTextures(): Could not load texture "<getTexture(texturestring)); + tsrc->getTextureForMesh(texturestring)); material.getTextureMatrix(0).makeIdentity(); // This allows setting per-material colors. However, until a real lighting @@ -1406,7 +1430,7 @@ void GenericCAO::updateTextures(const std::string &mod) tname += mod; scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); buf->getMaterial().setTexture(0, - tsrc->getTexture(tname)); + tsrc->getTextureForMesh(tname)); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest @@ -1431,7 +1455,7 @@ void GenericCAO::updateTextures(const std::string &mod) tname += mod; scene::IMeshBuffer *buf = mesh->getMeshBuffer(1); buf->getMaterial().setTexture(0, - tsrc->getTexture(tname)); + tsrc->getTextureForMesh(tname)); // This allows setting per-material colors. However, until a real lighting // system is added, the code below will have no effect. Once MineTest @@ -1461,9 +1485,18 @@ void GenericCAO::updateAnimation() { if(m_animated_meshnode == NULL) return; - m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y); - m_animated_meshnode->setAnimationSpeed(m_animation_speed); + + if (m_animated_meshnode->getStartFrame() != m_animation_range.X || + m_animated_meshnode->getEndFrame() != m_animation_range.Y) + m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y); + if (m_animated_meshnode->getAnimationSpeed() != m_animation_speed) + m_animated_meshnode->setAnimationSpeed(m_animation_speed); m_animated_meshnode->setTransitionTime(m_animation_blend); +// Requires Irrlicht 1.8 or greater +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR > 1 + if (m_animated_meshnode->getLoopMode() != m_animation_loop) + m_animated_meshnode->setLoopMode(m_animation_loop); +#endif } void GenericCAO::updateBonePosition() @@ -1487,20 +1520,11 @@ 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(); @@ -1561,6 +1585,9 @@ void GenericCAO::processMessage(const std::string &data) m_tx_basepos = m_prop.initial_sprite_basepos; } + if ((m_is_player && !m_is_local_player) && m_prop.nametag == "") + m_prop.nametag = m_name; + expireVisuals(); } else if(cmd == GENERIC_CMD_UPDATE_POSITION) @@ -1638,6 +1665,8 @@ void GenericCAO::processMessage(const std::string &data) m_animation_range = v2s32((s32)range.X, (s32)range.Y); m_animation_speed = readF1000(is); m_animation_blend = readF1000(is); + // these are sent inverted so we get true when the server sends nothing + m_animation_loop = !readU8(is); updateAnimation(); } else { LocalPlayer *player = m_env->getLocalPlayer(); @@ -1646,6 +1675,8 @@ void GenericCAO::processMessage(const std::string &data) m_animation_range = v2s32((s32)range.X, (s32)range.Y); m_animation_speed = readF1000(is); m_animation_blend = readF1000(is); + // these are sent inverted so we get true when the server sends nothing + m_animation_loop = !readU8(is); } // update animation only if local animations present // and received animation is unknown (except idle animation) @@ -1669,14 +1700,31 @@ void GenericCAO::processMessage(const std::string &data) m_bone_position[bone] = core::vector2d(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_ATTACH_TO) { + u16 parentID = readS16(is); + u16 oldparent = m_env->attachement_parent_ids[getId()]; + if (oldparent) { + m_children.erase(std::remove(m_children.begin(), m_children.end(), + getId()), m_children.end()); + } + m_env->attachement_parent_ids[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) { @@ -1717,13 +1765,22 @@ void GenericCAO::processMessage(const std::string &data) int rating = readS16(is); m_armor_groups[name] = rating; } + } else if (cmd == GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) { + // Deprecated, for backwards compatibility only. + readU8(is); // version + m_prop.nametag_color = readARGB8(is); + if (m_nametag != NULL) { + m_nametag->nametag_color = m_prop.nametag_color; + } } } - + +/* \pre punchitem != NULL + */ bool GenericCAO::directReportPunch(v3f dir, const ItemStack *punchitem, float time_from_last_punch) { - assert(punchitem); + assert(punchitem); // pre-condition const ToolCapabilities *toolcap = &punchitem->getToolCapabilities(m_gamedef->idef()); PunchDamageResult result = getPunchDamage( @@ -1763,7 +1820,7 @@ std::string GenericCAO::debugInfoText() os<<"GenericCAO hp="<first<<"="<second<<", "; }