Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-09-21 09:42:10 -06:00
committed by GitHub
27 changed files with 327 additions and 72 deletions
@@ -0,0 +1,49 @@
-- DB update 2022_09_19_08 -> 2022_09_21_00
--
UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x02000000 WHERE `entry` IN (14825, 14882, 14883);
UPDATE `creature_formations` SET `groupAI`=515 WHERE `LeaderGUID`=49359 AND `memberGUID` IN (49359,49361,49362,49389);
UPDATE `creature_formations` SET `groupAI`=515 WHERE `LeaderGUID`=49651 AND `memberGUID` IN (49651,49652,49653,49654);
DELETE FROM `creature_formations` WHERE `LeaderGUID` IN (49363,49383,49387,49397,49373) AND `memberGUID` IN (49363,49364,49365,49366,49367,49368,49369,49370,49371,49372,49373,49374,49375,49376,49377,49378,49379,49380,49381,49382,49383,49384,49385,49386,49387,49388,49390,49391,49392,49393,49394,49395,49396,49397,49398,49399,49400);
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(49363, 49363, 0, 0, 3, 0, 0),
(49363, 49370, 0, 0, 3, 0, 0),
(49363, 49364, 0, 0, 3, 0, 0),
(49363, 49368, 0, 0, 3, 0, 0),
(49363, 49372, 0, 0, 3, 0, 0),
(49363, 49371, 0, 0, 3, 0, 0),
(49363, 49367, 0, 0, 3, 0, 0),
(49363, 49365, 0, 0, 3, 0, 0),
(49363, 49366, 0, 0, 3, 0, 0),
(49363, 49369, 0, 0, 3, 0, 0),
(49383, 49383, 0, 0, 3, 0, 0),
(49383, 49384, 0, 0, 3, 0, 0),
(49383, 49385, 0, 0, 3, 0, 0),
(49383, 49386, 0, 0, 3, 0, 0),
(49387, 49387, 0, 0, 3, 0, 0),
(49387, 49393, 0, 0, 3, 0, 0),
(49387, 49388, 0, 0, 3, 0, 0),
(49387, 49392, 0, 0, 3, 0, 0),
(49387, 49390, 0, 0, 3, 0, 0),
(49387, 49396, 0, 0, 3, 0, 0),
(49387, 49391, 0, 0, 3, 0, 0),
(49387, 49395, 0, 0, 3, 0, 0),
(49387, 49394, 0, 0, 3, 0, 0),
(49397, 49397, 0, 0, 3, 0, 0),
(49397, 49398, 0, 0, 3, 0, 0),
(49397, 49399, 0, 0, 3, 0, 0),
(49397, 49400, 0, 0, 3, 0, 0),
(49373, 49373, 0, 0, 3, 0, 0),
(49373, 49381, 0, 0, 3, 0, 0),
(49373, 49382, 0, 0, 3, 0, 0),
(49373, 49380, 0, 0, 3, 0, 0),
(49373, 49379, 0, 0, 3, 0, 0),
(49373, 49375, 0, 0, 3, 0, 0),
(49373, 49378, 0, 0, 3, 0, 0),
(49373, 49376, 0, 0, 3, 0, 0),
(49373, 49377, 0, 0, 3, 0, 0),
(49373, 49374, 0, 0, 3, 0, 0);
@@ -0,0 +1,3 @@
-- DB update 2022_09_21_00 -> 2022_09_21_01
--
UPDATE `creature_formations` SET `groupAI` = 515 WHERE `leaderGUID` = 87648 AND `memberGUID` IN (87649, 87650, 87651);
@@ -0,0 +1,2 @@
-- DB update 2022_09_21_01 -> 2022_09_21_02
UPDATE `quest_offer_reward` SET `RewardText`='Hmmm, Narm sent you to me, did he?$b$bWell then, Narm could always be trusted, so that must mean you\'re ready to take part of the next sapta--the sapta of fire.$b$bI see it in your eyes already, the burning, the desire. You\'ve tasted power, and now you\'re ready for more of it. Patience, $N. Remember what earth taught you. Power and destruction will come easily, but you must still know when to stay your hand.' WHERE `ID`=2984;
@@ -0,0 +1,6 @@
-- DB update 2022_09_21_02 -> 2022_09_21_03
--
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_freeze_rookery_egg';
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
(15748, 'spell_item_freeze_rookery_egg'), -- item
(16028, 'spell_item_freeze_rookery_egg'); -- quest
@@ -868,6 +868,14 @@ StartHeroicPlayerLevel = 55
StartPlayerMoney = 0
#
# StartHeroicPlayerMoney
# Description: Amount of money (in Copper) that heroic class characters have after creation.
# Default: 2000
# 2000 - (20 Silver)
StartHeroicPlayerMoney = 2000
#
# MaxHonorPoints
# Description: Maximum honor points a character can have.
@@ -2156,6 +2164,14 @@ Visibility.Notify.Period.InBGArenas = 1000
Visibility.ObjectSparkles = 1
#
# Visibility.ObjectQuestMarkers
# Description: Show quest icons above game objects in the same way as creature quest givers.
# Default: 1 - (Show quest markers, post patch 2.3 behavior)
# 0 - (Hide quest markers, pre patch 2.3 behavior)
Visibility.ObjectQuestMarkers = 1
#
###################################################################################################
+21 -10
View File
@@ -3428,15 +3428,19 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me || !me->IsEngaged() || !me->GetVictim())
return;
if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max))
ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim());
else
if (me->IsInRange(me->GetVictim(), (float)e.event.rangeRepeat.minRange, (float)e.event.rangeRepeat.maxRange))
{
if (!e.event.minMaxRepeat.controller)
RecalcTimer(e, 500, 500); // xinef: make it predictable "Malcrom: This seems to be done to standardize min, max start rather than using the range values for the timer."
if (e.event.rangeRepeat.onlyFireOnRepeat == 2)
{
e.event.rangeRepeat.onlyFireOnRepeat = 1;
RecalcTimer(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax);
}
else
RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); // Malcrom: if param5 value is greater than 0 first action will not happen until after repeat timer fires.
ProcessTimedAction(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax, me->GetVictim());
}
else
RecalcTimer(e, 500, 500); // make it predictable
break;
}
case SMART_EVENT_VICTIM_CASTING:
@@ -4000,6 +4004,13 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
switch (e.GetEventType())
{
//set only events which have initial timers
case SMART_EVENT_RANGE:
// If onlyFireOnRepeat is true set to 2 before entering combat. Will be set back to 1 after entering combat to ignore initial firing.
if (e.event.rangeRepeat.onlyFireOnRepeat == 1)
e.event.rangeRepeat.onlyFireOnRepeat = 2;
// make it predictable
RecalcTimer(e, 500, 500);
break;
case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
RecalcTimer(e, e.event.nearPlayer.firstTimer, e.event.nearPlayer.firstTimer);
@@ -4291,10 +4302,10 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTrigger const* at)
InitTimer((*i));//calculate timers for first time use
if (i->GetEventType() == SMART_EVENT_RANGE && i->GetActionType() == SMART_ACTION_ALLOW_COMBAT_MOVEMENT)
{
if (i->action.combatMove.move == 1 && i->event.minMaxRepeat.min > minEnableDist)
minEnableDist = i->event.minMaxRepeat.min;
else if (i->action.combatMove.move == 0 && (i->event.minMaxRepeat.max < maxDisableDist || maxDisableDist == 0))
maxDisableDist = i->event.minMaxRepeat.max;
if (i->action.combatMove.move == 1 && i->event.rangeRepeat.minRange > minEnableDist)
minEnableDist = i->event.rangeRepeat.minRange;
else if (i->action.combatMove.move == 0 && (i->event.rangeRepeat.maxRange < maxDisableDist || maxDisableDist == 0))
maxDisableDist = i->event.rangeRepeat.maxRange;
}
// Xinef: if smartcast combat move flag is present
@@ -260,7 +260,6 @@ void SmartAIMgr::LoadSmartAIFromDB()
case SMART_EVENT_TARGET_HEALTH_PCT:
case SMART_EVENT_MANA_PCT:
case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE:
case SMART_EVENT_FRIENDLY_HEALTH:
case SMART_EVENT_FRIENDLY_HEALTH_PCT:
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
@@ -269,6 +268,13 @@ void SmartAIMgr::LoadSmartAIFromDB()
if (temp.event.minMaxRepeat.repeatMin == 0 && temp.event.minMaxRepeat.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_RANGE:
if (temp.event.rangeRepeat.repeatMin == 0 && temp.event.rangeRepeat.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
// Will only work properly if value is 0 or 1
if (temp.event.rangeRepeat.onlyFireOnRepeat > 1)
temp.event.rangeRepeat.onlyFireOnRepeat = 1;
break;
case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_IS_BEHIND_TARGET:
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0)
@@ -472,7 +478,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_DEATH: return NO_PARAMS;
case SMART_EVENT_EVADE: return NO_PARAMS;
case SMART_EVENT_SPELLHIT: return sizeof(SmartEvent::spellHit);
case SMART_EVENT_RANGE: return sizeof(SmartEvent::minMaxRepeat);
case SMART_EVENT_RANGE: return sizeof(SmartEvent::rangeRepeat);
case SMART_EVENT_OOC_LOS: return sizeof(SmartEvent::los);
case SMART_EVENT_RESPAWN: return sizeof(SmartEvent::respawn);
case SMART_EVENT_TARGET_HEALTH_PCT: return sizeof(SmartEvent::minMaxRepeat);
@@ -911,7 +917,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_MANA_PCT:
case SMART_EVENT_TARGET_HEALTH_PCT:
case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE:
case SMART_EVENT_DAMAGED:
case SMART_EVENT_DAMAGED_TARGET:
case SMART_EVENT_RECEIVE_HEAL:
@@ -921,6 +926,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsMinMaxValid(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax))
return false;
break;
case SMART_EVENT_RANGE:
if (!IsMinMaxValid(e, e.event.rangeRepeat.minRange, e.event.rangeRepeat.maxRange))
return false;
if (!IsMinMaxValid(e, e.event.rangeRepeat.repeatMin, e.event.rangeRepeat.repeatMax))
return false;
break;
case SMART_EVENT_SPELLHIT:
case SMART_EVENT_SPELLHIT_TARGET:
if (e.event.spellHit.spell)
@@ -124,7 +124,7 @@ enum SMART_EVENT
SMART_EVENT_DEATH = 6, // NONE
SMART_EVENT_EVADE = 7, // NONE
SMART_EVENT_SPELLHIT = 8, // SpellID, School, CooldownMin, CooldownMax
SMART_EVENT_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax
SMART_EVENT_RANGE = 9, // minRange, maxRange, repeatMin, repeatMax, onlyFireOnRepeat
SMART_EVENT_OOC_LOS = 10, // HostilityMode, MaxRnage, CooldownMin, CooldownMax, PlayerOnly
SMART_EVENT_RESPAWN = 11, // type, MapId, ZoneId
SMART_EVENT_TARGET_HEALTH_PCT = 12, // HPMin%, HPMax%, RepeatMin, RepeatMax
@@ -221,9 +221,17 @@ struct SmartEvent
uint32 max;
uint32 repeatMin;
uint32 repeatMax;
uint32 controller;
} minMaxRepeat;
struct
{
uint32 minRange;
uint32 maxRange;
uint32 repeatMin;
uint32 repeatMax;
uint32 onlyFireOnRepeat;
} rangeRepeat;
struct
{
uint32 cooldownMin;
@@ -2089,8 +2089,14 @@ void GameObject::CastSpell(Unit* target, uint32 spellId)
if (owner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
trigger->SetUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED);
if (owner->IsFFAPvP())
trigger->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
{
if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
sScriptMgr->OnFfaPvpStateUpdate(trigger, true);
trigger->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
}
// xinef: Remove Immunity flags
trigger->SetImmuneToNPC(false);
// xinef: set proper orientation, fixes cast against stealthed targets
+33 -8
View File
@@ -569,7 +569,9 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
InitRunes();
SetUInt32Value(PLAYER_FIELD_COINAGE, sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY));
SetUInt32Value(PLAYER_FIELD_COINAGE, getClass() != CLASS_DEATH_KNIGHT
? sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY)
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_MONEY));
SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
SetArenaPoints(sWorld->getIntConfig(CONFIG_START_ARENA_POINTS));
@@ -2177,8 +2179,11 @@ void Player::SetGameMaster(bool on)
pet->SetFaction(FACTION_FRIENDLY);
pet->getHostileRefMgr().setOnlineOfflineState(false);
}
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
}
ResetContestedPvP();
getHostileRefMgr().setOnlineOfflineState(false);
@@ -2210,8 +2215,13 @@ void Player::SetGameMaster(bool on)
// restore FFA PvP Server state
if (sWorld->IsFFAPvPRealm())
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
{
if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, true);
}
}
// restore FFA PvP area state, remove not allowed for GM mounts
UpdateArea(m_areaUpdateId);
@@ -2654,8 +2664,12 @@ void Player::InitStatsForLevel(bool reapplyMods)
RemovePlayerFlag(PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_ALLOW_ONLY_ABILITY);
RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY);
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
}
// restore if need some important flags
SetUInt32Value(PLAYER_FIELD_BYTES2, 0); // flags empty by default
@@ -15001,7 +15015,11 @@ void Player::SetIsSpectator(bool on)
AddUnitState(UNIT_STATE_ISOLATED);
//SetFaction(1100);
SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
}
ResetContestedPvP();
SetDisplayId(23691);
}
@@ -15021,7 +15039,14 @@ void Player::SetIsSpectator(bool on)
// restore FFA PvP Server state
// Xinef: it will be removed if necessery in UpdateArea called in WorldPortOpcode
if (sWorld->IsFFAPvPRealm())
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
{
if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, true);
}
}
}
}
}
@@ -396,8 +396,11 @@ void Player::UpdateFFAPvPFlag(time_t currTime)
}
pvpInfo.FFAPvPEndTimer = time_t(0);
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
}
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
@@ -982,42 +982,56 @@ void Player::UpdateWeaponSkill(Unit* victim, WeaponAttackType attType, Item* ite
void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defence, Item* item /*= nullptr*/)
{
uint8 plevel = getLevel(); // if defense than victim == attacker
uint8 greylevel = Acore::XP::GetGrayLevel(plevel);
uint8 moblevel = victim->getLevelForTarget(this);
uint8 playerLevel = getLevel();
uint16 currentSkillValue = defence ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType);
uint16 currentSkillMax = 5 * playerLevel;
int32 skillDiff = currentSkillMax - currentSkillValue;
// Max skill reached for level.
// Can in some cases be less than 0: having max skill and then .level -1 as example.
if (skillDiff <= 0)
{
return;
}
uint8 greylevel = Acore::XP::GetGrayLevel(playerLevel);
uint8 moblevel = defence ? victim->getLevelForTarget(this) : victim->getLevel(); // if defense than victim == attacker
/*if (moblevel < greylevel)
return;*/
// Patch 3.0.8 (2009-01-20): You can no longer skill up weapons on mobs that are immune to damage.
if (moblevel > plevel + 5)
moblevel = plevel + 5;
if (moblevel > playerLevel + 5)
{
moblevel = playerLevel + 5;
}
uint8 lvldif = moblevel - greylevel;
int16 lvldif = moblevel - greylevel;
if (lvldif < 3)
{
lvldif = 3;
}
uint32 skilldif = 5 * plevel - (defence ? GetBaseDefenseSkillValue()
: GetBaseWeaponSkillValue(attType));
if (skilldif <= 0)
return;
float chance = float(3 * lvldif * skilldif) / plevel;
float chance = float(3 * lvldif * skillDiff) / playerLevel;
if (!defence)
if (getClass() == CLASS_WARRIOR || getClass() == CLASS_ROGUE)
chance += chance * 0.02f * GetStat(STAT_INTELLECT);
{
chance += chance * 0.02f * GetStat(STAT_INTELLECT);
}
chance =
chance < 1.0f ? 1.0f : chance; // minimum chance to increase skill is 1%
chance = chance < 1.0f ? 1.0f : chance; // minimum chance to increase skill is 1%
LOG_DEBUG("entities.player", "Player::UpdateCombatSkills(defence:{}, playerLevel:{}, moblevel:{}) -> ({}/{}) chance to increase skill is {}\%", defence, playerLevel, moblevel, currentSkillValue, currentSkillMax, chance);
if (roll_chance_f(chance))
{
if (defence)
{
UpdateDefense();
}
else
{
UpdateWeaponSkill(victim, attType, item);
}
}
else
return;
}
void Player::UpdateSkillsForLevel()
@@ -1403,6 +1417,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/)
{
if (!IsFFAPvP())
{
sScriptMgr->OnFfaPvpStateUpdate(this, true);
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
for (ControlSet::iterator itr = m_Controlled.begin();
itr != m_Controlled.end(); ++itr)
@@ -1421,8 +1436,11 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/)
!pvpInfo.EndTimer)
{
pvpInfo.FFAPvPEndTimer = time_t(0);
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(this, false);
}
for (ControlSet::iterator itr = m_Controlled.begin();
itr != m_Controlled.end(); ++itr)
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1,
+5 -8
View File
@@ -15759,21 +15759,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
// Update skills here for players
// only when you are not fighting other players or their pets/totems (pvp)
if (GetTypeId() == TYPEID_PLAYER &&
target->GetTypeId() != TYPEID_PLAYER &&
!(target->IsTotem() && target->ToTotem()->GetOwner()->IsPlayer()) &&
!target->IsPet()
)
if (IsPlayer() && !target->IsCharmedOwnedByPlayerOrPlayer())
{
// On melee based hit/miss/resist/parry/dodge need to update skill (for victim and attacker)
if (procExtra & (PROC_EX_NORMAL_HIT | PROC_EX_MISS | PROC_EX_RESIST | PROC_EX_PARRY | PROC_EX_DODGE))
{
if (target->GetTypeId() != TYPEID_PLAYER)
ToPlayer()->UpdateCombatSkills(target, attType, isVictim, procSpell ? procSpell->m_weaponItem : nullptr);
ToPlayer()->UpdateCombatSkills(target, attType, isVictim, procSpell ? procSpell->m_weaponItem : nullptr);
}
// Update defence if player is victim and we block
// Update defence if player is victim and we block - TODO: confirm that blocked attacks only have a chance to increase defence skill
else if (isVictim && procExtra & (PROC_EX_BLOCK))
{
ToPlayer()->UpdateCombatSkills(target, attType, true);
}
}
// If exist crit/parry/dodge/block need update aura state (for victim and attacker)
if (procExtra & (PROC_EX_CRITICAL_HIT | PROC_EX_PARRY | PROC_EX_DODGE | PROC_EX_BLOCK))
+3 -1
View File
@@ -109,8 +109,10 @@ void Vehicle::Uninstall()
LOG_DEBUG("vehicles", "Vehicle::Uninstall {}", _me->GetGUID().ToString());
RemoveAllPassengers();
if (GetBase()->GetTypeId() == TYPEID_UNIT)
if (_me && _me->GetTypeId() == TYPEID_UNIT)
{
sScriptMgr->OnUninstall(this);
}
}
void Vehicle::Reset(bool evading /*= false*/)
@@ -422,7 +422,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
{
if (!sScriptMgr->CanAccountCreateCharacter(createInfo, GetAccountId()))
if (!sScriptMgr->CanAccountCreateCharacter(GetAccountId(), createInfo->Race, createInfo->Class))
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
@@ -948,7 +948,11 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
// Set FFA PvP for non GM in non-rest mode
if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING))
pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
sScriptMgr->OnFfaPvpStateUpdate(pCurrChar,true);
pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
if (pCurrChar->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP))
{
+1
View File
@@ -168,6 +168,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
if (loot)
{
sScriptMgr->OnBeforeLootMoney(player, loot);
loot->NotifyMoneyRemoved();
if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player
{
+7 -1
View File
@@ -772,8 +772,14 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data)
player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->entry);
if (sWorld->IsFFAPvPRealm())
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
{
if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{
player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
sScriptMgr->OnFfaPvpStateUpdate(player, false);
}
}
return;
}
+4 -1
View File
@@ -63,7 +63,10 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData)
case TYPEID_GAMEOBJECT:
{
LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject {}", guid.ToString());
questStatus = _player->GetQuestDialogStatus(questGiver);
if (sWorld->getBoolConfig(CONFIG_OBJECT_QUEST_MARKERS))
{
questStatus = _player->GetQuestDialogStatus(questGiver);
}
break;
}
default:
@@ -82,11 +82,11 @@ void ScriptMgr::OnFailedPasswordChange(uint32 accountId)
});
}
bool ScriptMgr::CanAccountCreateCharacter(std::shared_ptr<CharacterCreateInfo> createInfo, uint32 accountId)
bool ScriptMgr::CanAccountCreateCharacter(uint32 accountId, uint8 charRace, uint8 charClass)
{
auto ret = IsValidBoolScript<AccountScript>([&](AccountScript* script)
{
return !script->CanAccountCreateCharacter(createInfo, accountId);
return !script->CanAccountCreateCharacter(accountId, charRace, charClass);
});
if (ret && *ret)
@@ -170,6 +170,15 @@ CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature)
return tempScript ? tempScript->GetAI(creature) : nullptr;
}
//Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player
void ScriptMgr::OnFfaPvpStateUpdate(Creature* creature, bool InPvp)
{
ExecuteScript<AllCreatureScript>([&](AllCreatureScript* script)
{
script->OnFfaPvpStateUpdate(creature, InPvp);
});
}
void ScriptMgr::OnCreatureUpdate(Creature* creature, uint32 diff)
{
ASSERT(creature);
@@ -146,6 +146,14 @@ void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount)
});
}
void ScriptMgr::OnBeforeLootMoney(Player* player, Loot* loot)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnBeforeLootMoney(player, loot);
});
}
void ScriptMgr::OnGivePlayerXP(Player* player, uint32& amount, Unit* victim)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
@@ -1263,6 +1271,7 @@ void ScriptMgr::OnGetArenaTeamId(Player* player, uint8 slot, uint32& result)
});
}
//Signifies that IsFfaPvp has been called.
void ScriptMgr::OnIsFFAPvP(Player* player, bool& result)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
@@ -1270,6 +1279,14 @@ void ScriptMgr::OnIsFFAPvP(Player* player, bool& result)
script->OnIsFFAPvP(player, result);
});
}
//Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed
void ScriptMgr::OnFfaPvpStateUpdate(Player* player, bool result)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnFfaPvpStateUpdate(player, result);
});
}
void ScriptMgr::OnIsPvP(Player* player, bool& result)
{
+18 -2
View File
@@ -620,6 +620,9 @@ public:
// Called when a CreatureAI object is needed for the creature.
[[nodiscard]] virtual CreatureAI* GetCreatureAI(Creature* /*creature*/) const { return nullptr; }
//Called Whenever the UNIT_BYTE2_FLAG_FFA_PVP Bit is set on the creature
virtual void OnFfaPvpStateUpdate(Creature* /*creature*/, bool /*InPvp*/) {}
};
class AllItemScript : public ScriptObject
@@ -744,6 +747,10 @@ public:
// Called when a CreatureAI object is needed for the creature.
virtual CreatureAI* GetAI(Creature* /*creature*/) const { return nullptr; }
//Called whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player
virtual void OnFfaPvpStateUpdate(Creature* /*player*/, bool /*result*/) { }
};
class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
@@ -1023,6 +1030,9 @@ public:
// Called when a player's money is modified (before the modification is done)
virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
// Called before looted money is added to a player
virtual void OnBeforeLootMoney(Player* /*player*/, Loot* /*loot*/) {}
// Called when a player gains XP (before anything is given)
virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/) { }
@@ -1306,6 +1316,9 @@ public:
virtual void OnIsFFAPvP(Player* /*player*/, bool& /*result*/) { }
//Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player
virtual void OnFfaPvpStateUpdate(Player* /*player*/, bool /*result*/) { }
virtual void OnIsPvP(Player* /*player*/, bool& /*result*/) { }
virtual void OnGetMaxSkillValueForLevel(Player* /*player*/, uint16& /*result*/) { }
@@ -1463,7 +1476,7 @@ public:
virtual void OnFailedPasswordChange(uint32 /*accountId*/) { }
// Called when creating a character on the Account
[[nodiscard]] virtual bool CanAccountCreateCharacter(std::shared_ptr<CharacterCreateInfo> /*createInfo*/, uint32 /*accountId*/) { return true;}
[[nodiscard]] virtual bool CanAccountCreateCharacter(uint32 /*accountId*/, uint8 /*charRace*/, uint8 /*charClass*/) { return true;}
};
class GuildScript : public ScriptObject
@@ -2164,6 +2177,7 @@ public: /* CreatureScript */
void OnCreatureUpdate(Creature* creature, uint32 diff);
void OnCreatureAddWorld(Creature* creature);
void OnCreatureRemoveWorld(Creature* creature);
void OnFfaPvpStateUpdate(Creature* creature, bool InPvp);
public: /* GameObjectScript */
bool OnGossipHello(Player* player, GameObject* go);
@@ -2249,6 +2263,7 @@ public: /* PlayerScript */
void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints);
void OnPlayerTalentsReset(Player* player, bool noCost);
void OnPlayerMoneyChanged(Player* player, int32& amount);
void OnBeforeLootMoney(Player* player, Loot* loot);
void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim);
bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental);
void OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank newRank, ReputationRank oldRank, bool increased);
@@ -2361,6 +2376,7 @@ public: /* PlayerScript */
bool NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report);
bool NotVisibleGloballyFor(Player* player, Player const* u);
void OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result);
void OnFfaPvpStateUpdate(Player* player, bool result);
void OnGetArenaTeamId(Player* player, uint8 slot, uint32& result);
void OnIsFFAPvP(Player* player, bool& result);
void OnIsPvP(Player* player, bool& result);
@@ -2401,7 +2417,7 @@ public: /* AccountScript */
void OnFailedEmailChange(uint32 accountId);
void OnPasswordChange(uint32 accountId);
void OnFailedPasswordChange(uint32 accountId);
bool CanAccountCreateCharacter(std::shared_ptr<CharacterCreateInfo> createInfo, uint32 accountId);
bool CanAccountCreateCharacter(uint32 accountId, uint8 charRace, uint8 charClass);
public: /* GuildScript */
void OnGuildAddMember(Guild* guild, Player* player, uint8& plRank);
+2
View File
@@ -177,6 +177,7 @@ enum WorldBoolConfigs
CONFIG_LEAVE_GROUP_ON_LOGOUT,
CONFIG_VMAP_BLIZZLIKE_PVP_LOS,
CONFIG_OBJECT_SPARKLES,
CONFIG_OBJECT_QUEST_MARKERS,
BOOL_CONFIG_VALUE_COUNT
};
@@ -231,6 +232,7 @@ enum WorldIntConfigs
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
CONFIG_START_HEROIC_PLAYER_MONEY,
CONFIG_MAX_HONOR_POINTS,
CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT,
CONFIG_START_HONOR_POINTS,
+9
View File
@@ -849,6 +849,13 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
}
m_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY] = sConfigMgr->GetOption<int32>("StartHeroicPlayerMoney", 2000);
if (int32(m_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY]) < 0 || int32(m_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY]) > MAX_MONEY_AMOUNT)
{
LOG_ERROR("server.loading", "StartHeroicPlayerMoney ({}) must be in range 0..{}. Set to {}.", m_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY], MAX_MONEY_AMOUNT, 2000);
m_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY] = 2000;
}
m_int_configs[CONFIG_MAX_HONOR_POINTS] = sConfigMgr->GetOption<int32>("MaxHonorPoints", 75000);
if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
{
@@ -944,6 +951,8 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_OBJECT_SPARKLES] = sConfigMgr->GetOption<bool>("Visibility.ObjectSparkles", true);
m_bool_configs[CONFIG_OBJECT_QUEST_MARKERS] = sConfigMgr->GetOption<bool>("Visibility.ObjectQuestMarkers", true);
m_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfigMgr->GetOption<int32>("MailDeliveryDelay", HOUR);
m_int_configs[CONFIG_UPTIME_UPDATE] = sConfigMgr->GetOption<int32>("UpdateUptimeInterval", 10);
+13 -8
View File
@@ -655,13 +655,12 @@ class spell_hun_readiness : public SpellScript
SpellCooldowns& cooldowns = caster->GetSpellCooldownMap();
SpellCooldowns::iterator itr, next;
for (itr = cooldowns.begin(); itr != cooldowns.end(); itr = next)
{
next = itr;
++next;
std::set<std::pair<uint32, bool>> spellsToRemove;
std::set<uint32> categoriesToRemove;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
for (const auto& [spellId, cooldown] : cooldowns)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (spellInfo
&& spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER
&& spellInfo->Id != SPELL_HUNTER_READINESS
@@ -669,12 +668,18 @@ class spell_hun_readiness : public SpellScript
&& spellInfo->Id != SPELL_DRAENEI_GIFT_OF_THE_NAARU)
{
if (spellInfo->RecoveryTime > 0)
caster->RemoveSpellCooldown(spellInfo->Id, itr->second.needSendToClient);
spellsToRemove.insert(std::make_pair(spellInfo->Id, cooldown.needSendToClient));
if (spellInfo->CategoryRecoveryTime > 0)
caster->RemoveCategoryCooldown(spellInfo->GetCategory());
categoriesToRemove.insert(spellInfo->GetCategory());
}
}
// we can't remove spell cooldowns while iterating.
for (const auto& [spellId, sendToClient] : spellsToRemove)
caster->RemoveSpellCooldown(spellId, sendToClient);
for (const auto& category : categoriesToRemove)
caster->RemoveCategoryCooldown(category);
}
void Register() override
+24
View File
@@ -3702,6 +3702,29 @@ class spell_item_snowman : public SpellScript
}
};
// https://www.wowhead.com/wotlk/spell=16028 Freeze Rookery Egg - Prototype
// https://www.wowhead.com/wotlk/spell=15748 Freeze Rookery Egg
class spell_item_freeze_rookery_egg : public SpellScript
{
PrepareSpellScript(spell_item_freeze_rookery_egg);
void HandleOpenObject(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (GameObject* rookery = GetHitGObj())
{
if (rookery->getLootState() == GO_READY)
rookery->UseDoorOrButton(0, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_item_freeze_rookery_egg::HandleOpenObject, EFFECT_0, SPELL_EFFECT_OPEN_LOCK);
}
};
void AddSC_item_spell_scripts()
{
RegisterSpellScript(spell_item_massive_seaforium_charge);
@@ -3816,4 +3839,5 @@ void AddSC_item_spell_scripts()
RegisterSpellScript(spell_item_wraith_scythe_drain_life);
RegisterSpellScript(spell_item_mirrens_drinking_hat);
RegisterSpellScript(spell_item_snowman);
RegisterSpellScript(spell_item_freeze_rookery_egg);
}
@@ -104,9 +104,10 @@ char* DBCDatabaseLoader::Load(uint32& records, char**& indexTable)
break;
case FT_SORT:
case FT_NA:
case FT_NA_BYTE:
break;
default:
ASSERT(false, "Unsupported data type '%c' in table '{}'", *dbcFormat, _sqlTableName);
ASSERT(false, "Unsupported data type '{}' in table '{}'", *dbcFormat, _sqlTableName);
return nullptr;
}