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