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:
QAston
2011-09-15 17:44:03 +02:00
parent af05915b9e
commit e07535c3e3
6 changed files with 166 additions and 5 deletions
+1
View File
@@ -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
+6 -4
View File
@@ -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)
+126
View File
@@ -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())
+6
View File
@@ -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);
+4 -1
View File
@@ -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;