diff options
author | QAston <qaston@gmail.com> | 2011-09-15 17:44:03 +0200 |
---|---|---|
committer | QAston <qaston@gmail.com> | 2011-09-15 17:44:03 +0200 |
commit | e07535c3e3b9df05c894557b675ccf95bf7a622b (patch) | |
tree | 69af39ede1eb45c822abd0a293b281192208962b /src/server | |
parent | af05915b9e36497eda8f2f061c29ffee0c8042b6 (diff) |
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).
Diffstat (limited to 'src/server')
-rwxr-xr-x | src/server/game/DataStores/DBCEnums.h | 1 | ||||
-rwxr-xr-x | src/server/game/DataStores/DBCStructure.h | 10 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 126 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 6 | ||||
-rwxr-xr-x | src/server/game/Reputation/ReputationMgr.cpp | 23 | ||||
-rwxr-xr-x | src/server/game/Reputation/ReputationMgr.h | 5 |
6 files changed, 166 insertions, 5 deletions
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 0a4c6b70b9f..dcdc2b2ea0a 100755 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -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 diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index ff91964230a..431e803fa87 100755 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -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) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 29df2c20442..01410c19f99 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 19fa017e37c..a1566f14434 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -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); diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 0aaa3da0a38..a82764c62f9 100755 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -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); diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h index bb22f46585a..59ec826f0c5 100755 --- a/src/server/game/Reputation/ReputationMgr.h +++ b/src/server/game/Reputation/ReputationMgr.h @@ -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; |