|
82 | 82 | #include "SummonInfo.h" |
83 | 83 | #include "TemporarySummon.h" |
84 | 84 | #include "Totem.h" |
| 85 | +#include "TotemPackets.h" |
85 | 86 | #include "Transport.h" |
86 | 87 | #include "UnitAI.h" |
87 | 88 | #include "UpdateFieldFlags.h" |
@@ -379,6 +380,8 @@ Unit::Unit(bool isWorldObject) : |
379 | 380 |
|
380 | 381 | _oldFactionId = 0; |
381 | 382 | _isWalkingBeforeCharm = false; |
| 383 | + |
| 384 | + _slottedSummons.resize(AsUnderlyingType(SummonPropertiesSlot::Max), nullptr); |
382 | 385 | } |
383 | 386 |
|
384 | 387 | //////////////////////////////////////////////////////////// |
@@ -8824,16 +8827,73 @@ void Unit::RegisterSummon(SummonInfo* summon) |
8824 | 8827 | if (!summon) |
8825 | 8828 | return; |
8826 | 8829 |
|
8827 | | - if (!advstd::ranges::contains(_activeSummons, summon)) |
8828 | | - _activeSummons.push_back(summon); |
| 8830 | + SummonPropertiesSlot slot = summon->GetSummonSlot(); |
| 8831 | + |
| 8832 | + // Wild Summons usually don't need any tracking but some do have certain SummonPropertiesFlags which |
| 8833 | + // causes them to interact with the summoner in some way (e.g. despawning when the summoner died) |
| 8834 | + if (slot == SummonPropertiesSlot::None) |
| 8835 | + { |
| 8836 | + if (advstd::ranges::contains(_wildSummons, summon)) |
| 8837 | + return; |
| 8838 | + |
| 8839 | + _wildSummons.push_back(summon); |
| 8840 | + return; |
| 8841 | + } |
| 8842 | + |
| 8843 | + // Select any available totem slot if empty, otherwise they just replace the oldest summon of the same entry |
| 8844 | + if (slot == SummonPropertiesSlot::AnyAvailableTotem) |
| 8845 | + { |
| 8846 | + // @Todo |
| 8847 | + slot = SummonPropertiesSlot::Totem1; |
| 8848 | + } |
| 8849 | + |
| 8850 | + uint8 targetSlot = AsUnderlyingType(slot); |
| 8851 | + |
| 8852 | + // Another is occupying the slot. Unsummon that summon first |
| 8853 | + if (SummonInfo* activeSummon = _slottedSummons[targetSlot]) |
| 8854 | + activeSummon->GetSummonedCreature()->DespawnOrUnsummon(); |
| 8855 | + |
| 8856 | + _slottedSummons[targetSlot] = summon; |
| 8857 | + |
| 8858 | + switch (slot) |
| 8859 | + { |
| 8860 | + case SummonPropertiesSlot::Totem1: |
| 8861 | + case SummonPropertiesSlot::Totem2: |
| 8862 | + case SummonPropertiesSlot::Totem3: |
| 8863 | + case SummonPropertiesSlot::Totem4: |
| 8864 | + { |
| 8865 | + Creature const* summonedCreature = summon->GetSummonedCreature(); |
| 8866 | + if (Player* playerSummoner = Object::ToPlayer(summon->GetUnitSummoner())) |
| 8867 | + { |
| 8868 | + WorldPackets::Totem::TotemCreated totemCreated; |
| 8869 | + totemCreated.Totem = summonedCreature->GetGUID(); |
| 8870 | + totemCreated.SpellID = summonedCreature->GetUInt32Value(UNIT_CREATED_BY_SPELL); |
| 8871 | + totemCreated.Duration = summon->GetRemainingDuration().value_or(0ms).count(); |
| 8872 | + totemCreated.Slot = AsUnderlyingType(summon->GetSummonSlot()) - 1; |
| 8873 | + |
| 8874 | + playerSummoner->SendDirectMessage(totemCreated.Write()); |
| 8875 | + } |
| 8876 | + break; |
| 8877 | + } |
| 8878 | + default: |
| 8879 | + break; |
| 8880 | + } |
8829 | 8881 | } |
8830 | 8882 |
|
8831 | 8883 | void Unit::UnregisterSummon(SummonInfo* summon) |
8832 | 8884 | { |
8833 | 8885 | if (!summon) |
8834 | 8886 | return; |
8835 | 8887 |
|
8836 | | - std::erase(_activeSummons, summon); |
| 8888 | + SummonPropertiesSlot slot = summon->GetSummonSlot(); |
| 8889 | + if (slot == SummonPropertiesSlot::None) |
| 8890 | + { |
| 8891 | + std::erase(_wildSummons, summon); |
| 8892 | + return; |
| 8893 | + } |
| 8894 | + |
| 8895 | + uint8 targetSlot = AsUnderlyingType(slot); |
| 8896 | + _slottedSummons[targetSlot] = nullptr; |
8837 | 8897 | } |
8838 | 8898 |
|
8839 | 8899 | void Unit::SetShapeshiftForm(ShapeshiftForm form) |
@@ -9626,7 +9686,8 @@ void Unit::RemoveFromWorld() |
9626 | 9686 | } |
9627 | 9687 |
|
9628 | 9688 | // Clear all active summon references. If we are about to switch map instances, we want to make sure that we leave all summons behind so we won't do threadunsafe operations |
9629 | | - _activeSummons.clear(); |
| 9689 | + _wildSummons.clear(); |
| 9690 | + _slottedSummons.clear(); |
9630 | 9691 |
|
9631 | 9692 | WorldObject::RemoveFromWorld(); |
9632 | 9693 | m_duringRemoveFromWorld = false; |
|
0 commit comments