Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-12-27 09:50:12 -07:00
committed by GitHub
69 changed files with 2944 additions and 83 deletions
+12 -1
View File
@@ -578,7 +578,12 @@ void PetAI::SpellHit(Unit* caster, SpellInfo const* spellInfo)
{
me->GetCharmInfo()->SetForcedSpell(0);
me->GetCharmInfo()->SetForcedTargetGUID();
AttackStart(caster);
if (CanAttack(caster, spellInfo))
{
// Only chase if not commanded to stay or if stay but commanded to attack
DoAttack(caster, (!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) || me->GetCharmInfo()->IsCommandAttack()));
}
}
}
@@ -709,6 +714,12 @@ bool PetAI::CanAttack(Unit* target, SpellInfo const* spellInfo)
// Pets attacking something (or chasing) should only switch targets if owner tells them to
if (me->GetVictim() && me->GetVictim() != target)
{
// Forced change target if it's taunt
if (spellInfo && spellInfo->HasAura(SPELL_AURA_MOD_TAUNT))
{
return true;
}
// Check if our owner selected this target and clicked "attack"
Unit* ownerTarget = nullptr;
if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
@@ -316,6 +316,7 @@ void SmartAIMgr::LoadSmartAIFromDB()
case SMART_EVENT_DEATH:
case SMART_EVENT_KILL:
case SMART_EVENT_SUMMONED_UNIT:
case SMART_EVENT_SUMMONED_UNIT_DIES:
case SMART_EVENT_SPELLHIT:
case SMART_EVENT_SPELLHIT_TARGET:
case SMART_EVENT_DAMAGED:
@@ -194,10 +194,15 @@ enum SMART_EVENT
SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat
SMART_EVENT_COUNTER_SET = 77, // id, value, cooldownMin, cooldownMax
SMART_EVENT_TC_END = 78,
SMART_EVENT_SCENE_START = 78, // don't use on 3.3.5a
SMART_EVENT_SCENE_TRIGGER = 79, // don't use on 3.3.5a
SMART_EVENT_SCENE_CANCEL = 80, // don't use on 3.3.5a
SMART_EVENT_SCENE_COMPLETE = 81, // don't use on 3.3.5a
SMART_EVENT_SUMMONED_UNIT_DIES = 82, // CreatureId(0 all), CooldownMin, CooldownMax
SMART_EVENT_TC_END = 83,
/* AC Custom Events */
SMART_EVENT_AC_START = 100,
+24 -16
View File
@@ -269,7 +269,7 @@ namespace lfg
// Recalculate locked dungeons
for (LfgPlayerDataContainer::const_iterator it = PlayersStore.begin(); it != PlayersStore.end(); ++it)
if (Player* player = ObjectAccessor::FindConnectedPlayer(it->first))
InitializeLockedDungeons(player);
InitializeLockedDungeons(player, nullptr);
}
}
@@ -388,11 +388,10 @@ namespace lfg
@param[in] player Player we need to initialize the lock status map
*/
void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */)
void LFGMgr::InitializeLockedDungeons(Player* player, Group const* group)
{
ObjectGuid guid = player->GetGUID();
if (!level)
level = player->getLevel();
uint8 level = player->getLevel();
uint8 expansion = player->GetSession()->Expansion();
LfgDungeonSet const& dungeons = GetDungeonsByRandom(0);
LfgLockMap lock;
@@ -429,12 +428,15 @@ namespace lfg
// Check required items
for (const ProgressionRequirement* itemRequirement : ar->items)
{
if (itemRequirement->faction == TEAM_NEUTRAL || itemRequirement->faction == player->GetTeamId(true))
if (!itemRequirement->checkLeaderOnly || !group || group->GetLeaderGUID() == player->GetGUID())
{
if (!player->HasItemCount(itemRequirement->id, 1))
if (itemRequirement->faction == TEAM_NEUTRAL || itemRequirement->faction == player->GetTeamId(true))
{
lockData = LFG_LOCKSTATUS_MISSING_ITEM;
break;
if (!player->HasItemCount(itemRequirement->id, 1))
{
lockData = LFG_LOCKSTATUS_MISSING_ITEM;
break;
}
}
}
}
@@ -442,12 +444,15 @@ namespace lfg
//Check for quests
for (const ProgressionRequirement* questRequirement : ar->quests)
{
if (questRequirement->faction == TEAM_NEUTRAL || questRequirement->faction == player->GetTeamId(true))
if (!questRequirement->checkLeaderOnly || !group || group->GetLeaderGUID() == player->GetGUID())
{
if (!player->GetQuestRewardStatus(questRequirement->id))
if (questRequirement->faction == TEAM_NEUTRAL || questRequirement->faction == player->GetTeamId(true))
{
lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
break;
if (!player->GetQuestRewardStatus(questRequirement->id))
{
lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
break;
}
}
}
}
@@ -461,12 +466,15 @@ namespace lfg
//Check if player has the required achievements
for (const ProgressionRequirement* achievementRequirement : ar->achievements)
{
if (achievementRequirement->faction == TEAM_NEUTRAL || achievementRequirement->faction == player->GetTeamId(true))
if (!achievementRequirement->checkLeaderOnly || !group || group->GetLeaderGUID() == player->GetGUID())
{
if (!player->HasAchieved(achievementRequirement->id))
if (achievementRequirement->faction == TEAM_NEUTRAL || achievementRequirement->faction == player->GetTeamId(true))
{
lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT;
break;
if (!player->HasAchieved(achievementRequirement->id))
{
lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT;
break;
}
}
}
}
+1 -1
View File
@@ -491,7 +491,7 @@ namespace lfg
/// Get leader of the group (using internal data)
ObjectGuid GetLeader(ObjectGuid guid);
/// Initializes locked dungeons for given player (called at login or level change)
void InitializeLockedDungeons(Player* player, uint8 level = 0);
void InitializeLockedDungeons(Player* player, Group const* group = nullptr);
/// Sets player team
void SetTeam(ObjectGuid guid, TeamId teamId);
/// Sets player group
@@ -36,7 +36,7 @@ namespace lfg
if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES))
return;
sLFGMgr->InitializeLockedDungeons(player);
sLFGMgr->InitializeLockedDungeons(player, player->GetGroup());
}
void LFGPlayerScript::OnLogout(Player* player)
@@ -68,7 +68,8 @@ namespace lfg
ObjectGuid guid = player->GetGUID();
ObjectGuid gguid = sLFGMgr->GetGroup(guid);
if (Group const* group = player->GetGroup())
Group const* group = player->GetGroup();
if (group)
{
ObjectGuid gguid2 = group->GetGUID();
if (gguid != gguid2)
@@ -77,7 +78,7 @@ namespace lfg
}
}
sLFGMgr->InitializeLockedDungeons(player);
sLFGMgr->InitializeLockedDungeons(player, group);
sLFGMgr->SetTeam(player->GetGUID(), player->GetTeamId());
// TODO - Restore LfgPlayerData and send proper status to player if it was in a group
}
@@ -86,7 +87,7 @@ namespace lfg
{
MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
if (mapEntry->IsDungeon() && difficulty > DUNGEON_DIFFICULTY_NORMAL)
sLFGMgr->InitializeLockedDungeons(player);
sLFGMgr->InitializeLockedDungeons(player, player->GetGroup());
}
void LFGPlayerScript::OnMapChanged(Player* player)
@@ -200,30 +200,70 @@ void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target)
return;
}
}
else if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
for (auto const& itr : m_members)
{
return;
Creature* pMember = itr.first;
if (!pMember)
{
continue;
}
if (pMember == member || !pMember->IsAlive() || pMember->GetVictim())
{
continue;
}
if (pMember == m_leader && !(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
{
continue;
}
if (pMember->IsValidAttackTarget(target) && pMember->AI())
{
pMember->AI()->AttackStart(target);
}
}
}
Unit* CreatureGroup::GetNewTargetForMember(Creature* member)
{
uint8 const groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()].groupAI;
if (!(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_ACQUIRE_NEW_TARGET_ON_EVADE)))
{
return nullptr;
}
if (member == m_leader && !(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_LEADER_ASSIST_MEMBER)))
{
return nullptr;
}
for (auto const& itr : m_members)
{
Creature* pMember = itr.first;
if (m_leader) // avoid crash if leader was killed and reset.
LOG_DEBUG("entities.unit", "GROUP ATTACK: group instance id {} calls member instid {}", m_leader->GetInstanceId(), member->GetInstanceId());
//Skip one check
if (pMember == member)
if (!pMember)
{
continue;
}
if (!pMember->IsAlive())
if (pMember == member || !pMember->IsAlive() || !pMember->GetVictim())
{
continue;
}
if (pMember->GetVictim())
if (pMember == m_leader && !(groupAI & std::underlying_type_t<GroupAIFlags>(GroupAIFlags::GROUP_AI_FLAG_MEMBER_ASSIST_LEADER)))
{
continue;
}
if (pMember->IsValidAttackTarget(target) && pMember->AI())
pMember->AI()->AttackStart(target);
if (member->IsValidAttackTarget(pMember->GetVictim()))
{
return pMember->GetVictim();
}
}
return nullptr;
}
void CreatureGroup::MemberEvaded(Creature* member)
@@ -28,22 +28,23 @@ class CreatureGroup;
enum class GroupAIFlags : uint16
{
GROUP_AI_FLAG_MEMBER_ASSIST_LEADER = 0x001,
GROUP_AI_FLAG_LEADER_ASSIST_MEMBER = 0x002,
GROUP_AI_FLAG_EVADE_TOGETHER = 0x004,
GROUP_AI_FLAG_RESPAWN_ON_EVADE = 0x008,
GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE = 0x010,
//GROUP_AI_FLAG_UNK3 = 0x010,
//GROUP_AI_FLAG_UNK4 = 0x020,
//GROUP_AI_FLAG_UNK5 = 0x040,
//GROUP_AI_FLAG_UNK6 = 0x080,
//GROUP_AI_FLAG_UNK7 = 0x100,
GROUP_AI_FLAG_FOLLOW_LEADER = 0x200,
GROUP_AI_FLAG_MEMBER_ASSIST_LEADER = 0x001,
GROUP_AI_FLAG_LEADER_ASSIST_MEMBER = 0x002,
GROUP_AI_FLAG_EVADE_TOGETHER = 0x004,
GROUP_AI_FLAG_RESPAWN_ON_EVADE = 0x008,
GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE = 0x010,
GROUP_AI_FLAG_ACQUIRE_NEW_TARGET_ON_EVADE = 0x020,
//GROUP_AI_FLAG_UNK5 = 0x040,
//GROUP_AI_FLAG_UNK6 = 0x080,
//GROUP_AI_FLAG_UNK7 = 0x100,
GROUP_AI_FLAG_FOLLOW_LEADER = 0x200,
GROUP_AI_FLAG_EVADE_MASK = GROUP_AI_FLAG_EVADE_TOGETHER | GROUP_AI_FLAG_RESPAWN_ON_EVADE,
GROUP_AI_FLAG_ASSIST_MASK = GROUP_AI_FLAG_MEMBER_ASSIST_LEADER | GROUP_AI_FLAG_LEADER_ASSIST_MEMBER,
GROUP_AI_FLAG_EVADE_MASK = GROUP_AI_FLAG_EVADE_TOGETHER | GROUP_AI_FLAG_RESPAWN_ON_EVADE,
// Used to verify valid and usable flags
GROUP_AI_FLAG_SUPPORTED = GROUP_AI_FLAG_MEMBER_ASSIST_LEADER | GROUP_AI_FLAG_LEADER_ASSIST_MEMBER | GROUP_AI_FLAG_EVADE_MASK | GROUP_AI_FLAG_FOLLOW_LEADER
GROUP_AI_FLAG_SUPPORTED = GROUP_AI_FLAG_ASSIST_MASK | GROUP_AI_FLAG_EVADE_MASK | GROUP_AI_FLAG_DONT_RESPAWN_LEADER_ON_EVADE |
GROUP_AI_FLAG_FOLLOW_LEADER | GROUP_AI_FLAG_ACQUIRE_NEW_TARGET_ON_EVADE
};
struct FormationInfo
@@ -108,6 +109,7 @@ public:
void LeaderMoveTo(float x, float y, float z, bool run);
void MemberEngagingTarget(Creature* member, Unit* target);
Unit* GetNewTargetForMember(Creature* member);
void MemberEvaded(Creature* member);
void RespawnFormation(bool force = false);
[[nodiscard]] bool IsFormationInCombat();
+48 -10
View File
@@ -450,10 +450,25 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
data << uint32(0);
}
uint8 playerLevel = _session->GetPlayer() ? _session->GetPlayer()->getLevel() : 0;
data << uint32(quest->GetRewOrReqMoney(playerLevel));
uint32 questXp = uint32(quest->XPValue(playerLevel) * _session->GetPlayer()->GetQuestRate());
sScriptMgr->OnQuestComputeXP(_session->GetPlayer(), quest, questXp);
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
uint8 playerLevel = player ? player->getLevel() : 0;
if (player && (player->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
moneyRew += quest->GetRewOrReqMoney(player ? player->getLevel() : 0); // reward money (below max lvl)
data << moneyRew;
uint32 questXp;
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
{
questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate());
}
else
{
questXp = 0;
}
sScriptMgr->OnQuestComputeXP(player, quest, questXp);
data << questXp;
}
@@ -535,7 +550,16 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
data << uint32(0); // Hide money rewarded
else
data << uint32(quest->GetRewOrReqMoney(_session->GetPlayer() ? _session->GetPlayer()->getLevel() : 0)); // reward money (below max lvl)
{
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
if (player && (player->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
moneyRew += quest->GetRewOrReqMoney(player ? player->getLevel() : 0); // reward money (below max lvl)
data << moneyRew;
}
data << uint32(quest->GetRewMoneyMaxLevel()); // used in XP calculation at client
data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
@@ -679,11 +703,25 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
data << uint32(0);
}
uint8 playerLevel = _session->GetPlayer() ? _session->GetPlayer()->getLevel() : 0;
data << uint32(quest->GetRewOrReqMoney(playerLevel));
uint32 questXp = uint32(quest->XPValue(playerLevel) * _session->GetPlayer()->GetQuestRate());
sScriptMgr->OnQuestComputeXP(_session->GetPlayer(), quest, questXp);
uint32 moneyRew = 0;
Player* player = _session->GetPlayer();
uint8 playerLevel = player ? player->getLevel() : 0;
if (player && (player->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
{
moneyRew = quest->GetRewMoneyMaxLevel();
}
moneyRew += quest->GetRewOrReqMoney(player ? player->getLevel() : 0); // reward money (below max lvl)
data << moneyRew;
uint32 questXp;
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
{
questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate());
}
else
{
questXp = 0;
}
sScriptMgr->OnQuestComputeXP(player, quest, questXp);
data << questXp;
// rewarded honor points. Multiply with 10 to satisfy client
+34 -1
View File
@@ -2537,7 +2537,9 @@ void Player::InitStatsForLevel(bool reapplyMods)
PlayerLevelInfo info;
sObjectMgr->GetPlayerLevelInfo(getRace(true), getClass(), getLevel(), &info);
SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
uint32 maxPlayerLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
sScriptMgr->OnSetMaxLevel(this, maxPlayerLevel);
SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, maxPlayerLevel);
SetUInt32Value(PLAYER_NEXT_LEVEL_XP, sObjectMgr->GetXPForLevel(getLevel()));
// reset before any aura state sources (health set/aura apply)
@@ -10227,6 +10229,8 @@ void Player::ContinueTaxiFlight()
RemoveAurasByType(SPELL_AURA_MOUNTED);
}
SetCanTeleport(true);
GetSession()->SendDoFlight(mountDisplayId, path, startNode);
}
@@ -11150,6 +11154,35 @@ WorldLocation Player::GetStartPosition() const
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
}
bool Player::HaveAtClient(WorldObject const* u) const
{
if (u == this)
{
return true;
}
// Motion Transports are always present in player's client
if (GameObject const* gameobject = u->ToGameObject())
{
if (gameobject->IsMotionTransport())
{
return true;
}
}
return m_clientGUIDs.find(u->GetGUID()) != m_clientGUIDs.end();
}
bool Player::HaveAtClient(ObjectGuid guid) const
{
if (guid == GetGUID())
{
return true;
}
return m_clientGUIDs.find(guid) != m_clientGUIDs.end();
}
bool Player::IsNeverVisible() const
{
if (Unit::IsNeverVisible())
+2 -2
View File
@@ -2330,8 +2330,8 @@ public:
GuidUnorderedSet m_clientGUIDs;
std::vector<Unit*> m_newVisible; // pussywizard
bool HaveAtClient(WorldObject const* u) const { return u == this || m_clientGUIDs.find(u->GetGUID()) != m_clientGUIDs.end(); }
[[nodiscard]] bool HaveAtClient(ObjectGuid guid) const { return guid == GetGUID() || m_clientGUIDs.find(guid) != m_clientGUIDs.end(); }
[[nodiscard]] bool HaveAtClient(WorldObject const* u) const;
[[nodiscard]] bool HaveAtClient(ObjectGuid guid) const;
[[nodiscard]] bool IsNeverVisible() const override;
+13
View File
@@ -14481,6 +14481,9 @@ void Unit::setDeathState(DeathState s, bool despawn)
SetHealth(0);
SetPower(getPowerType(), 0);
// Stop emote on death
SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
// players in instance don't have ZoneScript, but they have InstanceScript
if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : (ZoneScript*)GetInstanceScript())
zoneScript->OnUnitDeath(this);
@@ -14690,6 +14693,16 @@ Unit* Creature::SelectVictim()
return nullptr;
}
// Last chance: creature group
if (CreatureGroup* group = GetFormation())
{
if (Unit* groupTarget = group->GetNewTargetForMember(this))
{
SetInFront(groupTarget);
return groupTarget;
}
}
// enter in evade mode in other case
AI()->EnterEvadeMode();
+3
View File
@@ -766,6 +766,9 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData)
case EMOTE_STATE_KNEEL:
case EMOTE_ONESHOT_NONE:
break;
case EMOTE_STATE_DANCE:
GetPlayer()->SetUInt32Value(UNIT_NPC_EMOTESTATE, emote_anim);
break;
default:
// Only allow text-emotes for "dead" entities (feign death included)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
+2 -2
View File
@@ -157,7 +157,7 @@ void WorldSession::HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& /*recvData*
sLFGMgr->GetRandomAndSeasonalDungeons(level, GetPlayer()->GetSession()->Expansion());
// Get player locked Dungeons
sLFGMgr->InitializeLockedDungeons(GetPlayer()); // pussywizard
sLFGMgr->InitializeLockedDungeons(GetPlayer(), GetPlayer()->GetGroup()); // pussywizard
lfg::LfgLockMap const& lock = sLFGMgr->GetLockedDungeons(guid);
uint32 rsize = uint32(randomDungeons.size());
uint32 lsize = uint32(lock.size());
@@ -239,7 +239,7 @@ void WorldSession::HandleLfgPartyLockInfoRequestOpcode(WorldPacket& /*recvData*
if (pguid == guid)
continue;
sLFGMgr->InitializeLockedDungeons(plrg); // pussywizard
sLFGMgr->InitializeLockedDungeons(plrg, group); // pussywizard
lockMap[pguid] = sLFGMgr->GetLockedDungeons(pguid);
}
@@ -370,6 +370,15 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
movementInfo.guid = guid;
ReadMovementInfo(recvData, &movementInfo);
// Stop emote on move
if (Player* plrMover = mover->ToPlayer())
{
if (plrMover->GetUInt32Value(UNIT_NPC_EMOTESTATE) != EMOTE_ONESHOT_NONE)
{
plrMover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
}
}
if (!movementInfo.pos.IsPositionValid())
{
if (plrMover)
+3 -1
View File
@@ -1148,7 +1148,9 @@ enum AcoreStrings
LANG_CMD_CHAR_CHANGE_ACC_SUCCESS = 5083,
// Room for more strings 5083-9999
LANG_CMD_CAST_ERROR_CODE = 5084,
// Room for more strings 5084-9999
// Level requirement notifications
LANG_SAY_REQ = 6604,
@@ -645,6 +645,14 @@ void ScriptMgr::OnFirstLogin(Player* player)
});
}
void ScriptMgr::OnSetMaxLevel(Player* player, uint32& maxPlayerLevel)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnSetMaxLevel(player, maxPlayerLevel);
});
}
bool ScriptMgr::CanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err)
{
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
@@ -53,11 +53,11 @@ void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32& damage)
});
}
void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage)
void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo)
{
ExecuteScript<UnitScript>([&](UnitScript* script)
{
script->ModifyPeriodicDamageAurasTick(target, attacker, damage);
script->ModifyPeriodicDamageAurasTick(target, attacker, damage, spellInfo);
});
}
+5 -2
View File
@@ -423,7 +423,7 @@ public:
// Called when DoT's Tick Damage is being Dealt
// Attacker can be nullptr if he is despawned while the aura still exists on target
virtual void ModifyPeriodicDamageAurasTick(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { }
virtual void ModifyPeriodicDamageAurasTick(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/, SpellInfo const* /*spellInfo*/) { }
// Called when Melee Damage is being Dealt
virtual void ModifyMeleeDamage(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { }
@@ -1226,6 +1226,8 @@ public:
virtual void OnFirstLogin(Player* /*player*/) { }
virtual void OnSetMaxLevel(Player* /*player*/, uint32& /*maxPlayerLevel*/) { }
[[nodiscard]] virtual bool CanJoinInBattlegroundQueue(Player* /*player*/, ObjectGuid /*BattlemasterGuid*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, GroupJoinBattlegroundResult& /*err*/) { return true; }
virtual bool ShouldBeRewardedWithMoneyInsteadOfExp(Player* /*player*/) { return false; }
@@ -2336,6 +2338,7 @@ public: /* PlayerScript */
void OnAfterUpdateAttackPowerAndDamage(Player* player, float& level, float& base_attPower, float& attPowerMod, float& attPowerMultiplier, bool ranged);
void OnBeforeInitTalentForLevel(Player* player, uint8& level, uint32& talentPointsForLevel);
void OnFirstLogin(Player* player);
void OnSetMaxLevel(Player* player, uint32& maxPlayerLevel);
void OnPlayerCompleteQuest(Player* player, Quest const* quest);
void OnBattlegroundDesertion(Player* player, BattlegroundDesertionType const desertionType);
bool CanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err);
@@ -2475,7 +2478,7 @@ public: /* Scheduled scripts */
public: /* UnitScript */
void OnHeal(Unit* healer, Unit* reciever, uint32& gain);
void OnDamage(Unit* attacker, Unit* victim, uint32& damage);
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage);
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo);
void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage);
void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage, SpellInfo const* spellInfo);
void ModifyHealReceived(Unit* target, Unit* healer, uint32& addHealth, SpellInfo const* spellInfo);
@@ -6298,7 +6298,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
uint32 damage = std::max(GetAmount(), 0);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage, GetSpellInfo());
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
@@ -6410,7 +6410,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
uint32 damage = std::max(GetAmount(), 0);
// Script Hook For HandlePeriodicHealthLeechAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage);
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage, GetSpellInfo());
if (GetBase()->GetType() == DYNOBJ_AURA_TYPE)
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetEffIndex(), 0.0f, GetBase()->GetStackAmount());
@@ -6618,7 +6618,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
uint32 heal = uint32(damage);
// Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal);
sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, heal, GetSpellInfo());
sScriptMgr->ModifyHealReceived(target, caster, heal, GetSpellInfo());
HealInfo healInfo(caster, target, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask());
@@ -4448,6 +4448,13 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPRESS_TARGET_PROCS;
});
// Summon Cauldron Stuff
ApplySpellFix({ 36549 }, [](SpellInfo* spellInfo)
{
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds
spellInfo->Effects[EFFECT_0].TargetB = TARGET_DEST_CASTER;
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+42 -6
View File
@@ -56,6 +56,17 @@ public:
return commandTable;
}
static bool CheckSpellCastResult(ChatHandler* handler, SpellCastResult result)
{
if (result != SPELL_CAST_OK)
{
handler->PSendSysMessage(LANG_CMD_CAST_ERROR_CODE, EnumUtils::ToTitle(SpellCastResult(result)), result);
return false;
}
return true;
}
static bool CheckSpellExistsAndIsValid(ChatHandler* handler, SpellInfo const* spell)
{
if (!spell)
@@ -103,7 +114,11 @@ public:
if (!triggerFlags)
return false;
handler->GetSession()->GetPlayer()->CastSpell(target, spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, handler->GetSession()->GetPlayer()->CastSpell(target, spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -125,7 +140,11 @@ public:
if (!triggerFlags)
return false;
caster->CastSpell(handler->GetSession()->GetPlayer(), spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, caster->CastSpell(handler->GetSession()->GetPlayer(), spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -141,7 +160,12 @@ public:
float x, y, z;
handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, dist);
handler->GetSession()->GetPlayer()->CastSpell(x, y, z, spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, handler->GetSession()->GetPlayer()->CastSpell(x, y, z, spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -163,7 +187,11 @@ public:
if (!triggerFlags)
return false;
target->CastSpell(target, spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, target->CastSpell(target, spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -192,7 +220,11 @@ public:
if (!triggerFlags)
return false;
caster->CastSpell(caster->GetVictim(), spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, caster->CastSpell(caster->GetVictim(), spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -214,7 +246,11 @@ public:
if (!triggerFlags)
return false;
caster->CastSpell(x, y, z, spell->Id, *triggerFlags);
if (!CheckSpellCastResult(handler, caster->CastSpell(x, y, z, spell->Id, *triggerFlags)))
{
handler->SetSentErrorMessage(true);
return false;
}
return true;
}
@@ -65,7 +65,6 @@ public:
{
creature->CastSpell(player, SPELL_MARK_OF_BITE, true);
player->KilledMonsterCredit(creature->GetEntry());
creature->DespawnOrUnsummon(1000);
}
else
{
+5 -1
View File
@@ -1073,7 +1073,11 @@ public:
//player->CastSpell(player, SPELL_SUMMON_RIZZLE, false);
if (Creature* creature = player->SummonCreature(NPC_RIZZLE, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0))
creature->CastSpell(player, SPELL_BLACKJACK, false);
{
// no need casting spell blackjack, it's casted by script npc_rizzle_sprysprocket.
//creature->CastSpell(player, SPELL_BLACKJACK, false);
creature->AI()->AttackStart(player);
}
return false;
}