From 8ec4e8575001e50ac2917b0a1599d2a6223aa337 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Mon, 7 Aug 2017 20:11:00 +0300
Subject: Add additional attributes to missile particle in items.

---
 src/CMakeLists.txt          |  1 +
 src/Makefile.am             |  1 +
 src/being/being.cpp         | 19 ++++++++------
 src/resources/db/itemdb.cpp | 60 +++++++++++++++++++++++++++++++++------------
 src/resources/iteminfo.cpp  |  2 +-
 src/resources/iteminfo.h    | 15 ++++++++----
 src/resources/missileinfo.h | 47 +++++++++++++++++++++++++++++++++++
 7 files changed, 116 insertions(+), 29 deletions(-)
 create mode 100644 src/resources/missileinfo.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5bfcfd164..e4bee33a8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -719,6 +719,7 @@ SET(SRCS
     resources/memorycounter.h
     resources/memorymanager.cpp
     resources/memorymanager.h
+    resources/missileinfo.h
     resources/mobileopenglscreenshothelper.cpp
     resources/mobileopenglscreenshothelper.h
     resources/modinfo.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 5226f3415..fd9cc531f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -881,6 +881,7 @@ BASE_SRC += events/actionevent.h \
 	      resources/memorycounter.h \
 	      resources/memorymanager.cpp \
 	      resources/memorymanager.h \
+	      resources/missileinfo.h \
 	      winver.h \
 	      enums/fs/fsentrytype.h \
 	      fs/virtfs/fileapi.h \
diff --git a/src/being/being.cpp b/src/being/being.cpp
index 36badf728..9e3104c5f 100644
--- a/src/being/being.cpp
+++ b/src/being/being.cpp
@@ -1329,11 +1329,16 @@ void Being::setGuild(Guild *restrict const guild) restrict2
 void Being::fireMissile(Being *restrict const victim,
                         const std::string &restrict particle) const restrict2
 {
-    if ((victim == nullptr) || particle.empty() || (particleEngine == nullptr))
-        return;
-
     BLOCK_START("Being::fireMissile")
 
+    if (victim == nullptr ||
+        particle.empty() ||
+        particleEngine == nullptr)
+    {
+        BLOCK_END("Being::fireMissile")
+        return;
+    }
+
     Particle *restrict const target = particleEngine->createChild();
 
     if (target == nullptr)
@@ -1350,12 +1355,12 @@ void Being::fireMissile(Being *restrict const victim,
     if (missile != nullptr)
     {
         target->moveBy(Vector(0.0F, 0.0F, 32.0F));
-        target->setLifetime(1000);
+        target->setLifetime(10000);
         victim->controlAutoParticle(target);
 
-        missile->setDestination(target, 7, 0);
-        missile->setDieDistance(8);
-        missile->setLifetime(900);
+        missile->setDestination(target, 1.0F, 0.0F);
+        missile->setDieDistance(1);
+        missile->setLifetime(9000);
     }
     BLOCK_END("Being::fireMissile")
 }
diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp
index e23623367..ded7e59f2 100644
--- a/src/resources/db/itemdb.cpp
+++ b/src/resources/db/itemdb.cpp
@@ -345,6 +345,14 @@ void ItemDB::loadXmlFile(const std::string &fileName,
         int attackRange = XML::getProperty(node, "attack-range", 0);
         std::string missileParticle = XML::getProperty(
             node, "missile-particle", "");
+        float missileZ = static_cast<float>(XML::getFloatProperty(
+            node, "missile-z", 32.0f));
+        int missileLifeTime = static_cast<float>(XML::getProperty(
+            node, "missile-lifetime", 3000));
+        float missileSpeed = static_cast<float>(XML::getFloatProperty(
+            node, "missile-speed", 7.0f));
+        float missileDieDistance = static_cast<float>(XML::getFloatProperty(
+            node, "missile-diedistance", 8.0f));
         int hitEffectId = XML::getProperty(node, "hit-effect-id",
             paths.getIntValue("hitEffectId"));
         int criticalEffectId = XML::getProperty(
@@ -464,46 +472,66 @@ void ItemDB::loadXmlFile(const std::string &fileName,
             }
         }
 
-        if ((view == 0) && (inheritItemInfo != nullptr))
+        if (view == 0 && inheritItemInfo != nullptr)
             view = inheritItemInfo->getView();
         itemInfo->setView(view);
-        if ((weight == 0) && (inheritItemInfo != nullptr))
+        if (weight == 0 && inheritItemInfo != nullptr)
             weight = inheritItemInfo->getWeight();
         itemInfo->setWeight(weight);
-        if (attackAction.empty() && (inheritItemInfo != nullptr))
+        if (attackAction.empty() && inheritItemInfo != nullptr)
             attackAction = inheritItemInfo->getAttackAction();
         itemInfo->setAttackAction(attackAction);
-        if (skyAttackAction.empty() && (inheritItemInfo != nullptr))
+        if (skyAttackAction.empty() && inheritItemInfo != nullptr)
             skyAttackAction = inheritItemInfo->getSkyAttackAction();
         itemInfo->setSkyAttackAction(skyAttackAction);
-        if (waterAttackAction.empty() && (inheritItemInfo != nullptr))
+        if (waterAttackAction.empty() && inheritItemInfo != nullptr)
             waterAttackAction = inheritItemInfo->getWaterAttackAction();
         itemInfo->setWaterAttackAction(waterAttackAction);
-        if (rideAttackAction.empty() && (inheritItemInfo != nullptr))
+        if (rideAttackAction.empty() && inheritItemInfo != nullptr)
             rideAttackAction = inheritItemInfo->getRideAttackAction();
         itemInfo->setRideAttackAction(rideAttackAction);
-        if ((attackRange == 0) && (inheritItemInfo != nullptr))
+        if (attackRange == 0 && inheritItemInfo != nullptr)
             attackRange = inheritItemInfo->getAttackRange();
         itemInfo->setAttackRange(attackRange);
-        if (missileParticle.empty() && (inheritItemInfo != nullptr))
-            missileParticle = inheritItemInfo->getMissileParticleFile();
-        itemInfo->setMissileParticleFile(missileParticle);
-        if ((hitEffectId == 0) && (inheritItemInfo != nullptr))
+
+        if (inheritItemInfo)
+        {
+            const MissileInfo &inheritMissile =
+                inheritItemInfo->getMissileConst();
+            if (missileParticle.empty())
+                missileParticle = inheritMissile.particle;
+            if (missileZ == 32.0F)
+                missileZ = inheritMissile.z;
+            if (missileLifeTime == 3000)
+                missileLifeTime = inheritMissile.lifeTime;
+            if (missileSpeed == 7.0F)
+                missileSpeed = inheritMissile.speed;
+            if (missileDieDistance == 8.0F)
+                missileDieDistance = inheritMissile.dieDistance;
+        }
+        MissileInfo &missile = itemInfo->getMissile();
+        missile.particle = missileParticle;
+        missile.z = missileZ;
+        missile.lifeTime = missileLifeTime;
+        missile.speed = missileSpeed;
+        missile.dieDistance = missileDieDistance;
+
+        if (hitEffectId == 0 && inheritItemInfo != nullptr)
             hitEffectId = inheritItemInfo->getHitEffectId();
         itemInfo->setHitEffectId(hitEffectId);
-        if ((criticalEffectId == 0) && (inheritItemInfo != nullptr))
+        if (criticalEffectId == 0 && inheritItemInfo != nullptr)
             criticalEffectId = inheritItemInfo->getCriticalHitEffectId();
         itemInfo->setCriticalHitEffectId(criticalEffectId);
-        if ((missEffectId == 0) && (inheritItemInfo != nullptr))
+        if (missEffectId == 0 && inheritItemInfo != nullptr)
             missEffectId = inheritItemInfo->getMissEffectId();
         itemInfo->setMissEffectId(missEffectId);
         itemInfo->setDrawBefore(-1, parseSpriteName(drawBefore));
         itemInfo->setDrawAfter(-1, parseSpriteName(drawAfter));
         itemInfo->setDrawPriority(-1, drawPriority);
-        if (colors.empty() && (inheritItemInfo != nullptr))
+        if (colors.empty() && inheritItemInfo != nullptr)
             colors = inheritItemInfo->getColorsListName();
         itemInfo->setColorsList(colors);
-        if (iconColors.empty() && (inheritItemInfo != nullptr))
+        if (iconColors.empty() && inheritItemInfo != nullptr)
             iconColors = inheritItemInfo->getIconColorsListName();
         itemInfo->setIconColorsList(iconColors);
         itemInfo->setMaxFloorOffsetX(maxFloorOffsetX);
@@ -518,7 +546,7 @@ void ItemDB::loadXmlFile(const std::string &fileName,
         if (!effect.empty() && !temp.empty())
             effect.append(" / ");
         effect.append(temp);
-        if (effect.empty() && (inheritItemInfo != nullptr))
+        if (effect.empty() && inheritItemInfo != nullptr)
             effect = inheritItemInfo->getEffect();
         itemInfo->setEffect(effect);
 
diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp
index 6c8840f75..26cd2dc20 100644
--- a/src/resources/iteminfo.cpp
+++ b/src/resources/iteminfo.cpp
@@ -38,8 +38,8 @@
 #include "debug.h"
 
 ItemInfo::ItemInfo() :
-    mMissileParticleFile(),
     mDisplay(),
+    mMissile(),
     mName(),
     mNameEn(),
     mDescription(),
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index a80442882..8abc78717 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -31,6 +31,7 @@
 
 #include "resources/cursors.h"
 #include "resources/itemcolordata.h"
+#include "resources/missileinfo.h"
 #include "resources/soundinfo.h"
 
 #include "resources/sprite/spritedisplay.h"
@@ -153,11 +154,17 @@ class ItemInfo final
         // Handlers for seting and getting the string
         // used for particles when attacking
         void setMissileParticleFile(const std::string &s) noexcept2
-        { mMissileParticleFile = s; }
+        { mMissile.particle = s; }
 
         const std::string &getMissileParticleFile() const noexcept2
                                                   A_WARN_UNUSED
-        { return mMissileParticleFile; }
+        { return mMissile.particle; }
+
+        MissileInfo &getMissile() noexcept2 A_WARN_UNUSED
+        { return mMissile; }
+
+        const MissileInfo &getMissileConst() const noexcept2 A_WARN_UNUSED
+        { return mMissile; }
 
         void setHitEffectId(const int s) noexcept2
         { mHitEffectId = s; }
@@ -246,9 +253,6 @@ class ItemInfo final
         ItemColor getCardColor() const noexcept2
         { return mCardColor; }
 
-        /** Effects to be shown when weapon attacks - see also effects.xml */
-        std::string mMissileParticleFile;
-
         int getReplaceToSpriteId(int id) const A_WARN_UNUSED;
 
         IntMap *addReplaceSprite(const int sprite,
@@ -324,6 +328,7 @@ class ItemInfo final
                                    const int def = -1) A_NONNULL(1);
 
         SpriteDisplay mDisplay;     /**< Display info (like icon) */
+        MissileInfo mMissile;
         std::string mName;
         std::string mNameEn;
         std::string mDescription;   /**< Short description. */
diff --git a/src/resources/missileinfo.h b/src/resources/missileinfo.h
new file mode 100644
index 000000000..41429f61c
--- /dev/null
+++ b/src/resources/missileinfo.h
@@ -0,0 +1,47 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2011-2017  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 RESOURCES_MISSILEINFO_H
+#define RESOURCES_MISSILEINFO_H
+
+#include <string>
+
+#include "localconsts.h"
+
+struct MissileInfo final
+{
+    MissileInfo() :
+        particle(),
+        z(32.0F),
+        speed(7.0F),
+        dieDistance(8.0F),
+        lifeTime(3000)
+    { }
+
+    A_DELETE_COPY(MissileInfo)
+
+    std::string particle;
+    float z;
+    float speed;
+    float dieDistance;
+    int lifeTime;
+};
+
+#endif  // RESOURCES_MISSILEINFO_H
-- 
cgit v1.2.3-70-g09d2