Merge branch 'master' into Playerbot
# Conflicts: # src/server/game/Entities/Player/Player.cpp # src/server/game/Entities/Player/Player.h # src/server/game/Entities/Unit/Unit.h
This commit is contained in:
@@ -3656,3 +3656,12 @@ uint32 Creature::GetPlayerDamageReq() const
|
||||
{
|
||||
return _playerDamageReq;
|
||||
}
|
||||
|
||||
std::string Creature::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Unit::GetDebugInfo() << "\n"
|
||||
<< "AIName: " << GetAIName() << " ScriptName: " << GetScriptName()
|
||||
<< " WaypointPath: " << GetWaypointPath() << " SpawnId: " << GetSpawnId();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -385,6 +385,8 @@ public:
|
||||
|
||||
void ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds duration);
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr);
|
||||
bool InitEntry(uint32 entry, const CreatureData* data = nullptr);
|
||||
|
||||
@@ -320,6 +320,15 @@ void TempSummon::RemoveFromWorld()
|
||||
Creature::RemoveFromWorld();
|
||||
}
|
||||
|
||||
std::string TempSummon::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Creature::GetDebugInfo() << "\n"
|
||||
<< std::boolalpha
|
||||
<< "TempSummonType : " << std::to_string(GetSummonType()) << " Summoner: " << GetSummonerGUID().ToString();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
Minion::Minion(SummonPropertiesEntry const* properties, ObjectGuid owner, bool isWorldObject) : TempSummon(properties, owner, isWorldObject)
|
||||
, m_owner(owner)
|
||||
{
|
||||
@@ -378,6 +387,15 @@ void Minion::setDeathState(DeathState s, bool despawn)
|
||||
}
|
||||
}
|
||||
|
||||
std::string Minion::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << TempSummon::GetDebugInfo() << "\n"
|
||||
<< std::boolalpha
|
||||
<< "Owner: " << (GetOwner() ? GetOwner()->GetGUID().ToString() : "");
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
Guardian::Guardian(SummonPropertiesEntry const* properties, ObjectGuid owner, bool isWorldObject) : Minion(properties, owner, isWorldObject)
|
||||
{
|
||||
m_unitTypeMask |= UNIT_MASK_GUARDIAN;
|
||||
@@ -416,6 +434,13 @@ void Guardian::InitSummon()
|
||||
}
|
||||
}
|
||||
|
||||
std::string Guardian::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Minion::GetDebugInfo();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
Puppet::Puppet(SummonPropertiesEntry const* properties, ObjectGuid owner) : Minion(properties, owner, false), m_owner(owner) //maybe true?
|
||||
{
|
||||
ASSERT(owner.IsPlayer());
|
||||
|
||||
@@ -52,12 +52,14 @@ public:
|
||||
[[nodiscard]] Unit* GetSummonerUnit() const;
|
||||
[[nodiscard]] Creature* GetSummonerCreatureBase() const;
|
||||
[[nodiscard]] GameObject* GetSummonerGameObject() const;
|
||||
ObjectGuid GetSummonerGUID() { return m_summonerGUID; }
|
||||
TempSummonType const& GetSummonType() { return m_type; }
|
||||
ObjectGuid GetSummonerGUID() const { return m_summonerGUID; }
|
||||
TempSummonType GetSummonType() const { return m_type; }
|
||||
uint32 GetTimer() { return m_timer; }
|
||||
void SetTimer(uint32 t) { m_timer = t; }
|
||||
|
||||
const SummonPropertiesEntry* const m_Properties;
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
private:
|
||||
TempSummonType m_type;
|
||||
uint32 m_timer;
|
||||
@@ -77,6 +79,8 @@ public:
|
||||
[[nodiscard]] bool IsPetGhoul() const {return GetEntry() == 26125 /*normal ghoul*/ || GetEntry() == 30230 /*Raise Ally ghoul*/;} // Ghoul may be guardian or pet
|
||||
[[nodiscard]] bool IsGuardianPet() const;
|
||||
void setDeathState(DeathState s, bool despawn = false) override; // override virtual Unit::setDeathState
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
protected:
|
||||
const ObjectGuid m_owner;
|
||||
float m_followAngle;
|
||||
@@ -97,6 +101,8 @@ public:
|
||||
void UpdateMaxPower(Powers power) override;
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||
void UpdateDamagePhysical(WeaponAttackType attType) override;
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
};
|
||||
|
||||
class Puppet : public Minion
|
||||
|
||||
@@ -131,7 +131,7 @@ void GameObject::RemoveFromOwner()
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_FATAL("entities.gameobject", "Delete GameObject ({} Entry: {} SpellId {} LinkedGO {}) that lost references to owner {} GO list. Crash possible later.",
|
||||
LOG_DEBUG("entities.gameobject", "Delete GameObject ({} Entry: {} SpellId {} LinkedGO {}) that lost references to owner {} GO list.",
|
||||
GetGUID().ToString(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), ownerGUID.ToString());
|
||||
|
||||
SetOwnerGUID(ObjectGuid::Empty);
|
||||
@@ -3091,3 +3091,11 @@ bool GameObject::IsInSkillupList(ObjectGuid playerGuid) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string GameObject::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << WorldObject::GetDebugInfo() << "\n"
|
||||
<< "SpawnId: " << GetSpawnId() << " GoState: " << std::to_string(GetGoState()) << " ScriptId: " << GetScriptId() << " AIName: " << GetAIName();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -1061,6 +1061,8 @@ public:
|
||||
void UpdateSaveToDb(bool enable);
|
||||
|
||||
void SavingStateOnDB();
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
protected:
|
||||
bool AIM_Initialize();
|
||||
GameObjectModel* CreateModel();
|
||||
|
||||
@@ -239,3 +239,10 @@ Item* Bag::GetItemByPos(uint8 slot) const
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string Bag::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Item::GetDebugInfo();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
|
||||
bool Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner) override;
|
||||
|
||||
void Clear();
|
||||
void StoreItem(uint8 slot, Item* pItem, bool update);
|
||||
void RemoveItem(uint8 slot, bool update);
|
||||
|
||||
@@ -58,6 +57,8 @@ public:
|
||||
|
||||
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
// Bag Storage space
|
||||
Item* m_bagslot[MAX_BAG_SIZE];
|
||||
|
||||
@@ -1097,7 +1097,7 @@ Item* Item::CreateItem(uint32 item, uint32 count, Player const* player, bool clo
|
||||
if (count > pProto->GetMaxStackSize())
|
||||
count = pProto->GetMaxStackSize();
|
||||
|
||||
ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already");
|
||||
ASSERT_NODEBUGINFO(count != 0 && "pProto->Stackable == 0 but checked at loading already");
|
||||
|
||||
Item* pItem = NewItemOrBag(pProto);
|
||||
if (pItem->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), item, player))
|
||||
@@ -1287,3 +1287,13 @@ bool Item::CheckSoulboundTradeExpire()
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Item::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Object::GetDebugInfo() << "\n"
|
||||
<< std::boolalpha
|
||||
<< "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount()
|
||||
<< " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -353,6 +353,8 @@ public:
|
||||
void RemoveFromObjectUpdate() override;
|
||||
|
||||
[[nodiscard]] uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
private:
|
||||
std::string m_text;
|
||||
uint8 m_slot;
|
||||
|
||||
@@ -1010,6 +1010,13 @@ bool Object::PrintIndexError(uint32 index, bool set) const
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Object::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << GetGUID().ToString() + " Entry " << GetEntry();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
void MovementInfo::OutDebug()
|
||||
{
|
||||
LOG_INFO("movement", "MOVEMENT INFO");
|
||||
@@ -2419,6 +2426,15 @@ Player* WorldObject::SelectNearestPlayer(float distance) const
|
||||
return target;
|
||||
}
|
||||
|
||||
std::string WorldObject::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << WorldLocation::GetDebugInfo() << "\n"
|
||||
<< Object::GetDebugInfo() << "\n"
|
||||
<< "Name: " << GetName();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>& gameobjectList, uint32 entry, float maxSearchRange) const
|
||||
{
|
||||
Acore::AllGameObjectsWithEntryInRange check(this, entry, maxSearchRange);
|
||||
|
||||
@@ -208,6 +208,8 @@ public:
|
||||
DynamicObject* ToDynObject() { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject*>(this); else return nullptr; }
|
||||
[[nodiscard]] DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject const*>(this); else return nullptr; }
|
||||
|
||||
virtual std::string GetDebugInfo() const;
|
||||
|
||||
DataMap CustomData;
|
||||
|
||||
protected:
|
||||
@@ -613,6 +615,8 @@ public:
|
||||
[[nodiscard]] bool HasAllowedLooter(ObjectGuid guid) const;
|
||||
[[nodiscard]] GuidUnorderedSet const& GetAllowedLooters() const;
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
ElunaEventProcessor* elunaEvents;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -208,3 +208,10 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& st
|
||||
buf << x << y << z << o;
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string WorldLocation::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << "MapID: " << m_mapId << " " << Position::ToString();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -317,6 +317,8 @@ public:
|
||||
}
|
||||
|
||||
uint32 m_mapId;
|
||||
|
||||
std::string GetDebugInfo() const;
|
||||
};
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
|
||||
|
||||
@@ -2439,3 +2439,13 @@ std::string Pet::GenerateActionBarData() const
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string Pet::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Guardian::GetDebugInfo() << "\n"
|
||||
<< std::boolalpha
|
||||
<< "PetType: " << std::to_string(getPetType()) << " "
|
||||
<< "PetNumber: " << m_charmInfo->GetPetNumber();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ public:
|
||||
void SetLoading(bool load) { m_loading = load; }
|
||||
|
||||
[[nodiscard]] bool HasTempSpell() const { return m_tempspell != 0; }
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
protected:
|
||||
Player* m_owner;
|
||||
int32 m_happinessTimer;
|
||||
|
||||
@@ -222,6 +222,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
||||
m_bHasDelayedTeleport = false;
|
||||
teleportStore_options = 0;
|
||||
m_canTeleport = false;
|
||||
m_canKnockback = false;
|
||||
|
||||
m_trade = nullptr;
|
||||
|
||||
@@ -1644,10 +1645,8 @@ void Player::ProcessDelayedOperations()
|
||||
{
|
||||
if (m_entryPointData.HasTaxiPath())
|
||||
{
|
||||
for (size_t i = 0; i < m_entryPointData.taxiPath.size() - 1; ++i)
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[i]);
|
||||
m_taxi.SetTaxiSegment(m_entryPointData.taxiPath[m_entryPointData.taxiPath.size() - 1]);
|
||||
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[0]);
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[1]);
|
||||
m_entryPointData.ClearTaxiPath();
|
||||
ContinueTaxiFlight();
|
||||
}
|
||||
@@ -10004,26 +10003,6 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
return false;
|
||||
}
|
||||
|
||||
// check node starting pos data set case if provided
|
||||
if (node->x != 0.0f || node->y != 0.0f || node->z != 0.0f)
|
||||
{
|
||||
if (node->map_id != GetMapId() ||
|
||||
(node->x - GetPositionX()) * (node->x - GetPositionX()) +
|
||||
(node->y - GetPositionY()) * (node->y - GetPositionY()) +
|
||||
(node->z - GetPositionZ()) * (node->z - GetPositionZ()) >
|
||||
(2 * INTERACTION_DISTANCE) * (2 * INTERACTION_DISTANCE) * (2 * INTERACTION_DISTANCE))
|
||||
{
|
||||
GetSession()->SendActivateTaxiReply(ERR_TAXITOOFARAWAY);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// node must have pos if taxi master case (npc != nullptr)
|
||||
else if (npc)
|
||||
{
|
||||
GetSession()->SendActivateTaxiReply(ERR_TAXIUNSPECIFIEDSERVERERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare to flight start now
|
||||
|
||||
// stop combat at start taxi flight if any
|
||||
@@ -10045,6 +10024,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
// fill destinations path tail
|
||||
uint32 sourcepath = 0;
|
||||
uint32 totalcost = 0;
|
||||
uint32 firstcost = 0;
|
||||
|
||||
uint32 prevnode = sourcenode;
|
||||
uint32 lastnode = 0;
|
||||
@@ -10063,6 +10043,8 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
}
|
||||
|
||||
totalcost += cost;
|
||||
if (i == 1)
|
||||
firstcost = cost;
|
||||
|
||||
if (prevnode == sourcenode)
|
||||
sourcepath = path;
|
||||
@@ -10091,7 +10073,16 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
uint32 money = GetMoney();
|
||||
|
||||
if (npc)
|
||||
totalcost = (uint32)ceil(totalcost * GetReputationPriceDiscount(npc));
|
||||
{
|
||||
float discount = GetReputationPriceDiscount(npc);
|
||||
totalcost = uint32(ceil(totalcost * discount));
|
||||
firstcost = uint32(ceil(firstcost * discount));
|
||||
m_taxi.SetFlightMasterFactionTemplateId(npc->GetFaction());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_taxi.SetFlightMasterFactionTemplateId(0);
|
||||
}
|
||||
|
||||
if (money < totalcost)
|
||||
{
|
||||
@@ -10102,8 +10093,6 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
|
||||
//Checks and preparations done, DO FLIGHT
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
|
||||
ModifyMoney(-(int32)totalcost);
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
|
||||
|
||||
// prevent stealth flight
|
||||
//RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
|
||||
@@ -10113,12 +10102,16 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
{
|
||||
TaxiNodesEntry const* lastPathNode = sTaxiNodesStore.LookupEntry(nodes[nodes.size() - 1]);
|
||||
m_taxi.ClearTaxiDestinations();
|
||||
ModifyMoney(-(int32)totalcost);
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
|
||||
TeleportTo(lastPathNode->map_id, lastPathNode->x, lastPathNode->y, lastPathNode->z, GetOrientation());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flightSpellActivated = spellid;
|
||||
ModifyMoney(-(int32)firstcost);
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, firstcost);
|
||||
GetSession()->SendActivateTaxiReply(ERR_TAXIOK);
|
||||
GetSession()->SendDoFlight(mount_display_id, sourcepath);
|
||||
}
|
||||
@@ -10214,6 +10207,39 @@ void Player::ContinueTaxiFlight()
|
||||
GetSession()->SendDoFlight(mountDisplayId, path, startNode);
|
||||
}
|
||||
|
||||
void Player::SendTaxiNodeStatusMultiple()
|
||||
{
|
||||
for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
|
||||
{
|
||||
if (!itr->IsCreature())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Creature* creature = ObjectAccessor::GetCreature(*this, *itr);
|
||||
if (!creature || creature->IsHostileTo(this))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!creature->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 nearestNode = sObjectMgr->GetNearestTaxiNode(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetMapId(), GetTeamId());
|
||||
if (!nearestNode)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_TAXINODE_STATUS, 9);
|
||||
data << *itr;
|
||||
data << uint8(m_taxi.IsTaximaskNodeKnown(nearestNode) ? 1 : 0);
|
||||
SendDirectMessage(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
|
||||
{
|
||||
PacketCooldowns cooldowns;
|
||||
@@ -10984,11 +11010,8 @@ void Player::SetEntryPoint()
|
||||
m_entryPointData.mountSpell = 0;
|
||||
m_entryPointData.joinPos = WorldLocation(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
|
||||
|
||||
std::vector<uint32> const& taxi = m_taxi.GetPath();
|
||||
for (std::vector<uint32>::const_iterator itr = taxi.begin(); itr != taxi.end(); ++itr)
|
||||
m_entryPointData.taxiPath.push_back(*itr);
|
||||
|
||||
m_entryPointData.taxiPath.push_back(m_taxi.GetTaxiSegment());
|
||||
m_entryPointData.taxiPath[0] = m_taxi.GetTaxiSource();
|
||||
m_entryPointData.taxiPath[1] = m_taxi.GetTaxiDestination();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -11353,6 +11376,7 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
SendEnchantmentDurations(); // must be after add to map
|
||||
SendItemDurations(); // must be after add to map
|
||||
SendQuestGiverStatusMultiple();
|
||||
SendTaxiNodeStatusMultiple();
|
||||
|
||||
// raid downscaling - send difficulty to player
|
||||
if (GetMap()->IsRaid())
|
||||
@@ -12007,23 +12031,21 @@ bool Player::GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
|
||||
|
||||
float Player::GetReputationPriceDiscount(Creature const* creature) const
|
||||
{
|
||||
FactionTemplateEntry const* vendorFaction = creature->GetFactionTemplateEntry();
|
||||
if (!vendorFaction)
|
||||
return GetReputationPriceDiscount(creature->GetFactionTemplateEntry());
|
||||
}
|
||||
|
||||
float Player::GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const
|
||||
{
|
||||
if (!factionTemplate || !factionTemplate->faction)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
return GetReputationPriceDiscount(vendorFaction);
|
||||
}
|
||||
|
||||
float Player::GetReputationPriceDiscount(FactionTemplateEntry const* vendorFaction) const
|
||||
{
|
||||
if (!vendorFaction->faction)
|
||||
return 1.0f;
|
||||
|
||||
ReputationRank rank = GetReputationRank(vendorFaction->faction);
|
||||
ReputationRank rank = GetReputationRank(factionTemplate->faction);
|
||||
if (rank <= REP_NEUTRAL)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
return 1.0f - 0.05f * (rank - REP_NEUTRAL);
|
||||
}
|
||||
@@ -13875,20 +13897,27 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
|
||||
|
||||
bool Player::CanResummonPet(uint32 spellid)
|
||||
{
|
||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
switch (getClass())
|
||||
{
|
||||
if (CanSeeDKPet())
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
if (CanSeeDKPet())
|
||||
return true;
|
||||
else if (spellid == 52150) //Raise Dead
|
||||
return false;
|
||||
break;
|
||||
case CLASS_MAGE:
|
||||
if (HasSpell(31687) && HasAura(70937)) //Has [Summon Water Elemental] spell and [Glyph of Eternal Water].
|
||||
return true;
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_WARLOCK:
|
||||
return true;
|
||||
else if (spellid == 52150)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (getClass() == CLASS_HUNTER || getClass() == CLASS_MAGE || getClass() == CLASS_WARLOCK)
|
||||
return true;
|
||||
|
||||
if (!HasSpell(spellid))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return HasSpell(spellid);
|
||||
}
|
||||
|
||||
bool Player::CanSeeSpellClickOn(Creature const* c) const
|
||||
@@ -14228,16 +14257,9 @@ void Player::_SaveEntryPoint(CharacterDatabaseTransaction trans)
|
||||
stmt->SetData (3, m_entryPointData.joinPos.GetPositionZ());
|
||||
stmt->SetData (4, m_entryPointData.joinPos.GetOrientation());
|
||||
stmt->SetData(5, m_entryPointData.joinPos.GetMapId());
|
||||
|
||||
std::ostringstream ss("");
|
||||
if (m_entryPointData.HasTaxiPath())
|
||||
{
|
||||
for (size_t i = 0; i < m_entryPointData.taxiPath.size(); ++i)
|
||||
ss << m_entryPointData.taxiPath[i] << ' '; // xinef: segment is stored as last point
|
||||
}
|
||||
|
||||
stmt->SetData(6, ss.str());
|
||||
stmt->SetData(7, m_entryPointData.mountSpell);
|
||||
stmt->SetData(6, m_entryPointData.taxiPath[0]);
|
||||
stmt->SetData(7, m_entryPointData.taxiPath[1]);
|
||||
stmt->SetData(8, m_entryPointData.mountSpell);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
@@ -15958,3 +15980,10 @@ void Player::ResetSpeakTimers()
|
||||
m_speakTime = 0;
|
||||
m_speakCount = 0;
|
||||
}
|
||||
|
||||
std::string Player::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << Unit::GetDebugInfo();
|
||||
return sstr.str();
|
||||
}
|
||||
@@ -1035,11 +1035,11 @@ struct EntryPointData
|
||||
}
|
||||
|
||||
uint32 mountSpell{0};
|
||||
std::vector<uint32> taxiPath;
|
||||
std::array<uint32, 2> taxiPath;
|
||||
WorldLocation joinPos;
|
||||
|
||||
void ClearTaxiPath() { taxiPath.clear(); }
|
||||
[[nodiscard]] bool HasTaxiPath() const { return !taxiPath.empty(); }
|
||||
void ClearTaxiPath() { taxiPath.fill(0); }
|
||||
[[nodiscard]] bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
|
||||
};
|
||||
|
||||
class Player : public Unit, public GridObject<Player>
|
||||
@@ -1126,6 +1126,7 @@ public:
|
||||
bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 1);
|
||||
void CleanupAfterTaxiFlight();
|
||||
void ContinueTaxiFlight();
|
||||
void SendTaxiNodeStatusMultiple();
|
||||
// mount_id can be used in scripting calls
|
||||
|
||||
[[nodiscard]] bool IsDeveloper() const { return HasPlayerFlag(PLAYER_FLAGS_DEVELOPER); }
|
||||
@@ -1336,8 +1337,8 @@ public:
|
||||
bool BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
||||
bool _StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore);
|
||||
|
||||
float GetReputationPriceDiscount(Creature const* creature) const;
|
||||
float GetReputationPriceDiscount(FactionTemplateEntry const* vendorFaction) const;
|
||||
[[nodiscard]] float GetReputationPriceDiscount(Creature const* creature) const;
|
||||
[[nodiscard]] float GetReputationPriceDiscount(FactionTemplateEntry const* factionTemplate) const;
|
||||
|
||||
[[nodiscard]] Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : nullptr; }
|
||||
[[nodiscard]] TradeData* GetTradeData() const { return m_trade; }
|
||||
@@ -2429,6 +2430,8 @@ public:
|
||||
|
||||
bool CanTeleport() { return m_canTeleport; }
|
||||
void SetCanTeleport(bool value) { m_canTeleport = value; }
|
||||
bool CanKnockback() { return m_canKnockback; }
|
||||
void SetCanKnockback(bool value) { m_canKnockback = value; }
|
||||
|
||||
bool isAllowedToLoot(Creature const* creature);
|
||||
|
||||
@@ -2557,6 +2560,8 @@ public:
|
||||
|
||||
void ResetSpeakTimers();
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
// Gamemaster whisper whitelist
|
||||
WhisperListContainer WhisperList;
|
||||
@@ -2884,6 +2889,7 @@ private:
|
||||
bool m_bMustDelayTeleport;
|
||||
bool m_bHasDelayedTeleport;
|
||||
bool m_canTeleport;
|
||||
bool m_canKnockback;
|
||||
|
||||
std::unique_ptr<PetStable> m_petStable;
|
||||
|
||||
|
||||
@@ -4894,21 +4894,9 @@ void Player::_LoadEntryPointData(PreparedQueryResult result)
|
||||
fields[2].Get<float>(), // Z
|
||||
fields[3].Get<float>()); // Orientation
|
||||
|
||||
std::string_view taxi = fields[5].Get<std::string_view>();
|
||||
if (!taxi.empty())
|
||||
{
|
||||
for (auto const& itr : Acore::Tokenize(taxi, ' ', false))
|
||||
{
|
||||
uint32 node = Acore::StringTo<uint32>(itr).value_or(0);
|
||||
m_entryPointData.taxiPath.emplace_back(node);
|
||||
}
|
||||
|
||||
// Check integrity
|
||||
if (m_entryPointData.taxiPath.size() < 3)
|
||||
m_entryPointData.ClearTaxiPath();
|
||||
}
|
||||
|
||||
m_entryPointData.mountSpell = fields[6].Get<uint32>();
|
||||
m_entryPointData.taxiPath[0] = fields[5].Get<uint32>();
|
||||
m_entryPointData.taxiPath[1] = fields[6].Get<uint32>();
|
||||
m_entryPointData.mountSpell = fields[7].Get<uint32>();
|
||||
}
|
||||
|
||||
bool Player::LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, ObjectGuid::LowType guid)
|
||||
@@ -5190,10 +5178,8 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons
|
||||
// xinef: restore taxi flight from entry point data
|
||||
if (m_entryPointData.HasTaxiPath())
|
||||
{
|
||||
for (size_t i = 0; i < m_entryPointData.taxiPath.size() - 1; ++i)
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[i]);
|
||||
m_taxi.SetTaxiSegment(m_entryPointData.taxiPath[m_entryPointData.taxiPath.size() - 1]);
|
||||
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[0]);
|
||||
m_taxi.AddTaxiDestination(m_entryPointData.taxiPath[1]);
|
||||
m_entryPointData.ClearTaxiPath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,6 @@
|
||||
#include "Tokenize.h"
|
||||
#include "StringConvert.h"
|
||||
|
||||
PlayerTaxi::PlayerTaxi() : _taxiSegment(0)
|
||||
{
|
||||
memset(m_taximask, 0, sizeof(m_taximask));
|
||||
}
|
||||
|
||||
void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level)
|
||||
{
|
||||
// class specific initial known nodes
|
||||
@@ -136,9 +131,25 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI
|
||||
{
|
||||
ClearTaxiDestinations();
|
||||
|
||||
for (auto const& itr : Acore::Tokenize(values, ' ', false))
|
||||
std::vector<std::string_view> tokens = Acore::Tokenize(values, ' ', false);
|
||||
auto itr = tokens.begin();
|
||||
if (itr != tokens.end())
|
||||
{
|
||||
if (Optional<uint32> node = Acore::StringTo<uint32>(itr))
|
||||
if (Optional<uint32> faction = Acore::StringTo<uint32>(*itr))
|
||||
{
|
||||
m_flightMasterFactionId = *faction;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
while ((++itr) != tokens.end())
|
||||
{
|
||||
if (Optional<uint32> node = Acore::StringTo<uint32>(*itr))
|
||||
{
|
||||
AddTaxiDestination(*node);
|
||||
}
|
||||
@@ -148,26 +159,33 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI
|
||||
}
|
||||
}
|
||||
|
||||
if (m_TaxiDestinations.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check integrity
|
||||
if (m_TaxiDestinations.size() < 3)
|
||||
if (m_TaxiDestinations.size() < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// xinef: current segment is saved as last destination in db
|
||||
_taxiSegment = m_TaxiDestinations[m_TaxiDestinations.size() - 1];
|
||||
m_TaxiDestinations.pop_back();
|
||||
|
||||
for (size_t i = 0; i < m_TaxiDestinations.size() - 1; ++i)
|
||||
for (size_t i = 1; i < m_TaxiDestinations.size(); ++i)
|
||||
{
|
||||
uint32 cost;
|
||||
uint32 path;
|
||||
sObjectMgr->GetTaxiPath(m_TaxiDestinations[i], m_TaxiDestinations[i + 1], path, cost);
|
||||
sObjectMgr->GetTaxiPath(m_TaxiDestinations[i - 1], m_TaxiDestinations[i], path, cost);
|
||||
if (!path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// can't load taxi path without mount set (quest taxi path?)
|
||||
if (!sObjectMgr->GetTaxiMountDisplayId(GetTaxiSource(), teamId, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -175,26 +193,34 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, TeamI
|
||||
std::string PlayerTaxi::SaveTaxiDestinationsToString()
|
||||
{
|
||||
if (m_TaxiDestinations.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
ASSERT(m_TaxiDestinations.size() >= 2);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << m_flightMasterFactionId << ' ';
|
||||
|
||||
for (size_t i = 0; i < m_TaxiDestinations.size(); ++i)
|
||||
{
|
||||
ss << m_TaxiDestinations[i] << ' ';
|
||||
}
|
||||
|
||||
ss << _taxiSegment << ' ';
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
uint32 PlayerTaxi::GetCurrentTaxiPath() const
|
||||
{
|
||||
if (m_TaxiDestinations.size() < 2 || m_TaxiDestinations.size() <= _taxiSegment + 1)
|
||||
if (m_TaxiDestinations.size() < 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 path;
|
||||
uint32 cost;
|
||||
|
||||
sObjectMgr->GetTaxiPath(m_TaxiDestinations[_taxiSegment], m_TaxiDestinations[_taxiSegment + 1], path, cost);
|
||||
sObjectMgr->GetTaxiPath(m_TaxiDestinations[0], m_TaxiDestinations[1], path, cost);
|
||||
|
||||
return path;
|
||||
}
|
||||
@@ -205,3 +231,8 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
|
||||
ss << taxi.m_taximask[i] << ' ';
|
||||
return ss;
|
||||
}
|
||||
|
||||
FactionTemplateEntry const* PlayerTaxi::GetFlightMasterFactionTemplate() const
|
||||
{
|
||||
return sFactionTemplateStore.LookupEntry(m_flightMasterFactionId);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class ByteBuffer;
|
||||
class AC_GAME_API PlayerTaxi
|
||||
{
|
||||
public:
|
||||
PlayerTaxi();
|
||||
PlayerTaxi() : m_flightMasterFactionId(0) { m_taximask.fill(0); }
|
||||
~PlayerTaxi() = default;
|
||||
|
||||
// Nodes
|
||||
@@ -59,29 +59,28 @@ public:
|
||||
bool LoadTaxiDestinationsFromString(std::string const& values, TeamId teamId);
|
||||
std::string SaveTaxiDestinationsToString();
|
||||
|
||||
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); _taxiSegment = 0; }
|
||||
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
|
||||
void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); }
|
||||
[[nodiscard]] uint32 GetTaxiSource() const { return m_TaxiDestinations.size() <= _taxiSegment + 1 ? 0 : m_TaxiDestinations[_taxiSegment]; }
|
||||
[[nodiscard]] uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() <= _taxiSegment + 1 ? 0 : m_TaxiDestinations[_taxiSegment + 1]; }
|
||||
[[nodiscard]] uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); }
|
||||
[[nodiscard]] uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; }
|
||||
[[nodiscard]] uint32 GetCurrentTaxiPath() const;
|
||||
uint32 NextTaxiDestination()
|
||||
{
|
||||
++_taxiSegment;
|
||||
m_TaxiDestinations.pop_front();
|
||||
return GetTaxiDestination();
|
||||
}
|
||||
|
||||
// xinef:
|
||||
void SetTaxiSegment(uint32 segment) { _taxiSegment = segment; }
|
||||
[[nodiscard]] uint32 GetTaxiSegment() const { return _taxiSegment; }
|
||||
|
||||
[[nodiscard]] std::vector<uint32> const& GetPath() const { return m_TaxiDestinations; }
|
||||
[[nodiscard]] std::deque<uint32> const& GetPath() const { return m_TaxiDestinations; }
|
||||
[[nodiscard]] bool empty() const { return m_TaxiDestinations.empty(); }
|
||||
[[nodiscard]] FactionTemplateEntry const* GetFlightMasterFactionTemplate() const;
|
||||
void SetFlightMasterFactionTemplateId(uint32 factionTemplateId) { m_flightMasterFactionId = factionTemplateId; }
|
||||
|
||||
friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
|
||||
|
||||
private:
|
||||
TaxiMask m_taximask;
|
||||
std::vector<uint32> m_TaxiDestinations;
|
||||
uint32 _taxiSegment;
|
||||
std::deque<uint32> m_TaxiDestinations;
|
||||
uint32 m_flightMasterFactionId;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -116,38 +116,40 @@ void Totem::UnSummon(uint32 msTime)
|
||||
CombatStop();
|
||||
RemoveAurasDueToSpell(GetSpell(), GetGUID());
|
||||
|
||||
Unit* owner = GetOwner();
|
||||
// clear owner's totem slot
|
||||
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
|
||||
if (Unit* owner = GetOwner())
|
||||
{
|
||||
if (owner->m_SummonSlot[i] == GetGUID())
|
||||
// clear owner's totem slot
|
||||
for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
|
||||
{
|
||||
owner->m_SummonSlot[i].Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
owner->RemoveAurasDueToSpell(GetSpell(), GetGUID());
|
||||
|
||||
// Remove Sentry Totem Aura
|
||||
if (GetEntry() == SENTRY_TOTEM_ENTRY)
|
||||
owner->RemoveAurasDueToSpell(SENTRY_TOTEM_SPELLID);
|
||||
|
||||
//remove aura all party members too
|
||||
if (Player* player = owner->ToPlayer())
|
||||
{
|
||||
player->SendAutoRepeatCancel(this);
|
||||
|
||||
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetUInt32Value(UNIT_CREATED_BY_SPELL)))
|
||||
player->SendCooldownEvent(spell, 0, nullptr, false);
|
||||
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
if (owner->m_SummonSlot[i] == GetGUID())
|
||||
{
|
||||
Player* target = itr->GetSource();
|
||||
if (target && target->IsInMap(player) && group->SameSubGroup(player, target))
|
||||
target->RemoveAurasDueToSpell(GetSpell(), GetGUID());
|
||||
owner->m_SummonSlot[i].Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
owner->RemoveAurasDueToSpell(GetSpell(), GetGUID());
|
||||
|
||||
// Remove Sentry Totem Aura
|
||||
if (GetEntry() == SENTRY_TOTEM_ENTRY)
|
||||
owner->RemoveAurasDueToSpell(SENTRY_TOTEM_SPELLID);
|
||||
|
||||
//remove aura all party members too
|
||||
if (Player* player = owner->ToPlayer())
|
||||
{
|
||||
player->SendAutoRepeatCancel(this);
|
||||
|
||||
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetUInt32Value(UNIT_CREATED_BY_SPELL)))
|
||||
player->SendCooldownEvent(spell, 0, nullptr, false);
|
||||
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* target = itr->GetSource();
|
||||
if (target && target->IsInMap(player) && group->SameSubGroup(player, target))
|
||||
target->RemoveAurasDueToSpell(GetSpell(), GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,3 +1004,10 @@ void StaticTransport::RemovePassenger(WorldObject* passenger, bool withAll)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string MotionTransport::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << GameObject::GetDebugInfo();
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ public:
|
||||
uint32 GetPeriod() const { return GetUInt32Value(GAMEOBJECT_LEVEL); }
|
||||
void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); }
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
private:
|
||||
void MoveToNextWaypoint();
|
||||
float CalculateSegmentPos(float perc);
|
||||
|
||||
@@ -465,6 +465,7 @@ void Unit::Update(uint32 p_time)
|
||||
// xinef: if attack time > 0, reduce by diff
|
||||
// if on next update, attack time < 0 assume player didnt attack - set to 0
|
||||
bool suspendAttackTimer = false;
|
||||
bool suspendRangedAttackTimer = false;
|
||||
if (IsPlayer() && HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
for (Spell* spell : m_currentSpells)
|
||||
@@ -473,6 +474,11 @@ void Unit::Update(uint32 p_time)
|
||||
{
|
||||
if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS))
|
||||
{
|
||||
if (spell->IsChannelActive())
|
||||
{
|
||||
suspendRangedAttackTimer = true;
|
||||
}
|
||||
|
||||
suspendAttackTimer = true;
|
||||
break;
|
||||
}
|
||||
@@ -493,9 +499,12 @@ void Unit::Update(uint32 p_time)
|
||||
}
|
||||
}
|
||||
|
||||
if (int32 ranged_attack = getAttackTimer(RANGED_ATTACK))
|
||||
if (!suspendRangedAttackTimer)
|
||||
{
|
||||
setAttackTimer(RANGED_ATTACK, ranged_attack > 0 ? ranged_attack - (int32) p_time : 0);
|
||||
if (int32 ranged_attack = getAttackTimer(RANGED_ATTACK))
|
||||
{
|
||||
setAttackTimer(RANGED_ATTACK, ranged_attack > 0 ? ranged_attack - (int32)p_time : 0);
|
||||
}
|
||||
}
|
||||
|
||||
// update abilities available only for fraction of time
|
||||
@@ -1109,7 +1118,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
{
|
||||
Player* he = duel_wasMounted ? victim->GetCharmer()->ToPlayer() : victim->ToPlayer();
|
||||
|
||||
ASSERT(he && he->duel);
|
||||
ASSERT_NODEBUGINFO(he && he->duel);
|
||||
|
||||
if (duel_wasMounted) // In this case victim==mount
|
||||
victim->SetHealth(1);
|
||||
@@ -2415,7 +2424,7 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BASE_A
|
||||
DealMeleeDamage(&damageInfo, true);
|
||||
|
||||
DamageInfo dmgInfo(damageInfo);
|
||||
ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage,
|
||||
Unit::ProcDamageAndSpell(damageInfo.attacker, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage,
|
||||
damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo);
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
@@ -5961,15 +5970,15 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo,
|
||||
SendSpellNonMeleeDamageLog(&log);
|
||||
}
|
||||
|
||||
void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo, uint32 procPhase)
|
||||
void Unit::ProcDamageAndSpell(Unit* actor, Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo, uint32 procPhase)
|
||||
{
|
||||
// Not much to do if no flags are set.
|
||||
if (procAttacker)
|
||||
ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase);
|
||||
if (procAttacker && actor)
|
||||
actor->ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase);
|
||||
// Now go on with a victim's events'n'auras
|
||||
// Not much to do if no flags are set or there is no victim
|
||||
if (victim && victim->IsAlive() && procVictim)
|
||||
victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase);
|
||||
victim->ProcDamageAndSpellFor(true, actor, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo, procPhase);
|
||||
}
|
||||
|
||||
void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
|
||||
@@ -6151,7 +6160,7 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
|
||||
}
|
||||
|
||||
//victim may be nullptr
|
||||
bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
|
||||
bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc /*= nullptr*/)
|
||||
{
|
||||
SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
|
||||
uint32 effIndex = triggeredByAura->GetEffIndex();
|
||||
@@ -7077,7 +7086,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
case 28719:
|
||||
{
|
||||
// mana back
|
||||
basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
|
||||
basepoints0 = int32(CalculatePct(spellProc->GetPowerCost(), 30));
|
||||
target = this;
|
||||
triggered_spell_id = 28742;
|
||||
break;
|
||||
@@ -16009,7 +16018,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
case SPELL_AURA_DUMMY:
|
||||
{
|
||||
LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id {} (triggered by {} dummy aura of spell {})", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
|
||||
if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown))
|
||||
if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown, procSpell))
|
||||
takeCharges = true;
|
||||
break;
|
||||
}
|
||||
@@ -17406,15 +17415,15 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
|
||||
if (killer && (killer->IsPet() || killer->IsTotem()))
|
||||
if (Unit* owner = killer->GetOwner())
|
||||
{
|
||||
owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
Unit::ProcDamageAndSpell(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature());
|
||||
}
|
||||
|
||||
if (killer != victim && !victim->IsCritter())
|
||||
killer->ProcDamageAndSpell(victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
Unit::ProcDamageAndSpell(killer, victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
|
||||
// Proc auras on death - must be before aura/combat remove
|
||||
victim->ProcDamageAndSpell(nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
Unit::ProcDamageAndSpell(victim, nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell);
|
||||
|
||||
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
|
||||
// and before Spirit of Redemption as it also removes auras
|
||||
@@ -18750,6 +18759,7 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
|
||||
player->SetCanFly(true, true);
|
||||
|
||||
sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
|
||||
player->SetCanKnockback(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20843,3 +20853,14 @@ bool Unit::IsInDisallowedMountForm() const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Unit::GetDebugInfo() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << WorldObject::GetDebugInfo() << "\n"
|
||||
<< std::boolalpha
|
||||
<< "AliveState: " << IsAlive()
|
||||
<< " UnitMovementFlags: " << GetUnitMovementFlags() << " ExtraUnitMovementFlags: " << GetExtraUnitMovementFlags()
|
||||
<< " Class: " << std::to_string(getClass());
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
@@ -1525,7 +1525,7 @@ public:
|
||||
static void Kill(Unit* killer, Unit* victim, bool durabilityLoss = true, WeaponAttackType attackType = BASE_ATTACK, SpellInfo const* spellProto = nullptr, Spell const* spell = nullptr);
|
||||
static int32 DealHeal(Unit* healer, Unit* victim, uint32 addhealth);
|
||||
|
||||
void ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/);
|
||||
static void ProcDamageAndSpell(Unit* actor, Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType = BASE_ATTACK, SpellInfo const* procSpellInfo = nullptr, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/);
|
||||
void ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura = nullptr, int8 procAuraEffectIndex = -1, Spell const* procSpell = nullptr, DamageInfo* damageInfo = nullptr, HealInfo* healInfo = nullptr, uint32 procPhase = 2 /*PROC_SPELL_PHASE_HIT*/);
|
||||
|
||||
void GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo);
|
||||
@@ -2431,6 +2431,8 @@ public:
|
||||
virtual bool SetCannotReachTarget(bool cannotReach, bool isChase = true);
|
||||
[[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; }
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
explicit Unit (bool isWorldObject);
|
||||
|
||||
@@ -2515,7 +2517,7 @@ protected:
|
||||
|
||||
private:
|
||||
bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo);
|
||||
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
|
||||
bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, Spell const* spellProc = nullptr);
|
||||
bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool* handled);
|
||||
bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, uint32 procPhase, ProcEventInfo& eventInfo);
|
||||
bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown);
|
||||
|
||||
Reference in New Issue
Block a user