From f9a7f96525c7485de4cf27f973f0b52f5d74f048 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Sun, 10 Jul 2016 22:03:10 +0300
Subject: Add support for initial particle effect for effect from
 status-effects.xml

---
 src/CMakeLists.txt              |  1 +
 src/Makefile.am                 |  1 +
 src/being/actorsprite.cpp       | 47 +++++++++++++++++++++++++++++------------
 src/being/actorsprite.h         | 10 ++++++---
 src/being/localplayer.cpp       |  7 ++++--
 src/being/localplayer.h         |  3 ++-
 src/enums/simpletypes/isstart.h | 33 +++++++++++++++++++++++++++++
 src/net/eathena/beingrecv.cpp   |  5 ++++-
 src/net/tmwa/beingrecv.cpp      |  6 +++++-
 9 files changed, 92 insertions(+), 21 deletions(-)
 create mode 100644 src/enums/simpletypes/isstart.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index af4c47d41..8b1ce79a0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1235,6 +1235,7 @@ SET(SRCS
     enums/simpletypes/ignorerecord.h
     enums/simpletypes/intdefines.h
     enums/simpletypes/issell.h
+    enums/simpletypes/isstart.h
     enums/simpletypes/itemcolor.h
     enums/simpletypes/keep.h
     enums/simpletypes/mainconfig.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 13ec19f27..fd9db6e8e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -686,6 +686,7 @@ SRC += events/actionevent.h \
 	      enums/simpletypes/ignorerecord.h \
 	      enums/simpletypes/intdefines.h \
 	      enums/simpletypes/issell.h \
+	      enums/simpletypes/isstart.h \
 	      enums/simpletypes/itemcolor.h \
 	      enums/simpletypes/keep.h \
 	      enums/simpletypes/mainconfig.h \
diff --git a/src/being/actorsprite.cpp b/src/being/actorsprite.cpp
index 6d072adc7..7007d52aa 100644
--- a/src/being/actorsprite.cpp
+++ b/src/being/actorsprite.cpp
@@ -119,7 +119,11 @@ void ActorSprite::logic()
             const StatusEffect *const effect
                 = StatusEffectDB::getStatusEffect(*it, Enable_true);
             if (effect && effect->mIsPersistent)
-                updateStatusEffect(*it, Enable_true);
+            {
+                updateStatusEffect(*it,
+                    Enable_true,
+                    IsStart_false);
+            }
         }
     }
 
