Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/game/Entities/Vehicle/Vehicle.cpp src/server/game/Globals/ObjectMgr.cpp src/server/game/Spells/SpellMgr.cpp src/server/game/Weather/Weather.h src/server/shared/Database/Implementation/WorldDatabase.cpp src/tools/CMakeLists.txt
This commit is contained in:
commit
71eaceae5d
74 files changed
+1107
-570
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
||||
SET @NPC_DRAKE := 29709;
|
||||
SET @NPC_DRAKE := 29709;
|
||||
|
||||
DELETE FROM `waypoint_data` WHERE `id`=@NPC_DRAKE;
|
||||
INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `Armor_mod`=0 WHERE `entry`=29747;
|
||||
@@ -0,0 +1,11 @@
|
||||
DELETE FROM `spell_target_position` WHERE `id` IN (64014,64024,64025,64028,64029,64030,64031,64032,65042);
|
||||
INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES
|
||||
(64014, 603, -705.9705, -92.55729, 430.8192, 0),
|
||||
(64024, 603, 2086.224, -24.05382, 422.2889, 0),
|
||||
(64025, 603, 2518.131, 2569.342, 412.6822, 0),
|
||||
(64028, 603, 553.243, -12.30903, 410.5428, 0),
|
||||
(64029, 603, 1859.563, -24.83773, 449.1945, 6.230825),
|
||||
(64030, 603, 1497.989, -24.16162, 421.6254, 0.03490658),
|
||||
(64031, 603, 926.2917, -11.44444, 418.9779, 0.01745329),
|
||||
(64032, 603, 131.1389, -35.36806, 410.187, 0),
|
||||
(65042, 603, 1855.073, -11.48785, 334.559, 5.532694);
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Lurgglbr
|
||||
DELETE FROM `creature_text` WHERE `entry`=25208;
|
||||
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES
|
||||
(25208,0,0, 'You can''t hold me against my will! You''ve all been brainwashed!', 12,0,100,0,0,0, 'Lurgglbr'),
|
||||
(25208,1,0, 'Together we will fight our way out of here. Are you ready?', 12,0,100,0,0,0, 'Lurgglbr'),
|
||||
(25208,2,0, 'This is far enough. I can make it on my own from here.', 12,0,100,0,0,0, 'Lurgglbr'),
|
||||
(25208,3,0, 'Thank you for rescuing me, $r. Please tell the king that I am back.', 12,0,100,0,0,0, 'Lurgglbr');
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
-- quest fix cuergo's gold (q2882)
|
||||
SET @ENTRY :=7898;
|
||||
UPDATE `creature_template` SET `AIName`= 'SmartAI', `ScriptName`='' WHERE `entry`=@ENTRY;
|
||||
DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY;
|
||||
DELETE FROM `smart_scripts` WHERE `source_type`=0 AND`entryorguid`=@ENTRY;
|
||||
DELETE FROM `smart_scripts` WHERE `source_type`=9 AND`entryorguid`=@ENTRY*100;
|
||||
INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
|
||||
(@ENTRY,0,0,0,63,0,100,0,0,0,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Trigger - on respawn - run script'),
|
||||
(@ENTRY*100,9,0,0,0,0,100,0,0,0,300000,300000,11,11463,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - spawn pirate1'),
|
||||
(@ENTRY*100,9,1,0,0,0,100,0,0,0,300000,300000,11,11463,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - spawn pirate2'),
|
||||
(@ENTRY*100,9,2,0,0,0,100,0,0,0,300000,300000,11,11485,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - spawn buccaneer1'),
|
||||
(@ENTRY*100,9,3,0,0,0,100,0,0,0,300000,300000,11,11485,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - spawn buccaneer2'),
|
||||
(@ENTRY*100,9,4,0,0,0,100,0,0,0,300000,300000,11,11487,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - spawn swashbuckler'),
|
||||
(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Timed Actionscript - despawn trigger');
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Remove Zulian Mudskunk from Zulian Crocolisk's loot template
|
||||
DELETE FROM `creature_loot_template` WHERE `entry`=15043 and `item`=19975;
|
||||
-- Add Vicious Oil (Item) into loot template of Vicious Oil (NPC)
|
||||
DELETE FROM `creature_loot_template` WHERE `entry`=30325 and `item`=42640;
|
||||
INSERT INTO `creature_loot_template` (`entry`, `item`, `ChanceOrQuestChance`, `lootmode`, `groupid`, `mincountOrRef`, `maxcount`) values
|
||||
(30325,42640,-100,1,0,1,1);
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Previous quest should be The Defense of Warsong Hold not To Conquest Hold, But Be Careful!
|
||||
UPDATE `quest_template` SET `PrevQuestId`=11596 WHERE `Id`=12486;
|
||||
-- Change grouping so Alliance and Horde quests are no longer in 1 group
|
||||
UPDATE `quest_template` SET `ExclusiveGroup`=-12222 WHERE `Id` IN(12222,12223);
|
||||
-- Hellscreams Champion requires some conditions to start the quest
|
||||
UPDATE `quest_template` SET `ExclusiveGroup`=0,`NextQuestId`=0 WHERE `Id` IN(11652,11705,11722);
|
||||
UPDATE `quest_template` SET `NextQuestId`=11709 WHERE `Id`=11705;
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (19,20) AND `SourceEntry`=11916;
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
|
||||
(20,0,11916,0,0,8,0,11652,0,0,0,0, '', 'Player must have completed The Plains of Nasam before been able to accept Hellscream''s Champion'),
|
||||
(19,0,11916,0,0,8,0,11652,0,0,0,0, '', 'Player must have completed The Plains of Nasam before been able to accept Hellscream''s Champion'),
|
||||
(20,0,11916,0,0,8,0,11705,0,0,0,0, '', 'Player must have completed The Foolish Endeavors before been able to accept Hellscream''s Champion'),
|
||||
(19,0,11916,0,0,8,0,11705,0,0,0,0, '', 'Player must have completed The Foolish Endeavors before been able to accept Hellscream''s Champion'),
|
||||
(20,0,11916,0,0,8,0,11722,0,0,0,0, '', 'Player must have completed The Trophies of Gammoth before been able to accept Hellscream''s Champion'),
|
||||
(19,0,11916,0,0,8,0,11722,0,0,0,0, '', 'Player must have completed The Trophies of Gammoth before been able to accept Hellscream''s Champion');
|
||||
-- Fix SAI issue for Hugh Glass (wrong npcflag was set)
|
||||
UPDATE `smart_scripts` SET `action_param1`=643 WHERE `entryorguid`=2648400 AND `source_type`=9 AND `id`=6;
|
||||
@@ -0,0 +1,14 @@
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_sindragosa_frost_breath';
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_unsated_craving';
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(69649,'spell_sindragosa_frost_breath'),
|
||||
(71056,'spell_sindragosa_frost_breath'),
|
||||
(71057,'spell_sindragosa_frost_breath'),
|
||||
(71058,'spell_sindragosa_frost_breath'),
|
||||
(73061,'spell_sindragosa_frost_breath'),
|
||||
(73062,'spell_sindragosa_frost_breath'),
|
||||
(73063,'spell_sindragosa_frost_breath'),
|
||||
(73064,'spell_sindragosa_frost_breath'),
|
||||
(71168,'spell_item_unsated_craving');
|
||||
|
||||
DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=71952;
|
||||
@@ -0,0 +1,73 @@
|
||||
-- creature_template.equipment_id deleted
|
||||
-- creature_equip_template.entry == creature_template.entry
|
||||
-- id field added to creature_equip_template -> PK(entry, id)
|
||||
-- id field in creature_equip_template starts at 1
|
||||
-- creature.equipment_id references id of creature_equip_template
|
||||
-- creature.equipment_id = 0 means no equipment at all (default 1)
|
||||
-- creature.equipment_id = -1 means pick a random equipment from creature_equip_template
|
||||
|
||||
-- Diff_entries should use the same template of the normal entry
|
||||
UPDATE `creature_template` SET `equipment_id` = 0 WHERE `name` LIKE '%(1)' OR `name` LIKE '%(2)' OR `name` LIKE '%(3)' OR `name` LIKE '%(4)';
|
||||
|
||||
-- Delete unused templates
|
||||
DROP TABLE IF EXISTS `temp_c_e`;
|
||||
CREATE TABLE IF NOT EXISTS `temp_c_e` (`entry` mediumint(8));
|
||||
ALTER TABLE `temp_c_e` ADD INDEX `ind` (`entry`);
|
||||
INSERT INTO `temp_c_e` SELECT `equipment_id` FROM `creature_template` WHERE `equipment_id` != 0 UNION
|
||||
SELECT `equipment_id` FROM `creature` WHERE `equipment_id` != 0 UNION
|
||||
SELECT `equipment_id` FROM `game_event_model_equip` WHERE `equipment_id` != 0;
|
||||
DELETE FROM `creature_equip_template` WHERE `entry` NOT IN (SELECT `entry` FROM `temp_c_e`);
|
||||
DROP TABLE `temp_c_e`;
|
||||
|
||||
-- Create temporary table to hold the values of creature_equip_template with converted entry
|
||||
DROP TABLE IF EXISTS `creature_equip_template2`;
|
||||
CREATE TABLE IF NOT EXISTS `creature_equip_template2` (
|
||||
`entry` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`id` tinyint(3) unsigned NOT NULL DEFAULT '1',
|
||||
`itemEntry1` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`itemEntry2` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`itemEntry3` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`entry`, `id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `creature_equip_template2` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`)
|
||||
SELECT `creature_template`.`entry`, 1, `itemEntry1`, `itemEntry2`, `itemEntry3`
|
||||
FROM `creature_template`
|
||||
JOIN `creature_equip_template` ON `creature_equip_template`.`entry` = `equipment_id`
|
||||
WHERE `equipment_id` != 0;
|
||||
|
||||
INSERT IGNORE INTO `creature_equip_template2` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`)
|
||||
SELECT `id`, 2, `itemEntry1`, `itemEntry2`, `itemEntry3`
|
||||
FROM `creature`
|
||||
JOIN `creature_equip_template` ON `creature_equip_template`.`entry` = `equipment_id`
|
||||
WHERE `equipment_id` != 0;
|
||||
|
||||
DROP TABLE `creature_equip_template`;
|
||||
RENAME TABLE `creature_equip_template2` TO `creature_equip_template`;
|
||||
|
||||
UPDATE `creature` SET `equipment_id` = 2 WHERE `equipment_id` != 0;
|
||||
UPDATE `creature` SET `equipment_id` = 1 WHERE `equipment_id` = 0;
|
||||
|
||||
-- From game_event_model_equip
|
||||
UPDATE `creature` SET `equipment_id` = 1 WHERE `guid` IN (12088, 12093, 12095, 79670, 79675, 79676, 79690, 79792, 79807, 79814);
|
||||
UPDATE `game_event_model_equip` SET `equipment_id` = 2 WHERE `guid` IN (12088, 12093, 12095, 79670, 79675, 79676, 79690, 79792, 79807, 79814);
|
||||
DELETE FROM `creature_equip_template` WHERE `entry` IN (1976, 23585, 424) AND `id`=2;
|
||||
INSERT INTO `creature_equip_template` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) VALUES
|
||||
(1976, 2, 2715, 143, 0),
|
||||
(23585, 2, 2715, 143, 0),
|
||||
(424, 2, 2715, 143, 0);
|
||||
|
||||
-- ALTER TABLE `creature_equip_template` CHANGE `entry` `entry` mediumint(8) unsigned NOT NULL;
|
||||
-- ALTER TABLE `creature_equip_template` ADD `id` tinyint(3) unsigned NOT NULL DEFAULT '1' AFTER `entry`;
|
||||
-- ALTER TABLE `creature_equip_template` DROP INDEX `PRIMARY`, ADD PRIMARY KEY (`entry`, `id`);
|
||||
ALTER TABLE `creature_template` DROP `equipment_id`;
|
||||
ALTER TABLE `creature` CHANGE `equipment_id` `equipment_id` tinyint(3) unsigned NOT NULL DEFAULT '1';
|
||||
ALTER TABLE `game_event_model_equip` CHANGE `equipment_id` `equipment_id` tinyint(3) unsigned NOT NULL DEFAULT '1';
|
||||
|
||||
-- Conversion from SAI
|
||||
UPDATE `smart_scripts` SET `action_param1` = 1 WHERE `entryorguid` = 2523901 AND `source_type` = 9 AND `id` = 3;
|
||||
UPDATE `smart_scripts` SET `action_param1` = 0 WHERE `entryorguid` = 2523900 AND `source_type` = 9 AND `id` = 2;
|
||||
UPDATE `smart_scripts` SET `action_param1` = 2 WHERE `entryorguid` = 32720 AND `source_type` = 0 AND `id` = 0;
|
||||
DELETE FROM `creature_equip_template` WHERE `entry` = 25239 AND `id`=1;
|
||||
INSERT INTO `creature_equip_template` (`entry`, `id`, `itemEntry1`, `itemEntry2`, `itemEntry3`) VALUES
|
||||
(25239, 1, 6829, 0, 0);
|
||||
@@ -0,0 +1,3 @@
|
||||
DELETE FROM `trinity_string` WHERE `entry` = 5036;
|
||||
INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES
|
||||
(5036, 'EquipmentId: %u (Original: %u).');
|
||||
@@ -370,9 +370,7 @@ void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO
|
||||
{
|
||||
if (loadDefault)
|
||||
{
|
||||
if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(me->GetEntry()))
|
||||
me->LoadEquipment(creatureInfo->equipmentId, true);
|
||||
|
||||
me->LoadEquipment(me->GetOriginalEquipmentId(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1459,15 +1459,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (Creature* npc = (*itr)->ToCreature())
|
||||
{
|
||||
uint32 slot[3];
|
||||
if (e.action.equip.entry)
|
||||
int8 equipId = (int8)e.action.equip.entry;
|
||||
if (equipId)
|
||||
{
|
||||
EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(e.action.equip.entry);
|
||||
EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId);
|
||||
if (!einfo)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info entry %u", e.action.equip.entry);
|
||||
sLog->outError(LOG_FILTER_SQL, "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature %u", equipId, npc->GetEntry());
|
||||
return;
|
||||
}
|
||||
npc->SetCurrentEquipmentId(e.action.equip.entry);
|
||||
npc->SetCurrentEquipmentId(equipId);
|
||||
slot[0] = einfo->ItemEntry[0];
|
||||
slot[1] = einfo->ItemEntry[1];
|
||||
slot[2] = einfo->ItemEntry[2];
|
||||
@@ -1478,11 +1479,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
slot[1] = e.action.equip.slot2;
|
||||
slot[2] = e.action.equip.slot3;
|
||||
}
|
||||
if (!e.action.equip.mask || e.action.equip.mask & 1)
|
||||
if (!e.action.equip.mask || (e.action.equip.mask & 1))
|
||||
npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, slot[0]);
|
||||
if (!e.action.equip.mask || e.action.equip.mask & 2)
|
||||
if (!e.action.equip.mask || (e.action.equip.mask & 2))
|
||||
npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, slot[1]);
|
||||
if (!e.action.equip.mask || e.action.equip.mask & 4)
|
||||
if (!e.action.equip.mask || (e.action.equip.mask & 4))
|
||||
npc->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, slot[2]);
|
||||
}
|
||||
}
|
||||
@@ -2028,6 +2029,45 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
delete targets;
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_SET_GO_FLAG:
|
||||
{
|
||||
ObjectList* targets = GetTargets(e, unit);
|
||||
if (!targets)
|
||||
break;
|
||||
|
||||
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
|
||||
if (IsGameObject(*itr))
|
||||
(*itr)->ToGameObject()->SetUInt32Value(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
|
||||
|
||||
delete targets;
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_ADD_GO_FLAG:
|
||||
{
|
||||
ObjectList* targets = GetTargets(e, unit);
|
||||
if (!targets)
|
||||
break;
|
||||
|
||||
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
|
||||
if (IsGameObject(*itr))
|
||||
(*itr)->ToGameObject()->SetFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
|
||||
|
||||
delete targets;
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_REMOVE_GO_FLAG:
|
||||
{
|
||||
ObjectList* targets = GetTargets(e, unit);
|
||||
if (!targets)
|
||||
break;
|
||||
|
||||
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
|
||||
if (IsGameObject(*itr))
|
||||
(*itr)->ToGameObject()->RemoveFlag(GAMEOBJECT_FLAGS, e.action.goFlag.flag);
|
||||
|
||||
delete targets;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog->outError(LOG_FILTER_SQL, "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
break;
|
||||
|
||||
@@ -907,6 +907,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_SET_HOME_POS:
|
||||
case SMART_ACTION_SET_HEALTH_REGEN:
|
||||
case SMART_ACTION_SET_ROOT:
|
||||
case SMART_ACTION_SET_GO_FLAG:
|
||||
case SMART_ACTION_ADD_GO_FLAG:
|
||||
case SMART_ACTION_REMOVE_GO_FLAG:
|
||||
break;
|
||||
default:
|
||||
sLog->outError(LOG_FILTER_SQL, "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
|
||||
|
||||
@@ -427,7 +427,6 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue(+pct, -flat)
|
||||
SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
|
||||
SMART_ACTION_SET_INGAME_PHASE_MASK = 44, // mask
|
||||
|
||||
SMART_ACTION_SET_DATA = 45, // Field, Data (only creature TODO)
|
||||
SMART_ACTION_MOVE_FORWARD = 46, // distance
|
||||
SMART_ACTION_SET_VISIBILITY = 47, // on/off
|
||||
@@ -450,7 +449,6 @@ enum SMART_ACTION
|
||||
SMART_ACTION_STORE_TARGET_LIST = 64, // varID,
|
||||
SMART_ACTION_WP_RESUME = 65, // none
|
||||
SMART_ACTION_SET_ORIENTATION = 66, //
|
||||
|
||||
SMART_ACTION_CREATE_TIMED_EVENT = 67, // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance
|
||||
SMART_ACTION_PLAYMOVIE = 68, // entry
|
||||
SMART_ACTION_MOVE_TO_POS = 69, // PointId, xyz
|
||||
@@ -488,8 +486,11 @@ enum SMART_ACTION
|
||||
SMART_ACTION_SET_HOME_POS = 101, // none
|
||||
SMART_ACTION_SET_HEALTH_REGEN = 102, // 0/1
|
||||
SMART_ACTION_SET_ROOT = 103, // off/on
|
||||
SMART_ACTION_SET_GO_FLAG = 104, // Flags
|
||||
SMART_ACTION_ADD_GO_FLAG = 105, // Flags
|
||||
SMART_ACTION_REMOVE_GO_FLAG = 106, // Flags
|
||||
|
||||
SMART_ACTION_END = 104
|
||||
SMART_ACTION_END = 107
|
||||
};
|
||||
|
||||
struct SmartAction
|
||||
@@ -926,6 +927,11 @@ struct SmartAction
|
||||
uint32 root;
|
||||
} setRoot;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 flag;
|
||||
} goFlag;
|
||||
|
||||
//! Note for any new future actions
|
||||
//! All parameters must have type uint32
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
@@ -56,7 +56,7 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
|
||||
RBACData* rbac = new RBACData(GetId(username), username, -1);
|
||||
// No need to Load From DB, as it's new data
|
||||
|
||||
RBACGroupContainer const& groupsToAdd = _defaultGroups[0]; // 0: Default sec level
|
||||
RBACGroupContainer const& groupsToAdd = _defaultSecGroups[0]; // 0: Default sec level
|
||||
for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it)
|
||||
rbac->AddGroup(*it, -1);
|
||||
|
||||
@@ -426,13 +426,23 @@ void AccountMgr::LoadRBAC()
|
||||
uint8 secId = field[0].GetUInt8();
|
||||
|
||||
if (lastSecId != secId)
|
||||
groups = &_defaultGroups[secId];
|
||||
groups = &_defaultSecGroups[secId];
|
||||
|
||||
groups->insert(field[1].GetUInt32());
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u permission definitions, %u role definitions and %u group definitions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime));
|
||||
|
||||
// Load default groups to be added to any RBAC Object.
|
||||
std::string defaultGroups = ConfigMgr::GetStringDefault("RBAC.DefaultGroups", "");
|
||||
Tokenizer tokens(defaultGroups, ',');
|
||||
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
|
||||
if (uint32 groupId = atoi(*itr))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_LFG, "Adding default group %u", groupId);
|
||||
_defaultGroups.insert(groupId);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId)
|
||||
@@ -459,7 +469,7 @@ void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 sec
|
||||
uint8 secLevel = field[0].GetUInt8();
|
||||
int32 realmId = field[1].GetUInt32();
|
||||
|
||||
RBACGroupContainer const& groupsToRemove = _defaultGroups[secLevel];
|
||||
RBACGroupContainer const& groupsToRemove = _defaultSecGroups[secLevel];
|
||||
for (RBACGroupContainer::const_iterator it = groupsToRemove.begin(); it != groupsToRemove.end(); ++it)
|
||||
rbac->RemoveGroup(*it, realmId);
|
||||
}
|
||||
@@ -467,7 +477,7 @@ void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 sec
|
||||
}
|
||||
|
||||
// Add new groups depending on the new security Level
|
||||
RBACGroupContainer const& groupsToAdd = _defaultGroups[securityLevel];
|
||||
RBACGroupContainer const& groupsToAdd = _defaultSecGroups[securityLevel];
|
||||
for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it)
|
||||
rbac->AddGroup(*it, realmId);
|
||||
|
||||
|
||||
@@ -77,12 +77,14 @@ class AccountMgr
|
||||
RBACGroupsContainer const& GetRBACGroupList() const { return _groups; }
|
||||
RBACRolesContainer const& GetRBACRoleList() const { return _roles; }
|
||||
RBACPermissionsContainer const& GetRBACPermissionList() const { return _permissions; }
|
||||
RBACGroupContainer const& GetRBACDefaultGroups() const { return _defaultGroups; }
|
||||
|
||||
private:
|
||||
RBACPermissionsContainer _permissions;
|
||||
RBACRolesContainer _roles;
|
||||
RBACGroupsContainer _groups;
|
||||
RBACDefaultSecurityGroupContainer _defaultGroups;
|
||||
RBACDefaultSecurityGroupContainer _defaultSecGroups;
|
||||
RBACGroupContainer _defaultGroups;
|
||||
};
|
||||
|
||||
#define sAccountMgr ACE_Singleton<AccountMgr, ACE_Null_Mutex>::instance()
|
||||
|
||||
@@ -296,6 +296,11 @@ void RBACData::LoadFromDB()
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
// Add default groups
|
||||
RBACGroupContainer const& groups = sAccountMgr->GetRBACDefaultGroups();
|
||||
for (RBACGroupContainer::const_iterator itr = groups.begin(); itr != groups.end(); ++itr)
|
||||
AddGroup(*itr);
|
||||
|
||||
// Force calculation of permissions, it wasn't performed at load time
|
||||
// while adding groups, roles and permissions
|
||||
CalculateNewPermissions();
|
||||
|
||||
@@ -135,7 +135,7 @@ class RBACGroup: public RBACObject
|
||||
RBACRoleContainer _roles; ///> Set of Roles
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* @name RBACData
|
||||
* @brief Contains all needed information about the acccount
|
||||
*
|
||||
|
||||
@@ -145,7 +145,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapCreature(),
|
||||
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLowGUID(0),
|
||||
m_PlayerDamageReq(0), m_lootRecipient(0), m_lootRecipientGroup(0), m_corpseRemoveTime(0), m_respawnTime(0),
|
||||
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
|
||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(1), m_originalEquipmentId(1), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
||||
m_creatureInfo(NULL), m_creatureData(NULL), m_path_id(0), m_formation(NULL)
|
||||
{
|
||||
@@ -323,8 +323,8 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data
|
||||
|
||||
// Load creature equipment
|
||||
if (!data || data->equipmentId == 0) // use default from the template
|
||||
LoadEquipment(cinfo->equipmentId);
|
||||
else if (data && data->equipmentId != -1) // override, -1 means no equipment
|
||||
LoadEquipment(GetOriginalEquipmentId());
|
||||
else if (data && data->equipmentId != 0) // override, 0 means no equipment
|
||||
LoadEquipment(data->equipmentId);
|
||||
|
||||
SetName(normalInfo->Name); // at normal entry always
|
||||
@@ -1080,7 +1080,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
data.mapid = mapid;
|
||||
data.phaseMask = phaseMask;
|
||||
data.displayid = displayId;
|
||||
data.equipmentId = GetEquipmentId();
|
||||
data.equipmentId = GetCurrentEquipmentId();
|
||||
data.posX = GetPositionX();
|
||||
data.posY = GetPositionY();
|
||||
data.posZ = GetPositionZMinusOffset();
|
||||
@@ -1115,7 +1115,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
stmt->setUInt8(index++, spawnMask);
|
||||
stmt->setUInt16(index++, uint16(GetPhaseMask()));
|
||||
stmt->setUInt32(index++, displayId);
|
||||
stmt->setInt32(index++, int32(GetEquipmentId()));
|
||||
stmt->setInt32(index++, int32(GetCurrentEquipmentId()));
|
||||
stmt->setFloat(index++, GetPositionX());
|
||||
stmt->setFloat(index++, GetPositionY());
|
||||
stmt->setFloat(index++, GetPositionZ());
|
||||
@@ -1270,14 +1270,14 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint3
|
||||
if (!vehId)
|
||||
vehId = cinfo->VehicleId;
|
||||
|
||||
if (vehId && !CreateVehicleKit(vehId, Entry))
|
||||
vehId = 0;
|
||||
|
||||
Object::_Create(guidlow, Entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT);
|
||||
|
||||
if (!UpdateEntry(Entry, team, data))
|
||||
return false;
|
||||
|
||||
if (vehId && !CreateVehicleKit(vehId, Entry))
|
||||
vehId = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1355,24 +1355,24 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature::LoadEquipment(uint32 equip_entry, bool force)
|
||||
void Creature::LoadEquipment(int8 id, bool force /*= true*/)
|
||||
{
|
||||
if (equip_entry == 0)
|
||||
if (id == 0)
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0);
|
||||
m_equipmentId = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(equip_entry);
|
||||
EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(GetEntry(), id);
|
||||
if (!einfo)
|
||||
return;
|
||||
|
||||
m_equipmentId = equip_entry;
|
||||
m_equipmentId = id;
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->ItemEntry[i]);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,6 @@ struct CreatureTemplate
|
||||
uint32 questItems[MAX_CREATURE_QUEST_ITEMS];
|
||||
uint32 movementId;
|
||||
bool RegenHealth;
|
||||
uint32 equipmentId;
|
||||
uint32 MechanicImmuneMask;
|
||||
uint32 flags_extra;
|
||||
uint32 ScriptID;
|
||||
@@ -234,7 +233,8 @@ struct EquipmentInfo
|
||||
};
|
||||
|
||||
// Benchmarked: Faster than std::map (insert/find)
|
||||
typedef UNORDERED_MAP<uint16, EquipmentInfo> EquipmentInfoContainer;
|
||||
typedef UNORDERED_MAP<uint8, EquipmentInfo> EquipmentInfoContainerInternal;
|
||||
typedef UNORDERED_MAP<uint32, EquipmentInfoContainerInternal> EquipmentInfoContainer;
|
||||
|
||||
// from `creature` table
|
||||
struct CreatureData
|
||||
@@ -244,7 +244,7 @@ struct CreatureData
|
||||
uint16 mapid;
|
||||
uint16 phaseMask;
|
||||
uint32 displayid;
|
||||
int32 equipmentId;
|
||||
int8 equipmentId;
|
||||
float posX;
|
||||
float posY;
|
||||
float posZ;
|
||||
@@ -453,13 +453,12 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||
bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData* data = NULL);
|
||||
bool LoadCreaturesAddon(bool reload = false);
|
||||
void SelectLevel(const CreatureTemplate* cinfo);
|
||||
void LoadEquipment(uint32 equip_entry, bool force=false);
|
||||
void LoadEquipment(int8 id = 1, bool force = false);
|
||||
|
||||
uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
|
||||
|
||||
void Update(uint32 time); // overwrited Unit::Update
|
||||
void GetRespawnPosition(float &x, float &y, float &z, float* ori = NULL, float* dist =NULL) const;
|
||||
uint32 GetEquipmentId() const { return GetCreatureTemplate()->equipmentId; }
|
||||
|
||||
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
|
||||
uint32 GetCorpseDelay() const { return m_corpseDelay; }
|
||||
@@ -552,8 +551,11 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||
void UpdateMaxPower(Powers power);
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false);
|
||||
void UpdateDamagePhysical(WeaponAttackType attType);
|
||||
|
||||
uint8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
|
||||
uint32 GetCurrentEquipmentId() { return m_equipmentId; }
|
||||
void SetCurrentEquipmentId(uint32 entry) { m_equipmentId = entry; }
|
||||
void SetCurrentEquipmentId(uint8 id) { m_equipmentId = id; }
|
||||
|
||||
float GetSpellDamageMod(int32 Rank);
|
||||
|
||||
VendorItemData const* GetVendorItems() const;
|
||||
@@ -748,7 +750,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||
void Regenerate(Powers power);
|
||||
MovementGeneratorType m_defaultMovementType;
|
||||
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
|
||||
uint32 m_equipmentId;
|
||||
uint8 m_equipmentId;
|
||||
uint8 m_originalEquipmentId;
|
||||
|
||||
bool m_AlreadyCallAssistance;
|
||||
bool m_AlreadySearchedAssistance;
|
||||
|
||||
@@ -26027,7 +26027,7 @@ bool Player::AddItem(uint32 itemId, uint32 count)
|
||||
ItemPosCountVec dest;
|
||||
InventoryResult msg = CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemId, count, &noSpaceForCount);
|
||||
if (msg != EQUIP_ERR_OK)
|
||||
count = noSpaceForCount;
|
||||
count -= noSpaceForCount;
|
||||
|
||||
if (count == 0 || dest.empty())
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "QuestDef.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "Unit.h"
|
||||
#include "Opcodes.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -1813,6 +1815,11 @@ class Player : public Unit, public GridObject<Player>
|
||||
return mMitems.erase(id) ? true : false;
|
||||
}
|
||||
|
||||
void SendOnCancelExpectedVehicleRideAura()
|
||||
{
|
||||
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
void PetSpellInitialize();
|
||||
void CharmSpellInitialize();
|
||||
void PossessSpellInitialize();
|
||||
|
||||
@@ -2936,7 +2936,9 @@ void Unit::DeMorph()
|
||||
Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, uint64 casterGUID /*= 0*/)
|
||||
{
|
||||
ASSERT(casterGUID || caster);
|
||||
if (!casterGUID)
|
||||
|
||||
// Check if these can stack anyway
|
||||
if (!casterGUID && !newAura->IsStackableOnOneSlotWithDifferentCasters())
|
||||
casterGUID = caster->GetGUID();
|
||||
|
||||
// passive and Incanter's Absorption and auras with different type can stack with themselves any number of times
|
||||
@@ -7585,48 +7587,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
// Shadow's Fate (Shadowmourne questline)
|
||||
case 71169:
|
||||
{
|
||||
// Victim needs more checks so bugs, rats or summons can not be affected by the proc.
|
||||
if (GetTypeId() != TYPEID_PLAYER || !victim || victim->GetTypeId() != TYPEID_UNIT || victim->GetCreatureType() == CREATURE_TYPE_CRITTER)
|
||||
return false;
|
||||
|
||||
Player* player = ToPlayer();
|
||||
if (player->GetQuestStatus(24547) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (player->GetDifficulty(true) == RAID_DIFFICULTY_25MAN_NORMAL || player->GetDifficulty(true) == RAID_DIFFICULTY_25MAN_HEROIC)
|
||||
{
|
||||
uint32 spellId = 0;
|
||||
uint32 questId = 0;
|
||||
switch (victim->GetEntry())
|
||||
{
|
||||
case 36678: // NPC: Professor Putricide
|
||||
questId = 24749; // Quest: Unholy Infusion
|
||||
spellId = 71516; // Spell: Shadow Infusion
|
||||
break;
|
||||
case 37955: // NPC: Blood-Queen Lana'thel
|
||||
questId = 24756; // Quest: Blood Infusion
|
||||
spellId = 72154; // Spell: Thirst Quenched
|
||||
break;
|
||||
case 36853: // NPC: Sindragosa
|
||||
questId = 24757; // Quest: Frost Infusion
|
||||
spellId = 72290; // Spell: Frost-Imbued Blade
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE || !player->HasAura(spellId))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
|
||||
@@ -10248,8 +10208,6 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
|
||||
{
|
||||
if (CreateVehicleKit(VehicleId, creatureEntry))
|
||||
{
|
||||
GetVehicleKit()->Reset();
|
||||
|
||||
// Send others that we now have a vehicle
|
||||
WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, GetPackGUID().size()+4);
|
||||
data.appendPackGUID(GetGUID());
|
||||
@@ -14823,7 +14781,10 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
|
||||
// dismount players when charmed
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
Dismount();
|
||||
RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
|
||||
if (charmer->GetTypeId() == TYPEID_PLAYER)
|
||||
charmer->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
|
||||
ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
|
||||
ASSERT((type == CHARM_TYPE_VEHICLE) == IsVehicle());
|
||||
@@ -16082,31 +16043,10 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a
|
||||
{
|
||||
if (vehicle->GetBase()->GetTypeId() == TYPEID_PLAYER && player->isInCombat())
|
||||
return;
|
||||
|
||||
InterruptNonMeleeSpells(false);
|
||||
player->StopCastingCharm();
|
||||
player->StopCastingBindSight();
|
||||
Dismount();
|
||||
RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
|
||||
// drop flag at invisible in bg
|
||||
if (Battleground* bg = player->GetBattleground())
|
||||
bg->EventPlayerDroppedFlag(player);
|
||||
|
||||
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
player->UnsummonPetTemporaryIfAny();
|
||||
}
|
||||
|
||||
ASSERT(!m_vehicle);
|
||||
m_vehicle = vehicle;
|
||||
|
||||
if (!m_vehicle->AddPassenger(this, seatId))
|
||||
{
|
||||
m_vehicle = NULL;
|
||||
return;
|
||||
}
|
||||
(void)vehicle->AddPassenger(this, seatId);
|
||||
}
|
||||
|
||||
void Unit::ChangeSeat(int8 seatId, bool next)
|
||||
@@ -16114,15 +16054,17 @@ void Unit::ChangeSeat(int8 seatId, bool next)
|
||||
if (!m_vehicle)
|
||||
return;
|
||||
|
||||
if (seatId < 0)
|
||||
{
|
||||
seatId = m_vehicle->GetNextEmptySeat(GetTransSeat(), next);
|
||||
if (seatId < 0)
|
||||
return;
|
||||
}
|
||||
else if (seatId == GetTransSeat() || !m_vehicle->HasEmptySeat(seatId))
|
||||
// Don't change if current and new seat are identical
|
||||
if (seatId == GetTransSeat())
|
||||
return;
|
||||
|
||||
SeatMap::const_iterator seat = (seatId < 0 ? m_vehicle->GetNextEmptySeat(GetTransSeat(), next) : m_vehicle->Seats.find(seatId));
|
||||
// The second part of the check will only return true if seatId >= 0. @Vehicle::GetNextEmptySeat makes sure of that.
|
||||
if (seat == m_vehicle->Seats.end() || seat->second.Passenger)
|
||||
return;
|
||||
|
||||
// Todo: the functions below could be consolidated and refactored to take
|
||||
// SeatMap::const_iterator as parameter, to save redundant map lookups.
|
||||
m_vehicle->RemovePassenger(this);
|
||||
if (!m_vehicle->AddPassenger(this, seatId))
|
||||
ASSERT(false);
|
||||
@@ -16149,6 +16091,9 @@ void Unit::ExitVehicle(Position const* /*exitPosition*/)
|
||||
|
||||
void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
{
|
||||
/// It's possible m_vehicle is NULL, when this function is called indirectly from @VehicleJoinEvent::Abort.
|
||||
/// In that case it was not possible to add the passenger to the vehicle. The vehicle aura has already been removed
|
||||
/// from the target in the aforementioned function and we don't need to do anything else at this point.
|
||||
if (!m_vehicle)
|
||||
return;
|
||||
|
||||
|
||||
@@ -332,6 +332,7 @@ class UnitAI;
|
||||
class Totem;
|
||||
class Transport;
|
||||
class Vehicle;
|
||||
class VehicleJoinEvent;
|
||||
class TransportBase;
|
||||
class SpellCastTargets;
|
||||
|
||||
@@ -2170,6 +2171,7 @@ class Unit : public WorldObject
|
||||
uint32 GetRedirectThreatPercent() { return _redirectThreadInfo.GetThreatPct(); }
|
||||
Unit* GetRedirectThreatTarget() { return _redirectThreadInfo.GetTargetGUID() ? GetUnit(*this, _redirectThreadInfo.GetTargetGUID()) : NULL; }
|
||||
|
||||
friend class VehicleJoinEvent;
|
||||
bool IsAIEnabled, NeedChangeAI;
|
||||
bool CreateVehicleKit(uint32 id, uint32 creatureEntry);
|
||||
void RemoveVehicleKit();
|
||||
|
||||
Executable → Regular
+411
-136
@@ -30,9 +30,12 @@
|
||||
#include "SpellInfo.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "EventProcessor.h"
|
||||
#include "Player.h"
|
||||
#include "Battleground.h"
|
||||
|
||||
Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) :
|
||||
_me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE)
|
||||
UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry), _status(STATUS_NONE)
|
||||
{
|
||||
for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i)
|
||||
{
|
||||
@@ -41,10 +44,16 @@ _me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntr
|
||||
{
|
||||
Seats.insert(std::make_pair(i, VehicleSeat(veSeat)));
|
||||
if (veSeat->CanEnterOrExit())
|
||||
++_usableSeatNum;
|
||||
++UsableSeatNum;
|
||||
}
|
||||
}
|
||||
|
||||
// Set or remove correct flags based on available seats. Will overwrite db data (if wrong).
|
||||
if (UsableSeatNum)
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
|
||||
else
|
||||
_me->RemoveFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
|
||||
|
||||
InitMovementInfoForBase();
|
||||
}
|
||||
|
||||
@@ -56,6 +65,15 @@ Vehicle::~Vehicle()
|
||||
ASSERT(!itr->second.Passenger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::Install()
|
||||
*
|
||||
* @brief Initializes power type for vehicle. Nothing more.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::Install()
|
||||
{
|
||||
if (Creature* creature = _me->ToCreature())
|
||||
@@ -114,15 +132,26 @@ void Vehicle::InstallAllAccessories(bool evading)
|
||||
InstallAccessory(itr->AccessoryEntry, itr->SeatId, itr->IsMinion, itr->SummonedType, itr->SummonTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::Uninstall()
|
||||
*
|
||||
* @brief Removes all passengers and sets status to STATUS_UNINSTALLING.
|
||||
* No new passengers can be added to the vehicle after this call.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::Uninstall()
|
||||
{
|
||||
/// @Prevent recursive uninstall call. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.)
|
||||
if (_status == STATUS_UNINSTALLING)
|
||||
if (_status == STATUS_UNINSTALLING && !GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to uninstall, but already has STATUS_UNINSTALLING! "
|
||||
"Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry());
|
||||
return;
|
||||
}
|
||||
|
||||
_status = STATUS_UNINSTALLING;
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
|
||||
RemoveAllPassengers();
|
||||
@@ -131,26 +160,39 @@ void Vehicle::Uninstall()
|
||||
sScriptMgr->OnUninstall(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::Reset(bool evading )
|
||||
*
|
||||
* @brief Reapplies immunities and reinstalls accessories. Only has effect for creatures.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param evading true if called from CreatureAI::EnterEvadeMode
|
||||
*/
|
||||
|
||||
void Vehicle::Reset(bool evading /*= false*/)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
|
||||
if (_me->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (_usableSeatNum)
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyAllImmunities();
|
||||
InstallAllAccessories(evading);
|
||||
if (_usableSeatNum)
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
}
|
||||
if (GetBase()->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
if (GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
sScriptMgr->OnReset(this);
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow());
|
||||
|
||||
ApplyAllImmunities();
|
||||
InstallAllAccessories(evading);
|
||||
|
||||
sScriptMgr->OnReset(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::ApplyAllImmunities()
|
||||
*
|
||||
* @brief Applies specific immunities that cannot be set in DB.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::ApplyAllImmunities()
|
||||
{
|
||||
// This couldn't be done in DB, because some spells have MECHANIC_NONE
|
||||
@@ -199,10 +241,28 @@ void Vehicle::ApplyAllImmunities()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::RemoveAllPassengers()
|
||||
*
|
||||
* @brief Removes all current and pending passengers from the vehicle.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::RemoveAllPassengers()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
|
||||
|
||||
/// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call
|
||||
/// This will properly "reset" the pending join process for the passenger.
|
||||
while (_pendingJoinEvents.size())
|
||||
{
|
||||
VehicleJoinEvent* e = _pendingJoinEvents.front();
|
||||
e->to_Abort = true;
|
||||
_pendingJoinEvents.pop_front();
|
||||
}
|
||||
|
||||
// Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle
|
||||
// We just remove the aura and the unapply handler will make the target leave the vehicle.
|
||||
// We don't need to iterate over Seats
|
||||
@@ -215,6 +275,19 @@ void Vehicle::RemoveAllPassengers()
|
||||
// ASSERT(!itr->second.passenger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn bool Vehicle::HasEmptySeat(int8 seatId) const
|
||||
*
|
||||
* @brief Checks if vehicle's seat specified by 'seatId' is empty.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param seatId Identifier for the seat.
|
||||
*
|
||||
* @return true if empty seat, false if not.
|
||||
*/
|
||||
|
||||
bool Vehicle::HasEmptySeat(int8 seatId) const
|
||||
{
|
||||
SeatMap::const_iterator seat = Seats.find(seatId);
|
||||
@@ -223,6 +296,19 @@ bool Vehicle::HasEmptySeat(int8 seatId) const
|
||||
return !seat->second.Passenger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn Unit* Vehicle::GetPassenger(int8 seatId) const
|
||||
*
|
||||
* @brief Gets a passenger on specified seat.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param seatId Seat to look on.
|
||||
*
|
||||
* @return null if it not found, else pointer to passenger if in world
|
||||
*/
|
||||
|
||||
Unit* Vehicle::GetPassenger(int8 seatId) const
|
||||
{
|
||||
SeatMap::const_iterator seat = Seats.find(seatId);
|
||||
@@ -232,78 +318,105 @@ Unit* Vehicle::GetPassenger(int8 seatId) const
|
||||
return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger);
|
||||
}
|
||||
|
||||
int8 Vehicle::GetNextEmptySeat(int8 seatId, bool next) const
|
||||
/**
|
||||
* @fn SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const
|
||||
*
|
||||
* @brief Gets the next empty seat based on current seat.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param seatId Identifier for the current seat.
|
||||
* @param next true if iterating forward, false means iterating backwards.
|
||||
*
|
||||
* @return The next empty seat.
|
||||
*/
|
||||
|
||||
SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const
|
||||
{
|
||||
SeatMap::const_iterator seat = Seats.find(seatId);
|
||||
if (seat == Seats.end())
|
||||
return -1;
|
||||
return seat;
|
||||
|
||||
while (seat->second.Passenger || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride()))
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
++seat;
|
||||
if (seat == Seats.end())
|
||||
if (++seat == Seats.end())
|
||||
seat = Seats.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seat == Seats.begin())
|
||||
if (seat-- == Seats.begin())
|
||||
seat = Seats.end();
|
||||
--seat;
|
||||
}
|
||||
|
||||
// Make sure we don't loop indefinetly
|
||||
if (seat->first == seatId)
|
||||
return -1; // no available seat
|
||||
return Seats.end();
|
||||
}
|
||||
|
||||
return seat->first;
|
||||
return seat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type,
|
||||
* uint32 summonTime)
|
||||
*
|
||||
* @brief Installs an accessory.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param entry The NPC entry of accessory.
|
||||
* @param seatId Identifier for the seat to add the accessory to.
|
||||
* @param minion true if accessory considered a 'minion'. Implies that the accessory will despawn when the vehicle despawns.
|
||||
* Essentially that it has no life without the vehicle. Their fates are bound.
|
||||
* @param type See enum @SummonType.
|
||||
* @param summonTime Time after which the minion is despawned in case of a timed despawn @type specified.
|
||||
*/
|
||||
|
||||
void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime)
|
||||
{
|
||||
/// @Prevent adding accessories when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.)
|
||||
if (_status == STATUS_UNINSTALLING)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to install accessory Entry: %u on seat %d with STATUS_UNINSTALLING! "
|
||||
"Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry(), entry, (int32)seatId);
|
||||
sLog->outError(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %i with STATUS_UNINSTALLING! "
|
||||
"Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(),
|
||||
(_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId);
|
||||
return;
|
||||
}
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle: Installing accessory entry %u on vehicle entry %u (seat:%i)", entry, GetCreatureEntry(), seatId);
|
||||
if (Unit* passenger = GetPassenger(seatId))
|
||||
{
|
||||
// already installed
|
||||
if (passenger->GetEntry() == entry)
|
||||
{
|
||||
ASSERT(passenger->GetTypeId() == TYPEID_UNIT);
|
||||
if (_me->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (_me->ToCreature()->IsInEvadeMode() && passenger->ToCreature()->IsAIEnabled)
|
||||
passenger->ToCreature()->AI()->EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
passenger->ExitVehicle(); // this should not happen
|
||||
}
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %i",
|
||||
_me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(),
|
||||
entry, (int32)seatId);
|
||||
|
||||
if (TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime))
|
||||
{
|
||||
if (minion)
|
||||
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
|
||||
TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), summonTime);
|
||||
ASSERT(accessory);
|
||||
|
||||
if (!_me->HandleSpellClick(accessory, seatId))
|
||||
{
|
||||
accessory->UnSummon();
|
||||
return;
|
||||
}
|
||||
if (minion)
|
||||
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
|
||||
|
||||
if (GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
sScriptMgr->OnInstallAccessory(this, accessory);
|
||||
}
|
||||
(void)_me->HandleSpellClick(accessory, seatId);
|
||||
|
||||
/// If for some reason adding accessory to vehicle fails it will unsummon in
|
||||
/// @VehicleJoinEvent::Abort
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
*
|
||||
* @brief Attempts to add a passenger to the vehicle on 'seatId'.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param [in,out] The prospective passenger.
|
||||
* @param seatId Identifier for the seat. Value of -1 indicates the next available seat.
|
||||
*
|
||||
* @return true if it succeeds, false if it fails.
|
||||
*/
|
||||
|
||||
bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
{
|
||||
/// @Prevent adding passengers when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.)
|
||||
@@ -314,10 +427,19 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unit->GetVehicle() != this)
|
||||
return false;
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %s) on seat %d",
|
||||
unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(),
|
||||
(_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), (int32)seatId);
|
||||
|
||||
// The seat selection code may kick other passengers off the vehicle.
|
||||
// While the validity of the following may be arguable, it is possible that when such a passenger
|
||||
// exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled
|
||||
// asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile.
|
||||
SeatMap::iterator seat;
|
||||
VehicleJoinEvent* e = new VehicleJoinEvent(this, unit);
|
||||
unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0));
|
||||
_pendingJoinEvents.push_back(e);
|
||||
|
||||
if (seatId < 0) // no specific seat requirement
|
||||
{
|
||||
for (seat = Seats.begin(); seat != Seats.end(); ++seat)
|
||||
@@ -325,86 +447,47 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
break;
|
||||
|
||||
if (seat == Seats.end()) // no available seat
|
||||
{
|
||||
CancelJoinEvent(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
e->Seat = seat;
|
||||
}
|
||||
else
|
||||
{
|
||||
seat = Seats.find(seatId);
|
||||
if (seat == Seats.end())
|
||||
{
|
||||
CancelJoinEvent(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
e->Seat = seat;
|
||||
if (seat->second.Passenger)
|
||||
{
|
||||
if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger))
|
||||
passenger->ExitVehicle();
|
||||
else
|
||||
seat->second.Passenger = 0;
|
||||
Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger);
|
||||
ASSERT(passenger);
|
||||
passenger->ExitVehicle();
|
||||
}
|
||||
|
||||
ASSERT(!seat->second.Passenger);
|
||||
}
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s enter vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first);
|
||||
|
||||
seat->second.Passenger = unit->GetGUID();
|
||||
if (seat->second.SeatInfo->CanEnterOrExit())
|
||||
{
|
||||
ASSERT(_usableSeatNum);
|
||||
--_usableSeatNum;
|
||||
if (!_usableSeatNum)
|
||||
{
|
||||
if (_me->GetTypeId() == TYPEID_PLAYER)
|
||||
_me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
|
||||
else
|
||||
_me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
}
|
||||
}
|
||||
|
||||
if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING))
|
||||
unit->AddUnitState(UNIT_STATE_ONVEHICLE);
|
||||
|
||||
VehicleSeatEntry const* veSeat = seat->second.SeatInfo;
|
||||
unit->m_movementInfo.t_pos.m_positionX = veSeat->m_attachmentOffsetX;
|
||||
unit->m_movementInfo.t_pos.m_positionY = veSeat->m_attachmentOffsetY;
|
||||
unit->m_movementInfo.t_pos.m_positionZ = veSeat->m_attachmentOffsetZ;
|
||||
unit->m_movementInfo.t_pos.SetOrientation(0);
|
||||
unit->m_movementInfo.t_time = 0; // 1 for player
|
||||
unit->m_movementInfo.t_seat = seat->first;
|
||||
unit->m_movementInfo.t_guid = _me->GetGUID();
|
||||
|
||||
if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER &&
|
||||
seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL)
|
||||
ASSERT(_me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE))
|
||||
|
||||
if (_me->IsInWorld())
|
||||
{
|
||||
unit->SendClearTarget(); // SMSG_BREAK_TARGET
|
||||
unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
// also adds MOVEMENTFLAG_ROOT
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.DisableTransportPathTransformations();
|
||||
init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ);
|
||||
init.SetFacing(0.0f);
|
||||
init.SetTransportEnter();
|
||||
init.Launch();
|
||||
|
||||
if (_me->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (_me->ToCreature()->IsAIEnabled)
|
||||
_me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, true);
|
||||
|
||||
// update all passenger's positions
|
||||
//Passenger's spline OR vehicle movement will update positions
|
||||
//RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation());
|
||||
}
|
||||
}
|
||||
|
||||
if (GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
sScriptMgr->OnAddPassenger(this, unit, seatId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::RemovePassenger(Unit* unit)
|
||||
*
|
||||
* @brief Removes the passenger from the vehicle.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param [in,out] unit The passenger to remove..
|
||||
*/
|
||||
|
||||
void Vehicle::RemovePassenger(Unit* unit)
|
||||
{
|
||||
if (unit->GetVehicle() != this)
|
||||
@@ -413,20 +496,12 @@ void Vehicle::RemovePassenger(Unit* unit)
|
||||
SeatMap::iterator seat = GetSeatIteratorForPassenger(unit);
|
||||
ASSERT(seat != Seats.end());
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first);
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Unit %s exit vehicle entry %u id %u dbguid %u seat %d",
|
||||
unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first);
|
||||
|
||||
seat->second.Passenger = 0;
|
||||
if (seat->second.SeatInfo->CanEnterOrExit())
|
||||
{
|
||||
if (!_usableSeatNum)
|
||||
{
|
||||
if (_me->GetTypeId() == TYPEID_PLAYER)
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
|
||||
else
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
}
|
||||
++_usableSeatNum;
|
||||
}
|
||||
if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum)
|
||||
_me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
|
||||
|
||||
unit->ClearUnitState(UNIT_STATE_ONVEHICLE);
|
||||
|
||||
@@ -435,7 +510,7 @@ void Vehicle::RemovePassenger(Unit* unit)
|
||||
|
||||
if (_me->IsInWorld())
|
||||
{
|
||||
unit->m_movementInfo.t_pos.Relocate(0, 0, 0, 0);
|
||||
unit->m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
unit->m_movementInfo.t_time = 0;
|
||||
unit->m_movementInfo.t_seat = 0;
|
||||
}
|
||||
@@ -451,7 +526,15 @@ void Vehicle::RemovePassenger(Unit* unit)
|
||||
sScriptMgr->OnRemovePassenger(this, unit);
|
||||
}
|
||||
|
||||
//! Must be called after m_base::Relocate
|
||||
/**
|
||||
* @fn void Vehicle::RelocatePassengers()
|
||||
*
|
||||
* @brief Relocate passengers. Must be called after m_base::Relocate
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::RelocatePassengers()
|
||||
{
|
||||
ASSERT(_me->GetMap());
|
||||
@@ -466,21 +549,40 @@ void Vehicle::RelocatePassengers()
|
||||
float px, py, pz, po;
|
||||
passenger->m_movementInfo.t_pos.GetPosition(px, py, pz, po);
|
||||
CalculatePassengerPosition(px, py, pz, po);
|
||||
|
||||
passenger->UpdatePosition(px, py, pz, po);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::Dismiss()
|
||||
*
|
||||
* @brief Dismiss the vehicle. Removes passengers and despawns self. Only valid for creatures.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::Dismiss()
|
||||
{
|
||||
if (GetBase()->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u", _creatureEntry, _me->GetGUIDLow());
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u, DBGuid: %u", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow());
|
||||
Uninstall();
|
||||
GetBase()->ToCreature()->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::InitMovementInfoForBase()
|
||||
*
|
||||
* @brief Sets correct MovementFlags2 based on VehicleFlags from DBC.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*/
|
||||
|
||||
void Vehicle::InitMovementInfoForBase()
|
||||
{
|
||||
uint32 vehicleFlags = GetVehicleInfo()->m_flags;
|
||||
@@ -497,6 +599,19 @@ void Vehicle::InitMovementInfoForBase()
|
||||
_me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING);
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger)
|
||||
*
|
||||
* @brief Returns information on the seat of specified passenger, represented by the format in VehicleSeat.dbc
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param [in,out] The passenger for which we check the seat info.
|
||||
*
|
||||
* @return null if passenger not found on vehicle, else the DBC record for the seat.
|
||||
*/
|
||||
|
||||
VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger)
|
||||
{
|
||||
SeatMap::iterator itr;
|
||||
@@ -507,6 +622,19 @@ VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit* passenger)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
|
||||
*
|
||||
* @brief Gets seat iterator for specified passenger.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param [in,out] passenger Passenger to look up.
|
||||
*
|
||||
* @return The seat iterator for specified passenger if it's found on the vehicle. Otherwise Seats.end() (invalid iterator).
|
||||
*/
|
||||
|
||||
SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
|
||||
{
|
||||
SeatMap::iterator itr;
|
||||
@@ -517,6 +645,17 @@ SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
|
||||
return Seats.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn uint8 Vehicle::GetAvailableSeatCount() const
|
||||
*
|
||||
* @brief Gets the available seat count.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @return The available seat count.
|
||||
*/
|
||||
|
||||
uint8 Vehicle::GetAvailableSeatCount() const
|
||||
{
|
||||
uint8 ret = 0;
|
||||
@@ -547,3 +686,139 @@ void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o)
|
||||
y = (iny - inx * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation()));
|
||||
x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void Vehicle::CancelJoinEvent(VehicleJoinEvent* e)
|
||||
*
|
||||
* @brief Aborts delayed @VehicleJoinEvent objects.
|
||||
* Implies that the related unit will not be boarding the vehicle after all.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param [in,out] e The VehicleJoinEvent* to process.
|
||||
*/
|
||||
|
||||
void Vehicle::CancelJoinEvent(VehicleJoinEvent* e)
|
||||
{
|
||||
e->to_Abort = true;
|
||||
_pendingJoinEvents.pop_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn bool VehicleJoinEvent::Execute(uint64, uint32)
|
||||
*
|
||||
* @brief Actually adds the passenger @Passenger to vehicle @Target.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param parameter1 Unused
|
||||
* @param parameter2 Unused.
|
||||
*
|
||||
* @return true, cannot fail.
|
||||
*
|
||||
*/
|
||||
|
||||
bool VehicleJoinEvent::Execute(uint64, uint32)
|
||||
{
|
||||
ASSERT(Passenger->IsInWorld());
|
||||
ASSERT(Target->GetBase()->IsInWorld());
|
||||
|
||||
Passenger->m_vehicle = Target;
|
||||
Seat->second.Passenger = Passenger->GetGUID();
|
||||
if (Seat->second.SeatInfo->CanEnterOrExit())
|
||||
{
|
||||
ASSERT(Target->UsableSeatNum);
|
||||
--(Target->UsableSeatNum);
|
||||
if (!Target->UsableSeatNum)
|
||||
{
|
||||
if (Target->GetBase()->GetTypeId() == TYPEID_PLAYER)
|
||||
Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
|
||||
else
|
||||
Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
}
|
||||
}
|
||||
|
||||
Passenger->InterruptNonMeleeSpells(false);
|
||||
|
||||
Player* player = Passenger->ToPlayer();
|
||||
if (player)
|
||||
{
|
||||
// drop flag
|
||||
if (Battleground* bg = player->GetBattleground())
|
||||
bg->EventPlayerDroppedFlag(player);
|
||||
|
||||
player->StopCastingCharm();
|
||||
player->StopCastingBindSight();
|
||||
player->SendOnCancelExpectedVehicleRideAura();
|
||||
player->UnsummonPetTemporaryIfAny();
|
||||
}
|
||||
|
||||
if (Seat->second.SeatInfo->m_flags && !(Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING))
|
||||
Passenger->AddUnitState(UNIT_STATE_ONVEHICLE);
|
||||
|
||||
VehicleSeatEntry const* veSeat = Seat->second.SeatInfo;
|
||||
Passenger->m_movementInfo.t_pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ);
|
||||
Passenger->m_movementInfo.t_time = 0; // 1 for player
|
||||
Passenger->m_movementInfo.t_seat = Seat->first;
|
||||
Passenger->m_movementInfo.t_guid = Target->GetBase()->GetGUID();
|
||||
|
||||
if (Target->GetBase()->GetTypeId() == TYPEID_UNIT && Passenger->GetTypeId() == TYPEID_PLAYER &&
|
||||
Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL)
|
||||
ASSERT(Target->GetBase()->SetCharmedBy(Passenger, CHARM_TYPE_VEHICLE)) // SMSG_CLIENT_CONTROL
|
||||
|
||||
Passenger->SendClearTarget(); // SMSG_BREAK_TARGET
|
||||
Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
// also adds MOVEMENTFLAG_ROOT
|
||||
|
||||
Movement::MoveSplineInit init(Passenger);
|
||||
init.DisableTransportPathTransformations();
|
||||
init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ, false, true);
|
||||
init.SetFacing(0.0f);
|
||||
init.SetTransportEnter();
|
||||
init.Launch();
|
||||
|
||||
if (Target->GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (Target->GetBase()->ToCreature()->IsAIEnabled)
|
||||
Target->GetBase()->ToCreature()->AI()->PassengerBoarded(Passenger, Seat->first, true);
|
||||
|
||||
sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first);
|
||||
|
||||
// Actually quite a redundant hook. Could just use OnAddPassenger and check for unit typemask inside script.
|
||||
if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
sScriptMgr->OnInstallAccessory(Target, Passenger->ToCreature());
|
||||
|
||||
// update all passenger's positions
|
||||
//Passenger's spline OR vehicle movement will update positions
|
||||
//RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void VehicleJoinEvent::Abort(uint64)
|
||||
*
|
||||
* @brief Aborts the event. Implies that unit @Passenger will not be boarding vehicle @Target after all.
|
||||
*
|
||||
* @author Machiavelli
|
||||
* @date 17-2-2013
|
||||
*
|
||||
* @param parameter1 Unused
|
||||
*/
|
||||
|
||||
void VehicleJoinEvent::Abort(uint64)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled",
|
||||
Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first);
|
||||
|
||||
/// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle.
|
||||
/// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove
|
||||
/// the aura manually.
|
||||
Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID());
|
||||
|
||||
if (Passenger->IsInWorld() && Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
Passenger->ToCreature()->DespawnOrUnsummon();
|
||||
}
|
||||
@@ -23,12 +23,12 @@
|
||||
#include "Object.h"
|
||||
#include "VehicleDefines.h"
|
||||
#include "Unit.h"
|
||||
#include <deque>
|
||||
|
||||
struct VehicleEntry;
|
||||
|
||||
class Unit;
|
||||
|
||||
typedef std::set<uint64> GuidSet;
|
||||
class VehicleJoinEvent;
|
||||
|
||||
class Vehicle : public TransportBase
|
||||
{
|
||||
@@ -46,7 +46,7 @@ class Vehicle : public TransportBase
|
||||
|
||||
bool HasEmptySeat(int8 seatId) const;
|
||||
Unit* GetPassenger(int8 seatId) const;
|
||||
int8 GetNextEmptySeat(int8 seatId, bool next) const;
|
||||
SeatMap::const_iterator GetNextEmptySeat(int8 seatId, bool next) const;
|
||||
uint8 GetAvailableSeatCount() const;
|
||||
|
||||
bool AddPassenger(Unit* passenger, int8 seatId = -1);
|
||||
@@ -61,10 +61,14 @@ class Vehicle : public TransportBase
|
||||
void SetLastShootPos(Position const& pos) { m_lastShootPos.Relocate(pos); }
|
||||
Position GetLastShootPos() { return m_lastShootPos; }
|
||||
|
||||
SeatMap Seats;
|
||||
SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones.
|
||||
|
||||
VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger);
|
||||
|
||||
protected:
|
||||
friend class VehicleJoinEvent;
|
||||
uint32 UsableSeatNum; ///< Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
|
||||
|
||||
protected:
|
||||
friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry);
|
||||
Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry);
|
||||
@@ -88,12 +92,27 @@ class Vehicle : public TransportBase
|
||||
/// This method transforms supplied global coordinates into local offsets
|
||||
void CalculatePassengerOffset(float& x, float& y, float& z, float& o);
|
||||
|
||||
Unit* _me;
|
||||
VehicleEntry const* _vehicleInfo;
|
||||
Unit* _me; ///< The underlying unit with the vehicle kit. Can be player or creature.
|
||||
VehicleEntry const* _vehicleInfo; ///< DBC data for vehicle
|
||||
GuidSet vehiclePlayers;
|
||||
uint32 _usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
|
||||
uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players
|
||||
Status _status;
|
||||
|
||||
uint32 _creatureEntry; ///< Can be different than the entry of _me in case of players
|
||||
Status _status; ///< Internal variable for sanity checks
|
||||
Position m_lastShootPos;
|
||||
std::deque<VehicleJoinEvent*> _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers
|
||||
void CancelJoinEvent(VehicleJoinEvent* e);
|
||||
};
|
||||
|
||||
class VehicleJoinEvent : public BasicEvent
|
||||
{
|
||||
friend class Vehicle;
|
||||
protected:
|
||||
VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {}
|
||||
bool Execute(uint64, uint32);
|
||||
void Abort(uint64);
|
||||
|
||||
Vehicle* Target;
|
||||
Unit* Passenger;
|
||||
SeatMap::iterator Seat;
|
||||
};
|
||||
#endif
|
||||
@@ -450,8 +450,8 @@ void GameEventMgr::LoadFromDB()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1 2 3
|
||||
QueryResult result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.eventEntry, game_event_model_equip.modelid, game_event_model_equip.equipment_id "
|
||||
// 0 1 2 3 4
|
||||
QueryResult result = WorldDatabase.Query("SELECT creature.guid, creature.id, game_event_model_equip.eventEntry, game_event_model_equip.modelid, game_event_model_equip.equipment_id "
|
||||
"FROM creature JOIN game_event_model_equip ON creature.guid=game_event_model_equip.guid");
|
||||
|
||||
if (!result)
|
||||
@@ -466,7 +466,8 @@ void GameEventMgr::LoadFromDB()
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 guid = fields[0].GetUInt32();
|
||||
uint16 event_id = fields[1].GetUInt8();
|
||||
uint32 entry = fields[1].GetUInt32();
|
||||
uint16 event_id = fields[2].GetUInt8();
|
||||
|
||||
if (event_id >= mGameEventModelEquip.size())
|
||||
{
|
||||
@@ -476,17 +477,18 @@ void GameEventMgr::LoadFromDB()
|
||||
|
||||
ModelEquipList& equiplist = mGameEventModelEquip[event_id];
|
||||
ModelEquip newModelEquipSet;
|
||||
newModelEquipSet.modelid = fields[2].GetUInt32();
|
||||
newModelEquipSet.equipment_id = fields[3].GetUInt32();
|
||||
newModelEquipSet.modelid = fields[3].GetUInt32();
|
||||
newModelEquipSet.equipment_id = fields[4].GetUInt8();
|
||||
newModelEquipSet.equipement_id_prev = 0;
|
||||
newModelEquipSet.modelid_prev = 0;
|
||||
|
||||
if (newModelEquipSet.equipment_id > 0)
|
||||
{
|
||||
if (!sObjectMgr->GetEquipmentInfo(newModelEquipSet.equipment_id))
|
||||
int8 equipId = static_cast<int8>(newModelEquipSet.equipment_id);
|
||||
if (!sObjectMgr->GetEquipmentInfo(entry, equipId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `game_event_model_equip` have creature (Guid: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.",
|
||||
guid, newModelEquipSet.equipment_id);
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `game_event_model_equip` have creature (Guid: %u, entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.",
|
||||
guid, entry, newModelEquipSet.equipment_id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1103,14 +1105,8 @@ void GameEventMgr::UnApplyEvent(uint16 event_id)
|
||||
|
||||
void GameEventMgr::ApplyNewEvent(uint16 event_id)
|
||||
{
|
||||
switch (sWorld->getIntConfig(CONFIG_EVENT_ANNOUNCE))
|
||||
{
|
||||
case 0: // disable
|
||||
break;
|
||||
case 1: // announce events
|
||||
sWorld->SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str());
|
||||
break;
|
||||
}
|
||||
if (sWorld->getBoolConfig(CONFIG_EVENT_ANNOUNCE))
|
||||
sWorld->SendWorldText(LANG_EVENTMESSAGE, mGameEvent[event_id].description.c_str());
|
||||
|
||||
sLog->outInfo(LOG_FILTER_GAMEEVENTS, "GameEvent %u \"%s\" started.", event_id, mGameEvent[event_id].description.c_str());
|
||||
|
||||
@@ -1332,7 +1328,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
|
||||
itr->second.equipement_id_prev = creature->GetCurrentEquipmentId();
|
||||
itr->second.modelid_prev = creature->GetDisplayId();
|
||||
creature->LoadEquipment(itr->second.equipment_id, true);
|
||||
if (itr->second.modelid >0 && itr->second.modelid_prev != itr->second.modelid)
|
||||
if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid)
|
||||
{
|
||||
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid);
|
||||
if (minfo)
|
||||
@@ -1347,7 +1343,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
|
||||
else
|
||||
{
|
||||
creature->LoadEquipment(itr->second.equipement_id_prev, true);
|
||||
if (itr->second.modelid_prev >0 && itr->second.modelid_prev != itr->second.modelid)
|
||||
if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid)
|
||||
{
|
||||
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev);
|
||||
if (minfo)
|
||||
@@ -1370,7 +1366,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
|
||||
sObjectMgr->GetCreatureModelRandomGender(&displayID);
|
||||
|
||||
if (data2->equipmentId == 0)
|
||||
itr->second.equipement_id_prev = cinfo->equipmentId;
|
||||
itr->second.equipement_id_prev = 1;
|
||||
else if (data2->equipmentId != -1)
|
||||
itr->second.equipement_id_prev = data->equipmentId;
|
||||
itr->second.modelid_prev = displayID;
|
||||
|
||||
@@ -73,9 +73,9 @@ struct GameEventData
|
||||
struct ModelEquip
|
||||
{
|
||||
uint32 modelid;
|
||||
uint32 equipment_id;
|
||||
uint32 modelid_prev;
|
||||
uint32 equipement_id_prev;
|
||||
uint8 equipment_id;
|
||||
uint8 equipement_id_prev;
|
||||
};
|
||||
|
||||
struct NPCVendorEntry
|
||||
|
||||
@@ -427,8 +427,8 @@ void ObjectMgr::LoadCreatureTemplates()
|
||||
"spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
|
||||
// 71 72 73 74 75 76 77 78 79 80 81 82
|
||||
"InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, "
|
||||
// 83 84 85 86 87 88 89
|
||||
" questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName "
|
||||
// 83 84 85 86 87 88
|
||||
" questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName "
|
||||
"FROM creature_template;");
|
||||
|
||||
if (!result)
|
||||
@@ -525,10 +525,9 @@ void ObjectMgr::LoadCreatureTemplates()
|
||||
|
||||
creatureTemplate.movementId = fields[82].GetUInt32();
|
||||
creatureTemplate.RegenHealth = fields[83].GetBool();
|
||||
creatureTemplate.equipmentId = fields[84].GetUInt32();
|
||||
creatureTemplate.MechanicImmuneMask = fields[85].GetUInt32();
|
||||
creatureTemplate.flags_extra = fields[86].GetUInt32();
|
||||
creatureTemplate.ScriptID = GetScriptId(fields[87].GetCString());
|
||||
creatureTemplate.MechanicImmuneMask = fields[84].GetUInt32();
|
||||
creatureTemplate.flags_extra = fields[85].GetUInt32();
|
||||
creatureTemplate.ScriptID = GetScriptId(fields[86].GetCString());
|
||||
|
||||
++count;
|
||||
}
|
||||
@@ -877,15 +876,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
|
||||
}
|
||||
|
||||
if (cInfo->equipmentId > 0) // 0 no equipment
|
||||
{
|
||||
if (!GetEquipmentInfo(cInfo->equipmentId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature_template` lists creature (Entry: %u) with `equipment_id` %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId);
|
||||
const_cast<CreatureTemplate*>(cInfo)->equipmentId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
|
||||
if (cInfo->scale <= 0.0f)
|
||||
{
|
||||
@@ -1011,11 +1001,28 @@ CreatureAddon const* ObjectMgr::GetCreatureTemplateAddon(uint32 entry)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry)
|
||||
EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry, int8& id)
|
||||
{
|
||||
EquipmentInfoContainer::const_iterator itr = _equipmentInfoStore.find(entry);
|
||||
if (itr != _equipmentInfoStore.end())
|
||||
return &(itr->second);
|
||||
if (itr == _equipmentInfoStore.end())
|
||||
return NULL;
|
||||
|
||||
if (itr->second.empty())
|
||||
return NULL;
|
||||
|
||||
if (id == -1) // select a random element
|
||||
{
|
||||
EquipmentInfoContainerInternal::const_iterator ritr = itr->second.begin();
|
||||
std::advance(ritr, urand(0u, itr->second.size()));
|
||||
id = std::distance(itr->second.begin(), ritr) + 1;
|
||||
return &ritr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
EquipmentInfoContainerInternal::const_iterator itr2 = itr->second.find(id);
|
||||
if (itr2 != itr->second.end())
|
||||
return &itr2->second;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1024,7 +1031,8 @@ void ObjectMgr::LoadEquipmentTemplates()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
QueryResult result = WorldDatabase.Query("SELECT entry, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template");
|
||||
// 0 1 2 3 4
|
||||
QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
@@ -1037,13 +1045,21 @@ void ObjectMgr::LoadEquipmentTemplates()
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint16 entry = fields[0].GetUInt16();
|
||||
uint32 entry = fields[0].GetUInt32();
|
||||
|
||||
EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry];
|
||||
if (!sObjectMgr->GetCreatureTemplate(entry))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Creature template (Entry: %u) does not exist but has a record in `creature_equip_template`", entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
equipmentInfo.ItemEntry[0] = fields[1].GetUInt32();
|
||||
equipmentInfo.ItemEntry[1] = fields[2].GetUInt32();
|
||||
equipmentInfo.ItemEntry[2] = fields[3].GetUInt32();
|
||||
uint8 id = fields[1].GetUInt8();
|
||||
|
||||
EquipmentInfo& equipmentInfo = _equipmentInfoStore[entry][id];
|
||||
|
||||
equipmentInfo.ItemEntry[0] = fields[2].GetUInt32();
|
||||
equipmentInfo.ItemEntry[1] = fields[3].GetUInt32();
|
||||
equipmentInfo.ItemEntry[2] = fields[4].GetUInt32();
|
||||
|
||||
for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
|
||||
{
|
||||
@@ -1054,8 +1070,8 @@ void ObjectMgr::LoadEquipmentTemplates()
|
||||
|
||||
if (!dbcItem)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u, forced to 0.",
|
||||
equipmentInfo.ItemEntry[i], i+1, entry);
|
||||
sLog->outError(LOG_FILTER_SQL, "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id=%u, forced to 0.",
|
||||
equipmentInfo.ItemEntry[i], i+1, entry, id);
|
||||
equipmentInfo.ItemEntry[i] = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -1070,8 +1086,8 @@ void ObjectMgr::LoadEquipmentTemplates()
|
||||
dbcItem->InventoryType != INVTYPE_THROWN &&
|
||||
dbcItem->InventoryType != INVTYPE_RANGEDRIGHT)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u is not equipable in a hand, forced to 0.",
|
||||
equipmentInfo.ItemEntry[i], i+1, entry);
|
||||
sLog->outError(LOG_FILTER_SQL, "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id = %u is not equipable in a hand, forced to 0.",
|
||||
equipmentInfo.ItemEntry[i], i+1, entry, id);
|
||||
equipmentInfo.ItemEntry[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1518,13 +1534,13 @@ void ObjectMgr::LoadCreatures()
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
// -1 no equipment, 0 use default
|
||||
if (data.equipmentId > 0)
|
||||
// -1 random, 0 no equipment, 1 is default (may or may not have equipment)
|
||||
if (data.equipmentId != 0)
|
||||
{
|
||||
if (!GetEquipmentInfo(data.equipmentId))
|
||||
if (!GetEquipmentInfo(data.id, data.equipmentId) && data.equipmentId != 1)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", data.id, data.equipmentId);
|
||||
data.equipmentId = -1;
|
||||
data.equipmentId = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1698,7 +1714,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 /*team*/, uint32 mapId, float
|
||||
data.id = entry;
|
||||
data.mapid = mapId;
|
||||
data.displayid = 0;
|
||||
data.equipmentId = cInfo->equipmentId;
|
||||
data.equipmentId = 1;
|
||||
data.posX = x;
|
||||
data.posY = y;
|
||||
data.posZ = z;
|
||||
|
||||
@@ -672,7 +672,7 @@ class ObjectMgr
|
||||
CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID);
|
||||
static uint32 ChooseDisplayId(uint32 team, const CreatureTemplate* cinfo, const CreatureData* data = NULL);
|
||||
static void ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data = NULL);
|
||||
EquipmentInfo const* GetEquipmentInfo(uint32 entry);
|
||||
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id);
|
||||
CreatureAddon const* GetCreatureAddon(uint32 lowguid);
|
||||
CreatureAddon const* GetCreatureTemplateAddon(uint32 entry);
|
||||
ItemTemplate const* GetItemTemplate(uint32 entry);
|
||||
|
||||
@@ -665,7 +665,7 @@ void Group::ChangeLeader(uint64 guid)
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
sScriptMgr->OnGroupChangeLeader(this, m_leaderGuid, guid);
|
||||
sScriptMgr->OnGroupChangeLeader(this, guid, m_leaderGuid);
|
||||
|
||||
if (!isBGGroup() && !isBFGroup())
|
||||
{
|
||||
|
||||
@@ -1650,8 +1650,7 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket& /*recvData*/)
|
||||
return;
|
||||
}
|
||||
|
||||
_player->Dismount();
|
||||
_player->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
_player->RemoveAurasByType(SPELL_AURA_MOUNTED); // Calls Dismount()
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
|
||||
|
||||
@@ -1041,7 +1041,8 @@ enum TrinityStrings
|
||||
LANG_COMMAND_NO_ACHIEVEMENT_CRITERIA_FOUND = 5033,
|
||||
LANG_COMMAND_NO_OUTDOOR_PVP_FORUND = 5034,
|
||||
LANG_CALL_FOR_HELP = 5035,
|
||||
// Room for more Trinity strings 5036-9999
|
||||
LANG_NPCINFO_EQUIPMENT = 5036,
|
||||
// Room for more Trinity strings 5037-9999
|
||||
|
||||
// Level requirement notifications
|
||||
LANG_SAY_REQ = 6604,
|
||||
|
||||
@@ -5320,10 +5320,7 @@ void AuraEffect::HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode,
|
||||
target->SendMessageToSet(&data, true);
|
||||
|
||||
if (apply)
|
||||
{
|
||||
data.Initialize(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
target->ToPlayer()->GetSession()->SendPacket(&data);
|
||||
}
|
||||
target->ToPlayer()->SendOnCancelExpectedVehicleRideAura();
|
||||
}
|
||||
|
||||
void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
||||
@@ -933,6 +933,10 @@ bool Aura::CanBeSaved() const
|
||||
if (HasEffectType(SPELL_AURA_OPEN_STABLE))
|
||||
return false;
|
||||
|
||||
// Can't save vehicle auras, it requires both caster & target to be in world
|
||||
if (HasEffectType(SPELL_AURA_CONTROL_VEHICLE))
|
||||
return false;
|
||||
|
||||
// Incanter's Absorbtion - considering the minimal duration and problems with aura stacking
|
||||
// we skip saving this aura
|
||||
// Also for some reason other auras put as MultiSlot crash core on keeping them after restart,
|
||||
@@ -1814,16 +1818,17 @@ void Aura::LoadScripts()
|
||||
|
||||
bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target)
|
||||
{
|
||||
bool result = true;
|
||||
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
|
||||
{
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET);
|
||||
std::list<AuraScript::CheckAreaTargetHandler>::iterator hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
if (!(*hookItr).Call(*scritr, target))
|
||||
return false;
|
||||
result &= hookItr->Call(*scritr, target);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Aura::CallScriptDispel(DispelInfo* dispelInfo)
|
||||
@@ -1833,7 +1838,8 @@ void Aura::CallScriptDispel(DispelInfo* dispelInfo)
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
|
||||
std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
(*hookItr).Call(*scritr, dispelInfo);
|
||||
hookItr->Call(*scritr, dispelInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1845,7 +1851,8 @@ void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo)
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
|
||||
std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
(*hookItr).Call(*scritr, dispelInfo);
|
||||
hookItr->Call(*scritr, dispelInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1858,14 +1865,15 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplicati
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
|
||||
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, mode);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, mode);
|
||||
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
|
||||
return preventDefault;
|
||||
}
|
||||
|
||||
@@ -1877,12 +1885,12 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplicat
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
|
||||
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, mode);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, mode);
|
||||
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
return preventDefault;
|
||||
@@ -1895,10 +1903,9 @@ void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraAppl
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp);
|
||||
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, mode);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, mode);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1910,10 +1917,9 @@ void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApp
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp);
|
||||
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, mode);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, mode);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1926,14 +1932,15 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplic
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
|
||||
std::list<AuraScript::EffectPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff);
|
||||
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
|
||||
return preventDefault;
|
||||
}
|
||||
|
||||
@@ -1944,10 +1951,9 @@ void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff)
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
|
||||
std::list<AuraScript::EffectUpdatePeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1959,10 +1965,9 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 &
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
|
||||
std::list<AuraScript::EffectCalcAmountHandler>::iterator effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, amount, canBeRecalculated);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, amount, canBeRecalculated);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1974,10 +1979,9 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool &
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
|
||||
std::list<AuraScript::EffectCalcPeriodicHandler>::iterator effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, isPeriodic, amplitude);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, isPeriodic, amplitude);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -1989,10 +1993,9 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellM
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
|
||||
std::list<AuraScript::EffectCalcSpellModHandler>::iterator effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, spellMod);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, spellMod);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2004,11 +2007,13 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
|
||||
std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
}
|
||||
defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
|
||||
if (!defaultPrevented)
|
||||
defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2020,10 +2025,9 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
|
||||
std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2035,10 +2039,9 @@ void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplicatio
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp);
|
||||
std::list<AuraScript::EffectManaShieldHandler>::iterator effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2050,10 +2053,9 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp);
|
||||
std::list<AuraScript::EffectManaShieldHandler>::iterator effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2065,26 +2067,27 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
|
||||
std::list<AuraScript::EffectSplitHandler>::iterator effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, dmgInfo, splitAmount);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, dmgInfo, splitAmount);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
|
||||
{
|
||||
bool result = true;
|
||||
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
|
||||
{
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
|
||||
std::list<AuraScript::CheckProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
if (!(*hookItr).Call(*scritr, eventInfo))
|
||||
return false;
|
||||
result &= hookItr->Call(*scritr, eventInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
return true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
|
||||
@@ -2095,12 +2098,14 @@ bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEven
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
|
||||
std::list<AuraScript::AuraProcHandler>::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
(*effItr).Call(*scritr, eventInfo);
|
||||
effItr->Call(*scritr, eventInfo);
|
||||
|
||||
if (prepare)
|
||||
prepare = !(*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
if (prepare && (*scritr)->_IsDefaultActionPrevented())
|
||||
prepare = false;
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
|
||||
return prepare;
|
||||
}
|
||||
|
||||
@@ -2111,7 +2116,8 @@ void Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo&
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
|
||||
std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
(*hookItr).Call(*scritr, eventInfo);
|
||||
hookItr->Call(*scritr, eventInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2123,7 +2129,8 @@ void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventI
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
|
||||
std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
|
||||
for (; hookItr != hookItrEnd; ++hookItr)
|
||||
(*hookItr).Call(*scritr, eventInfo);
|
||||
hookItr->Call(*scritr, eventInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
@@ -2136,12 +2143,12 @@ bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplicatio
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
|
||||
std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, eventInfo);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, eventInfo);
|
||||
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultActionPrevented();
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
return preventDefault;
|
||||
@@ -2154,10 +2161,9 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli
|
||||
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
|
||||
std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
|
||||
for (; effItr != effEndItr; ++effItr)
|
||||
{
|
||||
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
(*effItr).Call(*scritr, aurEff, eventInfo);
|
||||
}
|
||||
if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
|
||||
effItr->Call(*scritr, aurEff, eventInfo);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3610,7 +3610,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
|
||||
|
||||
unitTarget->CastSpell(unitTarget, iTmpSpellId, true);
|
||||
Creature* npc = unitTarget->ToCreature();
|
||||
npc->LoadEquipment(npc->GetEquipmentId());
|
||||
npc->LoadEquipment();
|
||||
return;
|
||||
}
|
||||
// Emblazon Runeblade
|
||||
|
||||
@@ -1188,6 +1188,12 @@ bool SpellInfo::IsMultiSlotAura() const
|
||||
return IsPassive() || Id == 55849 || Id == 40075 || Id == 44413; // Power Spark, Fel Flak Fire, Incanter's Absorption
|
||||
}
|
||||
|
||||
bool SpellInfo::IsStackableOnOneSlotWithDifferentCasters() const
|
||||
{
|
||||
/// TODO: Re-verify meaning of SPELL_ATTR3_STACK_FOR_DIFF_CASTERS and update conditions here
|
||||
return StackAmount > 1 && !IsChanneled() && !(AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS);
|
||||
}
|
||||
|
||||
bool SpellInfo::IsDeathPersistent() const
|
||||
{
|
||||
return AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT;
|
||||
|
||||
@@ -443,6 +443,7 @@ public:
|
||||
bool IsStackableWithRanks() const;
|
||||
bool IsPassiveStackableWithRanks() const;
|
||||
bool IsMultiSlotAura() const;
|
||||
bool IsStackableOnOneSlotWithDifferentCasters() const;
|
||||
bool IsDeathPersistent() const;
|
||||
bool IsRequiringDeadTarget() const;
|
||||
bool IsAllowingDeadTarget() const;
|
||||
|
||||
@@ -3354,6 +3354,17 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
case 64596: // Cosmic Smash (Algalon the Observer)
|
||||
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100yd
|
||||
break;
|
||||
case 64014: // Expedition Base Camp Teleport
|
||||
case 64024: // Conservatory Teleport
|
||||
case 64025: // Halls of Invention Teleport
|
||||
case 64028: // Colossal Forge Teleport
|
||||
case 64029: // Shattered Walkway Teleport
|
||||
case 64030: // Antechamber Teleport
|
||||
case 64031: // Scrapyard Teleport
|
||||
case 64032: // Formation Grounds Teleport
|
||||
case 65042: // Prison of Yogg-Saron Teleport
|
||||
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
|
||||
break;
|
||||
// ENDOF ULDUAR SPELLS
|
||||
//
|
||||
// TRIAL OF THE CRUSADER SPELLS
|
||||
@@ -3447,7 +3458,7 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
case 71518: // Unholy Infusion Quest Credit (Professor Putricide)
|
||||
case 72934: // Blood Infusion Quest Credit (Blood-Queen Lana'thel)
|
||||
case 72289: // Frost Infusion Quest Credit (Sindragosa)
|
||||
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // another missing radius
|
||||
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // another missing radius
|
||||
break;
|
||||
case 71708: // Empowered Flare (Blood Prince Council)
|
||||
case 72785: // Empowered Flare (Blood Prince Council)
|
||||
|
||||
@@ -222,6 +222,9 @@ bool Weather::UpdateWeather()
|
||||
char const* wthstr;
|
||||
switch (state)
|
||||
{
|
||||
case WEATHER_STATE_FOG:
|
||||
wthstr = "fog";
|
||||
break;
|
||||
case WEATHER_STATE_LIGHT_RAIN:
|
||||
wthstr = "light rain";
|
||||
break;
|
||||
|
||||
@@ -46,7 +46,7 @@ struct WeatherData
|
||||
enum WeatherState
|
||||
{
|
||||
WEATHER_STATE_FINE = 0,
|
||||
WEATHER_STATE_UNK = 1, // Used in some instance encounters.
|
||||
WEATHER_STATE_FOG = 1, // Used in some instance encounters.
|
||||
WEATHER_STATE_LIGHT_RAIN = 3,
|
||||
WEATHER_STATE_MEDIUM_RAIN = 4,
|
||||
WEATHER_STATE_HEAVY_RAIN = 5,
|
||||
|
||||
@@ -979,7 +979,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = ConfigMgr::GetIntDefault("ChatFlood.MessageDelay", 1);
|
||||
m_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = ConfigMgr::GetIntDefault("ChatFlood.MuteTime", 10);
|
||||
|
||||
m_int_configs[CONFIG_EVENT_ANNOUNCE] = ConfigMgr::GetIntDefault("Event.Announce", 0);
|
||||
m_bool_configs[CONFIG_EVENT_ANNOUNCE] = ConfigMgr::GetIntDefault("Event.Announce", false);
|
||||
|
||||
m_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = ConfigMgr::GetFloatDefault("CreatureFamilyFleeAssistanceRadius", 30.0f);
|
||||
m_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = ConfigMgr::GetFloatDefault("CreatureFamilyAssistanceRadius", 10.0f);
|
||||
@@ -1445,12 +1445,12 @@ void World::SetInitialWorldSettings()
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature Model Based Info Data...");
|
||||
sObjectMgr->LoadCreatureModelInfo();
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Equipment templates...");
|
||||
sObjectMgr->LoadEquipmentTemplates();
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature templates...");
|
||||
sObjectMgr->LoadCreatureTemplates();
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Equipment templates..."); // must be after LoadCreatureTemplates
|
||||
sObjectMgr->LoadEquipmentTemplates();
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creature template addons...");
|
||||
sObjectMgr->LoadCreatureTemplateAddons();
|
||||
|
||||
|
||||
@@ -174,6 +174,7 @@ enum WorldBoolConfigs
|
||||
CONFIG_WINTERGRASP_ENABLE,
|
||||
CONFIG_GUILD_LEVELING_ENABLED,
|
||||
CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs?
|
||||
CONFIG_EVENT_ANNOUNCE,
|
||||
BOOL_CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
@@ -265,7 +266,6 @@ enum WorldIntConfigs
|
||||
CONFIG_CHATFLOOD_MESSAGE_COUNT,
|
||||
CONFIG_CHATFLOOD_MESSAGE_DELAY,
|
||||
CONFIG_CHATFLOOD_MUTE_TIME,
|
||||
CONFIG_EVENT_ANNOUNCE,
|
||||
CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY,
|
||||
CONFIG_CREATURE_FAMILY_FLEE_DELAY,
|
||||
CONFIG_WORLD_BOSS_LEVEL_DIFF,
|
||||
|
||||
@@ -649,6 +649,7 @@ public:
|
||||
|
||||
handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUIDLow(), faction, npcflags, Entry, displayid, nativeid);
|
||||
handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction());
|
||||
handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str());
|
||||
|
||||
@@ -495,10 +495,9 @@ public:
|
||||
cInfo->questItems[5] = fields[78].GetUInt32();
|
||||
cInfo->movementId = fields[79].GetUInt32();
|
||||
cInfo->RegenHealth = fields[80].GetBool();
|
||||
cInfo->equipmentId = fields[81].GetUInt32();
|
||||
cInfo->MechanicImmuneMask = fields[82].GetUInt32();
|
||||
cInfo->flags_extra = fields[83].GetUInt32();
|
||||
cInfo->ScriptID = sObjectMgr->GetScriptId(fields[84].GetCString());
|
||||
cInfo->MechanicImmuneMask = fields[81].GetUInt32();
|
||||
cInfo->flags_extra = fields[82].GetUInt32();
|
||||
cInfo->ScriptID = sObjectMgr->GetScriptId(fields[83].GetCString());
|
||||
|
||||
sObjectMgr->CheckCreatureTemplate(cInfo);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,20 @@ enum Say
|
||||
SAY_LEASH = 1,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_CLEAVE = 1,
|
||||
EVENT_MORTAL_STRIKE = 2,
|
||||
EVENT_BLAST_WAVE = 3,
|
||||
EVENT_KNOCK_BACK = 4,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CLEAVE = 26350,
|
||||
SPELL_BLASTWAVE = 23331,
|
||||
SPELL_MORTALSTRIKE = 24573,
|
||||
SPELL_KNOCKBACK = 25778
|
||||
SPELL_BLAST_WAVE = 23331,
|
||||
SPELL_MORTAL_STRIKE = 24573,
|
||||
SPELL_KNOCK_BACK = 25778
|
||||
};
|
||||
|
||||
class boss_broodlord : public CreatureScript
|
||||
@@ -54,17 +62,13 @@ public:
|
||||
{
|
||||
boss_broodlordAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
uint32 Cleave_Timer;
|
||||
uint32 BlastWave_Timer;
|
||||
uint32 MortalStrike_Timer;
|
||||
uint32 KnockBack_Timer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Cleave_Timer = 8000; // These times are probably wrong
|
||||
BlastWave_Timer = 12000;
|
||||
MortalStrike_Timer = 20000;
|
||||
KnockBack_Timer = 30000;
|
||||
// These timers are probably wrong
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8000);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 12000);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 20000);
|
||||
events.ScheduleEvent(EVENT_KNOCK_BACK, 30000);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
@@ -78,45 +82,51 @@ public:
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Cleave_Timer
|
||||
if (Cleave_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_CLEAVE);
|
||||
Cleave_Timer = 7000;
|
||||
} else Cleave_Timer -= diff;
|
||||
if (EnterEvadeIfOutOfCombatArea(diff))
|
||||
Talk(SAY_LEASH);
|
||||
|
||||
// BlastWave
|
||||
if (BlastWave_Timer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_BLASTWAVE);
|
||||
BlastWave_Timer = urand(8000, 16000);
|
||||
} else BlastWave_Timer -= diff;
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
//MortalStrike_Timer
|
||||
if (MortalStrike_Timer <= diff)
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_MORTALSTRIKE);
|
||||
MortalStrike_Timer = urand(25000, 35000);
|
||||
} else MortalStrike_Timer -= diff;
|
||||
|
||||
if (KnockBack_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = me->getVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
DoCast(target, SPELL_KNOCKBACK);
|
||||
// Drop 50% aggro
|
||||
if (DoGetThreat(target))
|
||||
DoModifyThreatPercent(target, -50);
|
||||
case EVENT_CLEAVE:
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_CLEAVE, 8000);
|
||||
break;
|
||||
case EVENT_MORTAL_STRIKE:
|
||||
DoCastVictim(SPELL_MORTAL_STRIKE);
|
||||
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 20000);
|
||||
break;
|
||||
case EVENT_BLAST_WAVE:
|
||||
DoCastVictim(SPELL_BLAST_WAVE);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 12000);
|
||||
break;
|
||||
case EVENT_KNOCK_BACK:
|
||||
if (Unit* target = me->getVictim())
|
||||
{
|
||||
DoCast(target, SPELL_BLAST_WAVE);
|
||||
// Drop 50% of threat
|
||||
if (DoGetThreat(target))
|
||||
DoModifyThreatPercent(target, -50);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_KNOCK_BACK, 30000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
KnockBack_Timer = urand(15000, 30000);
|
||||
} else KnockBack_Timer -= diff;
|
||||
}
|
||||
|
||||
if (EnterEvadeIfOutOfCombatArea(diff))
|
||||
Talk(SAY_LEASH);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events; /// @todo: change BWL to instance script and bosses to BossAI
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -102,10 +102,8 @@ public:
|
||||
npc_unworthy_initiateAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
if (!me->GetEquipmentId())
|
||||
if (const CreatureTemplate* info = sObjectMgr->GetCreatureTemplate(28406))
|
||||
if (info->equipmentId)
|
||||
const_cast<CreatureTemplate*>(me->GetCreatureTemplate())->equipmentId = info->equipmentId;
|
||||
if (!me->GetCurrentEquipmentId())
|
||||
me->SetCurrentEquipmentId(me->GetOriginalEquipmentId());
|
||||
}
|
||||
|
||||
uint64 playerGUID;
|
||||
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
case 2:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
DoCast(me, SPELL_KOLTIRA_TRANSFORM);
|
||||
me->LoadEquipment(me->GetEquipmentId());
|
||||
me->LoadEquipment();
|
||||
break;
|
||||
case 3:
|
||||
SetEscortPaused(true);
|
||||
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
++_summonDeaths;
|
||||
if (_summonDeaths == 11) // All summons died
|
||||
{
|
||||
SendWeather(WEATHER_STATE_UNK, 0.0f);
|
||||
SendWeather(WEATHER_STATE_FOG, 0.0f);
|
||||
me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION);
|
||||
events.SetPhase(PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return new npc_aged_dying_ancient_kodoAI(creature);
|
||||
|
||||
@@ -45,11 +45,13 @@ enum Spells
|
||||
SPELL_SHROUD_OF_SORROW = 70986,
|
||||
SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949,
|
||||
SPELL_VAMPIRIC_BITE = 71726,
|
||||
SPELL_VAMPIRIC_BITE_DUMMY = 71837,
|
||||
SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879,
|
||||
SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL = 70872,
|
||||
SPELL_FRENZIED_BLOODTHIRST = 70877,
|
||||
SPELL_UNCONTROLLABLE_FRENZY = 70923,
|
||||
SPELL_PRESENCE_OF_THE_DARKFALLEN = 71952,
|
||||
SPELL_PRESENCE_OF_THE_DARKFALLEN = 70994,
|
||||
SPELL_PRESENCE_OF_THE_DARKFALLEN_2 = 71952,
|
||||
SPELL_BLOOD_MIRROR_DAMAGE = 70821,
|
||||
SPELL_BLOOD_MIRROR_VISUAL = 71510,
|
||||
SPELL_BLOOD_MIRROR_DUMMY = 70838,
|
||||
@@ -88,6 +90,7 @@ uint32 const vampireAuras[3][MAX_DIFFICULTY] =
|
||||
#define ESSENCE_OF_BLOOD_QUEEN_PLR RAID_MODE<uint32>(70879, 71525, 71530, 71531)
|
||||
#define FRENZIED_BLOODTHIRST RAID_MODE<uint32>(70877, 71474, 70877, 71474)
|
||||
#define DELIRIOUS_SLASH RAID_MODE<uint32>(71623, 71624, 71625, 71626)
|
||||
#define PRESENCE_OF_THE_DARKFALLEN RAID_MODE<uint32>(70994, 71962, 71963, 71964)
|
||||
|
||||
enum Events
|
||||
{
|
||||
@@ -220,6 +223,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN);
|
||||
instance->DoRemoveAurasDueToSpellOnPlayers(PRESENCE_OF_THE_DARKFALLEN);
|
||||
}
|
||||
|
||||
void DoAction(int32 const action)
|
||||
@@ -357,8 +361,11 @@ class boss_blood_queen_lana_thel : public CreatureScript
|
||||
{
|
||||
Unit* target = targets.front();
|
||||
DoCast(target, SPELL_VAMPIRIC_BITE);
|
||||
DoCastAOE(SPELL_VAMPIRIC_BITE_DUMMY, true);
|
||||
Talk(SAY_VAMPIRIC_BITE);
|
||||
_vampires.insert(target->GetGUID());
|
||||
target->CastSpell(target, SPELL_PRESENCE_OF_THE_DARKFALLEN, TRIGGERED_FULL_MASK);
|
||||
target->CastSpell(target, SPELL_PRESENCE_OF_THE_DARKFALLEN_2, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -377,9 +384,10 @@ class boss_blood_queen_lana_thel : public CreatureScript
|
||||
_offtank->CastSpell(me->getVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true);
|
||||
me->getVictim()->CastSpell(_offtank, SPELL_BLOOD_MIRROR_DUMMY, true);
|
||||
DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL);
|
||||
if (Item* shadowsEdge = _offtank->GetWeaponForAttack(BASE_ATTACK, true))
|
||||
if (!_offtank->HasAura(SPELL_THIRST_QUENCHED) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE && !_offtank->HasAura(SPELL_GUSHING_WOUND))
|
||||
_offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, true);
|
||||
if (Is25ManRaid() && _offtank->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE &&
|
||||
_offtank->HasAura(SPELL_UNSATED_CRAVING) && !_offtank->HasAura(SPELL_THIRST_QUENCHED) &&
|
||||
!_offtank->HasAura(SPELL_GUSHING_WOUND))
|
||||
_offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -396,13 +404,7 @@ class boss_blood_queen_lana_thel : public CreatureScript
|
||||
{
|
||||
std::list<Player*> targets;
|
||||
SelectRandomTarget(false, &targets);
|
||||
uint32 targetCount = 2;
|
||||
// do not combine these checks! we want it incremented TWICE when both conditions are met
|
||||
if (IsHeroic())
|
||||
++targetCount;
|
||||
if (Is25ManRaid())
|
||||
++targetCount;
|
||||
Trinity::Containers::RandomResizeList<Player*>(targets, targetCount);
|
||||
Trinity::Containers::RandomResizeList(targets, Is25ManRaid() ? 3 : 2);
|
||||
if (targets.size() > 1)
|
||||
{
|
||||
Talk(SAY_PACT_OF_THE_DARKFALLEN);
|
||||
@@ -554,33 +556,36 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader
|
||||
|
||||
uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_FRENZIED_BLOODTHIRST, GetCaster());
|
||||
GetCaster()->RemoveAura(spellId, 0, 0, AURA_REMOVE_BY_ENEMY_SPELL);
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, true);
|
||||
// Presence of the Darkfallen buff on Blood-Queen
|
||||
if (GetCaster()->GetMap()->IsHeroic())
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_PRESENCE_OF_THE_DARKFALLEN, true);
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, TRIGGERED_FULL_MASK);
|
||||
|
||||
// Shadowmourne questline
|
||||
if (GetCaster()->ToPlayer()->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE)
|
||||
if (Aura* aura = GetCaster()->GetAura(SPELL_GUSHING_WOUND))
|
||||
{
|
||||
if (Aura* aura = GetCaster()->GetAura(SPELL_GUSHING_WOUND))
|
||||
if (aura->GetStackAmount() == 3)
|
||||
{
|
||||
if (aura->GetStackAmount() == 3)
|
||||
{
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_THIRST_QUENCHED, true);
|
||||
GetCaster()->RemoveAura(aura);
|
||||
}
|
||||
else
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_GUSHING_WOUND, true);
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_THIRST_QUENCHED, TRIGGERED_FULL_MASK);
|
||||
GetCaster()->RemoveAura(aura);
|
||||
}
|
||||
else
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* bloodQueen = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_BLOOD_QUEEN_LANA_THEL)))
|
||||
bloodQueen->AI()->SetGUID(GetHitUnit()->GetGUID(), GUID_VAMPIRE);
|
||||
}
|
||||
|
||||
void HandlePresence(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PRESENCE_OF_THE_DARKFALLEN, TRIGGERED_FULL_MASK);
|
||||
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PRESENCE_OF_THE_DARKFALLEN_2, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_blood_queen_vampiric_bite_SpellScript::CheckTarget);
|
||||
BeforeHit += SpellHitFn(spell_blood_queen_vampiric_bite_SpellScript::OnCast);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_blood_queen_vampiric_bite_SpellScript::HandlePresence, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +84,9 @@ enum Spells
|
||||
SPELL_CONCUSSIVE_SHOCK = 71337,
|
||||
|
||||
// Frost Infusion
|
||||
SPELL_FROST_INFUSION_CREDIT = 72289
|
||||
SPELL_FROST_INFUSION_CREDIT = 72289,
|
||||
SPELL_FROST_IMBUED_BLADE = 72290,
|
||||
SPELL_FROST_INFUSION = 72292,
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -147,11 +149,7 @@ enum MovementPoints
|
||||
|
||||
enum Shadowmourne
|
||||
{
|
||||
QUEST_FROST_INFUSION = 24757,
|
||||
ITEM_SHADOW_S_EDGE = 49888,
|
||||
|
||||
SPELL_FROST_INFUSION = 72292,
|
||||
SPELL_FROST_IMBUED_BLADE = 72290,
|
||||
QUEST_FROST_INFUSION = 24757
|
||||
};
|
||||
|
||||
Position const RimefangFlyPos = {4413.309f, 2456.421f, 233.3795f, 2.890186f};
|
||||
@@ -390,47 +388,10 @@ class boss_sindragosa : public CreatureScript
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell)
|
||||
{
|
||||
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(70127, me))
|
||||
{
|
||||
if (spellId == spell->Id)
|
||||
{
|
||||
if (Aura const* mysticBuffet = target->GetAura(spell->Id))
|
||||
_mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Frost Infusion
|
||||
if (Player* player = target->ToPlayer())
|
||||
{
|
||||
if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1, me))
|
||||
{
|
||||
if (spellId == spell->Id)
|
||||
{
|
||||
Item* shadowsEdge = player->GetWeaponForAttack(BASE_ATTACK, true);
|
||||
if (player->GetQuestStatus(QUEST_FROST_INFUSION) == QUEST_STATUS_INCOMPLETE && shadowsEdge)
|
||||
{
|
||||
if (!player->HasAura(SPELL_FROST_IMBUED_BLADE) && shadowsEdge->GetEntry() == ITEM_SHADOW_S_EDGE)
|
||||
{
|
||||
if (Aura* infusion = player->GetAura(SPELL_FROST_INFUSION))
|
||||
{
|
||||
if (infusion->GetStackAmount() == 3)
|
||||
{
|
||||
player->CastSpell(player, SPELL_FROST_IMBUED_BLADE, true);
|
||||
player->RemoveAura(infusion);
|
||||
}
|
||||
else
|
||||
player->CastSpell(player, SPELL_FROST_INFUSION, true);
|
||||
}
|
||||
else
|
||||
player->CastSpell(player, SPELL_FROST_INFUSION, true);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 const diff)
|
||||
@@ -1155,6 +1116,50 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader
|
||||
}
|
||||
};
|
||||
|
||||
class spell_sindragosa_frost_breath : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_sindragosa_frost_breath() : SpellScriptLoader("spell_sindragosa_frost_breath") { }
|
||||
|
||||
class spell_sindragosa_frost_breath_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_sindragosa_frost_breath_SpellScript);
|
||||
|
||||
void HandleInfusion()
|
||||
{
|
||||
Player* target = GetHitPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE)
|
||||
return;
|
||||
|
||||
// Check if player has Shadow's Edge equipped and not ready for infusion
|
||||
if (!target->HasAura(SPELL_UNSATED_CRAVING) || target->HasAura(SPELL_FROST_IMBUED_BLADE))
|
||||
return;
|
||||
|
||||
Aura* infusion = target->GetAura(SPELL_FROST_INFUSION, target->GetGUID());
|
||||
if (infusion && infusion->GetStackAmount() >= 3)
|
||||
{
|
||||
target->RemoveAura(infusion);
|
||||
target->CastSpell(target, SPELL_FROST_IMBUED_BLADE, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
else
|
||||
target->CastSpell(target, SPELL_FROST_INFUSION, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_sindragosa_frost_breath_SpellScript::HandleInfusion);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_sindragosa_frost_breath_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_sindragosa_instability : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
@@ -1577,6 +1582,7 @@ void AddSC_boss_sindragosa()
|
||||
new npc_sindragosa_trash();
|
||||
new spell_sindragosa_s_fury();
|
||||
new spell_sindragosa_unchained_magic();
|
||||
new spell_sindragosa_frost_breath();
|
||||
new spell_sindragosa_instability();
|
||||
new spell_sindragosa_frost_beacon();
|
||||
new spell_sindragosa_ice_tomb();
|
||||
|
||||
@@ -56,6 +56,7 @@ enum SharedSpells
|
||||
SPELL_FROSTMOURNE_TELEPORT_VISUAL = 73078,
|
||||
|
||||
// Shadowmourne questline
|
||||
SPELL_UNSATED_CRAVING = 71168,
|
||||
SPELL_SHADOWS_FATE = 71169
|
||||
};
|
||||
|
||||
|
||||
@@ -435,7 +435,7 @@ class instance_icecrown_citadel : public InstanceMapScript
|
||||
// these 2 gates are functional only on 25man modes
|
||||
case GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_01:
|
||||
case GO_DOODAD_ICECROWN_ROOSTPORTCULLIS_04:
|
||||
if (instance->GetSpawnMode() & 1)
|
||||
if (instance->Is25ManRaid())
|
||||
AddDoor(go, true);
|
||||
break;
|
||||
case GO_LADY_DEATHWHISPER_ELEVATOR:
|
||||
|
||||
@@ -565,10 +565,6 @@ class instance_ulduar : public InstanceMapScript
|
||||
}
|
||||
HandleGameObject(KologarnBridgeGUID, false);
|
||||
}
|
||||
if (state == IN_PROGRESS)
|
||||
HandleGameObject(KologarnDoorGUID, false);
|
||||
else
|
||||
HandleGameObject(KologarnDoorGUID, true);
|
||||
break;
|
||||
case BOSS_HODIR:
|
||||
if (state == DONE)
|
||||
|
||||
+4
-4
@@ -316,7 +316,7 @@ public:
|
||||
me->SetDisplayId(MODEL_NIGHTELF);
|
||||
|
||||
// and reseting equipment
|
||||
me->LoadEquipment(me->GetEquipmentId());
|
||||
me->LoadEquipment();
|
||||
|
||||
if (instance && instance->GetData64(DATA_LEOTHERAS_EVENT_STARTER))
|
||||
{
|
||||
@@ -410,7 +410,7 @@ public:
|
||||
if (me->HasAura(AURA_BANISH))
|
||||
return;
|
||||
|
||||
me->LoadEquipment(me->GetEquipmentId());
|
||||
me->LoadEquipment();
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
@@ -558,7 +558,7 @@ public:
|
||||
{
|
||||
//switch to nightelf form
|
||||
me->SetDisplayId(MODEL_NIGHTELF);
|
||||
me->LoadEquipment(me->GetEquipmentId());
|
||||
me->LoadEquipment();
|
||||
|
||||
CastConsumingMadness();
|
||||
DespawnDemon();
|
||||
@@ -589,7 +589,7 @@ public:
|
||||
|
||||
Talk(SAY_FINAL_FORM);
|
||||
me->SetDisplayId(MODEL_NIGHTELF);
|
||||
me->LoadEquipment(me->GetEquipmentId());
|
||||
me->LoadEquipment();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -813,7 +813,40 @@ class spell_item_scroll_of_recall : public SpellScriptLoader
|
||||
enum ShadowsFate
|
||||
{
|
||||
SPELL_SOUL_FEAST = 71203,
|
||||
QUEST_A_FEAST_OF_SOULS = 24547
|
||||
};
|
||||
|
||||
class spell_item_unsated_craving : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_item_unsated_craving() : SpellScriptLoader("spell_item_unsated_craving") { }
|
||||
|
||||
class spell_item_unsated_craving_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_item_unsated_craving_AuraScript);
|
||||
|
||||
bool CheckProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
Unit* caster = procInfo.GetActor();
|
||||
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return false;
|
||||
|
||||
Unit* target = procInfo.GetActionTarget();
|
||||
if (!target || target->GetTypeId() != TYPEID_UNIT || target->GetCreatureType() == CREATURE_TYPE_CRITTER || target->isSummon())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_item_unsated_craving_AuraScript::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_item_unsated_craving_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_item_shadows_fate : public SpellScriptLoader
|
||||
@@ -825,41 +858,20 @@ class spell_item_shadows_fate : public SpellScriptLoader
|
||||
{
|
||||
PrepareAuraScript(spell_item_shadows_fate_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/)
|
||||
void HandleProc(ProcEventInfo& procInfo)
|
||||
{
|
||||
if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_FEAST))
|
||||
return false;
|
||||
if (!sObjectMgr->GetQuestTemplate(QUEST_A_FEAST_OF_SOULS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
Unit* caster = procInfo.GetActor();
|
||||
Unit* target = GetCaster();
|
||||
if (!caster || !target)
|
||||
return;
|
||||
|
||||
bool Load()
|
||||
{
|
||||
_procTarget = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
_procTarget = GetCaster();
|
||||
return _procTarget && _procTarget->GetTypeId() == TYPEID_PLAYER && _procTarget->ToPlayer()->GetQuestStatus(QUEST_A_FEAST_OF_SOULS) == QUEST_STATUS_INCOMPLETE;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetTarget()->CastSpell(_procTarget, SPELL_SOUL_FEAST, true);
|
||||
caster->CastSpell(target, SPELL_SOUL_FEAST, TRIGGERED_FULL_MASK);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_item_shadows_fate_AuraScript::CheckProc);
|
||||
OnEffectProc += AuraEffectProcFn(spell_item_shadows_fate_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
OnProc += AuraProcFn(spell_item_shadows_fate_AuraScript::HandleProc);
|
||||
}
|
||||
|
||||
private:
|
||||
Unit* _procTarget;
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
@@ -2481,6 +2493,7 @@ void AddSC_item_spell_scripts()
|
||||
new spell_item_piccolo_of_the_flaming_fire();
|
||||
new spell_item_savory_deviate_delight();
|
||||
new spell_item_scroll_of_recall();
|
||||
new spell_item_unsated_craving();
|
||||
new spell_item_shadows_fate();
|
||||
new spell_item_shadowmourne();
|
||||
new spell_item_shadowmourne_soul_fragment();
|
||||
|
||||
@@ -78,7 +78,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(WORLD_INS_CREATURE_TRANSPORT, "INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_TRANSPORT_EMOTE, "UPDATE creature_transport SET emote = ? WHERE transport_entry = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, equipment_id, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -1028,7 +1028,7 @@ Event.Announce = 0
|
||||
|
||||
#
|
||||
# BeepAtStart
|
||||
# Description: Beep when the world server finished starting (Unix/Linux systems).
|
||||
# Description: Beep when the world server finished starting.
|
||||
# Default: 1 - (Enabled)
|
||||
# 0 - (Disabled)
|
||||
|
||||
@@ -1093,6 +1093,14 @@ DBC.EnforceItemAttributes = 1
|
||||
|
||||
AccountInstancesPerHour = 5
|
||||
|
||||
#
|
||||
# RBAC.DefaultGroups
|
||||
# Description: Comma separated list of groups to be added to any account
|
||||
# Check auth.rbac_groups for correct ids
|
||||
# Default: "" (No group)
|
||||
|
||||
RBAC.DefaultGroups = ""
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
@@ -12,4 +12,6 @@ add_subdirectory(map_extractor)
|
||||
add_subdirectory(vmap4_assembler)
|
||||
add_subdirectory(vmap4_extractor)
|
||||
add_subdirectory(mmaps_generator)
|
||||
# add_subdirectory(mesh_extractor)
|
||||
#if (WITH_MESHEXTRACTOR)
|
||||
# add_subdirectory(mesh_extractor)
|
||||
#endif()
|
||||
Reference in new issue
Block a user