diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 84080502f..80e66020d 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4152,7 +4152,8 @@ The Biome API is still in an experimental phase and subject to change. -- ^ collision_removal: if true then particle is removed when it collides, -- ^ requires collisiondetection = true to have any effect attached = ObjectRef, - -- ^ attached: if defined, makes particle positions relative to this object. + -- ^ attached: if defined, particle positions, velocities and accelerations + -- ^ are relative to this object's position and yaw. vertical = false, -- ^ vertical: if true faces player using y axis only texture = "image.png", diff --git a/src/clientobject.h b/src/clientobject.h index c4e1a634b..83931e438 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -61,6 +61,7 @@ public: virtual bool getCollisionBox(aabb3f *toset){return false;} virtual bool collideWithObjects(){return false;} virtual v3f getPosition(){return v3f(0,0,0);} + virtual float getYaw() const {return 0;} virtual scene::ISceneNode *getSceneNode(){return NULL;} virtual scene::IMeshSceneNode *getMeshSceneNode(){return NULL;} virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode(){return NULL;} diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 88ed43a8c..6b35d5881 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -313,7 +313,8 @@ public: {return &m_selection_box;} v3f getPosition() {return m_position;} - + inline float getYaw() const + {return 0;} std::string infoText() {return m_infotext;} diff --git a/src/content_cao.h b/src/content_cao.h index 5b3471814..a158e8296 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -136,6 +136,10 @@ public: aabb3f *getSelectionBox(); v3f getPosition(); + inline float getYaw() const + { + return m_yaw; + } scene::ISceneNode *getSceneNode(); diff --git a/src/particles.cpp b/src/particles.cpp index f20fb4083..acf9cc815 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -253,12 +253,17 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) m_time += dtime; bool unloaded = false; - v3f attached_offset = v3f(0,0,0); + bool is_attached = false; + v3f attached_pos = v3f(0,0,0); + float attached_yaw = 0; if (m_attached_id != 0) { - if (ClientActiveObject *attached = env->getActiveObject(m_attached_id)) - attached_offset = attached->getPosition() / BS; - else + if (ClientActiveObject *attached = env->getActiveObject(m_attached_id)) { + attached_pos = attached->getPosition() / BS; + attached_yaw = attached->getYaw(); + is_attached = true; + } else { unloaded = true; + } } if (m_spawntime != 0) // Spawner exists for a predefined timespan @@ -277,8 +282,15 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) v3f pos = random_v3f(m_minpos, m_maxpos); v3f vel = random_v3f(m_minvel, m_maxvel); v3f acc = random_v3f(m_minacc, m_maxacc); - // Make relative to offest - pos += attached_offset; + + if (is_attached) { + // Apply attachment yaw and position + pos.rotateXZBy(attached_yaw); + pos += attached_pos; + vel.rotateXZBy(attached_yaw); + acc.rotateXZBy(attached_yaw); + } + float exptime = rand()/(float)RAND_MAX *(m_maxexptime-m_minexptime) +m_minexptime; @@ -321,10 +333,18 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) { if (rand()/(float)RAND_MAX < dtime) { - v3f pos = random_v3f(m_minpos, m_maxpos) - + attached_offset; + v3f pos = random_v3f(m_minpos, m_maxpos); v3f vel = random_v3f(m_minvel, m_maxvel); v3f acc = random_v3f(m_minacc, m_maxacc); + + if (is_attached) { + // Apply attachment yaw and position + pos.rotateXZBy(attached_yaw); + pos += attached_pos; + vel.rotateXZBy(attached_yaw); + acc.rotateXZBy(attached_yaw); + } + float exptime = rand()/(float)RAND_MAX *(m_maxexptime-m_minexptime) +m_minexptime;