diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.cpp | 21 | ||||
| -rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.h | 9 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2LoadInfo.h | 95 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 15 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 3 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 63 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 15 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 16 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 36 | 
11 files changed, 274 insertions, 5 deletions
| diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 81669da1420..d88ecc71d53 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -1529,6 +1529,27 @@ void HotfixDatabaseConnection::DoPrepareStatements()          " FROM spell_totems WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);      PREPARE_MAX_ID_STMT(HOTFIX_SEL_SPELL_TOTEMS, "SELECT MAX(ID) + 1 FROM spell_totems", CONNECTION_SYNCH); +    // SpellVisual.db2 +    PrepareStatement(HOTFIX_SEL_SPELL_VISUAL, "SELECT ID, MissileCastOffset1, MissileCastOffset2, MissileCastOffset3, MissileImpactOffset1, " +        "MissileImpactOffset2, MissileImpactOffset3, AnimEventSoundID, Flags, MissileAttachment, MissileDestinationAttachment, " +        "MissileCastPositionerID, MissileImpactPositionerID, MissileTargetingKit, HostileSpellVisualID, CasterSpellVisualID, SpellVisualMissileSetID, " +        "DamageNumberDelay, LowViolenceSpellVisualID, RaidSpellVisualMissileSetID, ReducedUnexpectedCameraMovementSpellVisualID FROM spell_visual" +        " WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); +    PREPARE_MAX_ID_STMT(HOTFIX_SEL_SPELL_VISUAL, "SELECT MAX(ID) + 1 FROM spell_visual", CONNECTION_SYNCH); + +    // SpellVisualEffectName.db2 +    PrepareStatement(HOTFIX_SEL_SPELL_VISUAL_EFFECT_NAME, "SELECT ID, ModelFileDataID, BaseMissileSpeed, Scale, MinAllowedScale, MaxAllowedScale, " +        "Alpha, Flags, TextureFileDataID, EffectRadius, Type, GenericID, RibbonQualityID, DissolveEffectID, ModelPosition, Unknown901" +        " FROM spell_visual_effect_name WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); +    PREPARE_MAX_ID_STMT(HOTFIX_SEL_SPELL_VISUAL_EFFECT_NAME, "SELECT MAX(ID) + 1 FROM spell_visual_effect_name", CONNECTION_SYNCH); + +    // SpellVisualMissile.db2 +    PrepareStatement(HOTFIX_SEL_SPELL_VISUAL_MISSILE, "SELECT CastOffset1, CastOffset2, CastOffset3, ImpactOffset1, ImpactOffset2, ImpactOffset3, ID, " +        "SpellVisualEffectNameID, SoundEntriesID, Attachment, DestinationAttachment, CastPositionerID, ImpactPositionerID, FollowGroundHeight, " +        "FollowGroundDropSpeed, FollowGroundApproach, Flags, SpellMissileMotionID, AnimKitID, ClutterLevel, DecayTimeAfterImpact, " +        "SpellVisualMissileSetID FROM spell_visual_missile WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); +    PREPARE_MAX_ID_STMT(HOTFIX_SEL_SPELL_VISUAL_MISSILE, "SELECT MAX(ID) + 1 FROM spell_visual_missile", CONNECTION_SYNCH); +      // SpellVisualKit.db2      PrepareStatement(HOTFIX_SEL_SPELL_VISUAL_KIT, "SELECT ID, FallbackPriority, FallbackSpellVisualKitId, DelayMin, DelayMax, Flags1, Flags2"          " FROM spell_visual_kit WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 73aa6c24e1c..ca7cfae3154 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -886,6 +886,15 @@ enum HotfixDatabaseStatements : uint32      HOTFIX_SEL_SPELL_TOTEMS,      HOTFIX_SEL_SPELL_TOTEMS_MAX_ID, +    HOTFIX_SEL_SPELL_VISUAL, +    HOTFIX_SEL_SPELL_VISUAL_MAX_ID, + +    HOTFIX_SEL_SPELL_VISUAL_EFFECT_NAME, +    HOTFIX_SEL_SPELL_VISUAL_EFFECT_NAME_MAX_ID, + +    HOTFIX_SEL_SPELL_VISUAL_MISSILE, +    HOTFIX_SEL_SPELL_VISUAL_MISSILE_MAX_ID, +      HOTFIX_SEL_SPELL_VISUAL_KIT,      HOTFIX_SEL_SPELL_VISUAL_KIT_MAX_ID, diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index 1d4b28ccfaa..2ddfdadf5ef 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -5846,6 +5846,101 @@ struct SpellTotemsLoadInfo      }  }; +struct SpellVisualLoadInfo +{ +    static DB2LoadInfo const* Instance() +    { +        static DB2FieldMeta const fields[] = +        { +            { false, FT_INT, "ID" }, +            { false, FT_FLOAT, "MissileCastOffset1" }, +            { false, FT_FLOAT, "MissileCastOffset2" }, +            { false, FT_FLOAT, "MissileCastOffset3" }, +            { false, FT_FLOAT, "MissileImpactOffset1" }, +            { false, FT_FLOAT, "MissileImpactOffset2" }, +            { false, FT_FLOAT, "MissileImpactOffset3" }, +            { false, FT_INT, "AnimEventSoundID" }, +            { true, FT_INT, "Flags" }, +            { true, FT_BYTE, "MissileAttachment" }, +            { true, FT_BYTE, "MissileDestinationAttachment" }, +            { false, FT_INT, "MissileCastPositionerID" }, +            { false, FT_INT, "MissileImpactPositionerID" }, +            { true, FT_INT, "MissileTargetingKit" }, +            { false, FT_INT, "HostileSpellVisualID" }, +            { false, FT_INT, "CasterSpellVisualID" }, +            { false, FT_SHORT, "SpellVisualMissileSetID" }, +            { false, FT_SHORT, "DamageNumberDelay" }, +            { false, FT_INT, "LowViolenceSpellVisualID" }, +            { false, FT_INT, "RaidSpellVisualMissileSetID" }, +            { true, FT_INT, "ReducedUnexpectedCameraMovementSpellVisualID" }, +        }; +        static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellVisualMeta::Instance(), HOTFIX_SEL_SPELL_VISUAL); +        return &loadInfo; +    } +}; + +struct SpellVisualEffectNameLoadInfo +{ +    static DB2LoadInfo const* Instance() +    { +        static DB2FieldMeta const fields[] = +        { +            { false, FT_INT, "ID" }, +            { true, FT_INT, "ModelFileDataID" }, +            { false, FT_FLOAT, "BaseMissileSpeed" }, +            { false, FT_FLOAT, "Scale" }, +            { false, FT_FLOAT, "MinAllowedScale" }, +            { false, FT_FLOAT, "MaxAllowedScale" }, +            { false, FT_FLOAT, "Alpha" }, +            { false, FT_INT, "Flags" }, +            { true, FT_INT, "TextureFileDataID" }, +            { false, FT_FLOAT, "EffectRadius" }, +            { false, FT_INT, "Type" }, +            { true, FT_INT, "GenericID" }, +            { false, FT_INT, "RibbonQualityID" }, +            { true, FT_INT, "DissolveEffectID" }, +            { true, FT_INT, "ModelPosition" }, +            { true, FT_BYTE, "Unknown901" }, +        }; +        static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellVisualEffectNameMeta::Instance(), HOTFIX_SEL_SPELL_VISUAL_EFFECT_NAME); +        return &loadInfo; +    } +}; + +struct SpellVisualMissileLoadInfo +{ +    static DB2LoadInfo const* Instance() +    { +        static DB2FieldMeta const fields[] = +        { +            { false, FT_FLOAT, "CastOffset1" }, +            { false, FT_FLOAT, "CastOffset2" }, +            { false, FT_FLOAT, "CastOffset3" }, +            { false, FT_FLOAT, "ImpactOffset1" }, +            { false, FT_FLOAT, "ImpactOffset2" }, +            { false, FT_FLOAT, "ImpactOffset3" }, +            { false, FT_INT, "ID" }, +            { false, FT_SHORT, "SpellVisualEffectNameID" }, +            { false, FT_INT, "SoundEntriesID" }, +            { true, FT_BYTE, "Attachment" }, +            { true, FT_BYTE, "DestinationAttachment" }, +            { false, FT_SHORT, "CastPositionerID" }, +            { false, FT_SHORT, "ImpactPositionerID" }, +            { true, FT_INT, "FollowGroundHeight" }, +            { false, FT_INT, "FollowGroundDropSpeed" }, +            { false, FT_SHORT, "FollowGroundApproach" }, +            { false, FT_INT, "Flags" }, +            { false, FT_SHORT, "SpellMissileMotionID" }, +            { false, FT_INT, "AnimKitID" }, +            { true, FT_BYTE, "ClutterLevel" }, +            { true, FT_INT, "DecayTimeAfterImpact" }, +            { false, FT_INT, "SpellVisualMissileSetID" }, +        }; +        static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellVisualMissileMeta::Instance(), HOTFIX_SEL_SPELL_VISUAL_MISSILE); +        return &loadInfo; +    } +}; +  struct SpellVisualKitLoadInfo  {      static DB2LoadInfo const* Instance() diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 2f629d2d2fe..21780c9935c 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -302,6 +302,9 @@ DB2Storage<SpellShapeshiftEntry>                sSpellShapeshiftStore("SpellShap  DB2Storage<SpellShapeshiftFormEntry>            sSpellShapeshiftFormStore("SpellShapeshiftForm.db2", SpellShapeshiftFormLoadInfo::Instance());  DB2Storage<SpellTargetRestrictionsEntry>        sSpellTargetRestrictionsStore("SpellTargetRestrictions.db2", SpellTargetRestrictionsLoadInfo::Instance());  DB2Storage<SpellTotemsEntry>                    sSpellTotemsStore("SpellTotems.db2", SpellTotemsLoadInfo::Instance()); +DB2Storage<SpellVisualEntry>                    sSpellVisualStore("SpellVisual.db2", SpellVisualLoadInfo::Instance()); +DB2Storage<SpellVisualEffectNameEntry>          sSpellVisualEffectNameStore("SpellVisualEffectName.db2", SpellVisualEffectNameLoadInfo::Instance()); +DB2Storage<SpellVisualMissileEntry>             sSpellVisualMissileStore("SpellVisualMissile.db2", SpellVisualMissileLoadInfo::Instance());  DB2Storage<SpellVisualKitEntry>                 sSpellVisualKitStore("SpellVisualKit.db2", SpellVisualKitLoadInfo::Instance());  DB2Storage<SpellXSpellVisualEntry>              sSpellXSpellVisualStore("SpellXSpellVisual.db2", SpellXSpellVisualLoadInfo::Instance());  DB2Storage<SummonPropertiesEntry>               sSummonPropertiesStore("SummonProperties.db2", SummonPropertiesLoadInfo::Instance()); @@ -476,6 +479,7 @@ namespace      std::unordered_set<std::pair<int32, uint32>> _specsBySpecSet;      std::unordered_set<uint8> _spellFamilyNames;      SpellProcsPerMinuteModContainer _spellProcsPerMinuteMods; +    std::unordered_map<int32, std::vector<SpellVisualMissileEntry const*>> _spellVisualMissilesBySet;      TalentsByPosition _talentsByPosition;      ToyItemIdsContainer _toys;      std::unordered_map<uint32, TransmogIllusionEntry const*> _transmogIllusionsByEnchantmentId; @@ -870,6 +874,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul      LOAD_DB2(sSpellShapeshiftFormStore);      LOAD_DB2(sSpellTargetRestrictionsStore);      LOAD_DB2(sSpellTotemsStore); +    LOAD_DB2(sSpellVisualStore); +    LOAD_DB2(sSpellVisualEffectNameStore); +    LOAD_DB2(sSpellVisualMissileStore);      LOAD_DB2(sSpellVisualKitStore);      LOAD_DB2(sSpellXSpellVisualStore);      LOAD_DB2(sSummonPropertiesStore); @@ -1361,6 +1368,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul      for (SpellProcsPerMinuteModEntry const* ppmMod : sSpellProcsPerMinuteModStore)          _spellProcsPerMinuteMods[ppmMod->SpellProcsPerMinuteID].push_back(ppmMod); +    for (SpellVisualMissileEntry const* spellVisualMissile : sSpellVisualMissileStore) +        _spellVisualMissilesBySet[spellVisualMissile->SpellVisualMissileSetID].push_back(spellVisualMissile); +      for (TalentEntry const* talentInfo : sTalentStore)      {          ASSERT(talentInfo->ClassID < MAX_CLASSES); @@ -2972,6 +2982,11 @@ std::vector<SpellProcsPerMinuteModEntry const*> DB2Manager::GetSpellProcsPerMinu      return std::vector<SpellProcsPerMinuteModEntry const*>();  } +std::vector<SpellVisualMissileEntry const*> const* DB2Manager::GetSpellVisualMissiles(int32 spellVisualMissileSetId) const +{ +    return Trinity::Containers::MapGetValuePtr(_spellVisualMissilesBySet, spellVisualMissileSetId); +} +  std::vector<TalentEntry const*> const& DB2Manager::GetTalentsByPosition(uint32 class_, uint32 tier, uint32 column) const  {      return _talentsByPosition[class_][tier][column]; diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index cd8e074fb7a..8a652478c06 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -225,6 +225,8 @@ TC_GAME_API extern DB2Storage<SpellShapeshiftEntry>                 sSpellShapes  TC_GAME_API extern DB2Storage<SpellShapeshiftFormEntry>             sSpellShapeshiftFormStore;  TC_GAME_API extern DB2Storage<SpellTargetRestrictionsEntry>         sSpellTargetRestrictionsStore;  TC_GAME_API extern DB2Storage<SpellTotemsEntry>                     sSpellTotemsStore; +TC_GAME_API extern DB2Storage<SpellVisualEntry>                     sSpellVisualStore; +TC_GAME_API extern DB2Storage<SpellVisualEffectNameEntry>           sSpellVisualEffectNameStore;  TC_GAME_API extern DB2Storage<SpellVisualKitEntry>                  sSpellVisualKitStore;  TC_GAME_API extern DB2Storage<SpellXSpellVisualEntry>               sSpellXSpellVisualStore;  TC_GAME_API extern DB2Storage<SummonPropertiesEntry>                sSummonPropertiesStore; @@ -449,6 +451,7 @@ public:      bool IsSpecSetMember(int32 specSetId, uint32 specId) const;      static bool IsValidSpellFamiliyName(SpellFamilyNames family);      std::vector<SpellProcsPerMinuteModEntry const*> GetSpellProcsPerMinuteMods(uint32 spellprocsPerMinuteId) const; +    std::vector<SpellVisualMissileEntry const*> const* GetSpellVisualMissiles(int32 spellVisualMissileSetId) const;      std::vector<TalentEntry const*> const& GetTalentsByPosition(uint32 class_, uint32 tier, uint32 column) const;      static bool IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);      bool IsToyItem(uint32 toy) const; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 6742d4f893c..7a3e476542e 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -3548,6 +3548,69 @@ struct SpellTotemsEntry      int32 Totem[MAX_SPELL_TOTEMS];  }; +struct SpellVisualEntry +{ +    uint32 ID; +    float MissileCastOffset[3]; +    float MissileImpactOffset[3]; +    uint32 AnimEventSoundID; +    int32 Flags; +    int8 MissileAttachment; +    int8 MissileDestinationAttachment; +    uint32 MissileCastPositionerID; +    uint32 MissileImpactPositionerID; +    int32 MissileTargetingKit; +    uint32 HostileSpellVisualID; +    uint32 CasterSpellVisualID; +    uint16 SpellVisualMissileSetID; +    uint16 DamageNumberDelay; +    uint32 LowViolenceSpellVisualID; +    uint32 RaidSpellVisualMissileSetID; +    int32 ReducedUnexpectedCameraMovementSpellVisualID; +}; + +struct SpellVisualEffectNameEntry +{ +    uint32 ID; +    int32 ModelFileDataID; +    float BaseMissileSpeed; +    float Scale; +    float MinAllowedScale; +    float MaxAllowedScale; +    float Alpha; +    uint32 Flags; +    int32 TextureFileDataID; +    float EffectRadius; +    uint32 Type; +    int32 GenericID; +    uint32 RibbonQualityID; +    int32 DissolveEffectID; +    int32 ModelPosition; +    int8 Unknown901; +}; + +struct SpellVisualMissileEntry +{ +    float CastOffset[3]; +    float ImpactOffset[3]; +    uint32 ID; +    uint16 SpellVisualEffectNameID; +    uint32 SoundEntriesID; +    int8 Attachment; +    int8 DestinationAttachment; +    uint16 CastPositionerID; +    uint16 ImpactPositionerID; +    int32 FollowGroundHeight; +    uint32 FollowGroundDropSpeed; +    uint16 FollowGroundApproach; +    uint32 Flags; +    uint16 SpellMissileMotionID; +    uint32 AnimKitID; +    int8 ClutterLevel; +    int32 DecayTimeAfterImpact; +    uint32 SpellVisualMissileSetID; +}; +  struct SpellVisualKitEntry  {      uint32 ID; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 26feffc2ac2..5f752cfe715 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -1493,6 +1493,21 @@ enum class SpellShapeshiftFormFlags : int32  DEFINE_ENUM_FLAG(SpellShapeshiftFormFlags); +enum class SpellVisualEffectNameType : uint32 +{ +    Model                           = 0, +    Item                            = 1, +    Creature                        = 2, +    UnitItemMainHand                = 3, +    UnitItemOffHand                 = 4, +    UnitItemRanged                  = 5, +    UnitAmmoBasic                   = 6, +    UnitAmmoPreferred               = 7, +    UnitItemMainHandIgnoreDisarmed  = 8, +    UnitItemOffHandIgnoreDisarmed   = 9, +    UnitItemRangedIgnoreDisarmed    = 10 +}; +  #define TaxiMaskSize 339  typedef std::array<uint8, TaxiMaskSize> TaxiMask; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 4ffbbf36085..470109e3e93 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -769,7 +769,7 @@ enum SpellAttr10 : uint32  {      SPELL_ATTR10_UNK0                            = 0x00000001, // TITLE Unknown attribute 0@Attr10      SPELL_ATTR10_UNK1                            = 0x00000002, // TITLE Unknown attribute 1@Attr10 -    SPELL_ATTR10_UNK2                            = 0x00000004, // TITLE Unknown attribute 2@Attr10 +    SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY  = 0x00000004, // TITLE Uses Ranged Slot (Cosmetic Only)      SPELL_ATTR10_UNK3                            = 0x00000008, // TITLE Unknown attribute 3@Attr10      SPELL_ATTR10_WATER_SPOUT                     = 0x00000010, // TITLE NPC Knockback - ignore doors      SPELL_ATTR10_UNK5                            = 0x00000020, // TITLE Unknown attribute 5@Attr10 diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp index 4c9293a97cf..df44e6cce30 100644 --- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp +++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp @@ -1017,7 +1017,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr10>::ToString(SpellAttr10 value)      {          case SPELL_ATTR10_UNK0: return { "SPELL_ATTR10_UNK0", "Unknown attribute 0@Attr10", "" };          case SPELL_ATTR10_UNK1: return { "SPELL_ATTR10_UNK1", "Unknown attribute 1@Attr10", "" }; -        case SPELL_ATTR10_UNK2: return { "SPELL_ATTR10_UNK2", "Unknown attribute 2@Attr10", "" }; +        case SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY: return { "SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY", "Uses Ranged Slot (Cosmetic Only)", "" };          case SPELL_ATTR10_UNK3: return { "SPELL_ATTR10_UNK3", "Unknown attribute 3@Attr10", "" };          case SPELL_ATTR10_WATER_SPOUT: return { "SPELL_ATTR10_WATER_SPOUT", "NPC Knockback - ignore doors", "" };          case SPELL_ATTR10_UNK5: return { "SPELL_ATTR10_UNK5", "Unknown attribute 5@Attr10", "" }; @@ -1061,7 +1061,7 @@ TC_API_EXPORT SpellAttr10 EnumUtils<SpellAttr10>::FromIndex(size_t index)      {          case 0: return SPELL_ATTR10_UNK0;          case 1: return SPELL_ATTR10_UNK1; -        case 2: return SPELL_ATTR10_UNK2; +        case 2: return SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY;          case 3: return SPELL_ATTR10_UNK3;          case 4: return SPELL_ATTR10_WATER_SPOUT;          case 5: return SPELL_ATTR10_UNK5; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index cbcf5218f14..997327c3147 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4276,7 +4276,7 @@ void Spell::SendSpellStart()      if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_fromClient)          castFlags |= CAST_FLAG_PENDING; -    if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA)) +    if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))          castFlags |= CAST_FLAG_PROJECTILE;      if ((m_caster->GetTypeId() == TYPEID_PLAYER || @@ -4377,7 +4377,7 @@ void Spell::SendSpellGo()      if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_fromClient)          castFlags |= CAST_FLAG_PENDING; -    if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA)) +    if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || m_spellInfo->HasAttribute(SPELL_ATTR10_USES_RANGED_SLOT_COSMETIC_ONLY) || m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NEEDS_AMMO_DATA))          castFlags |= CAST_FLAG_PROJECTILE;                        // arrows/bullets visual      if ((m_caster->GetTypeId() == TYPEID_PLAYER || @@ -4512,6 +4512,8 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo)      }      else if (Unit const* unitCaster = m_caster->ToUnit())      { +        uint32 nonRangedAmmoDisplayID = 0; +        uint32 nonRangedAmmoInventoryType = 0;          for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)          {              if (uint32 item_id = unitCaster->GetVirtualItemId(i)) @@ -4535,6 +4537,10 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo)                                  ammoDisplayID = 5998;       // is this need fixing?                                  ammoInventoryType = INVTYPE_AMMO;                                  break; +                            default: +                                nonRangedAmmoDisplayID = sDB2Manager.GetItemDisplayId(item_id, unitCaster->GetVirtualItemAppearanceMod(i)); +                                nonRangedAmmoInventoryType = itemEntry->InventoryType; +                                break;                          }                          if (ammoDisplayID) @@ -4543,6 +4549,12 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo)                  }              }          } + +        if (!ammoDisplayID && !ammoInventoryType) +        { +            ammoDisplayID = nonRangedAmmoDisplayID; +            ammoInventoryType = nonRangedAmmoInventoryType; +        }      }      ammo.DisplayID = ammoDisplayID; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 1dea10aee2e..50dc075c120 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3223,6 +3223,42 @@ void SpellMgr::LoadSpellInfoCustomAttributes()          }          spellInfoMutable->_InitializeExplicitTargetMask(); + +        if (spellInfoMutable->Speed > 0.0f) +        { +            auto visualNeedsAmmo = [](SpellXSpellVisualEntry const* spellXspellVisual) +            { +                SpellVisualEntry const* spellVisual = sSpellVisualStore.LookupEntry(spellXspellVisual->SpellVisualID); +                if (!spellVisual) +                    return false; + +                std::vector<SpellVisualMissileEntry const*> const* spellVisualMissiles = sDB2Manager.GetSpellVisualMissiles(spellVisual->SpellVisualMissileSetID); +                if (!spellVisualMissiles) +                    return false; + +                for (SpellVisualMissileEntry const* spellVisualMissile : *spellVisualMissiles) +                { +                    SpellVisualEffectNameEntry const* spellVisualEffectName = sSpellVisualEffectNameStore.LookupEntry(spellVisualMissile->SpellVisualEffectNameID); +                    if (!spellVisualEffectName) +                        continue; + +                    SpellVisualEffectNameType type = SpellVisualEffectNameType(spellVisualEffectName->Type); +                    if (type == SpellVisualEffectNameType::UnitAmmoBasic || type == SpellVisualEffectNameType::UnitAmmoPreferred) +                        return true; +                } + +                return false; +            }; + +            for (SpellXSpellVisualEntry const* spellXspellVisual : spellInfoMutable->_visuals) +            { +                if (visualNeedsAmmo(spellXspellVisual)) +                { +                    spellInfoMutable->AttributesCu |= SPELL_ATTR0_CU_NEEDS_AMMO_DATA; +                    break; +                } +            } +        }      }      // addition for binary spells, omit spells triggering other spells | 
