mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-06 06:47:53 +00:00
8
data/sql/updates/db_world/2026_05_06_00.sql
Normal file
8
data/sql/updates/db_world/2026_05_06_00.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- DB update 2026_05_05_04 -> 2026_05_06_00
|
||||
|
||||
-- Set SAI
|
||||
UPDATE `gameobject_template` SET `AIName` = 'SmartGameObjectAI' WHERE `entry` = 186565;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 1 AND `entryorguid` = 186565);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(186565, 1, 0, 0, 64, 0, 100, 0, 1, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ceremonial Dragonflayer Harpoon - On Gossip Hello - Despawn Instant');
|
||||
4
data/sql/updates/db_world/2026_05_07_00.sql
Normal file
4
data/sql/updates/db_world/2026_05_07_00.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- DB update 2026_05_06_00 -> 2026_05_07_00
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = -48323;
|
||||
INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
|
||||
(-48323, 48330, 0, 'On Indisposed Expiring - Cast Create Amberseeds');
|
||||
7
data/sql/updates/db_world/2026_05_07_01.sql
Normal file
7
data/sql/updates/db_world/2026_05_07_01.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- DB update 2026_05_07_00 -> 2026_05_07_01
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28521) AND (`source_type` = 0) AND (`id` IN (11));
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(28521, 0, 11, 5, 8, 0, 100, 0, 51910, 0, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Nass - On Spellhit \'Kickin` Nass: Quest Completion\' - Despawn Instant');
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` = 51910;
|
||||
3
data/sql/updates/db_world/2026_05_08_00.sql
Normal file
3
data/sql/updates/db_world/2026_05_08_00.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
-- DB update 2026_05_07_01 -> 2026_05_08_00
|
||||
UPDATE `conditions` SET `ConditionTypeOrReference` = 25 WHERE `SourceTypeOrReferenceId` = 14 AND `SourceGroup` = 1945 AND `SourceEntry` = 2605 AND `ConditionTypeOrReference` = 16 AND `ConditionValue1` = 14891 AND `NegativeCondition` = 1;
|
||||
UPDATE `conditions` SET `ConditionTypeOrReference` = 25 WHERE `SourceTypeOrReferenceId` = 15 AND `SourceGroup` = 1945 AND `SourceEntry` = 0 AND `ConditionTypeOrReference` = 16 AND `ConditionValue1` = 14891 AND `NegativeCondition` = 1;
|
||||
@@ -4360,14 +4360,6 @@ AllowTwoSide.Interaction.Calendar = 0
|
||||
|
||||
AllowTwoSide.Interaction.Chat = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Interaction.Emote
|
||||
# Description: Allow emote messages between factions (e.g. "/e looks into the sky")
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.Interaction.Emote = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Interaction.Channel
|
||||
# Description: Allow channel chat between factions.
|
||||
@@ -4409,38 +4401,6 @@ AllowTwoSide.Interaction.Arena = 0
|
||||
|
||||
AllowTwoSide.Interaction.Auction = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Interaction.Mail
|
||||
# Description: Allow sending mails between factions.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.Interaction.Mail = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.WhoList
|
||||
# Description: Show characters from both factions in the /who list.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.WhoList = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.AddFriend
|
||||
# Description: Allow adding friends from other faction the friends list.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.AddFriend = 0
|
||||
|
||||
#
|
||||
# AllowTwoSide.Trade
|
||||
# Description: Allow trading between factions.
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
AllowTwoSide.Trade = 0
|
||||
|
||||
#
|
||||
# TalentsInspecting
|
||||
# Description: Allow inspecting characters from the opposing faction.
|
||||
|
||||
@@ -364,6 +364,7 @@ void Battlefield::EndBattle(bool endByTimer)
|
||||
DoPlaySoundToAll(BF_HORDE_WINS);
|
||||
|
||||
OnBattleEnd(endByTimer);
|
||||
sScriptMgr->OnBattlefieldWarEnd(this, endByTimer);
|
||||
|
||||
// Reset battlefield timer
|
||||
Timer = NoWarBattleTime;
|
||||
|
||||
@@ -206,6 +206,10 @@ void ThreatReference::HeapNotifyDecreased()
|
||||
if (tWho->GetSummonerGUID().IsPlayer())
|
||||
return false;
|
||||
|
||||
// accessories are fully treated as components of the parent and cannot have threat
|
||||
if (cWho->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -396,15 +400,6 @@ void ThreatManager::AddThreat(Unit* target, float amount, SpellInfo const* spell
|
||||
return;
|
||||
}
|
||||
|
||||
// while riding a vehicle, all threat goes to the vehicle, not the pilot
|
||||
if (Unit* vehicle = target->GetVehicleBase())
|
||||
{
|
||||
AddThreat(vehicle, amount, spell, ignoreModifiers, ignoreRedirects);
|
||||
if (target->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) // accessories are fully treated as components of the parent and cannot have threat
|
||||
return;
|
||||
amount = 0.0f;
|
||||
}
|
||||
|
||||
// if we cannot actually have a threat list, we instead just set combat state and avoid creating threat refs altogether
|
||||
if (!CanHaveThreatList())
|
||||
{
|
||||
|
||||
@@ -15426,6 +15426,15 @@ void Player::ActivateSpec(uint8 spec)
|
||||
++iter;
|
||||
}
|
||||
|
||||
// Recheck shapeshift bonus auras: drop and re-apply form-tied passives
|
||||
// so buffs from talents missing in the new spec (e.g. Master Shapeshifter) go away
|
||||
Unit::AuraEffectList const& shapeshiftAuras = GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
for (AuraEffect* aurEff : shapeshiftAuras)
|
||||
{
|
||||
aurEff->HandleShapeshiftBoosts(this, false);
|
||||
aurEff->HandleShapeshiftBoosts(this, true);
|
||||
}
|
||||
|
||||
sScriptMgr->OnPlayerAfterSpecSlotChanged(this, GetActiveSpec());
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,10 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
|
||||
if (TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime))
|
||||
{
|
||||
if (minion)
|
||||
{
|
||||
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
|
||||
accessory->GetThreatMgr().Initialize(); // reinitialize CanHaveThreatList cached value
|
||||
}
|
||||
|
||||
if (!_me->HandleSpellClick(accessory, seatId))
|
||||
{
|
||||
@@ -455,9 +458,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
init.SetTransportEnter();
|
||||
init.Launch();
|
||||
|
||||
// Transfer threat from passenger to vehicle
|
||||
// Put the vehicle in combat with anything that was threatening the passenger; the threat itself stays on the passenger
|
||||
for (auto const& [guid, threatRef] : unit->GetThreatMgr().GetThreatenedByMeList())
|
||||
threatRef->GetOwner()->GetThreatMgr().AddThreat(_me, threatRef->GetThreat(), nullptr, true, true);
|
||||
threatRef->GetOwner()->GetThreatMgr().AddThreat(_me, 0.0f, nullptr, true, true);
|
||||
|
||||
if (_me->IsCreature())
|
||||
{
|
||||
|
||||
@@ -214,7 +214,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
|
||||
uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sCharacterCache->GetCharacterAccountIdByGuid(receiverGuid);
|
||||
|
||||
if (/*!accountBound*/ GetAccountId() != rc_account && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeamId() != rc_teamId && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL))
|
||||
if (/*!accountBound*/ GetAccountId() != rc_account && player->GetTeamId() != rc_teamId && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL))
|
||||
{
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM);
|
||||
return;
|
||||
|
||||
@@ -293,7 +293,6 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
|
||||
|
||||
for (auto const& target : sWhoListCacheMgr->GetWhoList())
|
||||
{
|
||||
// player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST
|
||||
if (target.GetTeamId() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
if (friendGuid == GetPlayer()->GetGUID())
|
||||
friendResult = FRIEND_SELF;
|
||||
else if (GetPlayer()->GetTeamId() != teamId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
|
||||
else if (GetPlayer()->GetTeamId() != teamId && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
|
||||
friendResult = FRIEND_ENEMY;
|
||||
else if (GetPlayer()->GetSocial()->HasFriend(friendGuid))
|
||||
friendResult = FRIEND_ALREADY;
|
||||
|
||||
@@ -723,7 +723,6 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
|
||||
}
|
||||
|
||||
if (pOther->GetTeamId() != _player->GetTeamId() &&
|
||||
!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) &&
|
||||
!GetPlayer()->GetSession()->HasPermission(rbac::RBAC_PERM_ALLOW_TWO_SIDE_TRADE))
|
||||
{
|
||||
info.Status = TRADE_STATUS_WRONG_FACTION;
|
||||
|
||||
@@ -44,6 +44,11 @@ void ScriptMgr::OnBattlefieldBeforeInvitePlayerToWar(Battlefield* bf, Player* pl
|
||||
CALL_ENABLED_HOOKS(BattlefieldScript, BATTLEFIELDHOOK_BEFORE_INVITE_PLAYER_TO_WAR, script->OnBattlefieldBeforeInvitePlayerToWar(bf, player));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnBattlefieldWarEnd(Battlefield* bf, bool endByTimer)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(BattlefieldScript, BATTLEFIELDHOOK_ON_WAR_END, script->OnBattlefieldWarEnd(bf, endByTimer));
|
||||
}
|
||||
|
||||
BattlefieldScript::BattlefieldScript(char const* name, std::vector<uint16> enabledHooks) :
|
||||
ScriptObject(name, BATTLEFIELDHOOK_END)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ enum BattlefieldHook
|
||||
BATTLEFIELDHOOK_ON_PLAYER_JOIN_WAR, // 2 - fires after player is added to the active war
|
||||
BATTLEFIELDHOOK_ON_PLAYER_LEAVE_WAR, // 3 - fires after player is removed from the active war
|
||||
BATTLEFIELDHOOK_BEFORE_INVITE_PLAYER_TO_WAR, // 4 - fires in InvitePlayerToWar before InvitedPlayers insert
|
||||
BATTLEFIELDHOOK_ON_WAR_END, // 5 - fires in EndBattle after OnBattleEnd(), before timer reset
|
||||
BATTLEFIELDHOOK_END
|
||||
};
|
||||
|
||||
@@ -87,6 +88,17 @@ public:
|
||||
* @param player The player being invited to war
|
||||
*/
|
||||
virtual void OnBattlefieldBeforeInvitePlayerToWar(Battlefield* /*bf*/, Player* /*player*/) { }
|
||||
|
||||
/**
|
||||
* @brief Called in EndBattle() after OnBattleEnd() completes, before the timer is reset.
|
||||
* All core PlayersInWar/InvitedPlayers structures have already been cleared.
|
||||
* Modules that maintain their own per-war player tracking should use this hook
|
||||
* to perform end-of-war cleanup (e.g. restoring cross-faction disguises).
|
||||
*
|
||||
* @param bf The Battlefield instance
|
||||
* @param endByTimer True if the war ended by the countdown timer expiring
|
||||
*/
|
||||
virtual void OnBattlefieldWarEnd(Battlefield* /*bf*/, bool /*endByTimer*/) { }
|
||||
};
|
||||
|
||||
#endif // SCRIPT_OBJECT_BATTLEFIELD_SCRIPT_H_
|
||||
|
||||
@@ -608,6 +608,7 @@ public: /* BattlefieldScript */
|
||||
void OnBattlefieldPlayerJoinWar(Battlefield* bf, Player* player);
|
||||
void OnBattlefieldPlayerLeaveWar(Battlefield* bf, Player* player);
|
||||
void OnBattlefieldBeforeInvitePlayerToWar(Battlefield* bf, Player* player);
|
||||
void OnBattlefieldWarEnd(Battlefield* bf, bool endByTimer);
|
||||
|
||||
public: /* BGScript */
|
||||
void OnBattlegroundStart(Battleground* bg);
|
||||
|
||||
@@ -1532,7 +1532,11 @@ void Spell::EffectHeal(SpellEffIndex effIndex)
|
||||
|
||||
int32 tickheal = targetAura->GetAmount();
|
||||
if (Unit* auraCaster = targetAura->GetCaster())
|
||||
{
|
||||
// MOD_HEALING_DONE_PERCENT is applied per-tick, not baked into GetAmount.
|
||||
tickheal = int32(float(tickheal) * auraCaster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT));
|
||||
tickheal = unitTarget->SpellHealingBonusTaken(auraCaster, targetAura->GetSpellInfo(), tickheal, DOT);
|
||||
}
|
||||
|
||||
//int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
|
||||
//It is said that talent bonus should not be included
|
||||
|
||||
@@ -204,11 +204,6 @@ void WorldConfig::BuildConfigCache()
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD, "AllowTwoSide.Interaction.Guild", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA, "AllowTwoSide.Interaction.Arena", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION, "AllowTwoSide.Interaction.Auction", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL, "AllowTwoSide.Interaction.Mail", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_WHO_LIST, "AllowTwoSide.WhoList", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND, "AllowTwoSide.AddFriend", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_TRADE, "AllowTwoSide.Trade", false);
|
||||
SetConfigValue<bool>(CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE, "AllowTwoSide.Interaction.Emote", false);
|
||||
|
||||
SetConfigValue<uint32>(CONFIG_MIN_PLAYER_NAME, "MinPlayerName", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= MAX_PLAYER_NAME; }, "> 0 && <= MAX_PLAYER_NAME");
|
||||
SetConfigValue<uint32>(CONFIG_MIN_CHARTER_NAME, "MinCharterName", 2, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0 && value <= MAX_CHARTER_NAME; }, "> 0 && <= MAX_CHARTER_NAME");
|
||||
|
||||
@@ -35,10 +35,6 @@ enum ServerConfigs
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
|
||||
CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
|
||||
CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND,
|
||||
CONFIG_ALLOW_TWO_SIDE_TRADE,
|
||||
CONFIG_ALL_TAXI_PATHS,
|
||||
CONFIG_INSTANCE_IGNORE_LEVEL,
|
||||
CONFIG_INSTANCE_IGNORE_RAID,
|
||||
@@ -119,7 +115,6 @@ enum ServerConfigs
|
||||
CONFIG_CLOSE_IDLE_CONNECTIONS,
|
||||
CONFIG_LFG_LOCATION_ALL,
|
||||
CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS,
|
||||
CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE,
|
||||
CONFIG_ITEMDELETE_METHOD,
|
||||
CONFIG_ITEMDELETE_VENDOR,
|
||||
CONFIG_DEBUG_BATTLEGROUND,
|
||||
|
||||
@@ -74,8 +74,10 @@ public:
|
||||
|
||||
static RBACCommandData GetRBACData(uint32 accountId, std::string const& accountName)
|
||||
{
|
||||
// session->GetRBACData() can be null after World::ReloadRBAC()
|
||||
if (WorldSession* session = sWorldSessionMgr->FindSession(accountId))
|
||||
return { session->GetRBACData(), false };
|
||||
if (rbac::RBACData* sessionRbac = session->GetRBACData())
|
||||
return { sessionRbac, false };
|
||||
|
||||
rbac::RBACData* rbac = new rbac::RBACData(accountId, accountName, realm.Id.Realm, AccountMgr::GetSecurity(accountId, realm.Id.Realm));
|
||||
rbac->LoadFromDB();
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
case 5:
|
||||
_owner.SetFacingTo(2.82f);
|
||||
_owner.SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
_owner.m_Events.AddEventAtOffset(new UtherBatteredHiltEvent(_owner, 6), 3s);
|
||||
break;
|
||||
case 6:
|
||||
if (InstanceScript* inst = _owner.GetInstanceScript())
|
||||
|
||||
@@ -709,11 +709,10 @@ struct boss_malygos : public BossAI
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, NPC_MALYGOS, 1);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
|
||||
@@ -3774,7 +3774,6 @@ private:
|
||||
29435 - Capture Female Kaliri Hatchling
|
||||
42268 - Quest - Mindless Abomination Explosion FX Master
|
||||
51592 - Pickup Primordial Hatchling
|
||||
51910 - Kickin' Nass: Quest Completion
|
||||
52267 - Despawn Horse
|
||||
54420 - Deliver Gryphon */
|
||||
class spell_gen_despawn_self : public SpellScript
|
||||
|
||||
@@ -70,14 +70,14 @@ Player* NPCStaveQuestAI::GetGossipPlayer()
|
||||
return ObjectAccessor::GetPlayer(*me, gossipPlayerGUID);
|
||||
}
|
||||
|
||||
bool NPCStaveQuestAI::IsAllowedEntry(uint32 entry)
|
||||
bool NPCStaveQuestAI::IsAllowedEntry(uint32 entry) const
|
||||
{
|
||||
uint32 allowedEntries[4] = { 0, 12999, 19833, 19921 }; //player, World Invisible Trigger(traps) and snake trap snakes
|
||||
bool isAllowed = std::find(std::begin(allowedEntries), std::end(allowedEntries), entry) != std::end(allowedEntries);
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit)
|
||||
bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit) const
|
||||
{
|
||||
if (!unit || playerGUID.IsEmpty())
|
||||
{
|
||||
@@ -108,7 +108,7 @@ bool NPCStaveQuestAI::UnitIsUnfair(Unit* unit)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NPCStaveQuestAI::IsFairFight()
|
||||
bool NPCStaveQuestAI::IsFairFight() const
|
||||
{
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
@@ -128,12 +128,10 @@ bool NPCStaveQuestAI::IsFairFight()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NPCStaveQuestAI::ValidThreatlist()
|
||||
bool NPCStaveQuestAI::ValidThreatlist() const
|
||||
{
|
||||
if (me->GetThreatMgr().GetThreatListSize() == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isFair = IsFairFight();
|
||||
|
||||
@@ -463,10 +461,10 @@ public:
|
||||
|
||||
struct npc_preciousAI : public NPCStaveQuestAI
|
||||
{
|
||||
npc_preciousAI(Creature *creature) : NPCStaveQuestAI(creature) { }
|
||||
explicit npc_preciousAI(Creature *creature) : NPCStaveQuestAI(creature) { }
|
||||
|
||||
EventMap events;
|
||||
bool flaggedForDespawn;
|
||||
bool flaggedForDespawn{};
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
@@ -512,6 +510,37 @@ public:
|
||||
{
|
||||
flaggedForDespawn = true;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_SIMONE_VALID_THREATLIST)
|
||||
return ValidThreatlist() ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_SIMONE_REVEAL:
|
||||
if (data)
|
||||
RevealForm();
|
||||
break;
|
||||
case DATA_SIMONE_PREPARE_ENCOUNTER:
|
||||
PrepareForEncounter();
|
||||
break;
|
||||
case DATA_SIMONE_SET_HOME:
|
||||
SetHomePosition();
|
||||
break;
|
||||
case DATA_SIMONE_CORPSE_REMOVED:
|
||||
EnterEvadeMode();
|
||||
FlagForDespawn();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -527,7 +556,7 @@ public:
|
||||
|
||||
struct npc_simoneAI : public NPCStaveQuestAI
|
||||
{
|
||||
npc_simoneAI(Creature *creature) : NPCStaveQuestAI(creature) { }
|
||||
explicit npc_simoneAI(Creature *creature) : NPCStaveQuestAI(creature) { }
|
||||
|
||||
EventMap events;
|
||||
ObjectGuid preciousGUID;
|
||||
@@ -535,39 +564,18 @@ public:
|
||||
void SetPreciousGUID()
|
||||
{
|
||||
if (CreatureGroup* formation = me->GetFormation())
|
||||
{
|
||||
const CreatureGroup::CreatureGroupMemberType& members = formation->GetMembers();
|
||||
for (CreatureGroup::CreatureGroupMemberType::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (itr->first && itr->first->GetOriginalEntry() == PRECIOUS_NORMAL_ENTRY)
|
||||
{
|
||||
preciousGUID = itr->first->GetGUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
for ([[maybe_unused]] auto const& [member, info] : formation->GetMembers())
|
||||
if (member && member->GetOriginalEntry() == PRECIOUS_NORMAL_ENTRY)
|
||||
preciousGUID = member->GetGUID();
|
||||
}
|
||||
|
||||
Creature* Precious()
|
||||
{
|
||||
if (preciousGUID.IsEmpty())
|
||||
{
|
||||
SetPreciousGUID();
|
||||
}
|
||||
|
||||
if (!preciousGUID.IsEmpty())
|
||||
{
|
||||
return ObjectAccessor::GetCreature(*me, preciousGUID);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
npc_precious::npc_preciousAI* PreciousAI()
|
||||
{
|
||||
if (Precious())
|
||||
{
|
||||
return CAST_AI(npc_precious::npc_preciousAI, Precious()->AI());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -632,21 +640,20 @@ public:
|
||||
|
||||
void CorpseRemoved(uint32& /*respawnDelay*/) override
|
||||
{
|
||||
if (!Precious())
|
||||
{
|
||||
Creature* creature = Precious();
|
||||
if (!creature)
|
||||
return;
|
||||
}
|
||||
|
||||
if (Precious()->IsInCombat())
|
||||
if (creature->IsInCombat())
|
||||
{
|
||||
// If Simone corpse is removed but pet is InCombat, EnterEvadeMode and auto despawn on pet reaching home
|
||||
PreciousAI()->EnterEvadeMode();
|
||||
PreciousAI()->FlagForDespawn();
|
||||
// If Simone corpse is removed but pet is InCombat, ask pet AI to enter evade and flag for despawn
|
||||
if (creature->AI())
|
||||
creature->AI()->SetData(DATA_SIMONE_CORPSE_REMOVED, 1);
|
||||
else
|
||||
creature->DespawnOrUnsummon(0ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
Precious()->DespawnOrUnsummon(0ms);
|
||||
}
|
||||
creature->DespawnOrUnsummon(0ms);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
@@ -704,10 +711,9 @@ public:
|
||||
break;
|
||||
case EVENT_REVEAL:
|
||||
RevealForm();
|
||||
if (PreciousAI())
|
||||
{
|
||||
PreciousAI()->RevealForm();
|
||||
}
|
||||
if (Creature* creature = Precious())
|
||||
if (creature->AI())
|
||||
creature->AI()->SetData(DATA_SIMONE_REVEAL, 1);
|
||||
break;
|
||||
// Prevent hunters from figthing Simone alone
|
||||
case SIMONE_EVENT_CHECK_PET_STATE:
|
||||
@@ -721,6 +727,8 @@ public:
|
||||
events.ScheduleEvent(SIMONE_EVENT_CHECK_PET_STATE, 1s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (UpdateVictim())
|
||||
@@ -760,23 +768,32 @@ public:
|
||||
}
|
||||
break;
|
||||
case EVENT_UNFAIR_FIGHT:
|
||||
if (!ValidThreatlist() || (PreciousAI() && !PreciousAI()->ValidThreatlist()))
|
||||
{
|
||||
Creature* creature = Precious();
|
||||
bool isPreciousThreatListValid = creature && creature->AI() && creature->AI()->GetData(DATA_SIMONE_VALID_THREATLIST) == 1;
|
||||
|
||||
if (!ValidThreatlist() || !isPreciousThreatListValid)
|
||||
{
|
||||
SetHomePosition();
|
||||
PreciousAI()->SetHomePosition();
|
||||
|
||||
Precious()->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
Precious()->SetImmuneToAll(true);
|
||||
me->DespawnOrUnsummon(5s);
|
||||
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
me->SetImmuneToAll(true);
|
||||
|
||||
Precious()->DespawnOrUnsummon(5s);
|
||||
if (creature)
|
||||
{
|
||||
if (creature->AI())
|
||||
creature->AI()->SetData(DATA_SIMONE_SET_HOME, 1);
|
||||
|
||||
creature->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1);
|
||||
creature->SetImmuneToAll(true);
|
||||
creature->DespawnOrUnsummon(5s);
|
||||
}
|
||||
|
||||
me->DespawnOrUnsummon(5s);
|
||||
break;
|
||||
}
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
}
|
||||
case SIMONE_EVENT_CHAIN_LIGHTNING:
|
||||
me->CastSpell(me->GetVictim(), SIMONE_SPELL_CHAIN_LIGHTNING, false);
|
||||
events.Repeat(7s);
|
||||
@@ -785,6 +802,8 @@ public:
|
||||
me->CastSpell(me->GetVictim(), SIMONE_SPELL_TEMPTRESS_KISS, false);
|
||||
events.Repeat(45s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
@@ -805,10 +824,10 @@ public:
|
||||
void ScheduleEncounterStart(ObjectGuid playerGUID)
|
||||
{
|
||||
PrepareForEncounter();
|
||||
if (PreciousAI())
|
||||
{
|
||||
PreciousAI()->PrepareForEncounter();
|
||||
}
|
||||
if (Creature* creature = Precious())
|
||||
if (creature->AI())
|
||||
creature->AI()->SetData(DATA_SIMONE_PREPARE_ENCOUNTER, 1);
|
||||
|
||||
gossipPlayerGUID = playerGUID;
|
||||
events.ScheduleEvent(EVENT_ENCOUNTER_START, 1s);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,15 @@ enum NPCPrecious
|
||||
PRECIOUS_EVIL_ENTRY = 14538
|
||||
};
|
||||
|
||||
enum SimoneAIData
|
||||
{
|
||||
DATA_SIMONE_REVEAL = 1,
|
||||
DATA_SIMONE_PREPARE_ENCOUNTER = 2,
|
||||
DATA_SIMONE_VALID_THREATLIST = 3,
|
||||
DATA_SIMONE_SET_HOME = 4,
|
||||
DATA_SIMONE_CORPSE_REMOVED = 5
|
||||
};
|
||||
|
||||
enum NPCNelson
|
||||
{
|
||||
NELSON_EVENT_DREADFUL_FRIGHT = 6,
|
||||
@@ -189,10 +198,10 @@ struct NPCStaveQuestAI : public ScriptedAI
|
||||
void RevealForm();
|
||||
void StorePlayerGUID();
|
||||
Player* GetGossipPlayer();
|
||||
bool IsAllowedEntry(uint32 /*entry*/);
|
||||
bool UnitIsUnfair(Unit* unit);
|
||||
bool IsFairFight();
|
||||
bool ValidThreatlist();
|
||||
bool IsAllowedEntry(uint32 /*entry*/) const;
|
||||
bool UnitIsUnfair(Unit* unit) const;
|
||||
bool IsFairFight() const;
|
||||
bool ValidThreatlist() const;
|
||||
void SetHomePosition();
|
||||
void PrepareForEncounter();
|
||||
void ClearLootIfUnfair(Unit* killer);
|
||||
|
||||
Reference in New Issue
Block a user