Merge branch 'master' into Playerbot
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
-- DB update 2024_07_05_00 -> 2024_09_03_00
|
||||
DROP TABLE IF EXISTS `character_achievement_offline_updates`;
|
||||
CREATE TABLE `character_achievement_offline_updates` (
|
||||
`guid` BIGINT UNSIGNED NOT NULL COMMENT 'Character\'s GUID',
|
||||
`guid` INT UNSIGNED NOT NULL COMMENT 'Character\'s GUID',
|
||||
`update_type` TINYINT UNSIGNED NOT NULL COMMENT 'Supported types: 1 - COMPLETE_ACHIEVEMENT; 2 - UPDATE_CRITERIA',
|
||||
`arg1` INT UNSIGNED NOT NULL COMMENT 'For type 1: achievement ID; for type 2: ACHIEVEMENT_CRITERIA_TYPE',
|
||||
`arg2` INT UNSIGNED DEFAULT NULL COMMENT 'For type 2: miscValue1 for updating achievement criteria',
|
||||
`arg3` INT UNSIGNED DEFAULT NULL COMMENT 'For type 2: miscValue2 for updating achievement criteria',
|
||||
INDEX `idx_guid` (`guid`)
|
||||
)
|
||||
COMMENT = 'Stores updates to character achievements when the character was offline';
|
||||
COMMENT = 'Stores updates to character achievements when the character was offline'
|
||||
CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_unicode_ci
|
||||
ENGINE = InnoDB
|
||||
;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- DB update 2024_09_11_01 -> 2024_09_15_00
|
||||
--
|
||||
UPDATE `creature_text` SET `TextRange` = 3 WHERE `CreatureId` = 22984;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- DB update 2024_09_15_00 -> 2024_09_15_01
|
||||
-- implement QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT
|
||||
-- extend column datatype from tinyint to int
|
||||
ALTER TABLE `quest_template_addon` MODIFY COLUMN `SpecialFlags` INT UNSIGNED DEFAULT 0 NOT NULL;
|
||||
|
||||
-- add flag to Corrupted Flower Quests in Felwood
|
||||
UPDATE `quest_template_addon` SET `SpecialFlags` = (`SpecialFlags` | 256)
|
||||
WHERE (`ID` IN (996, 998, 1514, 2523, 2878, 3363, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4221, 4222, 4343, 4401, 4403, 4443, 4444, 4445, 4446, 4447, 4448, 4461, 4462, 4464, 4465, 4466, 4467));
|
||||
@@ -0,0 +1,172 @@
|
||||
-- DB update 2024_09_15_01 -> 2024_09_16_00
|
||||
-- wp modify
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .gobject set $subcommand
|
||||
Type .gobject set to see the list of possible subcommands or .help gobject set $subcommand to see info on subcommands.' WHERE `name` = 'gobject set';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .skirmish [arena] [XvX] [Nick1] [Nick2] ... [NickN]
|
||||
[arena] can be \"all\" or comma-separated list of possible arenas (NA, BE, RL, DS, RV).
|
||||
[XvX] can be 1v1, 2v2, 3v3, 5v5. After [XvX] specify enough nicknames for that mode.' WHERE `name` = 'skirmish';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .bf $subcommand
|
||||
Type .bf to see the list of possible subcommands or .help bf $subcommand to see info on subcommands.' WHERE `name` = 'bf';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug entervehicle #entry #seatID
|
||||
Enter the targeted or given vehicle ID in the given seat.' WHERE `name` = 'debug entervehicle';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug getitemstate #itemState [unchanged/changed/new/removed/queue/check_all]
|
||||
Returns all items in a given player''s inventory with a given item state.' WHERE `name` = 'debug getitemstate';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug getitemvalue #GUID #index
|
||||
Returns the value of the given index for the given item GUID.' WHERE `name` = 'debug getitemvalue';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug getvalue #index #isInt
|
||||
Returns either an integer or float value at a given index of your target.' WHERE `name` = 'debug getvalue';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug hostile
|
||||
Returns the hostile reference list of a given player.' WHERE `name` = 'debug hostile';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug itemexpire #GUID
|
||||
Destroy an item with the given GUID.' WHERE `name` = 'debug itemexpire';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug lootrecipient
|
||||
Returns the loot recipient of the targeted creature.' WHERE `name` = 'debug lootrecipient';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug los
|
||||
Returns line of sight status between you and your target.' WHERE `name` = 'debug los';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug play $subcommand
|
||||
Type .debug play to see the list of possible subcommands or .help debug play $subcommand to see info on subcommands.' WHERE `name` = 'debug play';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send $subcommand
|
||||
Type .debug send to see the list of possible subcommands or .help debug send $subcommand to see info on subcommands.' WHERE `name` = 'debug send';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send buyerror #error
|
||||
Sends the given buy error result.' WHERE `name` = 'debug send buyerror';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send channelnotify #type
|
||||
Sends a channel notify message of the given type.' WHERE `name` = 'debug send channelnotify';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send chatmessage #type
|
||||
Sends a chat message of the given type.', `name` = 'debug send chatmessage' WHERE `name` = 'debug send chatmmessage';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send equiperror #error
|
||||
Sends the given equip error result.' WHERE `name` = 'debug send equiperror';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send largepacket
|
||||
Sends a system message of 128 kilobytes.' WHERE `name` = 'debug send largepacket';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send opcode
|
||||
Sends opcodes contained in "opcode.txt".' WHERE `name` = 'debug send opcode';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send qinvalidmsg #error
|
||||
Sends the given quest error result.' WHERE `name` = 'debug send qinvalidmsg';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send qpartymsg #message
|
||||
Sends the given party quest share message.' WHERE `name` = 'debug send qpartymsg';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send sellerror #error
|
||||
Sends the given sell error result.' WHERE `name` = 'debug send sellerror';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send setphaseshift #phaseShift
|
||||
Sends a phase shift message with the given phase shift value.' WHERE `name` = 'debug send setphaseshift';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug send spellfail #result #failArgument1 #failArgument2
|
||||
Sends a spell failure message with the given result and argument values.' WHERE `name` = 'debug send spellfail';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug setaurastate #state #apply
|
||||
Sets the selected units aura state using the given apply value.' WHERE `name` = 'debug setaurastate';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug setbit #index #bit
|
||||
Sets the unsigned 32-bit integer value of the target at the given index to the given bit.' WHERE `name` = 'debug setbit';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug setitemvalue #GUID #index #value
|
||||
Sets the value of the given index for the given item GUID to the given value.' WHERE `name` = 'debug setitemvalue';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug setvalue #index #value
|
||||
Sets the unsigned 32-bit integer or float value of the target at the given index to the given value.' WHERE `name` = 'debug setvalue';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug setvid #ID
|
||||
Currently disabled.
|
||||
Sets the given target''s vehicle ID to the given value.' WHERE `name` = 'debug setvid';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug spawnvehicle #entry #ID
|
||||
Creates a vehicle with the given ID.' WHERE `name` = 'debug spawnvehicle';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug threat
|
||||
Returns the threat list of a given creature.' WHERE `name` = 'debug threat';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug update #index #value
|
||||
Sets the unsigned 32-bit integer value of the target at the given index to the given bit.' WHERE `name` = 'debug update';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .debug uws #variable #value
|
||||
Sends a worldstate update for the given variable to the given value.' WHERE `name` = 'debug uws';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .gobject set state #GUIDLow, #objectType, #objectState
|
||||
Sets the byte value or sends a custom animation for a given gameobject GUID.' WHERE `name` = 'gobject set state';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .learn all $subcommand
|
||||
Type .learn all to see the list of possible subcommands or .help learn all $subcommand to see info on subcommands.' WHERE `name` = 'learn all';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .learn all my $subcommand
|
||||
Type .learn all my to see the list of possible subcommands or .help learn all my $subcommand to see info on subcommands.' WHERE `name` = 'learn all my';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .lfg $subcommand
|
||||
Type .lfg to see the list of possible subcommands or .help lfg $subcommand to see info on subcommands.' WHERE `name` = 'lfg';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .lookup player $subcommand
|
||||
Type .lookup player to see the list of possible subcommands or .help lookup player $subcommand to see info on subcommands.' WHERE `name` = 'lookup player';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .npc near #distance
|
||||
Returns all database creature spawns in a given distance.' WHERE `name` = 'npc near';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .npc set $subcommand
|
||||
Type .npc set to see the list of possible subcommands or .help npc set $subcommand to see info on subcommands.' WHERE `name` = 'npc set';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .npc tame
|
||||
Creates a player pet of the targeted creature.' WHERE `name` = 'npc tame';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .reload npc_spellclick_spells
|
||||
Reload npc_spellclick_spells table.' WHERE `name` = 'reload npc_spellclick_spells';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect $subcommand
|
||||
Type .spect to see the list of possible subcommands or .help spect $subcommand to see info on subcommands.' WHERE `name` = 'spect';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect leave
|
||||
Leave an arena you are spectating.' WHERE `name` = 'spect leave';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect reset
|
||||
Reset various values related to spectating.' WHERE `name` = 'spect reset';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect spectate #name
|
||||
Begin spectating the given player.' WHERE `name` = 'spect spectate';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect version #version
|
||||
Verify addon version for arena spectating.' WHERE `name` = 'spect version';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .spect watch #name
|
||||
Begin watching the given player.' WHERE `name` = 'spect watch';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .ticket complete #ticketID
|
||||
Mark a ticket of the given ID as complete.' WHERE `name` = 'ticket complete';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .ticket escalate #ticketID
|
||||
Add a ticket of the given ID to the escalation queue.' WHERE `name` = 'ticket escalate';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .ticket escalatedlist
|
||||
Return all open tickets in the escalation queue.' WHERE `name` = 'ticket escalatedlist';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .ticket response $subcommand
|
||||
Type .ticket response to see the list of possible subcommands or .help ticket response $subcommand to see info on subcommands.' WHERE `name` = 'ticket response';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .ticket togglesystem
|
||||
Toggle whether tickets are allowed or disallowed.' WHERE `name` = 'ticket togglesystem';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .titles $subcommand
|
||||
Type .titles to see the list of possible subcommands or .help titles $subcommand to see info on subcommands.' WHERE `name` = 'titles';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .titles set $subcommand
|
||||
Type .titles set to see the list of possible subcommands or .help titles set $subcommand to see info on subcommands.' WHERE `name` = 'titles set';
|
||||
|
||||
UPDATE `command` SET `help` = 'Syntax: .unban playeraccount #name
|
||||
Unban accounts for character name pattern.' WHERE `name` = 'unban playeraccount';
|
||||
@@ -1087,7 +1087,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||
for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
|
||||
{
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(*itr);
|
||||
if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID)
|
||||
if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID && !(quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT)))
|
||||
++counter;
|
||||
}
|
||||
SetCriteriaProgress(achievementCriteria, counter);
|
||||
@@ -2503,7 +2503,7 @@ void AchievementMgr::ProcessOfflineUpdate(AchievementOfflinePlayerUpdate const&
|
||||
{
|
||||
AchievementEntry const* achievement = sAchievementStore.LookupEntry(update.arg1);
|
||||
|
||||
ASSERT(achievement != NULL, "Not found achievement to complete for offline achievements update. Wrong arg1 ({}) value?", update.arg1);
|
||||
ASSERT(achievement, "Not found achievement to complete for offline achievements update. Wrong arg1 ({}) value?", update.arg1);
|
||||
|
||||
CompletedAchievement(achievement);
|
||||
break;
|
||||
@@ -3142,7 +3142,7 @@ void AchievementGlobalMgr::CompletedAchievementForOfflinePlayer(ObjectGuid::LowT
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_OFFLINE_UPDATES);
|
||||
stmt->SetData(0, playerLowGuid);
|
||||
stmt->SetData(1, uint32(ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_COMPLETE_ACHIEVEMENT));
|
||||
stmt->SetData(1, ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_COMPLETE_ACHIEVEMENT);
|
||||
stmt->SetData(2, entry->ID);
|
||||
stmt->SetData(3, 0);
|
||||
stmt->SetData(4, 0);
|
||||
@@ -3153,7 +3153,7 @@ void AchievementGlobalMgr::UpdateAchievementCriteriaForOfflinePlayer(ObjectGuid:
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_OFFLINE_UPDATES);
|
||||
stmt->SetData(0, playerLowGuid);
|
||||
stmt->SetData(1, uint32(ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_UPDATE_CRITERIA));
|
||||
stmt->SetData(1, ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_UPDATE_CRITERIA);
|
||||
stmt->SetData(2, type);
|
||||
stmt->SetData(3, miscValue1);
|
||||
stmt->SetData(4, miscValue2);
|
||||
|
||||
@@ -325,6 +325,9 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type)
|
||||
if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN])
|
||||
creature->SetRespawnDelay(RESPAWN_ONE_DAY); /// @todo: look if this can be done by database + also add this for the wingcommanders
|
||||
|
||||
if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_TOWERDEFENSE] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_TOWERDEFENSE])
|
||||
creature->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
|
||||
|
||||
if ((isStatic && cinfoid >= 10 && cinfoid <= 14) || (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) ||
|
||||
(cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3))))
|
||||
{
|
||||
|
||||
@@ -1118,21 +1118,21 @@ const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] =
|
||||
|
||||
enum BG_AV_CreatureIds
|
||||
{
|
||||
AV_NPC_A_TOWERDEFENSE = 0, // stormpike bowman
|
||||
AV_NPC_A_GRAVEDEFENSE0 = 1, // stormpike Defender
|
||||
AV_NPC_A_GRAVEDEFENSE1 = 2, // seasoned defender
|
||||
AV_NPC_A_GRAVEDEFENSE2 = 3, // veteran defender
|
||||
AV_NPC_A_GRAVEDEFENSE3 = 4, // champion defender
|
||||
AV_NPC_A_CAPTAIN = 5, // balinda
|
||||
AV_NPC_A_BOSS = 6, // vanndar
|
||||
AV_NPC_A_GRAVEDEFENSE0 = 0, // Stormpike defender
|
||||
AV_NPC_A_GRAVEDEFENSE1 = 1, // Seasoned defender
|
||||
AV_NPC_A_GRAVEDEFENSE2 = 2, // Veteran defender
|
||||
AV_NPC_A_GRAVEDEFENSE3 = 3, // Champion defender
|
||||
AV_NPC_A_TOWERDEFENSE = 4, // Stormpike bowman
|
||||
AV_NPC_A_CAPTAIN = 5, // Balinda
|
||||
AV_NPC_A_BOSS = 6, // Vanndar
|
||||
|
||||
AV_NPC_H_TOWERDEFENSE = 7, // frostwolf bowman
|
||||
AV_NPC_H_GRAVEDEFENSE0 = 8, // frostwolf guardian
|
||||
AV_NPC_H_GRAVEDEFENSE1 = 9, // seasoned guardian
|
||||
AV_NPC_H_GRAVEDEFENSE2 = 10, // veteran guardian
|
||||
AV_NPC_H_GRAVEDEFENSE3 = 11, // champion guardian
|
||||
AV_NPC_H_CAPTAIN = 12, // galvangar
|
||||
AV_NPC_H_BOSS = 13, // drek thar
|
||||
AV_NPC_H_GRAVEDEFENSE0 = 7, // Frostwolf guardian
|
||||
AV_NPC_H_GRAVEDEFENSE1 = 8, // Seasoned guardian
|
||||
AV_NPC_H_GRAVEDEFENSE2 = 9, // Veteran guardian
|
||||
AV_NPC_H_GRAVEDEFENSE3 = 10, // Champion guardian
|
||||
AV_NPC_H_TOWERDEFENSE = 11, // Frostwolf bowman
|
||||
AV_NPC_H_CAPTAIN = 12, // Galvangar
|
||||
AV_NPC_H_BOSS = 13, // Drek thar
|
||||
|
||||
AV_NPC_A_MARSHAL_SOUTH = 14,
|
||||
AV_NPC_MARSHAL_NORTH = 15,
|
||||
|
||||
@@ -12437,6 +12437,14 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/)
|
||||
if (!CanDualWield() && (offItem->GetTemplate()->InventoryType == INVTYPE_WEAPONOFFHAND || offItem->GetTemplate()->InventoryType == INVTYPE_WEAPON))
|
||||
force = true;
|
||||
|
||||
// unequip offhand weapon if player main hand weapon is a polearm or staff or fishing pole
|
||||
if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
|
||||
if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate())
|
||||
if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM ||
|
||||
mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF ||
|
||||
mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
|
||||
force = true;
|
||||
|
||||
// need unequip offhand for 2h-weapon without TitanGrip (in any from hands)
|
||||
if (!force && (CanTitanGrip() || (offItem->GetTemplate()->InventoryType != INVTYPE_2HWEAPON && !IsTwoHandUsed())))
|
||||
{
|
||||
|
||||
@@ -201,28 +201,11 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
|
||||
break;
|
||||
case INVTYPE_2HWEAPON:
|
||||
slots[0] = EQUIPMENT_SLOT_MAINHAND;
|
||||
if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
|
||||
{
|
||||
if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate())
|
||||
{
|
||||
if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
{
|
||||
const_cast<Player*>(this)->AutoUnequipOffhandIfNeed(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND))
|
||||
{
|
||||
if (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF)
|
||||
{
|
||||
const_cast<Player*>(this)->AutoUnequipOffhandIfNeed(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CanDualWield() && CanTitanGrip() && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && proto->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
|
||||
slots[1] = EQUIPMENT_SLOT_OFFHAND;
|
||||
if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
|
||||
if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate())
|
||||
if (mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE)
|
||||
slots[1] = EQUIPMENT_SLOT_OFFHAND;
|
||||
break;
|
||||
case INVTYPE_TABARD:
|
||||
slots[0] = EQUIPMENT_SLOT_TABARD;
|
||||
@@ -1962,6 +1945,14 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
|
||||
return EQUIP_ERR_CANT_DUAL_WIELD;
|
||||
}
|
||||
|
||||
// Do not allow offhand with main hand polearm, staff or fishing pole
|
||||
if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND))
|
||||
if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate())
|
||||
if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM ||
|
||||
mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF ||
|
||||
mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
|
||||
return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
|
||||
|
||||
if (IsTwoHandUsed())
|
||||
return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED;
|
||||
}
|
||||
@@ -1977,7 +1968,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool
|
||||
else if (eslot != EQUIPMENT_SLOT_MAINHAND)
|
||||
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
|
||||
|
||||
if (!CanTitanGrip())
|
||||
if (!CanTitanGrip() || (pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || pProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || pProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE))
|
||||
{
|
||||
// offhand item must can be stored in inventory for offhand item and it also must be unequipped
|
||||
Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
|
||||
|
||||
@@ -1847,7 +1847,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||
if (damageInfo->blocked_amount && damageInfo->TargetState != VICTIMSTATE_BLOCKS)
|
||||
victim->HandleEmoteCommand(EMOTE_ONESHOT_PARRY_SHIELD);
|
||||
|
||||
if (damageInfo->TargetState == VICTIMSTATE_PARRY)
|
||||
// Parry haste is enabled if it's not a creature or if the creature doesn't have the NO_PARRY_HASTEN flag.
|
||||
bool isParryHasteEnabled = !victim->IsCreature() ||
|
||||
!victim->ToCreature()->GetCreatureTemplate()->HasFlagsExtra(CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN);
|
||||
if (damageInfo->TargetState == VICTIMSTATE_PARRY && isParryHasteEnabled)
|
||||
{
|
||||
// Get attack timers
|
||||
float offtime = float(victim->getAttackTimer(OFF_ATTACK));
|
||||
@@ -20256,13 +20259,13 @@ void Unit::OutDebugInfo() const
|
||||
class AuraMunchingQueue : public BasicEvent
|
||||
{
|
||||
public:
|
||||
AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId, AuraEffect* aurEff) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId), _aurEff(aurEff) { }
|
||||
AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId) { }
|
||||
|
||||
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
|
||||
{
|
||||
if (_owner.IsInWorld() && _owner.FindMap())
|
||||
if (Unit* target = ObjectAccessor::GetUnit(_owner, _targetGUID))
|
||||
_owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, _aurEff, _owner.GetGUID());
|
||||
_owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, _owner.GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -20272,15 +20275,13 @@ private:
|
||||
ObjectGuid _targetGUID;
|
||||
int32 _basePoints;
|
||||
uint32 _spellId;
|
||||
AuraEffect* _aurEff;
|
||||
};
|
||||
|
||||
void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex)
|
||||
{
|
||||
AuraEffect* aurEff = nullptr;
|
||||
for (AuraEffectList::iterator i = m_modAuras[auraType].begin(); i != m_modAuras[auraType].end(); ++i)
|
||||
{
|
||||
aurEff = *i;
|
||||
AuraEffect* aurEff = *i;
|
||||
if (aurEff->GetCasterGUID() != caster->GetGUID() || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks())
|
||||
continue;
|
||||
|
||||
@@ -20290,9 +20291,9 @@ void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, Aura
|
||||
|
||||
// xinef: delay only for casting on different unit
|
||||
if (this == caster || !sWorld->getBoolConfig(CONFIG_MUNCHING_BLIZZLIKE))
|
||||
caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, aurEff, caster->GetGUID());
|
||||
caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, caster->GetGUID());
|
||||
else
|
||||
caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId, aurEff), caster->m_Events.CalculateQueueTime(400));
|
||||
caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId), caster->m_Events.CalculateQueueTime(400));
|
||||
}
|
||||
|
||||
void Unit::SendClearTarget()
|
||||
|
||||
@@ -982,8 +982,12 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
|
||||
|
||||
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS))
|
||||
{
|
||||
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true);
|
||||
pCurrChar->CheckAllAchievementCriteria();
|
||||
// If we process the check while players are loading they won't be notified of the changes.
|
||||
pCurrChar->m_Events.AddEventAtOffset([pCurrChar]
|
||||
{
|
||||
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true);
|
||||
pCurrChar->CheckAllAchievementCriteria();
|
||||
}, 1s);
|
||||
}
|
||||
|
||||
bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST);
|
||||
|
||||
@@ -761,6 +761,24 @@ void InstanceScript::LoadInstanceSavedGameobjectStateData()
|
||||
}
|
||||
}
|
||||
|
||||
bool InstanceScript::AllBossesDone() const
|
||||
{
|
||||
for (auto const& boss : bosses)
|
||||
if (boss.state != DONE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstanceScript::AllBossesDone(std::initializer_list<uint32> bossIds) const
|
||||
{
|
||||
for (auto const& bossId : bossIds)
|
||||
if (!IsBossDone(bossId))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string InstanceScript::GetBossStateName(uint8 state)
|
||||
{
|
||||
// See enum EncounterState in InstanceScript.h
|
||||
|
||||
@@ -275,6 +275,10 @@ public:
|
||||
|
||||
void LoadInstanceSavedGameobjectStateData();
|
||||
|
||||
[[nodiscard]] bool IsBossDone(uint32 bossId) const { return GetBossState(bossId) == DONE; };
|
||||
[[nodiscard]] bool AllBossesDone() const;
|
||||
[[nodiscard]] bool AllBossesDone(std::initializer_list<uint32> bossIds) const;
|
||||
|
||||
TaskScheduler scheduler;
|
||||
protected:
|
||||
void SetHeaders(std::string const& dataHeaders);
|
||||
|
||||
@@ -187,7 +187,7 @@ void Quest::LoadQuestTemplateAddon(Field* fields)
|
||||
RequiredMaxRepValue = fields[14].Get<int32>();
|
||||
StartItemCount = fields[15].Get<uint8>();
|
||||
RewardMailSenderEntry = fields[16].Get<uint32>();
|
||||
SpecialFlags = fields[17].Get<uint8>();
|
||||
SpecialFlags = fields[17].Get<uint32>();
|
||||
|
||||
if ((SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) && !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT))
|
||||
{
|
||||
|
||||
@@ -165,17 +165,18 @@ enum QuestSpecialFlags
|
||||
QUEST_SPECIAL_FLAGS_CAST = 0x0020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast)
|
||||
QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER = 0x0040, // Set by 64 in SpecialFlags in DB if the quest does not share rewarded reputation with other allied factions
|
||||
QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE = 0x0080, // Set by 128 in SpecialFlags in DB if the quest is allowed to fail in Player::FailQuest() independant of its current state
|
||||
QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT = 0x0100, // Set by 256 in SpecialFlags in DB if the quest should not count towards Loremaster Achievement
|
||||
// room for more custom flags
|
||||
|
||||
QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT |
|
||||
QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER |
|
||||
QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE,
|
||||
QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE | QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT,
|
||||
|
||||
QUEST_SPECIAL_FLAGS_DELIVER = 0x0100, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x0200, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_KILL = 0x0400, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_TIMED = 0x0800, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x1000 // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_DELIVER = 0x0200, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x0400, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_KILL = 0x0800, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_TIMED = 0x1000, // Internal flag computed only
|
||||
QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x2000 // Internal flag computed only
|
||||
};
|
||||
|
||||
struct QuestLocale
|
||||
|
||||
@@ -2931,8 +2931,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
|
||||
{
|
||||
if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
|
||||
{
|
||||
if (!m_triggeredByAuraSpell.spellInfo || (!(m_triggeredByAuraSpell.spellInfo->Effects[m_triggeredByAuraSpell.effectIndex].TriggerSpell == m_spellInfo->Id) && !(m_triggeredByAuraSpell.spellInfo->IsAuraEffectEqual(m_spellInfo))))
|
||||
m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS));
|
||||
m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS));
|
||||
|
||||
// Patch 3.0.8: All player spells which cause a creature to become aggressive to you will now also immediately cause the creature to be tapped.
|
||||
if (effectUnit->IsInCombatWith(m_caster))
|
||||
|
||||
@@ -4831,6 +4831,12 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS);
|
||||
});
|
||||
|
||||
// Paralyze
|
||||
ApplySpellFix({ 41083 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
@@ -23,6 +23,7 @@ Category: commandscripts
|
||||
EndScriptData */
|
||||
|
||||
#include "AccountMgr.h"
|
||||
#include "AchievementMgr.h"
|
||||
#include "Chat.h"
|
||||
#include "CommandScript.h"
|
||||
#include "DBCStores.h"
|
||||
@@ -272,6 +273,8 @@ public:
|
||||
stmt->SetData(1, playerGuid.GetCounter());
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
sAchievementMgr->UpdateAchievementCriteriaForOfflinePlayer(playerGuid.GetCounter(), ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
|
||||
|
||||
sCharacterCache->UpdateCharacterLevel(playerGuid, newLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
{
|
||||
{ "buyerror", HandleDebugSendBuyErrorCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "channelnotify", HandleDebugSendChannelNotifyCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "chatmmessage", HandleDebugSendChatMsgCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "chatmessage", HandleDebugSendChatMsgCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "equiperror", HandleDebugSendEquipErrorCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "largepacket", HandleDebugSendLargePacketCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
{ "opcode", HandleDebugSendOpcodeCommand, SEC_ADMINISTRATOR, Console::No },
|
||||
|
||||
@@ -157,9 +157,6 @@ public:
|
||||
|
||||
if (args.empty() || !tokens.size())
|
||||
{
|
||||
handler->PSendSysMessage("Usage: .skirmish [arena] [XvX] [Nick1] [Nick2] ... [NickN]");
|
||||
handler->PSendSysMessage("[arena] can be \"all\" or comma-separated list of possible arenas (NA, BE, RL, DS, RV).");
|
||||
handler->PSendSysMessage("[XvX] can be 1v1, 2v2, 3v3, 5v5. After [XvX] specify enough nicknames for that mode.");
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ enum DataTypes
|
||||
DATA_GATHIOS_THE_SHATTERER = 12,
|
||||
DATA_HIGH_NETHERMANCER_ZEREVOR = 13,
|
||||
DATA_LADY_MALANDE = 14,
|
||||
DATA_VERAS_DARKSHADOW = 15
|
||||
DATA_VERAS_DARKSHADOW = 15,
|
||||
DATA_BLACK_TEMPLE_TRIGGER = 16
|
||||
};
|
||||
|
||||
enum CreatureIds
|
||||
@@ -82,7 +83,8 @@ enum CreatureIds
|
||||
NPC_ASHTONGUE_STALKER = 23374,
|
||||
NPC_STORM_FURY = 22848,
|
||||
|
||||
NPC_DRAGON_TURTLE = 22885
|
||||
NPC_DRAGON_TURTLE = 22885,
|
||||
NPC_BLACK_TEMPLE_TRIGGER = 22984
|
||||
};
|
||||
|
||||
enum GameObjectIds
|
||||
@@ -113,6 +115,12 @@ enum MiscIds
|
||||
SPELL_SUMMON_SHADOWFIENDS = 41159
|
||||
};
|
||||
|
||||
enum Texts
|
||||
{
|
||||
EMOTE_NAJENTUS_DEFEATED = 0,
|
||||
EMOTE_LOWER_TEMPLE_DEFEATED = 1
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetBlackTempleAI(T* obj)
|
||||
{
|
||||
|
||||
@@ -1186,14 +1186,37 @@ struct npc_parasitic_shadowfiend : public ScriptedAI
|
||||
{
|
||||
npc_parasitic_shadowfiend(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
bool CanAIAttack(Unit const* who) const override
|
||||
{
|
||||
return !who->HasAura(SPELL_PARASITIC_SHADOWFIEND) && !who->HasAura(SPELL_PARASITIC_SHADOWFIEND_TRIGGER);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void IsSummonedBy(WorldObject* /*summoner*/) override
|
||||
{
|
||||
// Simulate blizz-like AI delay to avoid extreme overpopulation of adds
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
|
||||
scheduler.Schedule(2400ms, [this](TaskContext context)
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetInCombatWithZone();
|
||||
}, 2400ms);
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1298,12 +1321,21 @@ struct npc_flame_of_azzinoth : public ScriptedAI
|
||||
DoCastVictim(SPELL_FLAME_BLAST);
|
||||
|
||||
me->m_Events.AddEventAtOffset([&] {
|
||||
if (Unit* target = me->GetVictim())
|
||||
target->CastSpell(target, SPELL_BLAZE, true);
|
||||
DoCastVictim(SPELL_BLAZE);
|
||||
}, 1s);
|
||||
}, 15s, 20s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _bladeGUID;
|
||||
};
|
||||
|
||||
@@ -147,11 +147,11 @@ struct boss_illidari_council : public BossAI
|
||||
|
||||
bool spoken = false;
|
||||
|
||||
me->CastSpell(me, SPELL_EMPYREAL_BALANCE, true);
|
||||
DoCastSelf(SPELL_EMPYREAL_BALANCE, true);
|
||||
|
||||
ScheduleTimedEvent(3200ms, [&]
|
||||
{
|
||||
me->CastSpell(me, SPELL_EMPYREAL_EQUIVALENCY, true);
|
||||
DoCastSelf(SPELL_EMPYREAL_EQUIVALENCY, true);
|
||||
}, 3200ms);
|
||||
|
||||
for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i)
|
||||
@@ -239,7 +239,7 @@ struct boss_illidari_council_memberAI : public ScriptedAI
|
||||
{
|
||||
if (param == ACTION_ENRAGE)
|
||||
{
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
Talk(SAY_COUNCIL_ENRAGE);
|
||||
}
|
||||
}
|
||||
@@ -331,14 +331,14 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI
|
||||
events.ScheduleEvent(EVENT_SPELL_BLESSING, 15s);
|
||||
break;
|
||||
case EVENT_SPELL_AURA:
|
||||
me->CastSpell(me, _toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA);
|
||||
DoCastSelf(_toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA);
|
||||
_toggleAura = !_toggleAura;
|
||||
events.ScheduleEvent(EVENT_SPELL_AURA, 60s);
|
||||
break;
|
||||
case EVENT_SPELL_CONSECRATION:
|
||||
if (roll_chance_i(50))
|
||||
Talk(SAY_COUNCIL_SPECIAL);
|
||||
me->CastSpell(me, SPELL_CONSECRATION, false);
|
||||
DoCastSelf(SPELL_CONSECRATION);
|
||||
events.ScheduleEvent(EVENT_SPELL_AURA, 30s);
|
||||
break;
|
||||
case EVENT_SPELL_HAMMER_OF_JUSTICE:
|
||||
@@ -352,12 +352,12 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI
|
||||
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 0s);
|
||||
break;
|
||||
case EVENT_SPELL_SEAL:
|
||||
me->CastSpell(me, _toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD);
|
||||
DoCastSelf(_toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD);
|
||||
_toggleSeal = !_toggleSeal;
|
||||
events.ScheduleEvent(EVENT_SPELL_SEAL, 20s);
|
||||
break;
|
||||
case EVENT_SPELL_JUDGEMENT:
|
||||
me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT, false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT);
|
||||
events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 16s, 20s);
|
||||
break;
|
||||
}
|
||||
@@ -511,22 +511,22 @@ struct boss_lady_malande : public boss_illidari_council_memberAI
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_CIRCLE_OF_HEALING:
|
||||
me->CastSpell(me, SPELL_CIRCLE_OF_HEALING, false);
|
||||
DoCastSelf(SPELL_CIRCLE_OF_HEALING);
|
||||
events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20s);
|
||||
break;
|
||||
case EVENT_SPELL_REFLECTIVE_SHIELD:
|
||||
if (roll_chance_i(50))
|
||||
Talk(SAY_COUNCIL_SPECIAL);
|
||||
me->CastSpell(me, SPELL_REFLECTIVE_SHIELD, false);
|
||||
DoCastSelf(SPELL_REFLECTIVE_SHIELD);
|
||||
events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 40s);
|
||||
break;
|
||||
case EVENT_SPELL_DIVINE_WRATH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
|
||||
me->CastSpell(target, SPELL_DIVINE_WRATH, false);
|
||||
me->CastSpell(target, SPELL_DIVINE_WRATH);
|
||||
events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 20s);
|
||||
break;
|
||||
case EVENT_SPELL_EMPOWERED_SMITE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE, false);
|
||||
me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE);
|
||||
events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3s);
|
||||
break;
|
||||
}
|
||||
@@ -542,7 +542,7 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI
|
||||
me->SetCanDualWield(true);
|
||||
boss_illidari_council_memberAI::JustEngagedWith(who);
|
||||
events.ScheduleEvent(EVENT_SPELL_VANISH, 10s);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 90s);
|
||||
events.ScheduleEvent(EVENT_SPELL_ENRAGE, 15min);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
@@ -564,13 +564,13 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI
|
||||
case EVENT_SPELL_VANISH:
|
||||
if (roll_chance_i(50))
|
||||
Talk(SAY_COUNCIL_SPECIAL);
|
||||
me->CastSpell(me, SPELL_DEADLY_STRIKE, false);
|
||||
me->CastSpell(me, SPELL_VANISH, false);
|
||||
DoCastSelf(SPELL_DEADLY_STRIKE);
|
||||
DoCastSelf(SPELL_VANISH);
|
||||
events.ScheduleEvent(EVENT_SPELL_VANISH, 60s);
|
||||
events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29s);
|
||||
break;
|
||||
case EVENT_SPELL_VANISH_OUT:
|
||||
me->CastSpell(me, SPELL_VANISH_OUT, false);
|
||||
DoCastSelf(SPELL_VANISH_OUT);
|
||||
break;
|
||||
case EVENT_SPELL_ENRAGE:
|
||||
DoResetThreatList();
|
||||
|
||||
@@ -278,6 +278,7 @@ struct npc_akama_shade : public ScriptedAI
|
||||
}
|
||||
else if (damage >= me->GetHealth() && !_died)
|
||||
{
|
||||
_died = true;
|
||||
damage = me->GetHealth() - 1;
|
||||
Talk(SAY_DEATH);
|
||||
if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA))
|
||||
|
||||
@@ -62,6 +62,7 @@ ObjectData const creatureData[] =
|
||||
{ NPC_VERAS_DARKSHADOW, DATA_VERAS_DARKSHADOW },
|
||||
{ NPC_AKAMA_ILLIDAN, DATA_AKAMA_ILLIDAN },
|
||||
{ NPC_ILLIDAN_STORMRAGE, DATA_ILLIDAN_STORMRAGE },
|
||||
{ NPC_BLACK_TEMPLE_TRIGGER, DATA_BLACK_TEMPLE_TRIGGER },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -165,18 +166,31 @@ public:
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
if (type == DATA_SHADE_OF_AKAMA && state == DONE)
|
||||
if (state == DONE)
|
||||
{
|
||||
for (ObjectGuid const& guid : ashtongueGUIDs)
|
||||
if (Creature* ashtongue = instance->GetCreature(guid))
|
||||
ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
|
||||
}
|
||||
else if (type == DATA_ILLIDARI_COUNCIL && state == DONE)
|
||||
{
|
||||
if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN))
|
||||
akama->AI()->DoAction(0);
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case DATA_HIGH_WARLORD_NAJENTUS:
|
||||
if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER))
|
||||
trigger->AI()->Talk(EMOTE_NAJENTUS_DEFEATED);
|
||||
break;
|
||||
case DATA_SHADE_OF_AKAMA:
|
||||
for (ObjectGuid const& guid : ashtongueGUIDs)
|
||||
if (Creature* ashtongue = instance->GetCreature(guid))
|
||||
ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
|
||||
break;
|
||||
case DATA_ILLIDARI_COUNCIL:
|
||||
if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN))
|
||||
akama->AI()->DoAction(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (AllBossesDone({ DATA_SHADE_OF_AKAMA, DATA_TERON_GOREFIEND, DATA_GURTOGG_BLOODBOIL, DATA_RELIQUARY_OF_SOULS }))
|
||||
if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER))
|
||||
trigger->AI()->Talk(EMOTE_LOWER_TEMPLE_DEFEATED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user