Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -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,
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user