Core/Creatures: moved pre/post summon actions into SummonInfo API and disabled most old TemporarySummon functionalities
This commit is contained in:
1 parent
0841615951
commit
98d4a57db1
13 files changed
+272
-339
No files matched your search
@@ -336,9 +336,20 @@ void Creature::RemoveFromWorld()
|
||||
{
|
||||
// If the creature about to despawn, unregister it for the summoner
|
||||
if (SummonInfo* summonInfo = GetSummonInfo())
|
||||
{
|
||||
if (Unit* summoner = summonInfo->GetUnitSummoner())
|
||||
{
|
||||
summoner->UnregisterSummon(summonInfo);
|
||||
|
||||
if (summonInfo->GetControl() == SummonPropertiesControl::Pet)
|
||||
{
|
||||
summoner->SetPetGUID(ObjectGuid::Empty);
|
||||
//if (Player* playerSummoner = summoner->ToPlayer())
|
||||
// playerSummoner->SendRemoveControlBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetZoneScript())
|
||||
GetZoneScript()->OnCreatureRemove(this);
|
||||
|
||||
@@ -2814,45 +2825,6 @@ bool Creature::IsSummon() const
|
||||
return _summonInfo != nullptr;
|
||||
}
|
||||
|
||||
void Creature::HandlePreSummonActions()
|
||||
{
|
||||
SummonInfo* summonInfo = ASSERT_NOTNULL(GetSummonInfo());
|
||||
|
||||
if (Unit* summoner = summonInfo->GetUnitSummoner())
|
||||
{
|
||||
SummonPropertiesSlot slot = summonInfo->GetSummonSlot();
|
||||
|
||||
// Controlled summons always set their creator guid, which is being used to display summoner names in their title
|
||||
if (summonInfo->IsControlledBySummoner())
|
||||
SetCreatorGUID(summoner->GetGUID());
|
||||
|
||||
// Totem slot summons always send the TotemCreated packet. Some non-Shaman classes use this
|
||||
// to display summon icons that can be canceled (Consecration, DK ghouls, Wild Mushrooms)
|
||||
switch (slot)
|
||||
{
|
||||
case SummonPropertiesSlot::Totem1:
|
||||
case SummonPropertiesSlot::Totem2:
|
||||
case SummonPropertiesSlot::Totem3:
|
||||
case SummonPropertiesSlot::Totem4:
|
||||
{
|
||||
if (Player* playerSummoner = Object::ToPlayer(summoner))
|
||||
{
|
||||
WorldPackets::Totem::TotemCreated totemCreated;
|
||||
totemCreated.Totem = GetGUID();
|
||||
totemCreated.SpellID = GetUInt32Value(UNIT_CREATED_BY_SPELL);
|
||||
totemCreated.Duration = summonInfo->GetRemainingDuration().value_or(0ms).count();
|
||||
totemCreated.Slot = AsUnderlyingType(summonInfo->GetSummonSlot()) - 1;
|
||||
|
||||
playerSummoner->SendDirectMessage(totemCreated.Write());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::AllLootRemovedFromCorpse()
|
||||
{
|
||||
if (loot.loot_type != LOOT_SKINNING && !IsPet() && GetCreatureTemplate()->SkinLootId && hasLootRecipient())
|
||||
|
||||
@@ -430,9 +430,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
|
||||
|
||||
bool IsSummon() const override;
|
||||
|
||||
// Handles all summon based actions which happen before the creature is being added to the world
|
||||
void HandlePreSummonActions();
|
||||
|
||||
protected:
|
||||
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
|
||||
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
|
||||
#include "SummonInfo.h"
|
||||
|
||||
#include "CharmInfo.h"
|
||||
#include "Creature.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DBCEnums.h"
|
||||
#include "DBCStores.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "SummonInfoArgs.h"
|
||||
#include "TotemPackets.h"
|
||||
|
||||
SummonInfo::SummonInfo(Creature* summonedCreature, SummonInfoArgs const& args) :
|
||||
_summonedCreature(ASSERT_NOTNULL(summonedCreature)), _summonerGUID(args.Summoner ? args.Summoner->GetGUID() : ObjectGuid::Empty),
|
||||
@@ -64,6 +67,13 @@ void SummonInfo::InitializeSummonProperties(uint32 summonPropertiesId, Unit cons
|
||||
// Controlled summons inherit their summoner's faction if not overridden by DBC data
|
||||
if (!_factionId.has_value())
|
||||
_factionId = summoner->GetFaction();
|
||||
|
||||
// The summon is going to be treated as a pet. Prepare spell list.
|
||||
if (_control == SummonPropertiesControl::Pet)
|
||||
{
|
||||
if (CharmInfo* charmInfo = _summonedCreature->InitCharmInfo())
|
||||
charmInfo->InitCharmCreateSpells();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +113,86 @@ Optional<uint8> SummonInfo::GetCreatureLevel() const
|
||||
return _creatureLevel;
|
||||
}
|
||||
|
||||
void SummonInfo::HandlePreSummonActions()
|
||||
{
|
||||
if (Unit* summoner = GetUnitSummoner())
|
||||
{
|
||||
SummonPropertiesSlot slot = GetSummonSlot();
|
||||
|
||||
// Controlled summons always set their creator guid, which is being used to display summoner names in their title
|
||||
if (IsControlledBySummoner())
|
||||
_summonedCreature->SetCreatorGUID(summoner->GetGUID());
|
||||
|
||||
// Pets are set to Assist by default (this does not apply for class pets which save their states)
|
||||
if (_control == SummonPropertiesControl::Pet)
|
||||
_summonedCreature->SetReactState(REACT_ASSIST);
|
||||
|
||||
// Totem slot summons always send the TotemCreated packet. Some non-Shaman classes use this
|
||||
// to display summon icons that can be canceled (Consecration, DK ghouls, Wild Mushrooms)
|
||||
switch (slot)
|
||||
{
|
||||
case SummonPropertiesSlot::Totem1:
|
||||
case SummonPropertiesSlot::Totem2:
|
||||
case SummonPropertiesSlot::Totem3:
|
||||
case SummonPropertiesSlot::Totem4:
|
||||
{
|
||||
if (Player* playerSummoner = Object::ToPlayer(summoner))
|
||||
{
|
||||
WorldPackets::Totem::TotemCreated totemCreated;
|
||||
totemCreated.Totem = _summonedCreature->GetGUID();
|
||||
totemCreated.SpellID = _summonedCreature->GetUInt32Value(UNIT_CREATED_BY_SPELL);
|
||||
totemCreated.Duration = _remainingDuration.value_or(0ms).count();
|
||||
totemCreated.Slot = AsUnderlyingType(_summonSlot) - 1;
|
||||
|
||||
playerSummoner->SendDirectMessage(totemCreated.Write());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonInfo::HandlePostSummonActions()
|
||||
{
|
||||
// Register Pet and enable its control
|
||||
if (_control == SummonPropertiesControl::Pet)
|
||||
{
|
||||
if (Unit* summoner = GetUnitSummoner())
|
||||
{
|
||||
_summonedCreature->SetOwnerGUID(summoner->GetGUID());
|
||||
|
||||
// Only set the Summon GUID when it's empty (prevent multiple applications on multi-summons like Feral Spirit)
|
||||
if (summoner->GetMinionGUID() != _summonedCreature->GetGUID())
|
||||
{
|
||||
summoner->SetMinionGUID(_summonedCreature->GetGUID());
|
||||
|
||||
if (Player* playerSummoner = summoner->ToPlayer())
|
||||
{
|
||||
_summonedCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||
playerSummoner->SendPetSpells(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonInfo::HandlePreUnsummonActions()
|
||||
{
|
||||
Unit* summoner = GetUnitSummoner();
|
||||
if (!summoner)
|
||||
return;
|
||||
|
||||
// Clear the current pet action bar and reset the Summon GUID
|
||||
if (_control == SummonPropertiesControl::Pet && summoner->GetMinionGUID() == _summonedCreature->GetGUID())
|
||||
{
|
||||
summoner->SetMinionGUID(ObjectGuid::Empty);
|
||||
if (Player* player = summoner->ToPlayer())
|
||||
player->SendRemoveControlBar();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonInfo::UpdateRemainingDuration(Milliseconds deltaTime)
|
||||
{
|
||||
if (!_remainingDuration.has_value() || _remainingDuration <= 0ms)
|
||||
@@ -112,9 +202,9 @@ void SummonInfo::UpdateRemainingDuration(Milliseconds deltaTime)
|
||||
if (_remainingDuration <= 0ms)
|
||||
{
|
||||
if (DespawnsWhenExpired())
|
||||
GetSummonedCreature()->DespawnOrUnsummon();
|
||||
_summonedCreature->DespawnOrUnsummon();
|
||||
else
|
||||
GetSummonedCreature()->KillSelf();
|
||||
_summonedCreature->KillSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,3 +269,8 @@ SummonPropertiesSlot SummonInfo::GetSummonSlot() const
|
||||
{
|
||||
return _summonSlot;
|
||||
}
|
||||
|
||||
SummonPropertiesControl SummonInfo::GetControl() const
|
||||
{
|
||||
return _control;
|
||||
}
|
||||
@@ -59,6 +59,13 @@ public:
|
||||
// Returns the level of the creature that will override the default level calculation. Nullopt when the creature uses its default values.
|
||||
Optional<uint8> GetCreatureLevel() const;
|
||||
|
||||
// Handles all summon actions which must be performed before the summoned creature is being added to the world
|
||||
void HandlePreSummonActions();
|
||||
// Handles all summon actions which must be performed after the summoned creature has been added to the world
|
||||
void HandlePostSummonActions();
|
||||
// Handles all summon actions which much be performend before the summoned creature is being removed from the world
|
||||
void HandlePreUnsummonActions();
|
||||
|
||||
// Updates the remaining duration of a summon and triggers the expiration
|
||||
void UpdateRemainingDuration(Milliseconds deltaTime);
|
||||
|
||||
@@ -82,6 +89,8 @@ public:
|
||||
bool IsControlledBySummoner() const;
|
||||
// Returns the summon slot that the summon is going to be stored in
|
||||
SummonPropertiesSlot GetSummonSlot() const;
|
||||
// Returns the summon control type which determines how the summon can be controlled by the summoner
|
||||
SummonPropertiesControl GetControl() const;
|
||||
|
||||
private:
|
||||
Creature* _summonedCreature;
|
||||
|
||||
@@ -50,6 +50,7 @@ void TempSummon::Update(uint32 diff)
|
||||
{
|
||||
Creature::Update(diff);
|
||||
|
||||
/*
|
||||
if (m_deathState == DEAD)
|
||||
{
|
||||
UnSummon();
|
||||
@@ -147,10 +148,12 @@ void TempSummon::Update(uint32 diff)
|
||||
TC_LOG_ERROR("entities.unit", "Temporary summoned creature (entry: %u) have unknown type %u of ", GetEntry(), m_type);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void TempSummon::InitStats(uint32 duration)
|
||||
{
|
||||
/*
|
||||
ASSERT(!IsPet());
|
||||
|
||||
m_timer = duration;
|
||||
@@ -186,10 +189,12 @@ void TempSummon::InitStats(uint32 duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void TempSummon::InitSummon()
|
||||
{
|
||||
/*
|
||||
if (Unit* owner = GetSummoner())
|
||||
{
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled())
|
||||
@@ -197,6 +202,7 @@ void TempSummon::InitSummon()
|
||||
if (IsAIEnabled())
|
||||
AI()->IsSummonedBy(owner);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void TempSummon::UpdateObjectVisibilityOnCreate()
|
||||
@@ -206,8 +212,10 @@ void TempSummon::UpdateObjectVisibilityOnCreate()
|
||||
|
||||
void TempSummon::SetTempSummonType(TempSummonType type)
|
||||
{
|
||||
/*
|
||||
m_type = type;
|
||||
GetSummonInfo()->SetDespawnWhenExpired(true); // To maintain legacy behavior in which all summons just despawn when expired
|
||||
*/
|
||||
}
|
||||
|
||||
void TempSummon::UnSummon(uint32 msTime)
|
||||
@@ -220,6 +228,7 @@ void TempSummon::UnSummon(uint32 msTime)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
//ASSERT(!IsPet());
|
||||
if (IsPet())
|
||||
{
|
||||
@@ -234,6 +243,7 @@ void TempSummon::UnSummon(uint32 msTime)
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled())
|
||||
owner->ToCreature()->AI()->SummonedCreatureDespawn(this);
|
||||
}
|
||||
*/
|
||||
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
@@ -264,6 +274,7 @@ Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorl
|
||||
|
||||
void Minion::InitStats(uint32 duration)
|
||||
{
|
||||
/*
|
||||
TempSummon::InitStats(duration);
|
||||
SetReactState(REACT_PASSIVE);
|
||||
|
||||
@@ -286,6 +297,7 @@ void Minion::InitStats(uint32 duration)
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureTemplate()->npcflag);
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Minion::RemoveFromWorld()
|
||||
@@ -293,6 +305,7 @@ void Minion::RemoveFromWorld()
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
/*
|
||||
Unit* owner = GetOwner();
|
||||
|
||||
if ((IsMinion() || IsControlableGuardian()) && !IsTotem() && !IsVehicle())
|
||||
@@ -309,6 +322,7 @@ void Minion::RemoveFromWorld()
|
||||
if (totemOwner->m_Controlled.find(this) != totemOwner->m_Controlled.end())
|
||||
totemOwner->m_Controlled.erase(this);
|
||||
}
|
||||
*/
|
||||
|
||||
TempSummon::RemoveFromWorld();
|
||||
}
|
||||
@@ -338,15 +352,19 @@ Guardian::Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool is
|
||||
{
|
||||
memset(m_statFromOwner, 0, sizeof(float)*MAX_STATS);
|
||||
m_unitTypeMask |= UNIT_MASK_GUARDIAN;
|
||||
|
||||
/*
|
||||
if (properties && SummonTitle(properties->Title) == SummonTitle::Pet)
|
||||
{
|
||||
m_unitTypeMask |= UNIT_MASK_CONTROLABLE_GUARDIAN;
|
||||
InitCharmInfo();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Guardian::InitStats(uint32 duration)
|
||||
{
|
||||
/*
|
||||
Minion::InitStats(duration);
|
||||
|
||||
InitStatsForLevel(getLevel());
|
||||
@@ -355,18 +373,21 @@ void Guardian::InitStats(uint32 duration)
|
||||
m_charmInfo->InitCharmCreateSpells();
|
||||
|
||||
SetReactState(REACT_AGGRESSIVE);
|
||||
*/
|
||||
}
|
||||
|
||||
void Guardian::InitSummon()
|
||||
{
|
||||
TempSummon::InitSummon();
|
||||
|
||||
/*
|
||||
if (GetOwner()->GetTypeId() == TYPEID_PLAYER
|
||||
&& GetOwner()->GetMinionGUID() == GetGUID()
|
||||
&& !GetOwner()->GetCharmedGUID())
|
||||
{
|
||||
GetOwner()->ToPlayer()->CharmSpellInitialize();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner)
|
||||
@@ -379,19 +400,26 @@ Puppet::Puppet(SummonPropertiesEntry const* properties, Unit* owner)
|
||||
void Puppet::InitStats(uint32 duration)
|
||||
{
|
||||
Minion::InitStats(duration);
|
||||
|
||||
/*
|
||||
SetReactState(REACT_PASSIVE);
|
||||
*/
|
||||
}
|
||||
|
||||
void Puppet::InitSummon()
|
||||
{
|
||||
/*
|
||||
Minion::InitSummon();
|
||||
if (!SetCharmedBy(GetOwner(), CHARM_TYPE_POSSESS))
|
||||
ABORT();
|
||||
*/
|
||||
}
|
||||
|
||||
void Puppet::Update(uint32 time)
|
||||
{
|
||||
Minion::Update(time);
|
||||
|
||||
/*
|
||||
//check if caster is channelling?
|
||||
if (IsInWorld())
|
||||
{
|
||||
@@ -401,6 +429,7 @@ void Puppet::Update(uint32 time)
|
||||
/// @todo why long distance .die does not remove it
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Puppet::RemoveFromWorld()
|
||||
@@ -408,6 +437,8 @@ void Puppet::RemoveFromWorld()
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
/*
|
||||
RemoveCharmedBy(nullptr);
|
||||
*/
|
||||
Minion::RemoveFromWorld();
|
||||
}
|
||||
@@ -119,15 +119,6 @@ class TC_GAME_API Guardian : public Minion
|
||||
bool InitStatsForLevel(uint8 level);
|
||||
void InitSummon() override;
|
||||
|
||||
bool UpdateStats(Stats stat) override;
|
||||
bool UpdateAllStats() override;
|
||||
void UpdateResistances(uint32 school) override;
|
||||
void UpdateArmor() override;
|
||||
void UpdateMaxHealth() override;
|
||||
void UpdateMaxPower(Powers power) override;
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||
void UpdateDamagePhysical(WeaponAttackType attType) override;
|
||||
|
||||
int32 GetBonusDamage() const { return m_bonusSpellDamage; }
|
||||
float GetBonusStatFromOwner(Stats stat) const { return m_statFromOwner[stat]; }
|
||||
void SetBonusDamage(int32 damage);
|
||||
|
||||
@@ -2008,74 +2008,7 @@ void WorldObject::AddObjectToRemoveList()
|
||||
|
||||
TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonCreatureExtraArgs const& summonArgs /*= { }*/)
|
||||
{
|
||||
uint32 mask = UNIT_MASK_SUMMON;
|
||||
|
||||
if (summonArgs.SummonProperties)
|
||||
{
|
||||
switch (summonArgs.SummonProperties->Control)
|
||||
{
|
||||
case SUMMON_CATEGORY_PET:
|
||||
mask = UNIT_MASK_GUARDIAN;
|
||||
break;
|
||||
case SUMMON_CATEGORY_PUPPET:
|
||||
mask = UNIT_MASK_PUPPET;
|
||||
break;
|
||||
case SUMMON_CATEGORY_VEHICLE:
|
||||
mask = UNIT_MASK_MINION;
|
||||
break;
|
||||
case SUMMON_CATEGORY_WILD:
|
||||
case SUMMON_CATEGORY_ALLY:
|
||||
case SUMMON_CATEGORY_UNK:
|
||||
{
|
||||
switch (SummonTitle(summonArgs.SummonProperties->Title))
|
||||
{
|
||||
case SummonTitle::Minion:
|
||||
case SummonTitle::Guardian:
|
||||
case SummonTitle::Runeblade:
|
||||
mask = UNIT_MASK_GUARDIAN;
|
||||
break;
|
||||
case SummonTitle::Totem:
|
||||
case SummonTitle::Lightwell:
|
||||
mask = UNIT_MASK_TOTEM;
|
||||
break;
|
||||
case SummonTitle::Vehicle:
|
||||
case SummonTitle::Mount:
|
||||
mask = UNIT_MASK_SUMMON;
|
||||
break;
|
||||
case SummonTitle::Companion:
|
||||
mask = UNIT_MASK_MINION;
|
||||
break;
|
||||
default:
|
||||
if (summonArgs.SummonProperties->Flags & 512) // Mirror Image, Summon Gargoyle
|
||||
mask = UNIT_MASK_GUARDIAN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
TempSummon* summon = nullptr;
|
||||
switch (mask)
|
||||
{
|
||||
case UNIT_MASK_SUMMON:
|
||||
summon = new TempSummon(summonArgs.SummonProperties, summonArgs.Summoner, false);
|
||||
break;
|
||||
case UNIT_MASK_GUARDIAN:
|
||||
summon = new Guardian(summonArgs.SummonProperties, summonArgs.Summoner, false);
|
||||
break;
|
||||
case UNIT_MASK_PUPPET:
|
||||
summon = new Puppet(summonArgs.SummonProperties, summonArgs.Summoner);
|
||||
break;
|
||||
case UNIT_MASK_TOTEM:
|
||||
summon = new Totem(summonArgs.SummonProperties, summonArgs.Summoner);
|
||||
break;
|
||||
case UNIT_MASK_MINION:
|
||||
summon = new Minion(summonArgs.SummonProperties, summonArgs.Summoner, false);
|
||||
break;
|
||||
}
|
||||
TempSummon* summon = new TempSummon(summonArgs.SummonProperties, summonArgs.Summoner, false);
|
||||
|
||||
// Store special settings which have been extracted from spell effects/scripts
|
||||
SummonInfoArgs args;
|
||||
@@ -2118,8 +2051,10 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonCreatur
|
||||
transport->AddPassenger(summon);
|
||||
}
|
||||
|
||||
SummonInfo* summonInfo = ASSERT_NOTNULL(summon->GetSummonInfo());
|
||||
|
||||
summon->SetHomePosition(pos);
|
||||
summon->HandlePreSummonActions();
|
||||
summonInfo->HandlePreSummonActions();
|
||||
summon->InitStats(summonArgs.SummonDuration);
|
||||
summon->SetPrivateObjectOwner(summonArgs.PrivateObjectOwner);
|
||||
|
||||
@@ -2134,6 +2069,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonCreatur
|
||||
}
|
||||
|
||||
summon->InitSummon();
|
||||
summonInfo->HandlePostSummonActions();
|
||||
|
||||
// call MoveInLineOfSight for nearby creatures
|
||||
Trinity::AIRelocationNotifier notifier(*summon);
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#include <G3D/g3dmath.h>
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include "AccountMgr.h"
|
||||
#include "AchievementMgr.h"
|
||||
#include "Archaeology.h"
|
||||
@@ -36,13 +41,13 @@
|
||||
#include "CharmInfo.h"
|
||||
#include "Chat.h"
|
||||
#include "CinematicMgr.h"
|
||||
#include "CombatPackets.h"
|
||||
#include "CombatLogPackets.h"
|
||||
#include "CombatPackets.h"
|
||||
#include "Common.h"
|
||||
#include "ConditionMgr.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DisableMgr.h"
|
||||
#include "Formulas.h"
|
||||
#include "GameClient.h"
|
||||
@@ -57,13 +62,13 @@
|
||||
#include "GroupMgr.h"
|
||||
#include "Guild.h"
|
||||
#include "GuildMgr.h"
|
||||
#include "InstancePackets.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "InstancePackets.h"
|
||||
#include "ItemPackets.h"
|
||||
#include "KillRewarder.h"
|
||||
#include "Language.h"
|
||||
#include "LFGMgr.h"
|
||||
#include "Language.h"
|
||||
#include "Log.h"
|
||||
#include "LootItemStorage.h"
|
||||
#include "LootMgr.h"
|
||||
@@ -72,9 +77,9 @@
|
||||
#include "MapManager.h"
|
||||
#include "MiscPackets.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MovementStructures.h"
|
||||
#include "MovementPackets.h"
|
||||
#include "MovementPacketSender.h"
|
||||
#include "MovementPackets.h"
|
||||
#include "MovementStructures.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
@@ -102,6 +107,7 @@
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellPackets.h"
|
||||
#include "StringConvert.h"
|
||||
#include "SummonInfo.h"
|
||||
#include "TerrainMgr.h"
|
||||
#include "TicketMgr.h"
|
||||
#include "TradeData.h"
|
||||
@@ -119,8 +125,6 @@
|
||||
#include "WorldSession.h"
|
||||
#include "WorldStateMgr.h"
|
||||
#include "WorldStatePackets.h"
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
#include <G3D/g3dmath.h>
|
||||
|
||||
// corpse reclaim times
|
||||
static constexpr uint32 DEATH_EXPIRE_STEP = 5 * MINUTE;
|
||||
@@ -20756,6 +20760,49 @@ void Player::VehicleSpellInitialize()
|
||||
SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
void Player::SendPetSpells(SummonInfo* summonInfo)
|
||||
{
|
||||
if (!summonInfo)
|
||||
return;
|
||||
|
||||
Creature* summon = summonInfo->GetSummonedCreature();
|
||||
CharmInfo* charmInfo = summon->GetCharmInfo();
|
||||
if (!charmInfo)
|
||||
return;
|
||||
|
||||
uint8 maxCharmInfoSpells = 0;
|
||||
for (uint32 i = 0; i < MAX_SPELL_CHARM; ++i)
|
||||
if (charmInfo->GetCharmSpell(i)->GetAction())
|
||||
++maxCharmInfoSpells;
|
||||
|
||||
WorldPacket data(SMSG_PET_SPELLS, 8 + 2 + 4 + 4 + 4 * MAX_UNIT_ACTION_BAR_INDEX + 1 + 4 * maxCharmInfoSpells + 1);
|
||||
data << summon->GetGUID();
|
||||
data << uint16(summon->GetCreatureTemplate()->family);
|
||||
data << uint32(summonInfo->GetRemainingDuration().value_or(0ms).count());
|
||||
data << uint8(summon->GetReactState());
|
||||
data << uint8(charmInfo->GetCommandState());
|
||||
data << uint16(0);
|
||||
|
||||
// action bar loop
|
||||
charmInfo->BuildActionBar(&data);
|
||||
|
||||
data << uint8(maxCharmInfoSpells);
|
||||
|
||||
if (maxCharmInfoSpells)
|
||||
{
|
||||
for (uint32 i = 0; i < MAX_SPELL_CHARM; ++i)
|
||||
{
|
||||
CharmSpellInfo* cspell = charmInfo->GetCharmSpell(i);
|
||||
if (cspell->GetAction())
|
||||
data << uint32(cspell->packedData);
|
||||
}
|
||||
}
|
||||
|
||||
data << uint8(0); // cooldowns count
|
||||
|
||||
SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
void Player::CharmSpellInitialize()
|
||||
{
|
||||
Unit* charm = GetFirstControlled();
|
||||
|
||||
@@ -1532,6 +1532,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void CharmSpellInitialize();
|
||||
void PossessSpellInitialize();
|
||||
void VehicleSpellInitialize();
|
||||
void SendPetSpells(SummonInfo* summonInfo);
|
||||
void SendRemoveControlBar() const;
|
||||
bool HasSpell(uint32 spell) const override;
|
||||
bool HasActiveSpell(uint32 spell) const; // show in spellbook
|
||||
|
||||
@@ -1096,214 +1096,6 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
|
||||
######## ########
|
||||
#######################################*/
|
||||
|
||||
bool Guardian::UpdateStats(Stats stat)
|
||||
{
|
||||
if (stat >= MAX_STATS)
|
||||
return false;
|
||||
|
||||
// value = ((base_value * base_pct) + total_value) * total_pct
|
||||
float value = GetTotalStatValue(stat);
|
||||
//ApplyStatBuffMod(stat, m_statFromOwner[stat], false);
|
||||
float ownersBonus = 0.0f;
|
||||
|
||||
SetStat(stat, int32(value));
|
||||
m_statFromOwner[stat] = ownersBonus;
|
||||
UpdateStatBuffMod(stat);
|
||||
|
||||
switch (stat)
|
||||
{
|
||||
case STAT_STRENGTH:
|
||||
UpdateAttackPowerAndDamage();
|
||||
break;
|
||||
case STAT_AGILITY:
|
||||
UpdateArmor();
|
||||
break;
|
||||
case STAT_STAMINA:
|
||||
UpdateMaxHealth();
|
||||
break;
|
||||
case STAT_INTELLECT:
|
||||
UpdateMaxPower(POWER_MANA);
|
||||
break;
|
||||
case STAT_SPIRIT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Guardian::UpdateAllStats()
|
||||
{
|
||||
UpdateMaxHealth();
|
||||
|
||||
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
UpdateStats(Stats(i));
|
||||
|
||||
for (uint8 i = POWER_MANA; i < MAX_POWERS; ++i)
|
||||
UpdateMaxPower(Powers(i));
|
||||
|
||||
UpdateAllResistances();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Guardian::UpdateResistances(uint32 school)
|
||||
{
|
||||
if (school > SPELL_SCHOOL_NORMAL)
|
||||
{
|
||||
float value = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school));
|
||||
SetResistance(SpellSchools(school), int32(value));
|
||||
}
|
||||
else
|
||||
UpdateArmor();
|
||||
}
|
||||
|
||||
void Guardian::UpdateArmor()
|
||||
{
|
||||
float value = 0.0f;
|
||||
UnitMods unitMod = UNIT_MOD_ARMOR;
|
||||
|
||||
value = GetFlatModifierValue(unitMod, BASE_VALUE);
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
//value += GetStat(STAT_AGILITY) * 2.0f; (deprecated since 4.x)
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
|
||||
SetArmor(int32(value));
|
||||
}
|
||||
|
||||
void Guardian::UpdateMaxHealth()
|
||||
{
|
||||
UnitMods unitMod = UNIT_MOD_HEALTH;
|
||||
float stamina = GetStat(STAT_STAMINA) - GetCreateStat(STAT_STAMINA);
|
||||
float multiplicator = 10.0f;
|
||||
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetMaxHealth((uint32)value);
|
||||
}
|
||||
|
||||
void Guardian::UpdateMaxPower(Powers power)
|
||||
{
|
||||
if (GetPowerIndex(power) == MAX_POWERS)
|
||||
return;
|
||||
|
||||
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + AsUnderlyingType(power));
|
||||
|
||||
float addValue = (power == POWER_MANA) ? GetStat(STAT_INTELLECT) - GetCreateStat(STAT_INTELLECT) : 0.0f;
|
||||
float multiplicator = 15.0f;
|
||||
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowerValue(power);
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator;
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetMaxPower(power, int32(value));
|
||||
}
|
||||
|
||||
void Guardian::UpdateAttackPowerAndDamage(bool ranged)
|
||||
{
|
||||
if (ranged)
|
||||
return;
|
||||
|
||||
float ap_per_strength = 2.0f;
|
||||
float val = GetStat(STAT_STRENGTH) - 20.0f;
|
||||
|
||||
val *= ap_per_strength;
|
||||
|
||||
UnitMods unitMod = UNIT_MOD_ATTACK_POWER;
|
||||
|
||||
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, val);
|
||||
|
||||
// in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
|
||||
float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
|
||||
// UNIT_FIELD_(RANGED)_ATTACK_POWER field
|
||||
SetInt32Value(UNIT_FIELD_ATTACK_POWER, int32(base_attPower));
|
||||
// UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field
|
||||
SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_POS, int32(attPowerMod > 0.f ? attPowerMod : 0.f));
|
||||
// UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_NEG field
|
||||
SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_NEG, int32(attPowerMod < 0.f ? -attPowerMod : 0.f));
|
||||
// UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
|
||||
SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier);
|
||||
|
||||
// automatically update weapon damage after attack power modification
|
||||
UpdateDamagePhysical(BASE_ATTACK);
|
||||
|
||||
// update pet spell power
|
||||
int32 spellDamage = 0;
|
||||
for (auto itr : GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE))
|
||||
spellDamage += itr->GetAmount();
|
||||
|
||||
SetBonusDamage(spellDamage);
|
||||
}
|
||||
|
||||
void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
|
||||
{
|
||||
if (attType > BASE_ATTACK)
|
||||
return;
|
||||
|
||||
float bonusDamage = 0.0f;
|
||||
if (m_owner->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
//force of nature
|
||||
if (GetEntry() == ENTRY_TREANT)
|
||||
{
|
||||
int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + AsUnderlyingType(SPELL_SCHOOL_NATURE))) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + AsUnderlyingType(SPELL_SCHOOL_NATURE));
|
||||
if (spellDmg > 0)
|
||||
bonusDamage = spellDmg * 0.09f;
|
||||
}
|
||||
//greater fire elemental
|
||||
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
|
||||
{
|
||||
int32 spellDmg = int32(m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + AsUnderlyingType(SPELL_SCHOOL_FIRE))) + m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + AsUnderlyingType(SPELL_SCHOOL_FIRE));
|
||||
if (spellDmg > 0)
|
||||
bonusDamage = spellDmg * 0.4f;
|
||||
}
|
||||
}
|
||||
|
||||
UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND;
|
||||
|
||||
float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f;
|
||||
|
||||
float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed + bonusDamage;
|
||||
float base_pct = GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
|
||||
float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
|
||||
|
||||
float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
|
||||
float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
|
||||
|
||||
/// @todo: remove this
|
||||
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED);
|
||||
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
|
||||
{
|
||||
switch ((*itr)->GetSpellInfo()->Id)
|
||||
{
|
||||
case 61682:
|
||||
case 61683:
|
||||
AddPct(mindamage, -(*itr)->GetAmount());
|
||||
AddPct(maxdamage, -(*itr)->GetAmount());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage);
|
||||
SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage);
|
||||
}
|
||||
|
||||
void Guardian::SetBonusDamage(int32 damage)
|
||||
{
|
||||
//m_bonusSpellDamage = damage;
|
||||
|
||||
@@ -8863,6 +8863,9 @@ void Unit::UnregisterSummon(SummonInfo* summon)
|
||||
if (!summon)
|
||||
return;
|
||||
|
||||
// Perform cleanup actions if needed
|
||||
summon->HandlePreUnsummonActions();
|
||||
|
||||
SummonPropertiesSlot slot = summon->GetSummonSlot();
|
||||
if (slot == SummonPropertiesSlot::None)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
*/
|
||||
|
||||
#include "PetPackets.h"
|
||||
|
||||
#include "PetDefines.h"
|
||||
#include "Spell.h"
|
||||
|
||||
WorldPacket const* WorldPackets::Pet::PetDismissSound::Write()
|
||||
{
|
||||
@@ -80,3 +82,32 @@ WorldPacket const* WorldPackets::Pet::PetAdded::Write()
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Pet::PetSpells::Write()
|
||||
{
|
||||
_worldPacket << PetGUID;
|
||||
if (PetGUID.IsEmpty())
|
||||
return &_worldPacket;
|
||||
|
||||
_worldPacket << uint16(_CreatureFamily);
|
||||
_worldPacket << uint32(TimeLimit);
|
||||
_worldPacket << uint8(ReactState);
|
||||
_worldPacket << uint8(CommandState);
|
||||
_worldPacket << uint16(Flag);
|
||||
|
||||
_worldPacket.append(ActionButtons.data(), ActionButtons.size());
|
||||
|
||||
_worldPacket << uint8(Actions.size());
|
||||
_worldPacket.append(Actions.data(), Actions.size());
|
||||
|
||||
_worldPacket << uint8(Cooldowns.size());
|
||||
for (PetSpellCooldown const& cooldown : Cooldowns)
|
||||
{
|
||||
_worldPacket << int32(cooldown.SpellID);
|
||||
_worldPacket << uint16(cooldown.Category);
|
||||
_worldPacket << int32(cooldown.Duration);
|
||||
_worldPacket << int32(cooldown.CategoryDuration);
|
||||
}
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
@@ -94,6 +94,34 @@ namespace WorldPackets
|
||||
uint32 PetNumber = 0;
|
||||
uint8 Flags = 0;
|
||||
};
|
||||
|
||||
struct PetSpellCooldown
|
||||
{
|
||||
int32 SpellID = 0;
|
||||
int32 Duration = 0;
|
||||
int32 CategoryDuration = 0;
|
||||
uint16 Category = 0;
|
||||
};
|
||||
|
||||
class PetSpells final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
PetSpells() : ServerPacket(SMSG_PET_SPELLS, 100) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
ObjectGuid PetGUID;
|
||||
uint16 _CreatureFamily = 0; ///< @see enum CreatureFamily
|
||||
uint32 TimeLimit = 0;
|
||||
uint8 ReactState = 0;
|
||||
uint8 CommandState = 0;
|
||||
uint16 Flag = 0;
|
||||
|
||||
std::array<int, 10> ActionButtons = { };
|
||||
|
||||
std::vector<uint32> Actions;
|
||||
std::vector<PetSpellCooldown> Cooldowns;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user