Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-10-31 16:12:42 -06:00
committed by GitHub
42 changed files with 649 additions and 152 deletions
+106
View File
@@ -0,0 +1,106 @@
name: Auto Assign to Project(s)
on:
issues:
types: [opened, labeled]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
assign_one_project:
runs-on: ubuntu-latest
name: Assign to One Project
steps:
- name: Assign issues with `ChromieCraft Generic` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, 'ChromieCraft Generic')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/20'
- name: Assign issues with `1-19` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '1-19')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/14'
- name: Assign issues with `20-29` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '20-29')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/17'
- name: Assign issues with `30-39` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '30-39')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/23'
- name: Assign issues with `40-49` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '40-49')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/24'
- name: Assign issues with `50-59` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '50-59')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/25'
- name: Assign issues with `60` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '60')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/22'
- name: Assign issues with `61-64` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '61-64')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/32'
- name: Assign issues with `65-69` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '65-69')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/36'
- name: Assign issues with `70` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '70')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/26'
- name: Assign issues with `71-74` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '71-74')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/33'
- name: Assign issues with `75-79` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '75-79')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/37'
- name: Assign issues with `80` label to their project
uses: srggrs/assign-one-project-github-action@1.2.1
if: |
contains(github.event.issue.labels.*.name, '80')
with:
project: 'https://github.com/azerothcore/azerothcore-wotlk/projects/38'
@@ -0,0 +1,6 @@
-- DB update 2022_10_26_00 -> 2022_10_26_01
--
DELETE FROM `spell_proc_event` WHERE `entry` IN (64349,64350);
INSERT INTO `spell_proc_event` VALUES
(64349,0,0,0,0,0,0,0,0,0,0,60000),
(64350,0,0,0,0,0,0,0,0,0,0,60000);
@@ -0,0 +1,8 @@
-- DB update 2022_10_26_01 -> 2022_10_28_00
--
UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE entry IN (
15517, -- Ouro
15275, -- Emperor Vek'nilash
15276); -- Emperor Vek'lor
@@ -0,0 +1,3 @@
-- DB update 2022_10_28_00 -> 2022_10_29_00
--
UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask`|33554432 WHERE `entry` = 15276;
+127
View File
@@ -0,0 +1,127 @@
-- DB update 2022_10_29_00 -> 2022_10_29_01
--
ALTER TABLE `areatrigger_tavern` ADD COLUMN `faction` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `name`;
SET @FACTION_ALLIANCE := 2;
SET @FACTION_HORDE := 4;
SET @FACTION_BOTH := 6;
UPDATE `areatrigger_tavern` SET `faction` = @FACTION_ALLIANCE WHERE `id` IN (
71,
562,
682,
707,
708,
709,
710,
712,
713,
715,
716,
717,
1024,
1042,
2266,
2786,
4090,
4240,
4241,
4337,
4374,
4376,
4377,
4381,
4383,
4499,
4961,
4964,
4965,
4966,
4993,
4528,
4558,
4753,
4756,
4769,
4867,
5182);
UPDATE `areatrigger_tavern` SET `faction` = @FACTION_HORDE WHERE `id` IN (
178,
719,
720,
721,
722,
742,
843,
844,
862,
982,
1022,
1025,
1606,
1646,
2267,
2286,
2610,
3547,
3690,
3886,
4108,
4109,
4265,
4336,
4373,
4375,
4378,
4380,
4486,
4494,
4526,
5323,
5360,
4967,
4970,
4979,
4868,
4910,
5045,
4861,
4775,
4755,
4595);
UPDATE `areatrigger_tavern` SET `faction` = @FACTION_BOTH WHERE `id` IN (
98,
743,
1023,
2287,
3985,
4058,
4300,
4382,
4498,
4521,
4555,
4577,
5183,
5200,
5204,
5217,
5227,
5314,
5315,
5316,
5317,
5327,
5062,
5164,
5030,
4975,
4976,
4977,
4607,
4608,
4640,
4714,
4847);
@@ -0,0 +1,3 @@
-- DB update 2022_10_29_01 -> 2022_10_29_02
--
DELETE FROM `spell_proc_event` WHERE `entry`=46916;
@@ -0,0 +1,10 @@
-- DB update 2022_10_29_02 -> 2022_10_29_03
--
-- Lava Spawn (12265)
DELETE FROM `creature_text` WHERE `CreatureID`=12265;
INSERT INTO `creature_text` (`CreatureID`, `Text`, `Type`, `Probability`, `BroadcastTextId`, `comment`) VALUES
(12265, '%s splits into two new Lava Spawns!', 16, 100, 7570, 'Lava Spawn');
UPDATE `creature_template` SET `AiName`='', `ScriptName`='npc_lava_spawn' WHERE `entry`=12265;
DELETE FROM `smart_scripts` WHERE `entryorguid`=12265 AND `source_type`=0;
@@ -0,0 +1,9 @@
-- DB update 2022_10_29_03 -> 2022_10_29_04
--
DELETE FROM `creature` WHERE `guid`=91799;
INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES
(91799,15353,0,1,1,1,-4918.64,-983.141,501.538,2.43867,300,0,0,1,0,0,0,0,0,'',0);
DELETE FROM `game_event_creature` WHERE `guid`=91799;
INSERT INTO `game_event_creature` VALUES
(12,91799);
@@ -0,0 +1,3 @@
-- DB update 2022_10_29_04 -> 2022_10_30_00
--
UPDATE `creature_loot_template` SET `Chance`=100 WHERE `Entry` IN (20798, 19298) AND `Item` IN (29590, 29588);
@@ -0,0 +1,35 @@
-- DB update 2022_10_30_00 -> 2022_10_30_01
ALTER TABLE `creature` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_equip_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_questitem` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_template_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_template_resistance` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `creature_template_spell` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `gameobject` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `gameobject_questitem` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `gameobject_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `gameobject_template_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `gossip_menu_option` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `item_set_names` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `item_set_names_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `item_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `item_template_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `lfg_dungeon_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `npc_text` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `npc_vendor` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `page_text` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `page_text_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `points_of_interest_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_details` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_greeting` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_greeting_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_offer_reward` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_offer_reward_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_poi` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_poi_points` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_request_items` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_request_items_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_template` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `quest_template_locale` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
ALTER TABLE `spell_target_position` CHANGE COLUMN `VerifiedBuild` `VerifiedBuild` MEDIUMINT NULL DEFAULT NULL;
+10 -6
View File
@@ -1139,8 +1139,6 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
break;
}
LoadCreaturesAddon();
uint32 displayID = GetNativeDisplayId();
if (sObjectMgr->GetCreatureModelRandomGender(&displayID) && !IsTotem()) // Cancel load if no model defined or if totem
{
@@ -1148,6 +1146,8 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
SetNativeDisplayId(displayID);
}
LoadCreaturesAddon();
//! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there
m_positionZ += GetHoverHeight();
@@ -2032,11 +2032,15 @@ void Creature::Respawn(bool force)
setDeathState(JUST_RESPAWNED);
// MDic - Acidmanifesto
uint32 displayID = GetNativeDisplayId();
if (sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined
// Do not override transform auras
if (GetAuraEffectsByType(SPELL_AURA_TRANSFORM).empty())
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
uint32 displayID = GetNativeDisplayId();
if (sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
}
}
GetMotionMaster()->InitDefault();
+1 -5
View File
@@ -370,11 +370,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
// 0x08000000
if (unit->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED)
{
const G3D::Vector3* p = &unit->movespline->_Spline().getPoints(true)[0];
if (unit->movespline->_Spline().getPoints(true).empty() || (!unit->movespline->_Spline().getPoints(true).empty() && !p))
const_cast<Unit*>(unit)->DisableSpline();
else
Movement::PacketBuilder::WriteCreate(*unit->movespline, *data);
Movement::PacketBuilder::WriteCreate(*unit->movespline, *data);
}
}
else
+8 -1
View File
@@ -1052,7 +1052,14 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry;
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
if (petType == HUNTER_PET)
{
SetMeleeDamageSchool(SPELL_SCHOOL_NORMAL);
}
else
{
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
}
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
+57 -31
View File
@@ -13318,14 +13318,21 @@ uint32 Player::CalculateTalentsPoints() const
{
uint32 base_talent = getLevel() < 10 ? 0 : getLevel() - 9;
uint32 talentPointsForLevel = 0;
if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
return uint32(base_talent * sWorld->getRate(RATE_TALENT));
uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55;
talentPointsForLevel += m_questRewardTalentCount;
if (talentPointsForLevel > base_talent)
{
talentPointsForLevel = base_talent;
}
else
{
talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55;
talentPointsForLevel += m_questRewardTalentCount;
if (talentPointsForLevel > base_talent)
{
talentPointsForLevel = base_talent;
}
}
talentPointsForLevel += m_extraBonusTalentCount;
return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));
@@ -13623,16 +13630,23 @@ void Player::CompletedAchievement(AchievementEntry const* entry)
m_achievementMgr->CompletedAchievement(entry);
}
void Player::LearnTalent(uint32 talentId, uint32 talentRank)
void Player::LearnTalent(uint32 talentId, uint32 talentRank, bool command /*= false*/)
{
uint32 CurTalentPoints = GetFreeTalentPoints();
// xinef: check basic data
if (CurTalentPoints == 0)
return;
if (!command)
{
// xinef: check basic data
if (!CurTalentPoints)
{
return;
}
if (talentRank >= MAX_TALENT_RANK)
return;
if (talentRank >= MAX_TALENT_RANK)
{
return;
}
}
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
if (!talentInfo)
@@ -13661,10 +13675,15 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
if (currentTalentRank >= talentRank + 1)
return;
// xinef: check if we have enough free talent points
uint32 talentPointsChange = (talentRank - currentTalentRank + 1);
if (CurTalentPoints < talentPointsChange)
return;
if (!command)
{
// xinef: check if we have enough free talent points
if (CurTalentPoints < talentPointsChange)
{
return;
}
}
// xinef: check if talent deponds on another talent
if (talentInfo->DependsOn > 0)
@@ -13686,23 +13705,26 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
return;
}
// xinef: check amount of points spent in current talent tree
// xinef: be smart and quick
uint32 spentPoints = 0;
if (talentInfo->Row > 0)
if (!command)
{
const PlayerTalentMap& talentMap = GetTalentMap();
for (PlayerTalentMap::const_iterator itr = talentMap.begin(); itr != talentMap.end(); ++itr)
if (TalentSpellPos const* talentPos = GetTalentSpellPos(itr->first))
if (TalentEntry const* itrTalentInfo = sTalentStore.LookupEntry(talentPos->talent_id))
if (itrTalentInfo->TalentTab == talentInfo->TalentTab)
if (itr->second->State != PLAYERSPELL_REMOVED && itr->second->IsInSpec(GetActiveSpec())) // pussywizard
spentPoints += talentPos->rank + 1;
}
// xinef: check amount of points spent in current talent tree
// xinef: be smart and quick
uint32 spentPoints = 0;
if (talentInfo->Row > 0)
{
const PlayerTalentMap& talentMap = GetTalentMap();
for (PlayerTalentMap::const_iterator itr = talentMap.begin(); itr != talentMap.end(); ++itr)
if (TalentSpellPos const* talentPos = GetTalentSpellPos(itr->first))
if (TalentEntry const* itrTalentInfo = sTalentStore.LookupEntry(talentPos->talent_id))
if (itrTalentInfo->TalentTab == talentInfo->TalentTab)
if (itr->second->State != PLAYERSPELL_REMOVED && itr->second->IsInSpec(GetActiveSpec())) // pussywizard
spentPoints += talentPos->rank + 1;
}
// xinef: we do not have enough talent points to add talent of this tier
if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
return;
// xinef: we do not have enough talent points to add talent of this tier
if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
return;
}
// xinef: hacking attempt, tries to learn unknown rank
uint32 spellId = talentInfo->RankID[talentRank];
@@ -13735,7 +13757,11 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// xinef: update free talent points count
m_usedTalentCount += talentPointsChange;
SetFreeTalentPoints(CurTalentPoints - talentPointsChange);
if (!command)
{
SetFreeTalentPoints(CurTalentPoints - talentPointsChange);
}
sScriptMgr->OnPlayerLearnTalents(this, talentId, talentRank, spellId);
}
+1 -1
View File
@@ -1677,7 +1677,7 @@ public:
void BuildPlayerTalentsInfoData(WorldPacket* data);
void BuildPetTalentsInfoData(WorldPacket* data);
void SendTalentsInfoData(bool pet);
void LearnTalent(uint32 talentId, uint32 talentRank);
void LearnTalent(uint32 talentId, uint32 talentRank, bool command = false);
void LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank);
bool addTalent(uint32 spellId, uint8 addSpecMask, uint8 oldTalentRank);
+44 -13
View File
@@ -124,7 +124,8 @@ DamageInfo::DamageInfo(CalcDamageInfo const& dmgInfo) : DamageInfo(DamageInfo(dm
DamageInfo::DamageInfo(DamageInfo const& dmg1, DamageInfo const& dmg2)
: m_attacker(dmg1.m_attacker), m_victim(dmg1.m_victim), m_damage(dmg1.m_damage + dmg2.m_damage), m_spellInfo(dmg1.m_spellInfo), m_schoolMask(SpellSchoolMask(dmg1.m_schoolMask | dmg2.m_schoolMask)),
m_damageType(dmg1.m_damageType), m_attackType(dmg1.m_attackType), m_absorb(dmg1.m_absorb + dmg2.m_absorb), m_resist(dmg1.m_resist + dmg2.m_resist), m_block(dmg1.m_block)
m_damageType(dmg1.m_damageType), m_attackType(dmg1.m_attackType), m_absorb(dmg1.m_absorb + dmg2.m_absorb), m_resist(dmg1.m_resist + dmg2.m_resist), m_block(dmg1.m_block),
m_cleanDamage(dmg1.m_cleanDamage + dmg1.m_cleanDamage)
{
}
@@ -915,7 +916,9 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
}
if (attacker && shareDamageTarget->GetTypeId() == TYPEID_PLAYER)
attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell, shareDamage, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false);
{
attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell, shareDamage, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false, true);
}
Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false, false, damageSpell);
}
@@ -2359,7 +2362,9 @@ void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted, nullptr, -1, nullptr, &splittedDmgInfo);
if (attacker)
attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo(), splitted, schoolMask, splitted_absorb, splitted_resist, false, 0, false);
{
attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo(), splitted, schoolMask, splitted_absorb, splitted_resist, false, 0, false, true);
}
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
@@ -2430,7 +2435,9 @@ void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted);
if (attacker)
attacker->SendSpellNonMeleeDamageLog(caster, splitSpellInfo, splitted, splitSchoolMask, splitted_absorb, splitted_resist, false, 0, false);
{
attacker->SendSpellNonMeleeDamageLog(caster, splitSpellInfo, splitted, splitSchoolMask, splitted_absorb, splitted_resist, false, 0, false, true);
}
CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, splitSchoolMask, splitSpellInfo, false);
@@ -3148,20 +3155,18 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
// xinef: if from behind or spell requires cast from behind
if (!victim->HasInArc(M_PI, this))
{
if (!victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
if (!victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION) || spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
{
// Can`t dodge from behind in PvP (but its possible in PvE)
if (victim->GetTypeId() == TYPEID_PLAYER)
{
canDodge = false;
}
// Can`t parry or block
canParry = false;
canBlock = false;
}
else // Only deterrence as of 3.3.5
{
if (spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
canParry = false;
}
}
// Check creatures flags_extra for disable parry
@@ -6219,11 +6224,31 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log)
data << uint8 (log->unused); // unused
data << uint32(log->blocked); // blocked
data << uint32(log->HitInfo);
data << uint8 (0); // flag to use extend data
data << uint32(log->HitInfo);
data << uint8(log->HitInfo & (SPELL_HIT_TYPE_CRIT_DEBUG | SPELL_HIT_TYPE_HIT_DEBUG | SPELL_HIT_TYPE_ATTACK_TABLE_DEBUG));
//if (log->HitInfo & SPELL_HIT_TYPE_CRIT_DEBUG)
//{
// data << float(log->CritRoll);
// data << float(log->CritNeeded);
//}
//if (log->HitInfo & SPELL_HIT_TYPE_HIT_DEBUG)
//{
// data << float(log->HitRoll);
// data << float(log->HitNeeded);
//}
//if (log->HitInfo & SPELL_HIT_TYPE_ATTACK_TABLE_DEBUG)
//{
// data << float(log->MissChance);
// data << float(log->DodgeChance);
// data << float(log->ParryChance);
// data << float(log->BlockChance);
// data << float(log->GlanceChance);
// data << float(log->CrushChance);
//}
SendMessageToSet(&data, true);
}
void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit /*= false*/, bool Split /*= false*/)
{
SpellNonMeleeDamage log(this, target, spellInfo, damageSchoolMask);
log.damage = Damage;
@@ -6231,9 +6256,15 @@ void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo,
log.resist = Resist;
log.physicalLog = PhysicalDamage;
log.blocked = Blocked;
log.HitInfo = SPELL_HIT_TYPE_UNK1 | SPELL_HIT_TYPE_UNK3 | SPELL_HIT_TYPE_UNK6;
log.HitInfo = 0;
if (CriticalHit)
{
log.HitInfo |= SPELL_HIT_TYPE_CRIT;
}
if (Split)
{
log.HitInfo |= SPELL_HIT_TYPE_SPLIT;
}
SendSpellNonMeleeDamageLog(&log);
}
+1 -1
View File
@@ -1746,7 +1746,7 @@ public:
void SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount);
void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log);
void SendSpellNonMeleeReflectLog(SpellNonMeleeDamage* log, Unit* attacker);
void SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false);
void SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false, bool Split = false);
void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo);
void SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo);
void SendSpellDamageResist(Unit* target, uint32 spellId);
+4 -2
View File
@@ -6320,7 +6320,7 @@ void ObjectMgr::LoadTavernAreaTriggers()
_tavernAreaTriggerStore.clear(); // need for reload case
QueryResult result = WorldDatabase.Query("SELECT id FROM areatrigger_tavern");
QueryResult result = WorldDatabase.Query("SELECT id, faction FROM areatrigger_tavern");
if (!result)
{
@@ -6346,7 +6346,9 @@ void ObjectMgr::LoadTavernAreaTriggers()
continue;
}
_tavernAreaTriggerStore.insert(Trigger_ID);
uint32 faction = fields[1].Get<uint32>();
_tavernAreaTriggerStore.emplace(Trigger_ID, faction);
} while (result->NextRow());
LOG_INFO("server.loading", ">> Loaded {} Tavern Triggers in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+9 -3
View File
@@ -840,9 +840,15 @@ public:
return 0;
}
[[nodiscard]] bool IsTavernAreaTrigger(uint32 Trigger_ID) const
[[nodiscard]] bool IsTavernAreaTrigger(uint32 triggerID, uint32 faction) const
{
return _tavernAreaTriggerStore.find(Trigger_ID) != _tavernAreaTriggerStore.end();
auto itr = _tavernAreaTriggerStore.find(triggerID);
if (itr != _tavernAreaTriggerStore.end())
{
return (itr->second & faction) != 0;
}
return false;
}
[[nodiscard]] GossipText const* GetGossipText(uint32 Text_ID) const;
@@ -1449,7 +1455,7 @@ private:
typedef std::unordered_map<uint32, GossipText> GossipTextContainer;
typedef std::unordered_map<uint32, uint32> QuestAreaTriggerContainer;
typedef std::set<uint32> TavernAreaTriggerContainer;
typedef std::unordered_map<uint32, uint32> TavernAreaTriggerContainer;
QuestAreaTriggerContainer _questAreaTriggerStore;
TavernAreaTriggerContainer _tavernAreaTriggerStore;
+2 -1
View File
@@ -747,7 +747,8 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data)
return;
}
bool isTavernAreatrigger = sObjectMgr->IsTavernAreaTrigger(triggerId);
uint32 teamFaction = player->GetTeamId(true) == TEAM_ALLIANCE ? FACTION_MASK_ALLIANCE : FACTION_MASK_HORDE;
bool isTavernAreatrigger = sObjectMgr->IsTavernAreaTrigger(triggerId, teamFaction);
if (!player->IsInAreaTriggerRadius(atEntry, isTavernAreatrigger ? 5.f : 0.f))
{
LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player {} ({}) too far (trigger map: {} player map: {}), ignore Area Trigger ID: {}",
@@ -93,7 +93,7 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
{
if (Creature* cOwner2 = owner->ToCreature())
{
cOwner2->SetCannotReachTarget(i_path && i_path->GetPathType() & PATHFIND_INCOMPLETE ? target->GetGUID() : ObjectGuid::Empty);
cOwner2->SetCannotReachTarget();
}
i_recalculateTravel = false;
@@ -80,7 +80,7 @@ namespace Movement
void MoveSpline::computeFallElevation(float& el) const
{
float z_now = spline.getPoint(spline.first(), false).z - Movement::computeFallElevation(MSToSec(time_passed), false);
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed), false);
float final_z = FinalDestination().z;
el = std::max(z_now, final_z);
}
@@ -96,7 +96,7 @@ namespace Movement
float start_elevation;
inline int32 operator()(Spline<int32>& s, int32 i)
{
return Movement::computeFallTime(start_elevation - s.getPoint(i + 1, false).z, false) * 1000.f;
return Movement::computeFallTime(start_elevation - s.getPoint(i + 1).z, false) * 1000.f;
}
};
@@ -138,7 +138,7 @@ namespace Movement
// init spline timestamps
if (splineflags.falling)
{
FallInitializer init(spline.getPoint(spline.first(), false).z);
FallInitializer init(spline.getPoint(spline.first()).z);
spline.initLengths(init);
}
else
+3 -3
View File
@@ -71,7 +71,7 @@ namespace Movement
void init_spline(const MoveSplineInitArgs& args);
protected:
[[nodiscard]] const MySpline::ControlArray& getPath(bool visual) const { return spline.getPoints(visual); }
[[nodiscard]] const MySpline::ControlArray& getPath() const { return spline.getPoints(); }
void computeParabolicElevation(float& el) const;
void computeFallElevation(float& el) const;
@@ -117,8 +117,8 @@ namespace Movement
[[nodiscard]] bool isCyclic() const { return splineflags.cyclic; }
[[nodiscard]] bool isFalling() const { return splineflags.falling; }
[[nodiscard]] bool isWalking() const { return splineflags.walkmode; }
[[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last(), false) : Vector3(); }
[[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1, false) : Vector3(); }
[[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); }
[[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); }
[[nodiscard]] int32 currentPathIdx() const;
[[nodiscard]] bool HasAnimation() const { return splineflags.animation; }
@@ -135,11 +135,6 @@ namespace Movement
data << int8(unit->GetTransSeat());
}
Movement::SplineBase::ControlArray* visualPoints = const_cast<Movement::SplineBase::ControlArray*>(move_spline._Spline().allocateVisualPoints());
visualPoints->resize(move_spline._Spline().getPointCount());
// Xinef: Apply hover in creature movement packet
std::copy(move_spline._Spline().getPoints(false).begin(), move_spline._Spline().getPoints(false).end(), visualPoints->begin());
PacketBuilder::WriteMonsterMove(move_spline, data);
unit->SendMessageToSet(&data, true);
@@ -45,7 +45,7 @@ namespace Movement
MoveSplineFlag splineflags = move_spline.splineflags;
data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40)
data << move_spline.spline.getPoint(move_spline.spline.first(), true);
data << move_spline.spline.getPoint(move_spline.spline.first());
data << move_spline.GetId();
switch (splineflags & MoveSplineFlag::Mask_Final_Facing)
@@ -99,7 +99,7 @@ namespace Movement
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
{
uint32 last_idx = spline.getPointCount() - 3;
const Vector3* real_path = &spline.getPoint(1, true);
const Vector3* real_path = &spline.getPoint(1);
data << last_idx;
data << real_path[last_idx]; // destination
@@ -120,7 +120,7 @@ namespace Movement
{
uint32 count = spline.getPointCount() - 3;
data << count;
data.append<Vector3>(&spline.getPoint(2, true), count);
data.append<Vector3>(&spline.getPoint(2), count);
}
void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data, bool flying)
@@ -129,12 +129,12 @@ namespace Movement
data << uint32(count + 1);
if (flying)
{
data << spline.getPoint(1, true); // fake point, client will erase it from the spline after first cycle done
data.append<Vector3>(&spline.getPoint(2, true), count);
data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done
data.append<Vector3>(&spline.getPoint(2), count);
}
else
{
data.append<Vector3>(&spline.getPoint(2, true), count);
data.append<Vector3>(&spline.getPoint(2), count);
data << Vector3::zero(); //Xinef: fake point
}
}
@@ -189,9 +189,9 @@ namespace Movement
data << move_spline.vertical_acceleration; // added in 3.1
data << move_spline.effect_start_time; // added in 3.1
uint32 nodes = move_spline.getPath(true).size();
uint32 nodes = move_spline.getPath().size();
data << nodes;
data.append<Vector3>(&move_spline.getPath(true)[0], nodes);
data.append<Vector3>(&move_spline.getPath()[0], nodes);
data << uint8(move_spline.spline.mode()); // added in 3.1
data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
}
@@ -286,7 +286,6 @@ namespace Movement
index_lo = 0;
index_hi = 0;
points.clear();
pointsVisual.clear();
}
std::string SplineBase::ToString() const
+2 -4
View File
@@ -42,7 +42,6 @@ namespace Movement
protected:
ControlArray points;
ControlArray pointsVisual;
index_type index_lo{0};
index_type index_hi{0};
@@ -112,10 +111,9 @@ namespace Movement
[[nodiscard]] bool isCyclic() const { return cyclic;}
// Xinef: DO NOT USE EXCEPT FOR SPLINE INITIALIZATION!!!!!!
[[nodiscard]] const ControlArray* allocateVisualPoints() const { return &pointsVisual; }
[[nodiscard]] const ControlArray& getPoints(bool visual) const { return visual ? pointsVisual : points;}
[[nodiscard]] const ControlArray& getPoints() const { return points;}
[[nodiscard]] index_type getPointCount() const { return points.size();}
[[nodiscard]] const Vector3& getPoint(index_type i, bool visual) const { return visual ? pointsVisual[i] : points[i];}
[[nodiscard]] const Vector3& getPoint(index_type i) const { return points[i];}
/** Initializes spline. Don't call other methods while spline not initialized. */
void init_spline(const Vector3* controls, index_type count, EvaluationMode m);
+15 -3
View File
@@ -131,6 +131,16 @@ Quest::Quest(Field* questRecord)
}
_eventIdForQuest = 0;
if (sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT))
{
Flags &= ~QUEST_FLAGS_AUTO_ACCEPT;
}
if (sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE))
{
Flags &= ~QUEST_FLAGS_AUTOCOMPLETE;
}
}
void Quest::LoadQuestDetails(Field* fields)
@@ -180,8 +190,10 @@ void Quest::LoadQuestTemplateAddon(Field* fields)
RewardMailSenderEntry = fields[16].Get<uint32>();
SpecialFlags = fields[17].Get<uint8>();
if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
if ((SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) && !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT))
{
Flags |= QUEST_FLAGS_AUTO_ACCEPT;
}
}
uint32 Quest::XPValue(uint8 playerLevel) const
@@ -253,12 +265,12 @@ uint32 Quest::GetRewMoneyMaxLevel() const
bool Quest::IsAutoAccept() const
{
return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) ? false : (Flags & QUEST_FLAGS_AUTO_ACCEPT);
return HasFlag(QUEST_FLAGS_AUTO_ACCEPT);
}
bool Quest::IsAutoComplete() const
{
return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) ? false : HasFlag(QUEST_FLAGS_AUTOCOMPLETE);
return HasFlag(QUEST_FLAGS_AUTOCOMPLETE);
}
bool Quest::IsRaidQuest(Difficulty difficulty) const
+10 -7
View File
@@ -2923,15 +2923,18 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8>& targets, Unit* /*caster*/
for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
{
// xinef: check z level and los dependence
Unit* target = *itr;
float zLevel = GetDynobjOwner()->GetPositionZ();
if (target->GetPositionZ() + 3.0f < zLevel || target->GetPositionZ() - 5.0f > zLevel)
Optional<float> collisionHeight = { };
if (Unit* dynObjCaster = GetDynobjOwner()->GetCaster())
{
if (!spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) && !target->IsWithinLOSInMap(GetDynobjOwner()))
{
continue;
}
collisionHeight = dynObjCaster->GetCollisionHeight();
}
if (!spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) &&
!target->IsWithinLOSInMap(GetDynobjOwner(), VMAP::ModelIgnoreFlags::Nothing, LINEOFSIGHT_ALL_CHECKS, collisionHeight))
{
continue;
}
std::map<Unit*, uint8>::iterator existing = targets.find(*itr);
+23 -24
View File
@@ -3974,6 +3974,20 @@ void Spell::_cast(bool skipCheck)
if (modOwner)
modOwner->SetSpellModTakingSpell(this, true);
bool resetAttackTimers = IsAutoActionResetSpell() && !m_spellInfo->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS);
if (resetAttackTimers)
{
Unit::AuraEffectList const& vIgnoreReset = m_caster->GetAuraEffectsByType(SPELL_AURA_IGNORE_MELEE_RESET);
for (Unit::AuraEffectList::const_iterator i = vIgnoreReset.begin(); i != vIgnoreReset.end(); ++i)
{
if ((*i)->IsAffectedOnSpell(m_spellInfo))
{
resetAttackTimers = false;
break;
}
}
}
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled())/* xinef: we dont need this || m_spellInfo->Id == 14157*/)
{
@@ -4006,38 +4020,23 @@ void Spell::_cast(bool skipCheck)
handle_immediate();
}
if (IsAutoActionResetSpell())
if (resetAttackTimers)
{
bool found = false;
Unit::AuraEffectList const& vIgnoreReset = m_caster->GetAuraEffectsByType(SPELL_AURA_IGNORE_MELEE_RESET);
for (Unit::AuraEffectList::const_iterator i = vIgnoreReset.begin(); i != vIgnoreReset.end(); ++i)
if (m_casttime == 0 && m_spellInfo->CalcCastTime())
{
if ((*i)->IsAffectedOnSpell(m_spellInfo))
{
found = true;
break;
}
resetAttackTimers = false;
}
if (!found && !m_spellInfo->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS))
if (resetAttackTimers)
{
bool allow = true;
if (m_casttime == 0 && m_spellInfo->CalcCastTime())
m_caster->resetAttackTimer(BASE_ATTACK);
if (m_caster->haveOffhandWeapon())
{
allow = false;
m_caster->resetAttackTimer(OFF_ATTACK);
}
if (allow)
{
m_caster->resetAttackTimer(BASE_ATTACK);
if (m_caster->haveOffhandWeapon())
{
m_caster->resetAttackTimer(OFF_ATTACK);
}
m_caster->resetAttackTimer(RANGED_ATTACK);
}
m_caster->resetAttackTimer(RANGED_ATTACK);
}
}
+1 -1
View File
@@ -319,7 +319,7 @@ void Spell::EffectEnvironmentalDMG(SpellEffIndex /*effIndex*/)
Unit::DealDamageMods(unitTarget, envDamage, &absorb);
damage = envDamage;
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0, false);
m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo, damage, m_spellInfo->GetSchoolMask(), absorb, resist, false, 0);
}
}
@@ -4421,6 +4421,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].MiscValueB = 64;
});
// Uppercut
ApplySpellFix({ 26007 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPRESS_CASTER_PROCS;
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
+4 -1
View File
@@ -195,9 +195,12 @@ public:
if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo))
continue;
player->LearnTalent(talentInfo->TalentID, rankId);
player->LearnTalent(talentInfo->TalentID, rankId, true);
}
player->SetFreeTalentPoints(0);
player->SendTalentsInfoData(false);
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
return true;
}
@@ -19,6 +19,7 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
enum Texts
{
@@ -34,6 +35,13 @@ enum Spells
SPELL_FULL_HEALTH = 17683,
SPELL_FIRE_NOVA_VISUAL = 19823,
SPELL_PLAY_DEAD_PACIFY = 19951, // Server side spell
// Lava Spawn
SPELL_FIREBALL = 19391,
SPELL_SPLIT_1 = 19569,
SPELL_SPLIT_2 = 19570,
TALK_0 = 0
};
// Serrated Bites timer may be wrong
@@ -207,10 +215,60 @@ public:
}
};
struct npc_lava_spawn : public ScriptedAI
{
npc_lava_spawn(Creature* creature) : ScriptedAI(creature)
{
}
void Reset() override
{
_scheduler.CancelAll();
}
void EnterCombat(Unit* /*who*/) override
{
_scheduler.Schedule(15s, [this](TaskContext context)
{
std::list<Creature*> lavaSpawns;
me->GetCreatureListWithEntryInGrid(lavaSpawns, me->GetEntry(), 100.f);
if (lavaSpawns.size() < 16)
{
Talk(TALK_0);
DoCastSelf(SPELL_SPLIT_1, true);
DoCastSelf(SPELL_SPLIT_2, true);
me->DespawnOrUnsummon();
}
else
{
context.Repeat(15s);
}
});
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
_scheduler.Update(diff);
DoSpellAttackIfReady(SPELL_FIREBALL);
}
private:
TaskScheduler _scheduler;
};
void AddSC_molten_core()
{
// Creatures
new npc_mc_core_hound();
RegisterCreatureAI(npc_lava_spawn);
// Spells
new spell_mc_play_dead();
@@ -452,10 +452,9 @@ struct boss_cthun : public BossAI
target->m_Events.AddEventAtOffset([target, this]()
{
DoCast(target, SPELL_DIGESTIVE_ACID, true);
DoTeleportPlayer(target, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O);
target->RemoveAurasDueToSpell(SPELL_MIND_FLAY);
//Cast digestive acid on them
DoCast(target, SPELL_DIGESTIVE_ACID, true);
}, 3800ms);
}
@@ -546,6 +545,8 @@ struct boss_cthun : public BossAI
{
eye->DespawnOrUnsummon();
}
instance->SetData(DATA_CTHUN_PHASE, PHASE_CTHUN_DONE);
}
void SummonedCreatureDies(Creature* creature, Unit* /*killer*/) override
@@ -747,6 +748,8 @@ struct npc_giant_claw_tentacle : public ScriptedAI
}
}
}
_canAttack = false;
}
void JustDied(Unit* /*killer*/) override
@@ -770,14 +773,17 @@ struct npc_giant_claw_tentacle : public ScriptedAI
DoZoneInCombat();
_scheduler.Schedule(2s, [this](TaskContext context)
{
{
DoCastVictim(SPELL_HAMSTRING);
context.Repeat(10s);
}).Schedule(5s, [this](TaskContext context)
{
DoCastSelf(SPELL_THRASH);
context.Repeat(10s);
});
}).Schedule(5s, [this](TaskContext context)
{
DoCastSelf(SPELL_THRASH);
context.Repeat(10s);
}).Schedule(3s, [this](TaskContext /*context*/)
{
_canAttack = true;
});
ScheduleMeleeCheck();
}
@@ -825,6 +831,7 @@ struct npc_giant_claw_tentacle : public ScriptedAI
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
_scheduler.CancelAll();
_canAttack = false;
_scheduler.Schedule(5s, [this](TaskContext /*task*/)
{
@@ -851,6 +858,11 @@ struct npc_giant_claw_tentacle : public ScriptedAI
ScheduleMeleeCheck();
}
_scheduler.Schedule(3s, [this](TaskContext /*context*/)
{
_canAttack = true;
});
}
void UpdateAI(uint32 diff) override
@@ -861,12 +873,16 @@ struct npc_giant_claw_tentacle : public ScriptedAI
_scheduler.Update(diff);
DoMeleeAttackIfReady();
if (_canAttack)
{
DoMeleeAttackIfReady();
}
}
private:
TaskScheduler _scheduler;
ObjectGuid _portalGUID;
bool _canAttack;
};
struct npc_giant_eye_tentacle : public ScriptedAI
@@ -112,6 +112,11 @@ struct boss_ouro : public BossAI
_scheduler.SetValidator([this] { return !me->HasUnitState(UNIT_STATE_CASTING); });
}
bool CanAIAttack(Unit const* victim) const override
{
return me->IsWithinMeleeRange(victim);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (me->HealthBelowPctDamaged(20, damage) && !_enraged)
@@ -190,7 +195,9 @@ struct boss_ouro : public BossAI
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SAND_BLAST && target)
me->GetThreatMgr().ModifyThreatByPercent(target, 100);
{
me->GetThreatMgr().ModifyThreatByPercent(target, -100);
}
}
void Emerge()
@@ -202,7 +209,21 @@ struct boss_ouro : public BossAI
_scheduler
.Schedule(20s, GROUP_EMERGED, [this](TaskContext context)
{
DoCastVictim(SPELL_SAND_BLAST);
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, 0.0f, true))
{
me->SetTarget(target->GetGUID());
}
DoCastAOE(SPELL_SAND_BLAST);
me->m_Events.AddEventAtOffset([this]()
{
if (Unit* victim = me->GetVictim())
{
me->SetTarget(victim->GetGUID());
}
}, 3s);
context.Repeat();
})
.Schedule(22s, GROUP_EMERGED, [this](TaskContext context)
@@ -252,11 +273,14 @@ struct boss_ouro : public BossAI
void EnterEvadeMode(EvadeReason /*why*/) override
{
DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL);
me->DespawnOrUnsummon(1000);
instance->SetBossState(DATA_OURO, FAIL);
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
base->DespawnOrUnsummon();
if (me->GetThreatMgr().GetThreatList().empty())
{
DoCastSelf(SPELL_OURO_SUBMERGE_VISUAL);
me->DespawnOrUnsummon(1000);
instance->SetBossState(DATA_OURO, FAIL);
if (GameObject* base = me->FindNearestGameObject(GO_SANDWORM_BASE, 200.f))
base->DespawnOrUnsummon();
}
}
void EnterCombat(Unit* who) override
@@ -138,7 +138,7 @@ struct boss_sartura : public BossAI
case EVENT_SPELL_BERSERK:
if (!berserked)
{
DoCastSelf(SPELL_BERSERK);
DoCastSelf(SPELL_BERSERK, true);
berserked = true;
}
break;
@@ -309,7 +309,7 @@ struct boss_veknilash : public boss_twinemperorsAI
_scheduler
.Schedule(14s, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_UPPERCUT, 0, me->GetMeleeReach(), true, true);
DoCastRandomTarget(SPELL_UPPERCUT, 0, me->GetMeleeReach(), true);
context.Repeat(4s, 15s);
})
.Schedule(12s, [this](TaskContext context)
@@ -402,7 +402,8 @@ struct npc_obsidian_nullifier : public ScriptedAI
for (Unit* target : _targets)
{
DoCast(target, SPELL_DRAIN_MANA_NULLIFIER, true);
if (target)
DoCast(target, SPELL_DRAIN_MANA_NULLIFIER, true);
}
if (me->GetPowerPct(POWER_MANA) >= 100.f)
+1 -1
View File
@@ -122,7 +122,7 @@ class spell_rog_blade_flurry : public AuraScript
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
if (procTarget && damageInfo)
{
int32 damage = damageInfo->GetDamage();
int32 damage = damageInfo->GetUnmitigatedDamage();
CustomSpellValues values;
values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage);
+1 -1
View File
@@ -668,7 +668,7 @@ class spell_warr_sweeping_strikes : public AuraScript
}
else
{
int32 damage = damageInfo->GetDamage();
int32 damage = damageInfo->GetUnmitigatedDamage();
GetTarget()->CastCustomSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK_1, &damage, 0, 0, true, nullptr, aurEff);
}
}
+6 -6
View File
@@ -1504,12 +1504,12 @@ enum SpellMissInfo
enum SpellHitType
{
SPELL_HIT_TYPE_UNK1 = 0x00001,
SPELL_HIT_TYPE_CRIT = 0x00002,
SPELL_HIT_TYPE_UNK3 = 0x00004,
SPELL_HIT_TYPE_UNK4 = 0x00008,
SPELL_HIT_TYPE_UNK5 = 0x00010, // replace caster?
SPELL_HIT_TYPE_UNK6 = 0x00020
SPELL_HIT_TYPE_CRIT_DEBUG = 0x01,
SPELL_HIT_TYPE_CRIT = 0x02,
SPELL_HIT_TYPE_HIT_DEBUG = 0x04,
SPELL_HIT_TYPE_SPLIT = 0x08,
SPELL_HIT_TYPE_VICTIM_IS_ATTACKER = 0x10,
SPELL_HIT_TYPE_ATTACK_TABLE_DEBUG = 0x20
};
enum SpellDmgClass