@@ -174,14 +178,15 @@ struct EffectDescription final
 };
 
 void ActorSprite::setStatusEffect(const int32_t index,
-                                  const Enable active)
+                                  const Enable active,
+                                  const IsStart start)
 {
     const Enable wasActive = fromBool(
         mStatusEffects.find(index) != mStatusEffects.end(), Enable);
 
     if (active != wasActive)
     {
-        updateStatusEffect(index, active);
+        updateStatusEffect(index, active, start);
         if (active == Enable_true)
             mStatusEffects.insert(index);
         else
@@ -200,7 +205,9 @@ void ActorSprite::setStatusEffectBlock(const int offset,
 
         if (index != -1)
         {
-            setStatusEffect(index, fromBool(val, Enable));
+            setStatusEffect(index,
+                fromBool(val, Enable),
+                IsStart_false);
         }
         else if (val && config.getBoolValue("unimplimentedLog"))
         {
@@ -226,7 +233,9 @@ static void applyEffectByOption(ActorSprite *const actor,
         const Enable enable = (opt & option) != 0 ? Enable_true : Enable_false;
         option |= opt;
         option ^= opt;
-        actor->setStatusEffect(id, enable);
+        actor->setStatusEffect(id,
+            enable,
+            IsStart_false);
     }
     if (option && config.getBoolValue("unimplimentedLog"))
     {
@@ -251,12 +260,16 @@ static void applyEffectByOption1(ActorSprite *const actor,
         const int32_t id = (*it).second;
         if (opt == option)
         {
-            actor->setStatusEffect(id, Enable_true);
+            actor->setStatusEffect(id,
+                Enable_true,
+                IsStart_false);
             option = 0U;
         }
         else
         {
-            actor->setStatusEffect(id, Enable_false);
+            actor->setStatusEffect(id,
+                Enable_false,
+                IsStart_false);
         }
     }
     if (option && config.getBoolValue("unimplimentedLog"))
@@ -340,7 +353,8 @@ void ActorSprite::setStatusEffectOpiton0(const uint32_t option)
 }
 
 void ActorSprite::updateStatusEffect(const int32_t index,
-                                     const Enable newStatus)
+                                     const Enable newStatus,
+                                     const IsStart start)
 {
     StatusEffect *const effect = StatusEffectDB::getStatusEffect(
         index, newStatus);
@@ -358,19 +372,26 @@ void ActorSprite::updateStatusEffect(const int32_t index,
     else if (effect->mIsPostDelay)
         stopCast(newStatus == Enable_true);
 #endif
-    handleStatusEffect(effect, index);
+    handleStatusEffect(effect, index, start);
 }
 
 void ActorSprite::handleStatusEffect(const StatusEffect *const effect,
-                                     const int32_t effectId)
+                                     const int32_t effectId,
+                                     const IsStart start)
 {
     if (!effect)
         return;
 
-    Particle *const particle = effect->getParticle();
-
     if (effectId >= 0)
-        mStatusParticleEffects.setLocally(effectId, particle);
+    {
+        if (start == IsStart_true)
+        {
+            Particle *const particle = effect->getParticle();
+            mStatusParticleEffects.setLocally(effectId, particle);
+        }
+        // +++ here also need enable permanent status effects,
+        // need new field in StatusEffect
+    }
 }
 
 void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
diff --git a/src/being/actorsprite.h b/src/being/actorsprite.h
index 2ee96f73c..1a32ceaf9 100644
--- a/src/being/actorsprite.h
+++ b/src/being/actorsprite.h
@@ -34,6 +34,7 @@
 #include "enums/simpletypes/beingid.h"
 #include "enums/simpletypes/enable.h"
 #include "enums/simpletypes/forcedisplay.h"
+#include "enums/simpletypes/isstart.h"
 
 #include "enums/resources/map/blocktype.h"
 
@@ -108,7 +109,8 @@ class ActorSprite notfinal : public CompoundSprite, public Actor
         { mUsedTargetCursor = nullptr; }
 
         void setStatusEffect(const int32_t index,
-                             const Enable active);
+                             const Enable active,
+                             const IsStart start);
 
         void setStatusEffectOpitons(const uint32_t option,
                                     const uint32_t opt1,
@@ -197,7 +199,8 @@ class ActorSprite notfinal : public CompoundSprite, public Actor
          * The new flag is passed.
          */
         virtual void updateStatusEffect(const int32_t index,
-                                        const Enable newStatus);
+                                        const Enable newStatus,
+                                        const IsStart start);
 
         /**
          * Handle an update to a status or stun effect
@@ -206,7 +209,8 @@ class ActorSprite notfinal : public CompoundSprite, public Actor
          * \param effectId -1 for stun, otherwise the effect index
          */
         virtual void handleStatusEffect(const StatusEffect *const effect,
-                                        const int32_t effectId);
+                                        const int32_t effectId,
+                                        const IsStart start);
 
         void setupSpriteDisplay(const SpriteDisplay &display,
                                 const ForceDisplay forceDisplay
diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp
index dd2b52838..97845ae31 100644
--- a/src/being/localplayer.cpp
+++ b/src/being/localplayer.cpp
@@ -998,9 +998,12 @@ void LocalPlayer::setGotoTarget(Being *const target)
 }
 
 void LocalPlayer::handleStatusEffect(const StatusEffect *const effect,
-                                     const int32_t effectId)
+                                     const int32_t effectId,
+                                     const IsStart start)
 {
-    Being::handleStatusEffect(effect, effectId);
+    Being::handleStatusEffect(effect,
+        effectId,
+        start);
 
     if (effect)
     {
diff --git a/src/being/localplayer.h b/src/being/localplayer.h
index 14d731b74..08974a621 100644
--- a/src/being/localplayer.h
+++ b/src/being/localplayer.h
@@ -427,7 +427,8 @@ class LocalPlayer final : public Being,
         void updateCoords() override final;
 
         void handleStatusEffect(const StatusEffect *const effect,
-                                const int32_t effectId) override final;
+                                const int32_t effectId,
+                                const IsStart start) override final;
 
         void startWalking(const unsigned char dir);
 
diff --git a/src/enums/simpletypes/isstart.h b/src/enums/simpletypes/isstart.h
new file mode 100644
index 000000000..6652400b8
--- /dev/null
+++ b/src/enums/simpletypes/isstart.h
@@ -0,0 +1,33 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2015-2016  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ENUMS_SIMPLETYPES_ISSTART_H
+#define ENUMS_SIMPLETYPES_ISSTART_H
+
+#include "enums/simpletypes/booldefines.h"
+
+PRAGMA6(GCC diagnostic push)
+PRAGMA6(GCC diagnostic ignored "-Wunused-const-variable")
+
+defBoolEnum(IsStart);
+
+PRAGMA6(GCC diagnostic pop)
+
+#endif  // ENUMS_SIMPLETYPES_ISSTART_H
diff --git a/src/net/eathena/beingrecv.cpp b/src/net/eathena/beingrecv.cpp
index a40639457..aac0dd914 100644
--- a/src/net/eathena/beingrecv.cpp
+++ b/src/net/eathena/beingrecv.cpp
@@ -971,9 +971,12 @@ void BeingRecv::processBeingStatusChange(Net::MessageIn &msg)
         msg.readInt32("val3");
     }
 
+    IsStart start = msg.getVersion() == 20090121 ?
+        IsStart_false : IsStart_true;
+
     Being *const dstBeing = actorManager->findBeing(id);
     if (dstBeing)
-        dstBeing->setStatusEffect(status, flag);
+        dstBeing->setStatusEffect(status, flag, start);
     BLOCK_END("BeingRecv::processBeingStatusChange")
 }
 
diff --git a/src/net/tmwa/beingrecv.cpp b/src/net/tmwa/beingrecv.cpp
index a489d4179..843e10f1d 100644
--- a/src/net/tmwa/beingrecv.cpp
+++ b/src/net/tmwa/beingrecv.cpp
@@ -1137,7 +1137,11 @@ void BeingRecv::processBeingStatusChange(Net::MessageIn &msg)
 
     Being *const dstBeing = actorManager->findBeing(id);
     if (dstBeing)
-        dstBeing->setStatusEffect(status, flag);
+    {
+        // dont know on legacy servers is effect really started
+        // or not. Because this always sending IsStart_true
+        dstBeing->setStatusEffect(status, flag, IsStart_true);
+    }
     BLOCK_END("BeingRecv::processBeingStatusChange")
 }
 
-- 
cgit v1.2.3-70-g09d2