aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp2
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp14
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp6
-rw-r--r--src/server/game/Chat/Chat.cpp4
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp2
-rw-r--r--src/server/game/DataStores/DBCStores.cpp63
-rw-r--r--src/server/game/DataStores/DBCStores.h7
-rw-r--r--src/server/game/DataStores/DBCStructure.h2
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp14
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp53
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp22
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp10
-rw-r--r--src/server/game/Grids/GridDefines.h2
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp2
-rw-r--r--src/server/game/Handlers/ChannelHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp4
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp3
-rw-r--r--src/server/game/Loot/LootMgr.cpp4
-rw-r--r--src/server/game/Maps/Map.cpp141
-rw-r--r--src/server/game/Maps/Map.h37
-rw-r--r--src/server/game/Maps/MapManager.h14
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp24
-rw-r--r--src/server/game/Spells/Spell.cpp2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp4
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp43
-rw-r--r--src/server/scripts/Commands/cs_go.cpp4
-rw-r--r--src/server/scripts/Commands/cs_group.cpp4
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp4
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp38
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp55
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.h16
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp29
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp84
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h19
-rw-r--r--src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp58
-rw-r--r--src/server/scripts/Kalimdor/zone_ashenvale.cpp34
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp1
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp1
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp1
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp5
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp142
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp44
-rw-r--r--src/server/scripts/World/npcs_special.cpp93
-rw-r--r--src/server/shared/Containers.h114
52 files changed, 701 insertions, 544 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 977847e60c9..ef3357fa6ed 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -468,7 +468,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.map);
return false;
}
- if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !GetAreaEntryByAreaID(e.event.respawn.area))
+ if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !sAreaTableStore.LookupEntry(e.event.respawn.area))
{
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Area entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.area);
return false;
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 90e61826e35..ac8e0298a44 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -156,7 +156,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return true;
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA:
- if (!GetAreaEntryByAreaID(area.id))
+ if (!sAreaTableStore.LookupEntry(area.id))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) has wrong area id in value1 (%u), ignored.",
criteria->ID, criteria->requiredType, dataType, area.id);
@@ -1905,17 +1905,15 @@ bool AchievementMgr::RequirementsSatisfied(AchievementCriteriaEntry const* achie
bool matchFound = false;
for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
{
- uint32 area_id = worldOverlayEntry->areatableID[j];
- if (!area_id) // array have 0 only in empty tail
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(worldOverlayEntry->areatableID[j]);
+ if (!area)
break;
- int32 exploreFlag = GetAreaFlagByAreaID(area_id);
- if (exploreFlag < 0)
+ uint32 playerIndexOffset = uint32(area->exploreFlag) / 32;
+ if (playerIndexOffset >= PLAYER_EXPLORED_ZONES_SIZE)
continue;
- uint32 playerIndexOffset = uint32(exploreFlag) / 32;
- uint32 mask = 1 << (uint32(exploreFlag) % 32);
-
+ uint32 mask = 1 << (uint32(area->exploreFlag) % 32);
if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
{
matchFound = true;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 9ab96383ed1..1942ac9d648 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -389,6 +389,8 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
{
if (TotalTime >= BG_SA_ROUNDLENGTH)
{
+ CastSpellOnTeam(SPELL_END_OF_ROUND, ALLIANCE);
+ CastSpellOnTeam(SPELL_END_OF_ROUND, HORDE);
RoundScores[0].winner = Attackers;
RoundScores[0].time = BG_SA_ROUNDLENGTH;
TotalTime = 0;
@@ -401,8 +403,6 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
ToggleTimer();
ResetObjs();
GetBgMap()->UpdateAreaDependentAuras();
- CastSpellOnTeam(SPELL_END_OF_ROUND, ALLIANCE);
- CastSpellOnTeam(SPELL_END_OF_ROUND, HORDE);
return;
}
}
@@ -410,6 +410,8 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
{
if (TotalTime >= EndRoundTimer)
{
+ CastSpellOnTeam(SPELL_END_OF_ROUND, ALLIANCE);
+ CastSpellOnTeam(SPELL_END_OF_ROUND, HORDE);
RoundScores[1].time = BG_SA_ROUNDLENGTH;
RoundScores[1].winner = (Attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
if (RoundScores[0].time == RoundScores[1].time)
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 011b68a2bb3..8fe0810f3b9 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -296,11 +296,11 @@ bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, c
uint32 areaId = player->GetAreaId();
std::string areaName = "Unknown";
std::string zoneName = "Unknown";
- if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId))
{
int locale = GetSessionDbcLocale();
areaName = area->area_name[locale];
- if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone))
+ if (AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone))
zoneName = zone->area_name[locale];
}
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index d5367e919a3..4215a3a5d02 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1708,7 +1708,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
}
case CONDITION_ZONEID:
{
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(cond->ConditionValue1);
if (!areaEntry)
{
TC_LOG_ERROR("sql.sql", "%s Area (%u) does not exist, skipped.", cond->ToString(true).c_str(), cond->ConditionValue1);
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index c73350872cc..6c51c71fe7b 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -51,11 +51,9 @@ struct WMOAreaTableTripple
typedef std::map<WMOAreaTableTripple, WMOAreaTableEntry const*> WMOAreaInfoByTripple;
typedef std::multimap<uint32, CharSectionsEntry const*> CharSectionsMap;
-DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt);
+DBCStorage <AreaTableEntry> sAreaTableStore(AreaTableEntryfmt);
DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt);
DBCStorage <AreaPOIEntry> sAreaPOIStore(AreaPOIEntryfmt);
-static AreaFlagByAreaID sAreaFlagByAreaID;
-static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files
static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
@@ -286,21 +284,7 @@ void LoadDBCStores(const std::string& dataPath)
StoreProblemList bad_dbc_files;
uint32 availableDbcLocales = 0xFFFFFFFF;
- LoadDBC(availableDbcLocales, bad_dbc_files, sAreaStore, dbcPath, "AreaTable.dbc");
-
- // must be after sAreaStore loading
- for (uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0
- {
- if (AreaTableEntry const* area = sAreaStore.LookupEntry(i))
- {
- // fill AreaId->DBC records
- sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID), area->exploreFlag));
-
- // fill MapId->DBC records (skip sub zones and continents)
- if (area->zone == 0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571)
- sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid, area->exploreFlag));
- }
- }
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTableStore, dbcPath, "AreaTable.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex);
LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc");
@@ -721,7 +705,7 @@ void LoadDBCStores(const std::string& dataPath)
}
// Check loaded DBC files proper version
- if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) added in 3.3.5a
+ if (!sAreaTableStore.LookupEntry(4987) || // last area added in 3.3.5a
!sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a
!sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a
!sItemStore.LookupEntry(56806) || // last gem property added in 3.3.5a
@@ -773,41 +757,13 @@ uint32 GetTalentSpellCost(uint32 spellId)
return 0;
}
-int32 GetAreaFlagByAreaID(uint32 area_id)
-{
- AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id);
- if (i == sAreaFlagByAreaID.end())
- return -1;
-
- return i->second;
-}
WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid)
{
WMOAreaInfoByTripple::iterator i = sWMOAreaInfoByTripple.find(WMOAreaTableTripple(rootid, adtid, groupid));
- if (i == sWMOAreaInfoByTripple.end())
- return NULL;
- return i->second;
-}
-
-AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id)
-{
- int32 areaflag = GetAreaFlagByAreaID(area_id);
- if (areaflag < 0)
+ if (i == sWMOAreaInfoByTripple.end())
return NULL;
-
- return sAreaStore.LookupEntry(areaflag);
-}
-
-AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id)
-{
- if (area_flag)
- return sAreaStore.LookupEntry(area_flag);
-
- if (MapEntry const* mapEntry = sMapStore.LookupEntry(map_id))
- return GetAreaEntryByAreaID(mapEntry->linked_zone);
-
- return NULL;
+ return i->second;
}
char const* GetRaceName(uint8 race, uint8 locale)
@@ -822,15 +778,6 @@ char const* GetClassName(uint8 class_, uint8 locale)
return classEntry ? classEntry->name[locale] : NULL;
}
-uint32 GetAreaFlagByMapId(uint32 mapid)
-{
- AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid);
- if (i == sAreaFlagByMapID.end())
- return 0;
- else
- return i->second;
-}
-
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
{
if (mapid != 530 && mapid != 571) // speed for most cases
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 14f59b04e6d..56ee1f618dd 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -33,11 +33,6 @@ char* GetPetName(uint32 petfamily, uint32 dbclang);
uint32 GetTalentSpellCost(uint32 spellId);
TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
-int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found
-AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id);
-AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id);
-uint32 GetAreaFlagByMapId(uint32 mapid);
-
char const* GetRaceName(uint8 race, uint8 locale);
char const* GetClassName(uint8 class_, uint8 locale);
@@ -86,7 +81,7 @@ EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uin
extern DBCStorage <AchievementEntry> sAchievementStore;
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
-extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
+extern DBCStorage <AreaTableEntry> sAreaTableStore;
extern DBCStorage <AreaGroupEntry> sAreaGroupStore;
extern DBCStorage <AreaPOIEntry> sAreaPOIStore;
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 2f4820d0353..b5dc4489148 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -509,7 +509,7 @@ struct AreaTableEntry
uint32 ID; // 0
uint32 mapid; // 1
uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area
- uint32 exploreFlag; // 3, main index
+ uint32 exploreFlag; // 3
uint32 flags; // 4, unknown value but 312 for all cities
// 5-9 unused
int32 area_level; // 10
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 22a01dae9f0..c61ec997bc2 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -23,7 +23,7 @@ char const Achievementfmt[] = "niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxx
const std::string CustomAchievementfmt = "pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp";
const std::string CustomAchievementIndex = "ID";
char const AchievementCriteriafmt[] = "niiiiiiiixxxxxxxxxxxxxxxxxiiiix";
-char const AreaTableEntryfmt[] = "iiinixxxxxissssssssssssssssxiiiiixxx";
+char const AreaTableEntryfmt[] = "niiiixxxxxissssssssssssssssxiiiiixxx";
char const AreaGroupEntryfmt[] = "niiiiiii";
char const AreaPOIEntryfmt[] = "niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
char const AreaTriggerEntryfmt[] = "niffffffff";
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 1497eb4922c..5d62b740947 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -369,13 +369,13 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
// Load creature equipment
- if (!data || data->equipmentId == 0)
- LoadEquipment(); // use default equipment (if available)
- else if (data && data->equipmentId != 0) // override, 0 means no equipment
+ if (data && data->equipmentId != 0)
{
m_originalEquipmentId = data->equipmentId;
LoadEquipment(data->equipmentId);
}
+ else
+ LoadEquipment(0, true);
SetName(normalInfo->Name); // at normal entry always
@@ -1409,6 +1409,7 @@ void Creature::LoadEquipment(int8 id, bool force /*= true*/)
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0);
m_equipmentId = 0;
}
+
return;
}
@@ -1417,7 +1418,7 @@ void Creature::LoadEquipment(int8 id, bool force /*= true*/)
return;
m_equipmentId = id;
- for (uint8 i = 0; i < 3; ++i)
+ for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->ItemEntry[i]);
}
@@ -2148,6 +2149,11 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
if (GetMap()->IsDungeon())
return true;
+ // if the mob is actively being damaged, do not reset due to distance unless it's a world boss
+ if (!isWorldBoss())
+ if (time(NULL) - GetLastDamagedTime() <= MAX_AGGRO_RESET_TIME)
+ return true;
+
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
float dist = std::max(GetAttackDistance(victim), sWorld->getFloatConfig(CONFIG_THREAT_RADIUS)) + m_CombatDistance;
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index b030f42bef7..1acfeacbf83 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1399,7 +1399,10 @@ void GameObject::Use(Unit* user)
player->SendCinematicStart(info->camera.cinematicId);
if (info->camera.eventID)
+ {
GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
+ EventInform(info->camera.eventID, user);
+ }
return;
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8ce78f88906..9ae9f21c967 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -4682,6 +4682,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
// remove death flag + set aura
SetByteValue(UNIT_FIELD_BYTES_1, 3, 0x00);
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS);
// This must be called always even on Players with race != RACE_NIGHTELF in case of faction change
RemoveAurasDueToSpell(20584); // RACE_NIGHTELF speed bonuses
@@ -5102,10 +5103,10 @@ void Player::RepopAtGraveyard()
// note: this can be called also when the player is alive
// for example from WorldSession::HandleMovementOpcodes
- AreaTableEntry const* zone = GetAreaEntryByAreaID(GetAreaId());
+ AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId());
// Such zones are considered unreachable as a ghost and the player must be automatically revived
- if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < -500.0f)
+ if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY()))
{
ResurrectPlayer(0.5f);
SpawnCorpseBones();
@@ -5142,8 +5143,10 @@ void Player::RepopAtGraveyard()
GetSession()->SendPacket(&data);
}
}
- else if (GetPositionZ() < -500.0f)
+ else if (GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY()))
TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
+
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS);
}
bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone)
@@ -5188,7 +5191,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
if (GetSession()->PlayerLoading() && !IsBeingTeleportedFar())
return; // The client handles it automatically after loading, but not after teleporting
- AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone);
+ AreaTableEntry const* current_zone = sAreaTableStore.LookupEntry(newZone);
if (!current_zone)
return;
@@ -6429,22 +6432,32 @@ void Player::CheckAreaExploreAndOutdoor()
return;
bool isOutdoor;
- uint16 areaFlag = GetBaseMap()->GetAreaFlag(GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor);
+ uint32 areaId = GetBaseMap()->GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId);
if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !isOutdoor)
RemoveAurasWithAttribute(SPELL_ATTR0_OUTDOORS_ONLY);
- if (areaFlag == 0xffff)
+ if (!areaId)
return;
- int offset = areaFlag / 32;
+
+ if (!areaEntry)
+ {
+ TC_LOG_ERROR("entities.player", "Player '%s' (%s) discovered unknown area (x: %f y: %f z: %f map: %u)",
+ GetName().c_str(), GetGUID().ToString().c_str(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId());
+ return;
+ }
+
+ uint32 offset = areaEntry->exploreFlag / 32;
if (offset >= PLAYER_EXPLORED_ZONES_SIZE)
{
- TC_LOG_ERROR("entities.player", "Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < %u ).", areaFlag, GetPositionX(), GetPositionY(), offset, offset, PLAYER_EXPLORED_ZONES_SIZE);
+ TC_LOG_ERROR("entities.player", "Player::CheckAreaExploreAndOutdoor: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < %u ).",
+ areaEntry->exploreFlag, GetPositionX(), GetPositionY(), offset, offset, PLAYER_EXPLORED_ZONES_SIZE);
return;
}
- uint32 val = (uint32)(1 << (areaFlag % 32));
+ uint32 val = (uint32)(1 << (areaEntry->exploreFlag % 32));
uint32 currFields = GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset);
if (!(currFields & val))
@@ -6453,19 +6466,11 @@ void Player::CheckAreaExploreAndOutdoor()
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA);
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaFlagAndMap(areaFlag, GetMapId());
- if (!areaEntry)
- {
- TC_LOG_ERROR("entities.player", "Player %u discovered unknown area (x: %f y: %f z: %f map: %u", GetGUID().GetCounter(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId());
- return;
- }
-
if (areaEntry->area_level > 0)
{
- uint32 area = areaEntry->ID;
if (getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
- SendExplorationExperience(area, 0);
+ SendExplorationExperience(areaId, 0);
}
else
{
@@ -6489,9 +6494,9 @@ void Player::CheckAreaExploreAndOutdoor()
}
GiveXP(XP, NULL);
- SendExplorationExperience(area, XP);
+ SendExplorationExperience(areaId, XP);
}
- TC_LOG_DEBUG("entities.player", "Player %u discovered a new area: %u", GetGUID().GetCounter(), area);
+ TC_LOG_DEBUG("entities.player", "Player '%s' (%s) discovered a new area: %u", GetName().c_str(),GetGUID().ToString().c_str(), areaId);
}
}
}
@@ -7061,7 +7066,7 @@ void Player::UpdateArea(uint32 newArea)
// so apply them accordingly
m_areaUpdateId = newArea;
- AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(newArea);
pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
UpdatePvPState(true);
@@ -7109,7 +7114,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
// zone changed, so area changed as well, update it
UpdateArea(newArea);
- AreaTableEntry const* zone = GetAreaEntryByAreaID(newZone);
+ AreaTableEntry const* zone = sAreaTableStore.LookupEntry(newZone);
if (!zone)
return;
@@ -26154,11 +26159,11 @@ std::string Player::GetMapAreaAndZoneString()
uint32 areaId = GetAreaId();
std::string areaName = "Unknown";
std::string zoneName = "Unknown";
- if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId))
{
int locale = GetSession()->GetSessionDbcLocale();
areaName = area->area_name[locale];
- if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone))
+ if (AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone))
zoneName = zone->area_name[locale];
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 3aed5fde7b3..c224ef78ec8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -8328,8 +8328,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
case 52914:
case 52915:
case 52910:
- // Honor Among Thieves
- case 52916:
{
target = triggeredByAura->GetBase()->GetCaster();
if (!target)
@@ -12750,7 +12748,7 @@ Unit* Creature::SelectVictim()
}
}
else
- return NULL;
+ return nullptr;
if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target))
{
@@ -12759,14 +12757,6 @@ Unit* Creature::SelectVictim()
return target;
}
- // Case where mob is being kited.
- // Mob may not be in range to attack or may have dropped target. In any case,
- // don't evade if damage received within the last 10 seconds
- // Does not apply to world bosses to prevent kiting to cities
- if (!isWorldBoss() && !GetInstanceId())
- if (time(NULL) - GetLastDamagedTime() <= MAX_AGGRO_RESET_TIME)
- return target;
-
// last case when creature must not go to evade mode:
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
// for example at owner command to pet attack some far away creature
@@ -12775,12 +12765,12 @@ Unit* Creature::SelectVictim()
{
if ((*itr) && !CanCreatureAttack(*itr) && (*itr)->GetTypeId() != TYPEID_PLAYER
&& !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
- return NULL;
+ return nullptr;
}
/// @todo a vehicle may eat some mob, so mob should not evade
if (GetVehicle())
- return NULL;
+ return nullptr;
// search nearby enemy before enter evade mode
if (HasReactState(REACT_AGGRESSIVE))
@@ -12798,17 +12788,17 @@ Unit* Creature::SelectVictim()
{
if ((*itr)->GetBase()->IsPermanent())
{
- AI()->EnterEvadeMode();
+ AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_OTHER);
break;
}
}
- return NULL;
+ return nullptr;
}
// enter in evade mode in other case
AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES);
- return NULL;
+ return nullptr;
}
//======================================================================
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index d2064092a65..f45634e9684 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1756,7 +1756,7 @@ void ObjectMgr::LoadCreatures()
if (!ok)
continue;
- // -1 random, 0 no equipment,
+ // -1 random, 0 no equipment
if (data.equipmentId != 0)
{
if (!GetEquipmentInfo(data.id, data.equipmentId))
@@ -2773,7 +2773,7 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.ItemSet = 0;
}
- if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area))
+ if (itemTemplate.Area && !sAreaTableStore.LookupEntry(itemTemplate.Area))
TC_LOG_ERROR("sql.sql", "Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area);
if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map))
@@ -4143,7 +4143,7 @@ void ObjectMgr::LoadQuests()
// client quest log visual (area case)
if (qinfo->ZoneOrSort > 0)
{
- if (!GetAreaEntryByAreaID(qinfo->ZoneOrSort))
+ if (!sAreaTableStore.LookupEntry(qinfo->ZoneOrSort))
{
TC_LOG_ERROR("sql.sql", "Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist.",
qinfo->GetQuestId(), qinfo->ZoneOrSort);
@@ -5956,7 +5956,7 @@ void ObjectMgr::LoadGraveyardZones()
continue;
}
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId);
if (!areaEntry)
{
TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for not existing zone id (%u), skipped.", zoneId);
@@ -7796,7 +7796,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel()
uint32 entry = fields[0].GetUInt32();
int32 skill = fields[1].GetInt16();
- AreaTableEntry const* fArea = GetAreaEntryByAreaID(entry);
+ AreaTableEntry const* fArea = sAreaTableStore.LookupEntry(entry);
if (!fArea)
{
TC_LOG_ERROR("sql.sql", "AreaId %u defined in `skill_fishing_base_level` does not exist", entry);
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index 162c39b951b..24c9100b222 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -226,7 +226,7 @@ namespace Trinity
inline bool IsValidMapCoord(float x, float y, float z)
{
- return IsValidMapCoord(x, y) && std::isfinite(z);
+ return IsValidMapCoord(x, y) && IsValidMapCoord(z);
}
inline bool IsValidMapCoord(float x, float y, float z, float o)
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index c48d1947eec..571d56b618e 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -131,7 +131,7 @@ inline void CreatureUnitRelocationWorker(Creature* c, Unit* u)
if (!u->IsAlive() || !c->IsAlive() || c == u || u->IsInFlight())
return;
- if (c->HasReactState(REACT_AGGRESSIVE) && !c->HasUnitState(UNIT_STATE_SIGHTLESS))
+ if ((c->HasReactState(REACT_AGGRESSIVE) || c->IsTrigger()) && !c->HasUnitState(UNIT_STATE_SIGHTLESS))
{
if (c->IsAIEnabled && c->CanSeeOrDetect(u, false, true))
c->AI()->MoveInLineOfSight_Safe(u);
diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp
index 976860e8cc0..9285f4247b2 100644
--- a/src/server/game/Handlers/ChannelHandler.cpp
+++ b/src/server/game/Handlers/ChannelHandler.cpp
@@ -39,7 +39,7 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
if (!channel)
return;
- AreaTableEntry const* zone = GetAreaEntryByAreaID(GetPlayer()->GetZoneId());
+ AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId());
if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone))
return;
}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 6cd8bfc014e..5f5a66e7b20 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -319,7 +319,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
continue;
std::string aname;
- if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid))
+ if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(pzoneid))
aname = areaEntry->area_name[GetSessionDbcLocale()];
bool s_show = true;
@@ -1753,7 +1753,7 @@ void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recvData*/)
return;
}
- AreaTableEntry const* atEntry = GetAreaEntryByAreaID(_player->GetAreaId());
+ AreaTableEntry const* atEntry = sAreaTableStore.LookupEntry(_player->GetAreaId());
if (!atEntry || !(atEntry->flags & AREA_FLAG_WINTERGRASP_2))
return;
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index eea5c62fbd1..02702fc5622 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -386,7 +386,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
- if (movementInfo.pos.GetPositionZ() < -500.0f)
+ if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
{
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
@@ -395,6 +395,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
/// @todo discard movement packets after the player is rooted
if (plrMover->IsAlive())
{
+ plrMover->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS);
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// player can be alive if GM/etc
// change the death state to CORPSE to prevent the death timer from
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 530bcd2902c..19dc210ea5b 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -1580,8 +1580,8 @@ void LoadLootTemplates_Fishing()
uint32 count = LootTemplates_Fishing.LoadAndCollectLootIds(lootIdSet);
// remove real entries and check existence loot
- for (uint32 i = 1; i < sAreaStore.GetNumRows(); ++i)
- if (AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(i))
+ for (uint32 i = 1; i < sAreaTableStore.GetNumRows(); ++i)
+ if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(i))
if (lootIdSet.find(areaEntry->ID) != lootIdSet.end())
lootIdSet.erase(areaEntry->ID);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index a2cb84359f2..1560d4bdd08 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -37,7 +37,7 @@
#include "VMapFactory.h"
u_map_magic MapMagic = { {'M','A','P','S'} };
-u_map_magic MapVersionMagic = { {'v','1','.','3'} };
+u_map_magic MapVersionMagic = { {'v','1','.','7'} };
u_map_magic MapAreaMagic = { {'A','R','E','A'} };
u_map_magic MapHeightMagic = { {'M','H','G','T'} };
u_map_magic MapLiquidMagic = { {'M','L','I','Q'} };
@@ -1644,13 +1644,15 @@ GridMap::GridMap()
_flags = 0;
// Area data
_gridArea = 0;
- _areaMap = NULL;
+ _areaMap = nullptr;
// Height level data
_gridHeight = INVALID_HEIGHT;
_gridGetHeight = &GridMap::getHeightFromFlat;
_gridIntHeightMultiplier = 0;
- m_V9 = NULL;
- m_V8 = NULL;
+ m_V9 = nullptr;
+ m_V8 = nullptr;
+ _maxHeight = nullptr;
+ _minHeight = nullptr;
// Liquid data
_liquidType = 0;
_liquidOffX = 0;
@@ -1658,9 +1660,9 @@ GridMap::GridMap()
_liquidWidth = 0;
_liquidHeight = 0;
_liquidLevel = INVALID_HEIGHT;
- _liquidEntry = NULL;
- _liquidFlags = NULL;
- _liquidMap = NULL;
+ _liquidEntry = nullptr;
+ _liquidFlags = nullptr;
+ _liquidMap = nullptr;
}
GridMap::~GridMap()
@@ -1723,15 +1725,19 @@ void GridMap::unloadData()
delete[] _areaMap;
delete[] m_V9;
delete[] m_V8;
+ delete[] _maxHeight;
+ delete[] _minHeight;
delete[] _liquidEntry;
delete[] _liquidFlags;
delete[] _liquidMap;
- _areaMap = NULL;
- m_V9 = NULL;
- m_V8 = NULL;
- _liquidEntry = NULL;
- _liquidFlags = NULL;
- _liquidMap = NULL;
+ _areaMap = nullptr;
+ m_V9 = nullptr;
+ m_V8 = nullptr;
+ _maxHeight = nullptr;
+ _minHeight = nullptr;
+ _liquidEntry = nullptr;
+ _liquidFlags = nullptr;
+ _liquidMap = nullptr;
_gridGetHeight = &GridMap::getHeightFromFlat;
}
@@ -1746,7 +1752,7 @@ bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/)
_gridArea = header.gridArea;
if (!(header.flags & MAP_AREA_NO_AREA))
{
- _areaMap = new uint16 [16*16];
+ _areaMap = new uint16[16 * 16];
if (fread(_areaMap, sizeof(uint16), 16*16, in) != 16*16)
return false;
}
@@ -1796,6 +1802,16 @@ bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
}
else
_gridGetHeight = &GridMap::getHeightFromFlat;
+
+ if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS)
+ {
+ _maxHeight = new float[16 * 16];
+ _minHeight = new float[16 * 16];
+ if (fread(_maxHeight, sizeof(float), 16 * 16, in) != 16 * 16 ||
+ fread(_minHeight, sizeof(float), 16 * 16, in) != 16 * 16)
+ return false;
+ }
+
return true;
}
@@ -2066,6 +2082,18 @@ float GridMap::getHeightFromUint16(float x, float y) const
return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight;
}
+float GridMap::getMinHeight(float x, float y) const
+{
+ if (!_minHeight)
+ return -500.0f;
+
+ x = 16 * (CENTER_GRID_ID - x / SIZE_OF_GRIDS);
+ y = 16 * (CENTER_GRID_ID - y / SIZE_OF_GRIDS);
+ int lx = (int)x & 15;
+ int ly = (int)y & 15;
+ return _minHeight[lx * 16 + ly];
+}
+
float GridMap::getLiquidLevel(float x, float y) const
{
if (!_liquidMap)
@@ -2125,12 +2153,12 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R
uint32 liqTypeIdx = liquidEntry->Type;
if (entry < 21)
{
- if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(getArea(x, y), MAPID_INVALID))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y)))
{
uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
if (!overrideLiquid && area->zone)
{
- area = GetAreaEntryByAreaID(area->zone);
+ area = sAreaTableStore.LookupEntry(area->zone);
if (area)
overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type];
}
@@ -2266,6 +2294,14 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float
return mapHeight; // explicitly use map data
}
+float Map::GetMinHeight(float x, float y) const
+{
+ if (GridMap const* grid = const_cast<Map*>(this)->GetGrid(x, y))
+ return grid->getMinHeight(x, y);
+
+ return -500.0f;
+}
+
inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, int32 /*groupId*/, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
{
bool outdoor = true;
@@ -2304,7 +2340,7 @@ bool Map::IsOutdoors(float x, float y, float z) const
if (wmoEntry)
{
TC_LOG_DEBUG("maps", "Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId);
- atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
+ atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId);
}
return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
}
@@ -2328,7 +2364,7 @@ bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, in
return false;
}
-uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const
+uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const
{
uint32 mogpFlags;
int32 adtId, rootId, groupId;
@@ -2341,20 +2377,20 @@ uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const
haveAreaInfo = true;
wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
if (wmoEntry)
- atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
+ atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId);
}
- uint16 areaflag;
+ uint32 areaId;
if (atEntry)
- areaflag = atEntry->exploreFlag;
+ areaId = atEntry->ID;
else
{
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
- areaflag = gmap->getArea(x, y);
+ areaId = gmap->getArea(x, y);
// this used while not all *.map files generated (instances)
else
- areaflag = GetAreaFlagByMapId(i_mapEntry->MapID);
+ areaId = i_mapEntry->linked_zone;
}
if (isOutdoors)
@@ -2364,8 +2400,31 @@ uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const
else
*isOutdoors = true;
}
- return areaflag;
- }
+ return areaId;
+}
+
+uint32 Map::GetAreaId(float x, float y, float z) const
+{
+ return GetAreaId(x, y, z, nullptr);
+}
+
+uint32 Map::GetZoneId(float x, float y, float z) const
+{
+ uint32 areaId = GetAreaId(x, y, z);
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId))
+ if (area->zone)
+ return area->zone;
+
+ return areaId;
+}
+
+void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
+{
+ areaid = zoneid = GetAreaId(x, y, z);
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid))
+ if (area->zone)
+ zoneid = area->zone;
+}
uint8 Map::GetTerrainType(float x, float y) const
{
@@ -2401,12 +2460,12 @@ ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp
if (liquid_type && liquid_type < 21)
{
- if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(GetAreaFlag(x, y, z), GetId()))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(x, y, z)))
{
uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType];
if (!overrideLiquid && area->zone)
{
- area = GetAreaEntryByAreaID(area->zone);
+ area = sAreaTableStore.LookupEntry(area->zone);
if (area)
overrideLiquid = area->LiquidTypeOverride[liquidFlagType];
}
@@ -2468,34 +2527,6 @@ float Map::GetWaterLevel(float x, float y) const
return 0;
}
-uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag, uint32 map_id)
-{
- AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
-
- if (entry)
- return entry->ID;
- else
- return 0;
-}
-
-uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag, uint32 map_id)
-{
- AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
-
- if (entry)
- return (entry->zone != 0) ? entry->zone : entry->ID;
- else
- return 0;
-}
-
-void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag, uint32 map_id)
-{
- AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
-
- areaid = entry ? entry->ID : 0;
- zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0;
-}
-
bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
{
return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 01db38d9c30..13d48db0f9d 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -98,9 +98,10 @@ struct map_areaHeader
uint16 gridArea;
};
-#define MAP_HEIGHT_NO_HEIGHT 0x0001
-#define MAP_HEIGHT_AS_INT16 0x0002
-#define MAP_HEIGHT_AS_INT8 0x0004
+#define MAP_HEIGHT_NO_HEIGHT 0x0001
+#define MAP_HEIGHT_AS_INT16 0x0002
+#define MAP_HEIGHT_AS_INT8 0x0004
+#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008
struct map_heightHeader
{
@@ -166,6 +167,8 @@ class GridMap
uint16* m_uint16_V8;
uint8* m_uint8_V8;
};
+ float* _maxHeight;
+ float* _minHeight;
// Height level data
float _gridHeight;
float _gridIntHeightMultiplier;
@@ -206,6 +209,7 @@ public:
uint16 getArea(float x, float y) const;
inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);}
+ float getMinHeight(float x, float y) const;
float getLiquidLevel(float x, float y) const;
uint8 getTerrainType(float x, float y) const;
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0);
@@ -326,11 +330,15 @@ class Map : public GridRefManager<NGridType>
// some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height
float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
+ float GetMinHeight(float x, float y) const;
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const;
- uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=nullptr) const;
- bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const;
+ uint32 GetAreaId(float x, float y, float z, bool *isOutdoors) const;
+ bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const;
+ uint32 GetAreaId(float x, float y, float z) const;
+ uint32 GetZoneId(float x, float y, float z) const;
+ void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const;
bool IsOutdoors(float x, float y, float z) const;
@@ -339,25 +347,6 @@ class Map : public GridRefManager<NGridType>
bool IsInWater(float x, float y, float z, LiquidData* data = nullptr) const;
bool IsUnderWater(float x, float y, float z) const;
- static uint32 GetAreaIdByAreaFlag(uint16 areaflag, uint32 map_id);
- static uint32 GetZoneIdByAreaFlag(uint16 areaflag, uint32 map_id);
- static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag, uint32 map_id);
-
- uint32 GetAreaId(float x, float y, float z) const
- {
- return GetAreaIdByAreaFlag(GetAreaFlag(x, y, z), GetId());
- }
-
- uint32 GetZoneId(float x, float y, float z) const
- {
- return GetZoneIdByAreaFlag(GetAreaFlag(x, y, z), GetId());
- }
-
- void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
- {
- GetZoneAndAreaIdByAreaFlag(zoneid, areaid, GetAreaFlag(x, y, z), GetId());
- }
-
void MoveAllCreaturesInMoveList();
void MoveAllGameObjectsInMoveList();
void MoveAllDynamicObjectsInMoveList();
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index 51bb418bdf5..7f9621593d4 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -42,22 +42,20 @@ class MapManager
Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0);
Map* FindMap(uint32 mapId, uint32 instanceId) const;
- uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const
- {
- Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
- return m->GetAreaFlag(x, y, z);
- }
uint32 GetAreaId(uint32 mapid, float x, float y, float z) const
{
- return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z), mapid);
+ Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
+ return m->GetAreaId(x, y, z);
}
uint32 GetZoneId(uint32 mapid, float x, float y, float z) const
{
- return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z), mapid);
+ Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
+ return m->GetZoneId(x, y, z);
}
void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z)
{
- Map::GetZoneAndAreaIdByAreaFlag(zoneid, areaid, GetAreaFlag(mapid, x, y, z), mapid);
+ Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid);
+ m->GetZoneAndAreaId(zoneid, areaid, x, y, z);
}
void Initialize(void);
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index 868cba9a5b9..d329ab27de9 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -687,7 +687,7 @@ void OutdoorPvP::BroadcastWorker(Worker& _worker, uint32 zoneId)
void OutdoorPvP::SetMapFromZone(uint32 zone)
{
- AreaTableEntry const* areaTable = GetAreaEntryByAreaID(zone);
+ AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(zone);
ASSERT(areaTable);
Map* map = sMapMgr->CreateBaseMap(areaTable->mapid);
ASSERT(!map->Instanceable());
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6a10d113553..207908c6d51 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4683,11 +4683,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
break;
- case 52916: // Honor Among Thieves
- if (target->GetTypeId() == TYPEID_PLAYER)
- if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget()))
- target->CastSpell(spellTarget, 51699, true);
- break;
case 71563:
if (Aura* newAura = target->AddAura(71564, target))
newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount);
@@ -5619,25 +5614,6 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster)
target->RemoveAurasDueToSpell(28820);
return;
}
- // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
- case 38443:
- {
- bool all = true;
- for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
- {
- if (!target->m_SummonSlot[i])
- {
- all = false;
- break;
- }
- }
-
- if (all)
- target->CastSpell(target, 38437, true, NULL, this);
- else
- target->RemoveAurasDueToSpell(38437);
- return;
- }
}
break;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 63fe148dd93..7c1ccbdb463 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5477,7 +5477,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_originalCaster && m_originalCaster->GetTypeId() == TYPEID_PLAYER && m_originalCaster->IsAlive())
{
Battlefield* Bf = sBattlefieldMgr->GetBattlefieldToZoneId(m_originalCaster->GetZoneId());
- if (AreaTableEntry const* area = GetAreaEntryByAreaID(m_originalCaster->GetAreaId()))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(m_originalCaster->GetAreaId()))
if (area->flags & AREA_FLAG_NO_FLY_ZONE || (Bf && !Bf->CanFlyIn()))
return (_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE;
}
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index f961654f279..b2aa44e28df 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4137,14 +4137,14 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
return;
// Players can only fight a duel in zones with this flag
- AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetAreaId());
+ AreaTableEntry const* casterAreaEntry = sAreaTableStore.LookupEntry(caster->GetAreaId());
if (casterAreaEntry && !(casterAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
{
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return;
}
- AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetAreaId());
+ AreaTableEntry const* targetAreaEntry = sAreaTableStore.LookupEntry(target->GetAreaId());
if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
{
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ff8fc4539ff..40e8f2d4e24 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -1159,7 +1159,7 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
if (!player)
return false;
- AreaTableEntry const* pArea = GetAreaEntryByAreaID(player->GetAreaId());
+ AreaTableEntry const* pArea = sAreaTableStore.LookupEntry(player->GetAreaId());
if (!(pArea && pArea->flags & AREA_FLAG_NO_FLY_ZONE))
return false;
if (!player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY))
@@ -2618,7 +2618,7 @@ void SpellMgr::LoadSpellAreas()
}
}
- if (spellArea.areaId && !GetAreaEntryByAreaID(spellArea.areaId))
+ if (spellArea.areaId && !sAreaTableStore.LookupEntry(spellArea.areaId))
{
TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_area` have wrong area (%u) requirement", spell, spellArea.areaId);
continue;
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 8d3ee939e2c..499f0c9cbf0 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -191,7 +191,6 @@ void CreatureTextMgr::LoadCreatureTextLocales()
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u creature localized texts in %u ms", textCount, GetMSTimeDiffToNow(oldMSTime));
-
}
uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject const* whisperTarget /*= nullptr*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/)
@@ -228,42 +227,10 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
tempGroup = textGroupContainer;
}
- uint8 count = 0;
- float lastChance = -1;
- bool isEqualChanced = true;
-
- float totalChance = 0;
-
- for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)
+ auto iter = Trinity::Containers::SelectRandomWeightedContainerElement(tempGroup, [](CreatureTextEntry const& t) -> double
{
- if (lastChance >= 0 && lastChance != iter->probability)
- isEqualChanced = false;
-
- lastChance = iter->probability;
- totalChance += iter->probability;
- ++count;
- }
-
- int32 offset = -1;
- if (!isEqualChanced)
- {
- for (CreatureTextGroup::const_iterator iter = tempGroup.begin(); iter != tempGroup.end(); ++iter)
- {
- uint32 chance = uint32(iter->probability);
- uint32 r = urand(0, 100);
- ++offset;
- if (r <= chance)
- break;
- }
- }
-
- uint32 pos = 0;
- if (isEqualChanced || offset < 0)
- pos = urand(0, count - 1);
- else if (offset >= 0)
- pos = offset;
-
- CreatureTextGroup::const_iterator iter = tempGroup.begin() + pos;
+ return t.probability;
+ });
ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType;
Language finalLang = (language == LANG_ADDON) ? iter->lang : language;
@@ -293,9 +260,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
}
- if (isEqualChanced || totalChance == 100.0f)
- SetRepeatId(source, textGroup, iter->id);
-
+ SetRepeatId(source, textGroup, iter->id);
return iter->duration;
}
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index b7acfb85f50..039af61c010 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -424,7 +424,7 @@ public:
uint32 areaId = id ? (uint32)atoi(id) : player->GetZoneId();
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId);
if (x < 0 || x > 100 || y < 0 || y > 100 || !areaEntry)
{
@@ -434,7 +434,7 @@ public:
}
// update to parent zone if exist (client map show only zones without parents)
- AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry;
+ AreaTableEntry const* zoneEntry = areaEntry->zone ? sAreaTableStore.LookupEntry(areaEntry->zone) : areaEntry;
ASSERT(zoneEntry);
Map const* map = sMapMgr->CreateBaseMap(zoneEntry->mapid);
diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp
index 5e8952ce881..9f2bc86f9c0 100644
--- a/src/server/scripts/Commands/cs_group.cpp
+++ b/src/server/scripts/Commands/cs_group.cpp
@@ -348,10 +348,10 @@ public:
phase = (!p->IsGameMaster() ? p->GetPhaseMask() : -1);
uint32 locale = handler->GetSessionDbcLocale();
- AreaTableEntry const* area = GetAreaEntryByAreaID(p->GetAreaId());
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(p->GetAreaId());
if (area)
{
- AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
+ AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone);
if (zone)
zoneName = zone->area_name[locale];
}
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index 4e749d33fcf..61e6acfb4d8 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -97,9 +97,9 @@ public:
wstrToLower(wNamePart);
// Search in AreaTable.dbc
- for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows(); ++areaflag)
+ for (uint32 i = 0; i < sAreaTableStore.GetNumRows(); ++i)
{
- AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(i);
if (areaEntry)
{
int locale = handler->GetSessionDbcLocale();
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 6ae509af443..c70246f7fb5 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -198,8 +198,8 @@ public:
uint32 mapId = object->GetMapId();
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
- AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zoneId);
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId);
+ AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(zoneId);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId);
float zoneX = object->GetPositionX();
float zoneY = object->GetPositionY();
@@ -961,7 +961,7 @@ public:
uint32 zoneId = player->GetZoneId();
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId);
+ AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId);
if (!areaEntry || areaEntry->zone !=0)
{
handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, graveyardId, zoneId);
@@ -1052,17 +1052,23 @@ public:
return false;
}
- int32 area = GetAreaFlagByAreaID(atoi((char*)args));
- int32 offset = area / 32;
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args));
+ if (!area)
+ {
+ handler->SendSysMessage(LANG_BAD_VALUE);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
- if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE)
+ int32 offset = area->exploreFlag / 32;
+ if (offset >= PLAYER_EXPLORED_ZONES_SIZE)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
- uint32 val = uint32((1 << (area % 32)));
+ uint32 val = uint32((1 << (area->exploreFlag % 32)));
uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset);
playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields | val)));
@@ -1083,17 +1089,23 @@ public:
return false;
}
- int32 area = GetAreaFlagByAreaID(atoi((char*)args));
- int32 offset = area / 32;
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args));
+ if (!area)
+ {
+ handler->SendSysMessage(LANG_BAD_VALUE);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
- if (area < 0 || offset >= PLAYER_EXPLORED_ZONES_SIZE)
+ int32 offset = area->exploreFlag / 32;
+ if (offset >= PLAYER_EXPLORED_ZONES_SIZE)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
- uint32 val = uint32((1 << (area % 32)));
+ uint32 val = uint32((1 << (area->exploreFlag % 32)));
uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset);
playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields ^ val)));
@@ -1737,12 +1749,12 @@ public:
// Position data
MapEntry const* map = sMapStore.LookupEntry(mapId);
- AreaTableEntry const* area = GetAreaEntryByAreaID(areaId);
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId);
if (area)
{
areaName = area->area_name[locale];
- AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone);
+ AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone);
if (zone)
zoneName = zone->area_name[locale];
}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp
index b23b9e645d0..b725f421c8f 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp
@@ -44,6 +44,13 @@ EndScriptData */
11 - Nightbane
*/
+const Position OptionalSpawn[] =
+{
+ { -10960.981445f, -1940.138428f, 46.178097f, 4.12f }, // Hyakiss the Lurker
+ { -10899.903320f, -2085.573730f, 49.474449f, 1.38f }, // Rokad the Ravager
+ { -10945.769531f, -2040.153320f, 49.474438f, 0.077f } // Shadikith the Glider
+};
+
class instance_karazhan : public InstanceMapScript
{
public:
@@ -64,6 +71,7 @@ public:
// 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
m_uiOperaEvent = urand(1, 3);
m_uiOzDeathCount = 0;
+ OptionalBossCount = 0;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
@@ -71,6 +79,7 @@ public:
uint32 m_uiOperaEvent;
uint32 m_uiOzDeathCount;
+ uint32 OptionalBossCount;
ObjectGuid m_uiCurtainGUID;
ObjectGuid m_uiStageDoorLeftGUID;
@@ -107,6 +116,29 @@ public:
}
}
+ void OnUnitDeath(Unit* unit) override
+ {
+ Creature* creature = unit->ToCreature();
+ if (!creature)
+ return;
+
+ switch (creature->GetEntry())
+ {
+ case NPC_COLDMIST_WIDOW:
+ case NPC_COLDMIST_STALKER:
+ case NPC_SHADOWBAT:
+ case NPC_VAMPIRIC_SHADOWBAT:
+ case NPC_GREATER_SHADOWBAT:
+ case NPC_PHASE_HOUND:
+ case NPC_DREADBEAST:
+ case NPC_SHADOWBEAST:
+ SetData(TYPE_OPTIONAL_BOSS, NOT_STARTED);
+ break;
+ default:
+ break;
+ }
+ }
+
void SetData(uint32 type, uint32 uiData) override
{
switch (type)
@@ -118,7 +150,28 @@ public:
m_auiEncounter[1] = uiData;
break;
case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break;
- case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break;
+ case TYPE_OPTIONAL_BOSS:
+ m_auiEncounter[3] = uiData;
+ if (uiData == NOT_STARTED)
+ {
+ ++OptionalBossCount;
+ if (OptionalBossCount == 50)
+ {
+ switch (urand(0, 2))
+ {
+ case 0:
+ instance->SummonCreature(NPC_HYAKISS_THE_LURKER, OptionalSpawn[0]);
+ break;
+ case 1:
+ instance->SummonCreature(NPC_ROKAD_THE_RAVAGER, OptionalSpawn[1]);
+ break;
+ case 2:
+ instance->SummonCreature(NPC_SHADIKITH_THE_GLIDER, OptionalSpawn[2]);
+ break;
+ }
+ }
+ }
+ break;
case TYPE_OPERA:
m_auiEncounter[4] = uiData;
if (uiData == DONE)
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h
index db68484c4a8..4d86492257c 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h
@@ -64,4 +64,20 @@ enum OperaEvents
EVENT_RAJ = 3
};
+enum MiscCreatures
+{
+ NPC_HYAKISS_THE_LURKER = 16179,
+ NPC_ROKAD_THE_RAVAGER = 16181,
+ NPC_SHADIKITH_THE_GLIDER = 16180,
+
+ // Trash
+ NPC_COLDMIST_WIDOW = 16171,
+ NPC_COLDMIST_STALKER = 16170,
+ NPC_SHADOWBAT = 16173,
+ NPC_VAMPIRIC_SHADOWBAT = 16175,
+ NPC_GREATER_SHADOWBAT = 16174,
+ NPC_PHASE_HOUND = 16178,
+ NPC_DREADBEAST = 16177,
+ NPC_SHADOWBEAST = 16176
+};
#endif
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
index b48f0edec25..6386bb50e1a 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
@@ -16,8 +16,10 @@
*/
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
#include "InstanceScript.h"
#include "magisters_terrace.h"
+#include "EventMap.h"
/*
0 - Selin Fireheart
@@ -36,6 +38,8 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM } // END
};
+Position const KalecgosSpawnPos = { 164.3747f, -397.1197f, 2.151798f, 1.66219f };
+
class instance_magisters_terrace : public InstanceMapScript
{
public:
@@ -93,6 +97,10 @@ class instance_magisters_terrace : public InstanceMapScript
case NPC_DELRISSA:
DelrissaGUID = creature->GetGUID();
break;
+ case NPC_KALECGOS:
+ case NPC_HUMAN_KALECGOS:
+ KalecgosGUID = creature->GetGUID();
+ break;
default:
break;
}
@@ -139,6 +147,25 @@ class instance_magisters_terrace : public InstanceMapScript
}
}
+ void ProcessEvent(WorldObject* obj, uint32 eventId) override
+ {
+ if (eventId == EVENT_SPAWN_KALECGOS)
+ if (!ObjectAccessor::GetCreature(*obj, KalecgosGUID) && Events.Empty())
+ Events.ScheduleEvent(EVENT_SPAWN_KALECGOS, Minutes(1));
+ }
+
+ void Update(uint32 diff) override
+ {
+ Events.Update(diff);
+
+ if (Events.ExecuteEvent() == EVENT_SPAWN_KALECGOS)
+ if (Creature* kalecgos = instance->SummonCreature(NPC_KALECGOS, KalecgosSpawnPos))
+ {
+ kalecgos->GetMotionMaster()->MovePath(PATH_KALECGOS_FLIGHT, false);
+ kalecgos->AI()->Talk(SAY_KALECGOS_SPAWN);
+ }
+ }
+
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
@@ -177,10 +204,12 @@ class instance_magisters_terrace : public InstanceMapScript
}
protected:
+ EventMap Events;
ObjectGuid SelinGUID;
ObjectGuid DelrissaGUID;
ObjectGuid KaelStatue[2];
ObjectGuid EscapeOrbGUID;
+ ObjectGuid KalecgosGUID;
uint32 DelrissaDeathCount;
};
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp
index e216a024468..5b90ac8ccf4 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp
@@ -31,7 +31,8 @@ EndContentData */
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "Player.h"
-#include "SpellInfo.h"
+#include "magisters_terrace.h"
+#include "EventMap.h"
/*######
## npc_kalecgos
@@ -39,30 +40,29 @@ EndContentData */
enum Spells
{
- SPELL_TRANSFORM_TO_KAEL = 44670,
+ SPELL_KALECGOS_TRANSFORM = 44670,
+ SPELL_TRANSFORM_VISUAL = 24085,
+ SPELL_CAMERA_SHAKE = 44762,
SPELL_ORB_KILL_CREDIT = 46307
};
-enum Creatures
+enum MovementPoints
{
- NPC_KAEL = 24848 //human form entry
+ POINT_ID_PREPARE_LANDING = 6
};
-enum Misc
+enum EventIds
{
- POINT_ID_LAND = 1
+ EVENT_KALECGOS_TRANSFORM = 1,
+ EVENT_KALECGOS_LANDING = 2
};
-const float afKaelLandPoint[] = {225.045f, -276.236f, -5.434f};
-
#define GOSSIP_ITEM_KAEL_1 "Who are you?"
#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?"
#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?"
#define GOSSIP_ITEM_KAEL_4 "You're not alone here?"
#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?"
-// This is friendly keal that appear after used Orb.
-// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is
class npc_kalecgos : public CreatureScript
{
public:
@@ -115,52 +115,46 @@ public:
struct npc_kalecgosAI : public ScriptedAI
{
- npc_kalecgosAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
+ npc_kalecgosAI(Creature* creature) : ScriptedAI(creature) { }
- void Initialize()
+ void MovementInform(uint32 type, uint32 pointId) override
{
- m_uiTransformTimer = 0;
- }
-
- uint32 m_uiTransformTimer;
-
- void Reset() override
- {
- Initialize();
-
- // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here
- if (me->GetEntry() != NPC_KAEL)
- me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]);
- }
-
- void MovementInform(uint32 uiType, uint32 uiPointId) override
- {
- if (uiType != POINT_MOTION_TYPE)
+ if (type != WAYPOINT_MOTION_TYPE)
return;
- if (uiPointId == POINT_ID_LAND)
- m_uiTransformTimer = MINUTE*IN_MILLISECONDS;
+ if (pointId == POINT_ID_PREPARE_LANDING)
+ {
+ me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
+ me->SetDisableGravity(false);
+ me->SetHover(false);
+ events.ScheduleEvent(EVENT_KALECGOS_LANDING, Seconds(2));
+ }
}
- void UpdateAI(uint32 uiDiff) override
+ void UpdateAI(uint32 diff) override
{
- if (m_uiTransformTimer)
+ events.Update(diff);
+
+ switch (events.ExecuteEvent())
{
- if (m_uiTransformTimer <= uiDiff)
- {
+ case EVENT_KALECGOS_LANDING:
+ DoCastAOE(SPELL_CAMERA_SHAKE);
+ me->SetObjectScale(0.6f);
+ events.ScheduleEvent(EVENT_KALECGOS_TRANSFORM, Seconds(1));
+ break;
+ case EVENT_KALECGOS_TRANSFORM:
DoCast(me, SPELL_ORB_KILL_CREDIT, true);
-
- // Transform and update entry, now ready for quest/read gossip
- DoCast(me, SPELL_TRANSFORM_TO_KAEL, false);
- me->UpdateEntry(NPC_KAEL);
-
- m_uiTransformTimer = 0;
- } else m_uiTransformTimer -= uiDiff;
+ DoCast(me, SPELL_TRANSFORM_VISUAL, false);
+ DoCast(me, SPELL_KALECGOS_TRANSFORM, false);
+ me->UpdateEntry(NPC_HUMAN_KALECGOS);
+ break;
+ default:
+ break;
}
}
+
+ private:
+ EventMap events;
};
};
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
index 917ad0eb50b..05718dfc1dd 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
@@ -42,7 +42,9 @@ enum CreatureIds
{
NPC_SELIN = 24723,
NPC_DELRISSA = 24560,
- NPC_FEL_CRYSTAL = 24722
+ NPC_FEL_CRYSTAL = 24722,
+ NPC_KALECGOS = 24844,
+ NPC_HUMAN_KALECGOS = 24848
};
enum GameObjectIds
@@ -57,4 +59,19 @@ enum GameObjectIds
GO_ESCAPE_ORB = 188173
};
+enum InstanceEventIds
+{
+ EVENT_SPAWN_KALECGOS = 16547
+};
+
+enum InstanceText
+{
+ SAY_KALECGOS_SPAWN = 0
+};
+
+enum MovementData
+{
+ PATH_KALECGOS_FLIGHT = 248440
+};
+
#endif
diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
index b1a00f35bb5..a01b93a140b 100644
--- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp
@@ -25,7 +25,6 @@ EndScriptData */
/* ContentData
npcs_dithers_and_arbington
-npc_myranda_the_hag
npc_the_scourge_cauldron
npc_andorhal_tower
EndContentData */
@@ -33,7 +32,6 @@ EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
-#include "ScriptedEscortAI.h"
#include "Player.h"
#include "WorldSession.h"
@@ -120,54 +118,6 @@ public:
};
/*######
-## npc_myranda_the_hag
-######*/
-
-enum Myranda
-{
- ILLUSION_GOSSIP = 4773,
- QUEST_SUBTERFUGE = 5862,
- QUEST_IN_DREAMS = 5944,
- SPELL_SCARLET_ILLUSION = 17961
-};
-
-class npc_myranda_the_hag : public CreatureScript
-{
-public:
- npc_myranda_the_hag() : CreatureScript("npc_myranda_the_hag") { }
-
- bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- {
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_SCARLET_ILLUSION, false);
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(QUEST_SUBTERFUGE) == QUEST_STATUS_COMPLETE &&
- player->GetQuestStatus(QUEST_IN_DREAMS) != QUEST_STATUS_COMPLETE &&
- !player->HasAura(SPELL_SCARLET_ILLUSION))
- {
- player->ADD_GOSSIP_ITEM_DB(Player::GetDefaultGossipMenuForSource(creature), 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(ILLUSION_GOSSIP, creature->GetGUID());
- return true;
- }
- else
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
-/*######
## npc_the_scourge_cauldron
######*/
@@ -195,7 +145,7 @@ public:
me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
//override any database `spawntimesecs` to prevent duplicated summons
uint32 rTime = me->GetRespawnDelay();
- if (rTime<600)
+ if (rTime < 600)
me->SetRespawnDelay(600);
}
@@ -274,7 +224,6 @@ public:
}
void MoveInLineOfSight(Unit* who) override
-
{
if (!who || who->GetTypeId() != TYPEID_PLAYER)
return;
@@ -286,14 +235,9 @@ public:
};
};
-/*######
-##
-######*/
-
void AddSC_western_plaguelands()
{
new npcs_dithers_and_arbington();
- new npc_myranda_the_hag();
new npc_the_scourge_cauldron();
new npc_andorhal_tower();
}
diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp
index 52a83c02a8a..50730507b8f 100644
--- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp
+++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp
@@ -31,6 +31,7 @@ EndContentData */
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "Player.h"
+#include "SpellScript.h"
/*####
# npc_ruul_snowhoof
@@ -344,9 +345,42 @@ class go_naga_brazier : public GameObjectScript
}
};
+enum KingoftheFoulwealdMisc
+{
+ GO_BANNER = 178205
+};
+
+class spell_destroy_karangs_banner : public SpellScriptLoader
+{
+ public:
+ spell_destroy_karangs_banner() : SpellScriptLoader("spell_destroy_karangs_banner") { }
+
+ class spell_destroy_karangs_banner_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_destroy_karangs_banner_SpellScript);
+
+ void HandleAfterCast()
+ {
+ if (GameObject* banner = GetCaster()->FindNearestGameObject(GO_BANNER, GetSpellInfo()->GetMaxRange(true)))
+ banner->Delete();
+ }
+
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_destroy_karangs_banner_SpellScript::HandleAfterCast);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_destroy_karangs_banner_SpellScript();
+ }
+};
+
void AddSC_ashenvale()
{
new npc_ruul_snowhoof();
new npc_muglash();
new go_naga_brazier();
+ new spell_destroy_karangs_banner();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index b8e7dcc91d5..f59701b9c25 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -1222,7 +1222,6 @@ class npc_kinetic_bomb : public CreatureScript
_x = 0.f;
_y = 0.f;
_groundZ = 0.f;
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
}
void Reset() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 0f721148b72..2db9d206a00 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -317,14 +317,12 @@ class boss_professor_putricide : public CreatureScript
// no possible aura seen in sniff adding the aurastate
summon->ModifyAuraState(AURA_STATE_UNKNOWN22, true);
summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true);
- summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
summon->SetReactState(REACT_PASSIVE);
break;
case NPC_VOLATILE_OOZE:
// no possible aura seen in sniff adding the aurastate
summon->ModifyAuraState(AURA_STATE_UNKNOWN19, true);
summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true);
- summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
summon->SetReactState(REACT_PASSIVE);
break;
case NPC_CHOKING_GAS_BOMB:
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index fd945db4604..89868fc7bf2 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -980,7 +980,7 @@ class go_celestial_planetarium_access : public GameObjectScript
bool GossipHello(Player* player) override
{
if (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE))
- return false;
+ return true;
bool hasKey = true;
if (LockEntry const* lock = sLockStore.LookupEntry(go->GetGOInfo()->goober.lockId))
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
index df5877d9220..05beacca638 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp
@@ -222,7 +222,6 @@ class npc_iron_roots : public CreatureScript
{
SetCombatMovement(false);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip
me->setFaction(14);
me->SetReactState(REACT_PASSIVE);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
index 385f7d6a69d..09d95b34521 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp
@@ -380,7 +380,6 @@ class npc_saronite_vapors : public CreatureScript
{
Talk(EMOTE_VAPORS);
instance = me->GetInstanceScript();
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip jump effect
me->SetReactState(REACT_PASSIVE);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 4d6aa046d10..f435c669935 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -1637,7 +1637,7 @@ class go_mimiron_hardmode_button : public GameObjectScript
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
if (go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE))
- return false;
+ return true;
InstanceScript* instance = go->GetInstanceScript();
if (!instance)
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index 88217cb384e..1e020edd10a 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -213,7 +213,6 @@ class npc_tournament_training_dummy : public CreatureScript
void Reset() override
{
me->SetControlled(true, UNIT_STATE_STUNNED);
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
Initialize();
// Cast Defend spells to max stack size
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 5c3ee1d7f4a..abde43ef952 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1930,10 +1930,7 @@ class spell_gen_mount : public SpellScriptLoader
if (map == 530 || (map == 571 && target->HasSpell(SPELL_COLD_WEATHER_FLYING)))
canFly = true;
- float x, y, z;
- target->GetPosition(x, y, z);
- uint32 areaFlag = target->GetBaseMap()->GetAreaFlag(x, y, z);
- AreaTableEntry const* area = sAreaStore.LookupEntry(areaFlag);
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(target->GetAreaId());
if (!area || (canFly && (area->flags & AREA_FLAG_NO_FLY_ZONE)))
canFly = false;
diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp
index 3ca2db40d65..9b577d4e140 100644
--- a/src/server/scripts/Spells/spell_rogue.cpp
+++ b/src/server/scripts/Spells/spell_rogue.cpp
@@ -41,6 +41,9 @@ enum RogueSpells
SPELL_ROGUE_SHIV_TRIGGERED = 5940,
SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933,
SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628,
+ SPELL_ROGUE_HONOR_AMONG_THIEVES = 51698,
+ SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC = 52916,
+ SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699
};
// 13877, 33735, (check 51211, 65956) - Blade Flurry
@@ -703,6 +706,143 @@ class spell_rog_tricks_of_the_trade_proc : public SpellScriptLoader
}
};
+// 51698,51700,51701 - Honor Among Thieves
+class spell_rog_honor_among_thieves : public SpellScriptLoader
+{
+public:
+ spell_rog_honor_among_thieves() : SpellScriptLoader("spell_rog_honor_among_thieves") { }
+
+ class spell_rog_honor_among_thieves_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rog_honor_among_thieves_AuraScript);
+
+ bool CheckProc(ProcEventInfo& /*eventInfo*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return false;
+
+ if (!caster->GetSpellHistory()->HasCooldown(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell))
+ return true;
+
+ return false;
+ }
+
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ Unit* target = GetTarget();
+ target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), nullptr, aurEff, caster->GetGUID());
+ }
+
+ void Register() override
+ {
+ DoCheckProc += AuraCheckProcFn(spell_rog_honor_among_thieves_AuraScript::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_rog_honor_among_thieves_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_rog_honor_among_thieves_AuraScript();
+ }
+};
+
+// 52916 - Honor Among Thieves (Proc)
+class spell_rog_honor_among_thieves_proc : public SpellScriptLoader
+{
+public:
+ spell_rog_honor_among_thieves_proc() : SpellScriptLoader("spell_rog_honor_among_thieves_proc") { }
+
+ class spell_rog_honor_among_thieves_proc_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_rog_honor_among_thieves_proc_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC))
+ return false;
+
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.clear();
+
+ Unit* target = GetOriginalCaster();
+ if (!target)
+ return;
+
+ targets.push_back(target);
+ }
+
+ void HandleBeforeHit()
+ {
+ Unit* target = GetHitUnit();
+ if (!target)
+ return;
+
+ /*
+ * The applied aura has a duration of 8 seconds
+ * This prevents new applications while its active
+ * Removing it on each new proc enables the application from different sources (different grouped players)
+ * and on new procs after the source cooldown is finished (1 second)
+ */
+ if (target->HasAura(GetSpellInfo()->Id))
+ target->RemoveAura(GetSpellInfo()->Id);
+ }
+
+ void TriggerCooldown()
+ {
+ Unit* target = GetHitUnit();
+ if (!target)
+ return;
+
+ target->GetSpellHistory()->AddCooldown(GetSpellInfo()->Id, 0, std::chrono::seconds(1));
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rog_honor_among_thieves_proc_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY);
+ BeforeHit += SpellHitFn(spell_rog_honor_among_thieves_proc_SpellScript::HandleBeforeHit);
+ AfterHit += SpellHitFn(spell_rog_honor_among_thieves_proc_SpellScript::TriggerCooldown);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_rog_honor_among_thieves_proc_SpellScript();
+ }
+
+ class spell_rog_honor_among_thieves_proc_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rog_honor_among_thieves_proc_AuraScript);
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Player* player = GetTarget()->ToPlayer())
+ if (Unit* spellTarget = ObjectAccessor::GetUnit(*player, player->GetTarget()))
+ player->CastSpell(spellTarget, SPELL_ROGUE_HONOR_AMONG_THIEVES_2, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_rog_honor_among_thieves_proc_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_rog_honor_among_thieves_proc_AuraScript();
+ }
+};
+
void AddSC_rogue_spell_scripts()
{
new spell_rog_blade_flurry();
@@ -716,4 +856,6 @@ void AddSC_rogue_spell_scripts()
new spell_rog_shiv();
new spell_rog_tricks_of_the_trade();
new spell_rog_tricks_of_the_trade_proc();
+ new spell_rog_honor_among_thieves();
+ new spell_rog_honor_among_thieves_proc();
}
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index c8b0264995b..41e72b1388b 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -55,7 +55,8 @@ enum ShamanSpells
SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB = 64695,
SPELL_SHAMAN_TOTEM_EARTHBIND_TOTEM = 6474,
SPELL_SHAMAN_TOTEM_EARTHEN_POWER = 59566,
- SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL = 52042
+ SPELL_SHAMAN_TOTEM_HEALING_STREAM_HEAL = 52042,
+ SPELL_SHAMAN_TOTEMIC_MASTERY = 38437
};
enum ShamanSpellIcons
@@ -1025,6 +1026,46 @@ class spell_sha_thunderstorm : public SpellScriptLoader
}
};
+// 38443 - Totemic Mastery (Tier 6 - 2P)
+class spell_sha_totemic_mastery : public SpellScriptLoader
+{
+public:
+ spell_sha_totemic_mastery() : SpellScriptLoader("spell_sha_totemic_mastery") { }
+
+ class spell_sha_totemic_mastery_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_sha_totemic_mastery_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_TOTEMIC_MASTERY))
+ return false;
+ return true;
+ }
+
+ void HandleDummy(AuraEffect const* /*aurEff*/)
+ {
+ Unit* target = GetTarget();
+ for (uint8 i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
+ if (!target->m_SummonSlot[i])
+ return;
+
+ target->CastSpell(target, SPELL_SHAMAN_TOTEMIC_MASTERY, true);
+ PreventDefaultAction();
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_sha_totemic_mastery_AuraScript::HandleDummy, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_sha_totemic_mastery_AuraScript();
+ }
+};
+
void AddSC_shaman_spell_scripts()
{
new spell_sha_ancestral_awakening_proc();
@@ -1048,4 +1089,5 @@ void AddSC_shaman_spell_scripts()
new spell_sha_mana_tide_totem();
new spell_sha_sentry_totem();
new spell_sha_thunderstorm();
+ new spell_sha_totemic_mastery();
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 40f9e63f4f6..56d48949fac 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -1485,7 +1485,6 @@ public:
void Reset() override
{
me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
- me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave
_events.Reset();
_damageTimes.clear();
@@ -2635,6 +2634,97 @@ public:
}
};
+enum PandarenMonkMisc
+{
+ SPELL_PANDAREN_MONK = 69800,
+ EVENT_FOCUS = 1,
+ EVENT_EMOTE = 2,
+ EVENT_FOLLOW = 3,
+ EVENT_DRINK = 4
+};
+
+class npc_pandaren_monk : public CreatureScript
+{
+public:
+ npc_pandaren_monk() : CreatureScript("npc_pandaren_monk") {}
+
+ struct npc_pandaren_monkAI : public NullCreatureAI
+ {
+ npc_pandaren_monkAI(Creature* creature) : NullCreatureAI(creature) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_FOCUS, 1000);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (!_EnterEvadeMode(why))
+ return;
+
+ Reset();
+ }
+
+ void ReceiveEmote(Player* /*player*/, uint32 emote) override
+ {
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ me->StopMoving();
+
+ switch (emote)
+ {
+ case TEXT_EMOTE_BOW:
+ _events.ScheduleEvent(EVENT_FOCUS, 1000);
+ break;
+ case TEXT_EMOTE_DRINK:
+ _events.ScheduleEvent(EVENT_DRINK, 1000);
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ if (Unit* owner = me->GetCharmerOrOwner())
+ if (!me->IsWithinDist(owner, 30.f))
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FOCUS:
+ if (Unit* owner = me->GetCharmerOrOwner())
+ me->SetFacingToObject(owner);
+ _events.ScheduleEvent(EVENT_EMOTE, 1000);
+ break;
+ case EVENT_EMOTE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
+ _events.ScheduleEvent(EVENT_FOLLOW, 1000);
+ break;
+ case EVENT_FOLLOW:
+ if (Unit* owner = me->GetCharmerOrOwner())
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ break;
+ case EVENT_DRINK:
+ me->CastSpell(me, SPELL_PANDAREN_MONK, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_pandaren_monkAI(creature);
+ }
+};
+
void AddSC_npcs_special()
{
new npc_air_force_bots();
@@ -2661,4 +2751,5 @@ void AddSC_npcs_special()
new npc_stable_master();
new npc_train_wrecker();
new npc_egbert();
+ new npc_pandaren_monk();
}
diff --git a/src/server/shared/Containers.h b/src/server/shared/Containers.h
deleted file mode 100644
index c2ebbf58a1e..00000000000
--- a/src/server/shared/Containers.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_CONTAINERS_H
-#define TRINITY_CONTAINERS_H
-
-#include "Define.h"
-#include <list>
-
-//! Because circular includes are bad
-extern uint32 urand(uint32 min, uint32 max);
-
-namespace Trinity
-{
- namespace Containers
- {
- template<class T>
- void RandomResizeList(std::list<T> &list, uint32 size)
- {
- size_t list_size = list.size();
-
- while (list_size > size)
- {
- typename std::list<T>::iterator itr = list.begin();
- std::advance(itr, urand(0, list_size - 1));
- list.erase(itr);
- --list_size;
- }
- }
-
- template<class T, class Predicate>
- void RandomResizeList(std::list<T> &list, Predicate& predicate, uint32 size)
- {
- //! First use predicate filter
- std::list<T> listCopy;
- for (typename std::list<T>::iterator itr = list.begin(); itr != list.end(); ++itr)
- if (predicate(*itr))
- listCopy.push_back(*itr);
-
- if (size)
- RandomResizeList(listCopy, size);
-
- list = listCopy;
- }
-
- /* Select a random element from a container. Note: make sure you explicitly empty check the container */
- template <class C> typename C::value_type const& SelectRandomContainerElement(C const& container)
- {
- typename C::const_iterator it = container.begin();
- std::advance(it, urand(0, container.size() - 1));
- return *it;
- }
-
- /**
- * @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
- *
- * @brief Checks if two SORTED containers have a common element
- *
- * @param first1 Iterator pointing to start of the first container
- * @param last1 Iterator pointing to end of the first container
- * @param first2 Iterator pointing to start of the second container
- * @param last2 Iterator pointing to end of the second container
- *
- * @return true if containers have a common element, false otherwise.
- */
- template<class Iterator1, class Iterator2>
- bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
- {
- while (first1 != last1 && first2 != last2)
- {
- if (*first1 < *first2)
- ++first1;
- else if (*first2 < *first1)
- ++first2;
- else
- return true;
- }
-
- return false;
- }
-
- template<class K, class V, template<class, class, class...> class M, class... Rest>
- void MultimapErasePair(M<K, V, Rest...>& multimap, K const& key, V const& value)
- {
- auto range = multimap.equal_range(key);
- for (auto itr = range.first; itr != range.second;)
- {
- if (itr->second == value)
- itr = multimap.erase(itr);
- else
- ++itr;
- }
- }
-
- }
- //! namespace Containers
-}
-//! namespace Trinity
-
-#endif //! #ifdef TRINITY_CONTAINERS_H