Refactor the areatrigger_teleport to use condition system.
- this commit is paired with a world database update.
This commit is contained in:
parent
983ea0c038
commit
42dbd2756c
@ -274,7 +274,7 @@ bool ChatHandler::HandleTriggerCommand(char* args)
|
|||||||
|
|
||||||
AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id);
|
AreaTrigger const* at = sObjectMgr.GetAreaTrigger(atEntry->id);
|
||||||
if (at)
|
if (at)
|
||||||
{ PSendSysMessage(LANG_TRIGGER_REQ_LEVEL, at->requiredLevel); }
|
{ PSendSysMessage(LANG_TRIGGER_CONDITION, at->condition); }
|
||||||
|
|
||||||
if (uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger(atEntry->id))
|
if (uint32 quest_id = sObjectMgr.GetQuestForAreaTrigger(atEntry->id))
|
||||||
{
|
{
|
||||||
@ -282,25 +282,6 @@ bool ChatHandler::HandleTriggerCommand(char* args)
|
|||||||
ShowQuestListHelper(quest_id, loc_idx, pl);
|
ShowQuestListHelper(quest_id, loc_idx, pl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (at)
|
|
||||||
{
|
|
||||||
if (at->requiredItem || at->requiredItem2)
|
|
||||||
{
|
|
||||||
SendSysMessage(LANG_TRIGGER_REQ_ITEMS);
|
|
||||||
|
|
||||||
if (at->requiredItem)
|
|
||||||
{ ShowItemListHelper(at->requiredItem, loc_idx, pl); }
|
|
||||||
if (at->requiredItem2)
|
|
||||||
{ ShowItemListHelper(at->requiredItem2, loc_idx, pl); }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (at->requiredQuest)
|
|
||||||
{
|
|
||||||
SendSysMessage(LANG_TRIGGER_REQ_QUEST);
|
|
||||||
ShowQuestListHelper(at->requiredQuest, loc_idx, pl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +131,38 @@ bool operator < (const HonorStanding& lhs, const HonorStanding& rhs)
|
|||||||
return lhs.honorPoints > rhs.honorPoints;
|
return lhs.honorPoints > rhs.honorPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO improve the algorithm based on conditions
|
||||||
|
bool AreaTrigger::IsLessOrEqualThan(AreaTrigger const* l) const // Expected to have same map
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(target_mapId == l->target_mapId);
|
||||||
|
if (!condition)
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
if (!l->condition)
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
if (condition == l->condition)
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
// most conditions for AT have level requirement
|
||||||
|
// let's order by the least restrictive
|
||||||
|
const PlayerCondition* pCond1 = sConditionStorage.LookupEntry<PlayerCondition>(condition);
|
||||||
|
const PlayerCondition* pCond2 = sConditionStorage.LookupEntry<PlayerCondition>(l->condition);
|
||||||
|
if (pCond1->m_condition == CONDITION_LEVEL && pCond2->m_condition == CONDITION_LEVEL)
|
||||||
|
{
|
||||||
|
return (pCond1->m_value1 <= pCond2->m_value1);
|
||||||
|
}
|
||||||
|
if (pCond1->m_condition == CONDITION_LEVEL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pCond2->m_condition == CONDITION_LEVEL)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectMgr::ObjectMgr() :
|
ObjectMgr::ObjectMgr() :
|
||||||
m_AuctionIds("Auction ids"),
|
m_AuctionIds("Auction ids"),
|
||||||
m_GuildIds("Guild ids"),
|
m_GuildIds("Guild ids"),
|
||||||
@ -5065,8 +5097,8 @@ void ObjectMgr::LoadAreaTriggerTeleports()
|
|||||||
|
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9
|
// 0 1 2 3 4 5 6 7 8 9
|
||||||
QueryResult* result = WorldDatabase.Query("SELECT id, required_level, required_item, required_item2, required_quest_done, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
|
QueryResult* result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation, condition_id FROM areatrigger_teleport");
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
BarGoLink bar(1);
|
BarGoLink bar(1);
|
||||||
@ -5090,15 +5122,12 @@ void ObjectMgr::LoadAreaTriggerTeleports()
|
|||||||
|
|
||||||
AreaTrigger at;
|
AreaTrigger at;
|
||||||
|
|
||||||
at.requiredLevel = fields[1].GetUInt8();
|
at.target_mapId = fields[1].GetUInt32();
|
||||||
at.requiredItem = fields[2].GetUInt32();
|
at.target_X = fields[2].GetFloat();
|
||||||
at.requiredItem2 = fields[3].GetUInt32();
|
at.target_Y = fields[3].GetFloat();
|
||||||
at.requiredQuest = fields[4].GetUInt32();
|
at.target_Z = fields[4].GetFloat();
|
||||||
at.target_mapId = fields[5].GetUInt32();
|
at.target_Orientation = fields[5].GetFloat();
|
||||||
at.target_X = fields[6].GetFloat();
|
at.condition = fields[6].GetUInt16();
|
||||||
at.target_Y = fields[7].GetFloat();
|
|
||||||
at.target_Z = fields[8].GetFloat();
|
|
||||||
at.target_Orientation = fields[9].GetFloat();
|
|
||||||
|
|
||||||
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID);
|
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID);
|
||||||
if (!atEntry)
|
if (!atEntry)
|
||||||
@ -5107,36 +5136,6 @@ void ObjectMgr::LoadAreaTriggerTeleports()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (at.requiredItem)
|
|
||||||
{
|
|
||||||
ItemPrototype const* pProto = GetItemPrototype(at.requiredItem);
|
|
||||||
if (!pProto)
|
|
||||||
{
|
|
||||||
sLog.outError("Table `areatrigger_teleport` has nonexistent key item %u for trigger %u, removing key requirement.", at.requiredItem, Trigger_ID);
|
|
||||||
at.requiredItem = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (at.requiredItem2)
|
|
||||||
{
|
|
||||||
ItemPrototype const* pProto = GetItemPrototype(at.requiredItem2);
|
|
||||||
if (!pProto)
|
|
||||||
{
|
|
||||||
sLog.outError("Table `areatrigger_teleport` has nonexistent second key item %u for trigger %u, remove key requirement.", at.requiredItem2, Trigger_ID);
|
|
||||||
at.requiredItem2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (at.requiredQuest)
|
|
||||||
{
|
|
||||||
QuestMap::iterator qReqItr = mQuestTemplates.find(at.requiredQuest);
|
|
||||||
if (qReqItr == mQuestTemplates.end())
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("Table `areatrigger_teleport` has nonexistent required quest %u for trigger %u, remove quest done requirement.", at.requiredQuest, Trigger_ID);
|
|
||||||
at.requiredQuest = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
|
MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
|
||||||
if (!mapEntry)
|
if (!mapEntry)
|
||||||
{
|
{
|
||||||
@ -5150,6 +5149,12 @@ void ObjectMgr::LoadAreaTriggerTeleports()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (at.condition && !sConditionStorage.LookupEntry<PlayerCondition>(at.condition))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Table `areatrigger_teleport` has nonexistent condition (ID:%u) for Area trigger (ID:%u).", at.condition, Trigger_ID);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
mAreaTriggers[Trigger_ID] = at;
|
mAreaTriggers[Trigger_ID] = at;
|
||||||
}
|
}
|
||||||
while (result->NextRow());
|
while (result->NextRow());
|
||||||
@ -6870,10 +6875,10 @@ void ObjectMgr::LoadFishingBaseSkillLevel()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if a player meets condition conditionId
|
// Check if a player meets condition conditionId
|
||||||
bool ObjectMgr::IsPlayerMeetToCondition(uint16 conditionId, Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const
|
bool ObjectMgr::IsPlayerMeetToCondition(uint16 conditionId, Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType, ConditionEntry* entry) const
|
||||||
{
|
{
|
||||||
if (const PlayerCondition* condition = sConditionStorage.LookupEntry<PlayerCondition>(conditionId))
|
if (const PlayerCondition* condition = sConditionStorage.LookupEntry<PlayerCondition>(conditionId))
|
||||||
{ return condition->Meets(pPlayer, map, source, conditionSourceType); }
|
{ return condition->Meets(pPlayer, map, source, conditionSourceType, entry); }
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -6891,15 +6896,23 @@ char const* conditionSourceToStr[] =
|
|||||||
"vendor's item check",
|
"vendor's item check",
|
||||||
"spell_area check",
|
"spell_area check",
|
||||||
"npc_spellclick_spells check", // Unused. For 3.x and later.
|
"npc_spellclick_spells check", // Unused. For 3.x and later.
|
||||||
"DBScript engine"
|
"DBScript engine",
|
||||||
|
"area trigger check"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Checks if player meets the condition
|
// Checks if player meets the condition
|
||||||
bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const
|
bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject const* source, ConditionSource conditionSourceType, ConditionEntry* entry) const
|
||||||
{
|
{
|
||||||
DEBUG_LOG("Condition-System: Check condition %u, type %i - called from %s with params plr: %s, map %i, src %s",
|
DEBUG_LOG("Condition-System: Check condition %u, type %i - called from %s with params plr: %s, map %i, src %s",
|
||||||
m_entry, m_condition, conditionSourceToStr[conditionSourceType], player ? player->GetGuidStr().c_str() : "<NULL>", map ? map->GetId() : -1, source ? source->GetGuidStr().c_str() : "<NULL>");
|
m_entry, m_condition, conditionSourceToStr[conditionSourceType], player ? player->GetGuidStr().c_str() : "<NULL>", map ? map->GetId() : -1, source ? source->GetGuidStr().c_str() : "<NULL>");
|
||||||
|
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
entry->type = m_condition;
|
||||||
|
entry->param1 = m_value1;
|
||||||
|
entry->param2 = m_value2;
|
||||||
|
}
|
||||||
|
|
||||||
if (!CheckParamRequirements(player, map, source, conditionSourceType))
|
if (!CheckParamRequirements(player, map, source, conditionSourceType))
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
|
||||||
@ -6907,13 +6920,13 @@ bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject co
|
|||||||
{
|
{
|
||||||
case CONDITION_NOT:
|
case CONDITION_NOT:
|
||||||
// Checked on load
|
// Checked on load
|
||||||
return !sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType);
|
return !sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType, entry);
|
||||||
case CONDITION_OR:
|
case CONDITION_OR:
|
||||||
// Checked on load
|
// Checked on load
|
||||||
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType) || sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player, map, source, conditionSourceType);
|
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType, entry) || sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player, map, source, conditionSourceType, entry);
|
||||||
case CONDITION_AND:
|
case CONDITION_AND:
|
||||||
// Checked on load
|
// Checked on load
|
||||||
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType) && sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player, map, source, conditionSourceType);
|
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player, map, source, conditionSourceType, entry) && sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player, map, source, conditionSourceType, entry);
|
||||||
case CONDITION_NONE:
|
case CONDITION_NONE:
|
||||||
return true; // empty condition, always met
|
return true; // empty condition, always met
|
||||||
case CONDITION_AURA:
|
case CONDITION_AURA:
|
||||||
@ -7168,6 +7181,15 @@ bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject co
|
|||||||
}
|
}
|
||||||
return pGo;
|
return pGo;
|
||||||
}
|
}
|
||||||
|
case CONDITION_PVP_RANK:
|
||||||
|
{
|
||||||
|
switch (m_value2)
|
||||||
|
{
|
||||||
|
case 0: return player->GetHonorRankInfo().rank == m_value1;
|
||||||
|
case 1: return player->GetHonorRankInfo().rank >= m_value1;
|
||||||
|
case 2: return player->GetHonorRankInfo().rank <= m_value1;
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -7238,6 +7260,14 @@ bool PlayerCondition::CheckParamRequirements(Player const* pPlayer, Map const* m
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CONDITION_PVP_RANK:
|
||||||
|
if (!pPlayer)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CONDITION %u type %u used with bad parameters, called from %s, used with %s, map %i, src %s",
|
||||||
|
m_entry, m_condition, conditionSourceToStr[conditionSourceType], pPlayer ? pPlayer->GetGuidStr().c_str() : "NULL", map ? map->GetId() : -1, source ? source->GetGuidStr().c_str() : "NULL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!pPlayer)
|
if (!pPlayer)
|
||||||
{
|
{
|
||||||
@ -7600,6 +7630,15 @@ bool PlayerCondition::IsValid(uint16 entry, ConditionType condition, uint32 valu
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CONDITION_PVP_RANK:
|
||||||
|
{
|
||||||
|
if (value2 > 2)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("PVP rank condition (entry %u, type %u) has invalid argument %u (must be 0..2), skipped", entry, condition, value2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CONDITION_NONE:
|
case CONDITION_NONE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -66,10 +66,7 @@ typedef UNORDERED_MAP<uint32, GameTele > GameTeleMap;
|
|||||||
|
|
||||||
struct AreaTrigger
|
struct AreaTrigger
|
||||||
{
|
{
|
||||||
uint8 requiredLevel;
|
uint32 condition;
|
||||||
uint32 requiredItem;
|
|
||||||
uint32 requiredItem2;
|
|
||||||
uint32 requiredQuest;
|
|
||||||
uint32 target_mapId;
|
uint32 target_mapId;
|
||||||
float target_X;
|
float target_X;
|
||||||
float target_Y;
|
float target_Y;
|
||||||
@ -79,15 +76,10 @@ struct AreaTrigger
|
|||||||
// Operators
|
// Operators
|
||||||
bool IsMinimal() const
|
bool IsMinimal() const
|
||||||
{
|
{
|
||||||
return requiredLevel == 0 && requiredItem == 0 && requiredItem2 == 0 && requiredQuest == 0;
|
return condition == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLessOrEqualThan(AreaTrigger const* l) const // Expected to have same map
|
bool IsLessOrEqualThan(AreaTrigger const* l) const;
|
||||||
{
|
|
||||||
MANGOS_ASSERT(target_mapId == l->target_mapId);
|
|
||||||
return requiredLevel <= l->requiredLevel && requiredItem <= l->requiredItem && requiredItem2 <= l->requiredItem2
|
|
||||||
&& requiredQuest <= l->requiredQuest;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map < uint32/*player guid*/, uint32/*instance*/ > CellCorpseSet;
|
typedef std::map < uint32/*player guid*/, uint32/*instance*/ > CellCorpseSet;
|
||||||
@ -330,6 +322,7 @@ enum ConditionType
|
|||||||
// value2: if != 0 only consider players in range of this value
|
// value2: if != 0 only consider players in range of this value
|
||||||
CONDITION_CREATURE_IN_RANGE = 37, // value1: creature entry; value2: range; returns only alive creatures
|
CONDITION_CREATURE_IN_RANGE = 37, // value1: creature entry; value2: range; returns only alive creatures
|
||||||
CONDITION_GAMEOBJECT_IN_RANGE = 38, // value1: gameobject entry; value2: range
|
CONDITION_GAMEOBJECT_IN_RANGE = 38, // value1: gameobject entry; value2: range
|
||||||
|
CONDITION_PVP_RANK = 39, // value1: rank; value2: 0 = eq, 1 = equal or higher, 2 = equal or less
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ConditionSource // From where was the condition called?
|
enum ConditionSource // From where was the condition called?
|
||||||
@ -344,10 +337,20 @@ enum ConditionSource // From where was th
|
|||||||
CONDITION_FROM_SPELL_AREA = 7, // Used to check a condition from spell_area table
|
CONDITION_FROM_SPELL_AREA = 7, // Used to check a condition from spell_area table
|
||||||
CONDITION_FROM_RESERVED_1 = 8, // reserved for 3.x and later
|
CONDITION_FROM_RESERVED_1 = 8, // reserved for 3.x and later
|
||||||
CONDITION_FROM_DBSCRIPTS = 9, // Used to check a condition from DB Scripts Engine
|
CONDITION_FROM_DBSCRIPTS = 9, // Used to check a condition from DB Scripts Engine
|
||||||
|
CONDITION_AREA_TRIGGER = 10, // Used to check a condition from CMSG_AREATRIGGER
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConditionEntry
|
||||||
|
{
|
||||||
|
ConditionEntry() : type(CONDITION_NONE), param1(0), param2(0) {}
|
||||||
|
ConditionType type;
|
||||||
|
uint32 param1;
|
||||||
|
uint32 param2;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerCondition
|
class PlayerCondition
|
||||||
{
|
{
|
||||||
|
friend struct AreaTrigger;
|
||||||
public:
|
public:
|
||||||
// Default constructor, required for SQL Storage (Will give errors if used elsewise)
|
// Default constructor, required for SQL Storage (Will give errors if used elsewise)
|
||||||
PlayerCondition() : m_entry(0), m_condition(CONDITION_AND), m_value1(0), m_value2(0) {}
|
PlayerCondition() : m_entry(0), m_condition(CONDITION_AND), m_value1(0), m_value2(0) {}
|
||||||
@ -365,7 +368,11 @@ class PlayerCondition
|
|||||||
static bool CanBeUsedWithoutPlayer(uint16 entry);
|
static bool CanBeUsedWithoutPlayer(uint16 entry);
|
||||||
|
|
||||||
// Checks if the player meets the condition
|
// Checks if the player meets the condition
|
||||||
bool Meets(Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const;
|
// if the param entry is not null, it will be filled at return as follows:
|
||||||
|
// - if function fails, entry will contain the first faulty condition
|
||||||
|
// - if function succeeds, entry will contain the last condition checked (if chained)
|
||||||
|
// entry is only useful on failure case
|
||||||
|
bool Meets(Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType, ConditionEntry* entry = NULL) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckParamRequirements(Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const;
|
bool CheckParamRequirements(Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const;
|
||||||
@ -987,7 +994,7 @@ class ObjectMgr
|
|||||||
LocaleConstant GetLocaleForIndex(int i);
|
LocaleConstant GetLocaleForIndex(int i);
|
||||||
|
|
||||||
// Check if a player meets condition conditionId
|
// Check if a player meets condition conditionId
|
||||||
bool IsPlayerMeetToCondition(uint16 conditionId, Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType) const;
|
bool IsPlayerMeetToCondition(uint16 conditionId, Player const* pPlayer, Map const* map, WorldObject const* source, ConditionSource conditionSourceType, ConditionEntry* entry = NULL) const;
|
||||||
|
|
||||||
GameTele const* GetGameTele(uint32 id) const
|
GameTele const* GetGameTele(uint32 id) const
|
||||||
{
|
{
|
||||||
|
@ -17678,15 +17678,27 @@ void Player::SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockS
|
|||||||
|
|
||||||
switch (lockStatus)
|
switch (lockStatus)
|
||||||
{
|
{
|
||||||
case AREA_LOCKSTATUS_TOO_LOW_LEVEL:
|
case AREA_LOCKSTATUS_LEVEL_TOO_LOW:
|
||||||
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement);
|
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MINREQUIRED), miscRequirement);
|
||||||
break;
|
break;
|
||||||
|
case AREA_LOCKSTATUS_LEVEL_TOO_HIGH:
|
||||||
|
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MAXREQUIRED), miscRequirement);
|
||||||
|
break;
|
||||||
|
case AREA_LOCKSTATUS_LEVEL_NOT_EQUAL:
|
||||||
|
GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_EQUALREQUIRED), miscRequirement);
|
||||||
|
break;
|
||||||
case AREA_LOCKSTATUS_ZONE_IN_COMBAT:
|
case AREA_LOCKSTATUS_ZONE_IN_COMBAT:
|
||||||
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ZONE_IN_COMBAT);
|
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_ZONE_IN_COMBAT);
|
||||||
break;
|
break;
|
||||||
case AREA_LOCKSTATUS_INSTANCE_IS_FULL:
|
case AREA_LOCKSTATUS_INSTANCE_IS_FULL:
|
||||||
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAX_PLAYERS);
|
GetSession()->SendTransferAborted(mapEntry->MapID, TRANSFER_ABORT_MAX_PLAYERS);
|
||||||
break;
|
break;
|
||||||
|
case AREA_LOCKSTATUS_WRONG_TEAM:
|
||||||
|
if (miscRequirement == 469)
|
||||||
|
GetSession()->SendAreaTriggerMessage("%s", GetSession()->GetMangosString(LANG_WRONG_TEAM_ALLIANCE));
|
||||||
|
else
|
||||||
|
GetSession()->SendAreaTriggerMessage("%s", GetSession()->GetMangosString(LANG_WRONG_TEAM_HORDE));
|
||||||
|
break;
|
||||||
case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED:
|
case AREA_LOCKSTATUS_QUEST_NOT_COMPLETED:
|
||||||
if (mapEntry->IsContinent()) // do not report anything for quest areatrigge
|
if (mapEntry->IsContinent()) // do not report anything for quest areatrigge
|
||||||
{
|
{
|
||||||
@ -17697,7 +17709,7 @@ void Player::SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockS
|
|||||||
break;
|
break;
|
||||||
case AREA_LOCKSTATUS_MISSING_ITEM:
|
case AREA_LOCKSTATUS_MISSING_ITEM:
|
||||||
if (AreaTrigger const* at = sObjectMgr.GetMapEntranceTrigger(mapEntry->MapID))
|
if (AreaTrigger const* at = sObjectMgr.GetMapEntranceTrigger(mapEntry->MapID))
|
||||||
{ GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, sObjectMgr.GetItemPrototype(miscRequirement)->Name1); }
|
{ GetSession()->SendAreaTriggerMessage(GetSession()->GetMangosString(LANG_REQUIRED_ITEM), sObjectMgr.GetItemPrototype(miscRequirement)->Name1); }
|
||||||
break;
|
break;
|
||||||
case AREA_LOCKSTATUS_NOT_ALLOWED:
|
case AREA_LOCKSTATUS_NOT_ALLOWED:
|
||||||
case AREA_LOCKSTATUS_RAID_LOCKED:
|
case AREA_LOCKSTATUS_RAID_LOCKED:
|
||||||
@ -19430,55 +19442,63 @@ AreaLockStatus Player::GetAreaTriggerLockStatus(AreaTrigger const* at, uint32& m
|
|||||||
if (isGameMaster())
|
if (isGameMaster())
|
||||||
{ return AREA_LOCKSTATUS_OK; }
|
{ return AREA_LOCKSTATUS_OK; }
|
||||||
|
|
||||||
// Level Requirements
|
|
||||||
if (getLevel() < at->requiredLevel && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL))
|
|
||||||
{
|
|
||||||
miscRequirement = at->requiredLevel;
|
|
||||||
return AREA_LOCKSTATUS_TOO_LOW_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raid Requirements
|
// Raid Requirements
|
||||||
if (mapEntry->IsRaid() && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID))
|
if (mapEntry->IsRaid() && !sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID))
|
||||||
if (!GetGroup() || !GetGroup()->isRaidGroup())
|
if (!GetGroup() || !GetGroup()->isRaidGroup())
|
||||||
{ return AREA_LOCKSTATUS_RAID_LOCKED; }
|
{ return AREA_LOCKSTATUS_RAID_LOCKED; }
|
||||||
|
|
||||||
// Item Requirements: must have requiredItem OR requiredItem2, report the first one that's missing
|
if (at->condition) //condition validity is checked at startup
|
||||||
if (at->requiredItem)
|
|
||||||
{
|
{
|
||||||
if (!HasItemCount(at->requiredItem, 1) &&
|
ConditionEntry fault;
|
||||||
(!at->requiredItem2 || !HasItemCount(at->requiredItem2, 1)))
|
if (!sObjectMgr.IsPlayerMeetToCondition(at->condition, this, GetMap(),NULL, CONDITION_AREA_TRIGGER, &fault))
|
||||||
{
|
{
|
||||||
miscRequirement = at->requiredItem;
|
switch (fault.type)
|
||||||
return AREA_LOCKSTATUS_MISSING_ITEM;
|
{
|
||||||
|
case CONDITION_LEVEL:
|
||||||
|
{
|
||||||
|
if (sWorld.getConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
miscRequirement = fault.param1;
|
||||||
|
switch (fault.param2)
|
||||||
|
{
|
||||||
|
case 0: { return AREA_LOCKSTATUS_LEVEL_NOT_EQUAL; }
|
||||||
|
case 1: { return AREA_LOCKSTATUS_LEVEL_TOO_HIGH; }
|
||||||
|
case 2: { return AREA_LOCKSTATUS_LEVEL_TOO_LOW; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case CONDITION_ITEM:
|
||||||
|
{
|
||||||
|
miscRequirement = fault.param1;
|
||||||
|
return AREA_LOCKSTATUS_MISSING_ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CONDITION_QUESTREWARDED:
|
||||||
|
{
|
||||||
|
miscRequirement = fault.param1;
|
||||||
|
return AREA_LOCKSTATUS_QUEST_NOT_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CONDITION_TEAM:
|
||||||
|
{
|
||||||
|
miscRequirement = fault.param1;
|
||||||
|
return AREA_LOCKSTATUS_WRONG_TEAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CONDITION_PVP_RANK:
|
||||||
|
{
|
||||||
|
miscRequirement = fault.param1;
|
||||||
|
return AREA_LOCKSTATUS_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return AREA_LOCKSTATUS_UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (at->requiredItem2 && !HasItemCount(at->requiredItem2, 1))
|
|
||||||
{
|
|
||||||
miscRequirement = at->requiredItem2;
|
|
||||||
return AREA_LOCKSTATUS_MISSING_ITEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quest Requirements
|
|
||||||
if (at->requiredQuest && !GetQuestRewardStatus(at->requiredQuest))
|
|
||||||
{
|
|
||||||
miscRequirement = at->requiredQuest;
|
|
||||||
return AREA_LOCKSTATUS_QUEST_NOT_COMPLETED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO remove this hack! change areatrigger_teleport to include conditionID, add condition about PvP rank
|
|
||||||
switch (at->target_mapId)
|
|
||||||
{
|
|
||||||
case 449:
|
|
||||||
if (GetTeam() == HORDE || GetHonorRankInfo().rank < 10)
|
|
||||||
return AREA_LOCKSTATUS_NOT_ALLOWED;
|
|
||||||
break;
|
|
||||||
case 450:
|
|
||||||
if (GetTeam() == ALLIANCE || GetHonorRankInfo().rank < 10)
|
|
||||||
return AREA_LOCKSTATUS_NOT_ALLOWED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the map is not created, assume it is possible to enter it.
|
// If the map is not created, assume it is possible to enter it.
|
||||||
DungeonPersistentState* state = GetBoundInstanceSaveForSelfOrGroup(at->target_mapId);
|
DungeonPersistentState* state = GetBoundInstanceSaveForSelfOrGroup(at->target_mapId);
|
||||||
|
@ -2548,15 +2548,17 @@ enum AreaLockStatus
|
|||||||
{
|
{
|
||||||
AREA_LOCKSTATUS_OK = 0,
|
AREA_LOCKSTATUS_OK = 0,
|
||||||
AREA_LOCKSTATUS_UNKNOWN_ERROR = 1,
|
AREA_LOCKSTATUS_UNKNOWN_ERROR = 1,
|
||||||
AREA_LOCKSTATUS_TOO_LOW_LEVEL = 2,
|
AREA_LOCKSTATUS_LEVEL_NOT_EQUAL = 2,
|
||||||
AREA_LOCKSTATUS_TOO_HIGH_LEVEL = 3,
|
AREA_LOCKSTATUS_LEVEL_TOO_LOW = 3,
|
||||||
AREA_LOCKSTATUS_RAID_LOCKED = 4,
|
AREA_LOCKSTATUS_LEVEL_TOO_HIGH = 4,
|
||||||
AREA_LOCKSTATUS_QUEST_NOT_COMPLETED = 5,
|
AREA_LOCKSTATUS_RAID_LOCKED = 5,
|
||||||
AREA_LOCKSTATUS_MISSING_ITEM = 6,
|
AREA_LOCKSTATUS_QUEST_NOT_COMPLETED = 6,
|
||||||
AREA_LOCKSTATUS_ZONE_IN_COMBAT = 7,
|
AREA_LOCKSTATUS_MISSING_ITEM = 7,
|
||||||
AREA_LOCKSTATUS_INSTANCE_IS_FULL = 8,
|
AREA_LOCKSTATUS_ZONE_IN_COMBAT = 8,
|
||||||
AREA_LOCKSTATUS_NOT_ALLOWED = 9,
|
AREA_LOCKSTATUS_INSTANCE_IS_FULL = 9,
|
||||||
AREA_LOCKSTATUS_HAS_BIND = 10,
|
AREA_LOCKSTATUS_NOT_ALLOWED = 10,
|
||||||
|
AREA_LOCKSTATUS_HAS_BIND = 11,
|
||||||
|
AREA_LOCKSTATUS_WRONG_TEAM = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TrackedAuraType
|
enum TrackedAuraType
|
||||||
|
@ -79,7 +79,7 @@ enum MangosStrings
|
|||||||
LANG_NON_EXIST_CHARACTER = 47,
|
LANG_NON_EXIST_CHARACTER = 47,
|
||||||
LANG_FRIEND_IGNORE_UNKNOWN = 48,
|
LANG_FRIEND_IGNORE_UNKNOWN = 48,
|
||||||
LANG_LEVEL_MINREQUIRED = 49,
|
LANG_LEVEL_MINREQUIRED = 49,
|
||||||
LANG_LEVEL_MINREQUIRED_AND_ITEM = 50,
|
LANG_REQUIRED_ITEM = 50,
|
||||||
LANG_NPC_TAINER_HELLO = 51,
|
LANG_NPC_TAINER_HELLO = 51,
|
||||||
LANG_COMMAND_INVALID_ITEM_COUNT = 52,
|
LANG_COMMAND_INVALID_ITEM_COUNT = 52,
|
||||||
LANG_COMMAND_MAIL_ITEMS_LIMIT = 53,
|
LANG_COMMAND_MAIL_ITEMS_LIMIT = 53,
|
||||||
@ -96,7 +96,11 @@ enum MangosStrings
|
|||||||
LANG_GM_NO_WHISPER = 64,
|
LANG_GM_NO_WHISPER = 64,
|
||||||
LANG_USING_SCRIPT_LIB_UNKNOWN = 65,
|
LANG_USING_SCRIPT_LIB_UNKNOWN = 65,
|
||||||
LANG_USING_SCRIPT_LIB_NONE = 66,
|
LANG_USING_SCRIPT_LIB_NONE = 66,
|
||||||
// Room for more level 0 67-99 not used
|
LANG_WRONG_TEAM_HORDE = 67,
|
||||||
|
LANG_WRONG_TEAM_ALLIANCE = 68,
|
||||||
|
LANG_LEVEL_MAXREQUIRED = 69,
|
||||||
|
LANG_LEVEL_EQUALREQUIRED = 70,
|
||||||
|
// Room for more level 0 71-99 not used
|
||||||
|
|
||||||
// level 1 chat
|
// level 1 chat
|
||||||
LANG_GLOBAL_NOTIFY = 100,
|
LANG_GLOBAL_NOTIFY = 100,
|
||||||
@ -363,9 +367,9 @@ enum MangosStrings
|
|||||||
LANG_TRIGGER_TAVERN = 364,
|
LANG_TRIGGER_TAVERN = 364,
|
||||||
LANG_TRIGGER_QUEST = 365,
|
LANG_TRIGGER_QUEST = 365,
|
||||||
LANG_TRIGGER_EXPLORE_QUEST = 366,
|
LANG_TRIGGER_EXPLORE_QUEST = 366,
|
||||||
LANG_TRIGGER_REQ_LEVEL = 367,
|
LANG_TRIGGER_CONDITION = 367,
|
||||||
LANG_TRIGGER_REQ_ITEMS = 368,
|
// 368
|
||||||
LANG_TRIGGER_REQ_QUEST = 369,
|
// 369
|
||||||
// 370 used in master branch
|
// 370 used in master branch
|
||||||
// 371 used in master branch
|
// 371 used in master branch
|
||||||
// 372 used in master branch
|
// 372 used in master branch
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#define CHAR_DB_UPDATE_DESCRIPTION "Fix SoR paladin"
|
#define CHAR_DB_UPDATE_DESCRIPTION "Fix SoR paladin"
|
||||||
|
|
||||||
#define WORLD_DB_VERSION_NR 21
|
#define WORLD_DB_VERSION_NR 21
|
||||||
#define WORLD_DB_STRUCTURE_NR 3
|
#define WORLD_DB_STRUCTURE_NR 4
|
||||||
#define WORLD_DB_CONTENT_NR 2
|
#define WORLD_DB_CONTENT_NR 1
|
||||||
#define WORLD_DB_UPDATE_DESCRIPTION "Fix Random MMGen Scripts"
|
#define WORLD_DB_UPDATE_DESCRIPTION "Refactor areatrigger_teleport"
|
||||||
#endif // __REVISION_H__
|
#endif // __REVISION_H__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user