Core/Entities: Add new functions: Unit::GetReactionTo and Unit::GetFactionReactionTo for more direct reaction checks than Unit::IsFriendly/HostileTo (those functions have many duplicated code and have many checks unrelated to unit reaction).
This commit is contained in:
@@ -307,6 +307,7 @@ enum FactionTemplateFlags
|
||||
{
|
||||
FACTION_TEMPLATE_FLAG_PVP = 0x00000800, // flagged for PvP
|
||||
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats
|
||||
FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT= 0x00002000,
|
||||
};
|
||||
|
||||
enum FactionMasks
|
||||
|
||||
@@ -870,6 +870,12 @@ struct FactionEntry
|
||||
// 39 string flags
|
||||
//char* description[16]; // 40-55 m_description_lang
|
||||
// 56 string flags
|
||||
|
||||
// helpers
|
||||
bool CanHaveReputation() const
|
||||
{
|
||||
return reputationListID >=0;
|
||||
}
|
||||
};
|
||||
|
||||
#define MAX_FACTION_RELATIONS 4
|
||||
@@ -889,8 +895,6 @@ struct FactionTemplateEntry
|
||||
// helpers
|
||||
bool IsFriendlyTo(FactionTemplateEntry const& entry) const
|
||||
{
|
||||
if (ID == entry.ID)
|
||||
return true;
|
||||
if (entry.faction)
|
||||
{
|
||||
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
|
||||
@@ -904,8 +908,6 @@ struct FactionTemplateEntry
|
||||
}
|
||||
bool IsHostileTo(FactionTemplateEntry const& entry) const
|
||||
{
|
||||
if (ID == entry.ID)
|
||||
return false;
|
||||
if (entry.faction)
|
||||
{
|
||||
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
|
||||
|
||||
@@ -9239,6 +9239,122 @@ FactionTemplateEntry const* Unit::getFactionTemplateEntry() const
|
||||
return entry;
|
||||
}
|
||||
|
||||
ReputationRank Unit::GetReactionTo(Unit const* target) const
|
||||
{
|
||||
// always friendly to self
|
||||
if (this == target)
|
||||
return REP_FRIENDLY;
|
||||
|
||||
// always friendly to charmer or owner
|
||||
if (GetCharmerOrOwnerOrSelf() == target->GetCharmerOrOwnerOrSelf())
|
||||
return REP_FRIENDLY;
|
||||
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
|
||||
{
|
||||
if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
|
||||
{
|
||||
Player const* selfPlayerOwner = GetAffectingPlayer();
|
||||
Player const* targetPlayerOwner = target->GetAffectingPlayer();
|
||||
|
||||
if (selfPlayerOwner && targetPlayerOwner)
|
||||
{
|
||||
// always friendly to other unit controlled by player, or to the player himself
|
||||
if (selfPlayerOwner == targetPlayerOwner)
|
||||
return REP_FRIENDLY;
|
||||
|
||||
// duel - always hostile to opponent
|
||||
if (selfPlayerOwner->duel && selfPlayerOwner->duel->opponent == targetPlayerOwner && selfPlayerOwner->duel->startTime != 0)
|
||||
return REP_HOSTILE;
|
||||
|
||||
// same group - checks dependant only on our faction - skip FFA_PVP for example
|
||||
if (selfPlayerOwner->IsInRaidWith(targetPlayerOwner))
|
||||
return GetFactionReactionTo(getFactionTemplateEntry(), target);
|
||||
}
|
||||
|
||||
// check FFA_PVP
|
||||
if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP
|
||||
&& target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP)
|
||||
return REP_HOSTILE;
|
||||
|
||||
if (selfPlayerOwner)
|
||||
{
|
||||
if (FactionTemplateEntry const* targetFactionTemplateEntry = target->getFactionTemplateEntry())
|
||||
{
|
||||
if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
|
||||
return *repRank;
|
||||
if (!selfPlayerOwner->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_IGNORE_REPUTATION))
|
||||
{
|
||||
if (FactionEntry const* targetFactionEntry = sFactionStore.LookupEntry(targetFactionTemplateEntry->faction))
|
||||
{
|
||||
if (targetFactionEntry->CanHaveReputation())
|
||||
{
|
||||
// check contested flags
|
||||
if (targetFactionTemplateEntry->factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD
|
||||
&& selfPlayerOwner->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
|
||||
return REP_HOSTILE;
|
||||
|
||||
// if faction have reputation then hostile state dependent only from at_war state
|
||||
if (selfPlayerOwner->GetReputationMgr().IsAtWar(targetFactionEntry))
|
||||
return REP_HOSTILE;
|
||||
return REP_FRIENDLY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// do checks dependant only on our faction
|
||||
return GetFactionReactionTo(getFactionTemplateEntry(), target);
|
||||
}
|
||||
|
||||
ReputationRank Unit::GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, Unit const* target)
|
||||
{
|
||||
// always neutral when no template entry found
|
||||
if (!factionTemplateEntry)
|
||||
return REP_NEUTRAL;
|
||||
|
||||
FactionTemplateEntry const* targetFactionTemplateEntry = target->getFactionTemplateEntry();
|
||||
if (!targetFactionTemplateEntry)
|
||||
return REP_NEUTRAL;
|
||||
|
||||
if (Player const* targetPlayerOwner = target->GetAffectingPlayer())
|
||||
{
|
||||
// check contested flags
|
||||
if (factionTemplateEntry->factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD
|
||||
&& targetPlayerOwner->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
|
||||
return REP_HOSTILE;
|
||||
if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry))
|
||||
return *repRank;
|
||||
if (!target->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_IGNORE_REPUTATION))
|
||||
{
|
||||
if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction))
|
||||
{
|
||||
if (factionEntry->CanHaveReputation())
|
||||
{
|
||||
// CvP case - check reputation, don't allow state higher than neutral when at war
|
||||
ReputationRank repRank = targetPlayerOwner->GetReputationMgr().GetRank(factionEntry);
|
||||
if (targetPlayerOwner->GetReputationMgr().IsAtWar(factionEntry))
|
||||
repRank = std::min(REP_NEUTRAL, repRank);
|
||||
return repRank;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// common faction based check
|
||||
if (factionTemplateEntry->IsHostileTo(*targetFactionTemplateEntry))
|
||||
return REP_HOSTILE;
|
||||
if (factionTemplateEntry->IsFriendlyTo(*targetFactionTemplateEntry))
|
||||
return REP_FRIENDLY;
|
||||
if (targetFactionTemplateEntry->IsFriendlyTo(*factionTemplateEntry))
|
||||
return REP_FRIENDLY;
|
||||
if (factionTemplateEntry->factionFlags & FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT)
|
||||
return REP_HOSTILE;
|
||||
// neutral by default
|
||||
return REP_NEUTRAL;
|
||||
}
|
||||
|
||||
bool Unit::IsHostileTo(Unit const* unit) const
|
||||
{
|
||||
if (!unit)
|
||||
@@ -9797,6 +9913,16 @@ Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() const
|
||||
return GetTypeId() == TYPEID_PLAYER ? (Player*)this : NULL;
|
||||
}
|
||||
|
||||
Player* Unit::GetAffectingPlayer() const
|
||||
{
|
||||
if (!GetCharmerOrOwnerGUID())
|
||||
return GetTypeId() == TYPEID_PLAYER ? (Player*)this : NULL;
|
||||
|
||||
if (Unit* owner = GetCharmerOrOwner())
|
||||
return owner->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Minion *Unit::GetFirstMinion() const
|
||||
{
|
||||
if (uint64 pet_guid = GetMinionGUID())
|
||||
|
||||
@@ -611,6 +611,7 @@ enum UnitFlags2
|
||||
{
|
||||
UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
|
||||
UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip)
|
||||
UNIT_FLAG2_IGNORE_REPUTATION = 0x00000004,
|
||||
UNIT_FLAG2_COMPREHEND_LANG = 0x00000008,
|
||||
UNIT_FLAG2_MIRROR_IMAGE = 0x00000010,
|
||||
UNIT_FLAG2_FORCE_MOVE = 0x00000040,
|
||||
@@ -1386,6 +1387,10 @@ class Unit : public WorldObject
|
||||
uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); }
|
||||
void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); }
|
||||
FactionTemplateEntry const* getFactionTemplateEntry() const;
|
||||
|
||||
ReputationRank GetReactionTo(Unit const* target) const;
|
||||
ReputationRank static GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, Unit const* target);
|
||||
|
||||
bool IsHostileTo(Unit const* unit) const;
|
||||
bool IsHostileToPlayers() const;
|
||||
bool IsFriendlyTo(Unit const* unit) const;
|
||||
@@ -1662,6 +1667,7 @@ class Unit : public WorldObject
|
||||
return (Unit*)this;
|
||||
}
|
||||
Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
|
||||
Player* GetAffectingPlayer() const;
|
||||
|
||||
void SetMinion(Minion *minion, bool apply);
|
||||
void GetAllMinionsByEntry(std::list<Creature*>& Minions, uint32 entry);
|
||||
|
||||
@@ -39,6 +39,29 @@ ReputationRank ReputationMgr::ReputationToRank(int32 standing)
|
||||
return MIN_REPUTATION_RANK;
|
||||
}
|
||||
|
||||
bool ReputationMgr::IsAtWar(uint32 faction_id) const
|
||||
{
|
||||
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
|
||||
|
||||
if (!factionEntry)
|
||||
{
|
||||
sLog->outError("ReputationMgr::IsAtWar: Can't get AtWat flag of %s for unknown faction (faction id) #%u.", m_player->GetName(), faction_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return IsAtWar(factionEntry);
|
||||
}
|
||||
|
||||
bool ReputationMgr::IsAtWar(FactionEntry const* factionEntry) const
|
||||
{
|
||||
if (!factionEntry)
|
||||
return false;
|
||||
|
||||
if (FactionState const* factionState = GetState(factionEntry))
|
||||
return (factionState->Flags & FACTION_FLAG_AT_WAR);
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 ReputationMgr::GetReputation(uint32 faction_id) const
|
||||
{
|
||||
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
|
||||
|
||||
@@ -86,7 +86,7 @@ class ReputationMgr
|
||||
|
||||
FactionState const* GetState(FactionEntry const* factionEntry) const
|
||||
{
|
||||
return factionEntry->reputationListID >= 0 ? GetState(factionEntry->reputationListID) : NULL;
|
||||
return factionEntry->CanHaveReputation() ? GetState(factionEntry->reputationListID) : NULL;
|
||||
}
|
||||
|
||||
FactionState const* GetState(RepListID id) const
|
||||
@@ -95,6 +95,9 @@ class ReputationMgr
|
||||
return repItr != m_factions.end() ? &repItr->second : NULL;
|
||||
}
|
||||
|
||||
bool IsAtWar(uint32 faction_id) const;
|
||||
bool IsAtWar(FactionEntry const* factionEntry) const;
|
||||
|
||||
int32 GetReputation(uint32 faction_id) const;
|
||||
int32 GetReputation(FactionEntry const* factionEntry) const;
|
||||
int32 GetBaseReputation(FactionEntry const* factionEntry) const;
|
||||
|
||||
Reference in New Issue
Block a user