mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Merge remote branch 'origin/master' into 330
Conflicts: src/game/ObjectMgr.h
This commit is contained in:
commit
7c6cae1af7
58 changed files with 1937 additions and 990 deletions
288
sql/mangos.sql
288
sql/mangos.sql
|
|
@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
|
|||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`cache_id` int(10) default '0',
|
||||
`required_8912_01_mangos_spell_proc_event` bit(1) default NULL
|
||||
`required_8965_02_mangos_command` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
|
|
@ -705,6 +705,7 @@ INSERT INTO `command` VALUES
|
|||
('quest add',3,'Syntax: .quest add #quest_id\r\n\r\nAdd to character quest log quest #quest_id. Quest started from item can\'t be added by this command but correct .additem call provided in command output.'),
|
||||
('quest complete',3,'Syntax: .quest complete #questid\r\nMark all quest objectives as completed for target character active quest. After this target character can go and get quest reward.'),
|
||||
('quest remove',3,'Syntax: .quest remove #quest_id\r\n\r\nSet quest #quest_id state to not completed and not active (and remove from active quest list) for selected player.'),
|
||||
('quit',4,'Syntax: quit\r\n\r\nClose RA connection. Command must be typed fully (quit).'),
|
||||
('recall',1,'Syntax: .recall [$playername]\r\n\r\nTeleport $playername or selected player to the place where he has been before last use of a teleportation command. If no $playername is entered and no player is selected, it will teleport you.'),
|
||||
('reload all',3,'Syntax: .reload all\r\n\r\nReload all tables with reload support added and that can be _safe_ reloaded.'),
|
||||
('reload all_area',3,'Syntax: .reload all_area\r\n\r\nReload all `areatrigger_*` tables if reload support added for this table and this table can be _safe_ reloaded.'),
|
||||
|
|
@ -1078,6 +1079,7 @@ CREATE TABLE `creature_template` (
|
|||
`name` char(100) NOT NULL default '0',
|
||||
`subname` char(100) default NULL,
|
||||
`IconName` char(100) default NULL,
|
||||
`gossip_menu_id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`minlevel` tinyint(3) unsigned NOT NULL default '1',
|
||||
`maxlevel` tinyint(3) unsigned NOT NULL default '1',
|
||||
`minhealth` int(10) unsigned NOT NULL default '0',
|
||||
|
|
@ -1155,7 +1157,7 @@ CREATE TABLE `creature_template` (
|
|||
LOCK TABLES `creature_template` WRITE;
|
||||
/*!40000 ALTER TABLE `creature_template` DISABLE KEYS */;
|
||||
INSERT INTO `creature_template` VALUES
|
||||
(1,0,0,0,0,0,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,1,2000,2200,8,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,1.0,1.0,0,0,0,0,0,0,0,0,1,0,0,0x82,'');
|
||||
(1,0,0,0,0,0,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,0,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,1,2000,2200,8,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,1.0,1.0,0,0,0,0,0,0,0,0,1,0,0,0x82,'');
|
||||
/*!40000 ALTER TABLE `creature_template` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
|
@ -1899,6 +1901,115 @@ LOCK TABLES `gameobject_template` WRITE;
|
|||
/*!40000 ALTER TABLE `gameobject_template` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `gossip_menu`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS gossip_menu;
|
||||
CREATE TABLE gossip_menu (
|
||||
entry smallint(6) unsigned NOT NULL default '0',
|
||||
text_id mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_1_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_2_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (entry, text_id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `gossip_menu`
|
||||
--
|
||||
|
||||
LOCK TABLES `gossip_menu` WRITE;
|
||||
/*!40000 ALTER TABLE `gossip_menu` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `gossip_menu` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `gossip_menu_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS gossip_menu_option;
|
||||
CREATE TABLE gossip_menu_option (
|
||||
menu_id smallint(6) unsigned NOT NULL default '0',
|
||||
id smallint(6) unsigned NOT NULL default '0',
|
||||
option_icon mediumint(8) unsigned NOT NULL default '0',
|
||||
option_text text,
|
||||
option_id tinyint(3) unsigned NOT NULL default '0',
|
||||
npc_option_npcflag int(10) unsigned NOT NULL default '0',
|
||||
action_menu_id mediumint(8) unsigned NOT NULL default '0',
|
||||
action_poi_id mediumint(8) unsigned NOT NULL default '0',
|
||||
action_script_id mediumint(8) unsigned NOT NULL default '0',
|
||||
box_coded tinyint(3) unsigned NOT NULL default '0',
|
||||
box_money int(11) unsigned NOT NULL default '0',
|
||||
box_text text,
|
||||
cond_1 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_1_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_2_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_3 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_3_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_3_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (menu_id, id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `gossip_menu_option`
|
||||
--
|
||||
|
||||
LOCK TABLES `gossip_menu_option` WRITE;
|
||||
/*!40000 ALTER TABLE `gossip_menu_option` DISABLE KEYS */;
|
||||
INSERT INTO gossip_menu_option VALUES
|
||||
(0,0,0,'GOSSIP_OPTION_QUESTGIVER',2,2,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,1,1,'GOSSIP_OPTION_VENDOR',3,128,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,2,2,'GOSSIP_OPTION_TAXIVENDOR',4,8192,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,3,3,'GOSSIP_OPTION_TRAINER',5,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,4,4,'GOSSIP_OPTION_SPIRITHEALER',6,16384,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,5,4,'GOSSIP_OPTION_SPIRITGUIDE',7,32768,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,6,5,'GOSSIP_OPTION_INNKEEPER',8,65536,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,7,6,'GOSSIP_OPTION_BANKER',9,131072,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,8,7,'GOSSIP_OPTION_PETITIONER',10,262144,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,9,8,'GOSSIP_OPTION_TABARDDESIGNER',11,524288,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,10,9,'GOSSIP_OPTION_BATTLEFIELD',12,1048576,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,11,6,'GOSSIP_OPTION_AUCTIONEER',13,2097152,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,12,0,'GOSSIP_OPTION_STABLEPET',14,4194304,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,13,1,'GOSSIP_OPTION_ARMORER',15,4096,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,14,2,'GOSSIP_OPTION_UNLEARNTALENTS',16,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,15,2,'GOSSIP_OPTION_UNLEARNPETSKILLS',17,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0);
|
||||
/*!40000 ALTER TABLE `gossip_menu_option` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `gossip_scripts`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `gossip_scripts`;
|
||||
CREATE TABLE `gossip_scripts` (
|
||||
`id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`delay` int(10) unsigned NOT NULL default '0',
|
||||
`command` mediumint(8) unsigned NOT NULL default '0',
|
||||
`datalong` mediumint(8) unsigned NOT NULL default '0',
|
||||
`datalong2` int(10) unsigned NOT NULL default '0',
|
||||
`dataint` int(11) NOT NULL default '0',
|
||||
`x` float NOT NULL default '0',
|
||||
`y` float NOT NULL default '0',
|
||||
`z` float NOT NULL default '0',
|
||||
`o` float NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `gossip_scripts`
|
||||
--
|
||||
|
||||
LOCK TABLES `gossip_scripts` WRITE;
|
||||
/*!40000 ALTER TABLE `gossip_scripts` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `gossip_scripts` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `instance_template`
|
||||
--
|
||||
|
|
@ -2344,6 +2455,42 @@ LOCK TABLES `locales_gameobject` WRITE;
|
|||
/*!40000 ALTER TABLE `locales_gameobject` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `locales_gossip_menu_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `locales_gossip_menu_option`;
|
||||
CREATE TABLE `locales_gossip_menu_option` (
|
||||
`menu_id` smallint(6) unsigned NOT NULL default '0',
|
||||
`id` smallint(6) unsigned NOT NULL default '0',
|
||||
`option_text_loc1` text,
|
||||
`option_text_loc2` text,
|
||||
`option_text_loc3` text,
|
||||
`option_text_loc4` text,
|
||||
`option_text_loc5` text,
|
||||
`option_text_loc6` text,
|
||||
`option_text_loc7` text,
|
||||
`option_text_loc8` text,
|
||||
`box_text_loc1` text,
|
||||
`box_text_loc2` text,
|
||||
`box_text_loc3` text,
|
||||
`box_text_loc4` text,
|
||||
`box_text_loc5` text,
|
||||
`box_text_loc6` text,
|
||||
`box_text_loc7` text,
|
||||
`box_text_loc8` text,
|
||||
PRIMARY KEY (`menu_id`, `id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `locales_gossip_menu_option`
|
||||
--
|
||||
|
||||
LOCK TABLES `locales_gossip_menu_option` WRITE;
|
||||
/*!40000 ALTER TABLE `locales_gossip_menu_option` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `locales_gossip_menu_option` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `locales_item`
|
||||
--
|
||||
|
|
@ -2379,42 +2526,6 @@ LOCK TABLES `locales_item` WRITE;
|
|||
/*!40000 ALTER TABLE `locales_item` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `locales_npc_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `locales_npc_option`;
|
||||
CREATE TABLE `locales_npc_option` (
|
||||
`entry` mediumint(8) unsigned NOT NULL default '0',
|
||||
`option_text_loc1` text,
|
||||
`option_text_loc2` text,
|
||||
`option_text_loc3` text,
|
||||
`option_text_loc4` text,
|
||||
`option_text_loc5` text,
|
||||
`option_text_loc6` text,
|
||||
`option_text_loc7` text,
|
||||
`option_text_loc8` text,
|
||||
`box_text_loc1` text,
|
||||
`box_text_loc2` text,
|
||||
`box_text_loc3` text,
|
||||
`box_text_loc4` text,
|
||||
`box_text_loc5` text,
|
||||
`box_text_loc6` text,
|
||||
`box_text_loc7` text,
|
||||
`box_text_loc8` text,
|
||||
PRIMARY KEY (`entry`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `locales_npc_option`
|
||||
--
|
||||
|
||||
LOCK TABLES `locales_npc_option` WRITE;
|
||||
/*!40000 ALTER TABLE `locales_npc_option` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `locales_npc_option` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `locales_npc_text`
|
||||
--
|
||||
|
|
@ -3446,6 +3557,7 @@ INSERT INTO `mangos_string` VALUES
|
|||
(1012,'===========================================================================',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1013,'|%15s| %20s | %15s |%4d| %9d |',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1014,'No online players.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1015,'Used not fully typed quit command, need type it fully (quit), or command used not in RA command line.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1100,'Account %s (Id: %u) have up to %u expansion allowed now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1101,'Message of the day changed to:\r\n%s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
(1102,'Message sent to %s: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
|
||||
|
|
@ -3530,54 +3642,6 @@ LOCK TABLES `npc_gossip` WRITE;
|
|||
/*!40000 ALTER TABLE `npc_gossip` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `npc_gossip_textid`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `npc_gossip_textid`;
|
||||
CREATE TABLE `npc_gossip_textid` (
|
||||
`zoneid` smallint(5) unsigned NOT NULL default '0',
|
||||
`action` smallint(5) unsigned NOT NULL default '0',
|
||||
`textid` mediumint(8) unsigned NOT NULL default '0',
|
||||
KEY `zoneid` (`zoneid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `npc_gossip_textid`
|
||||
--
|
||||
|
||||
LOCK TABLES `npc_gossip_textid` WRITE;
|
||||
/*!40000 ALTER TABLE `npc_gossip_textid` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `npc_gossip_textid` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `npc_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `npc_option`;
|
||||
CREATE TABLE `npc_option` (
|
||||
`id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`gossip_id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`npcflag` int(10) unsigned NOT NULL default '0',
|
||||
`icon` tinyint(3) unsigned NOT NULL default '0',
|
||||
`action` mediumint(8) unsigned NOT NULL default '0',
|
||||
`box_money` int(10) unsigned NOT NULL default '0',
|
||||
`coded` tinyint(3) unsigned NOT NULL default '0',
|
||||
`option_text` text,
|
||||
`box_text` text,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
--
|
||||
-- Dumping data for table `npc_option`
|
||||
--
|
||||
|
||||
LOCK TABLES `npc_option` WRITE;
|
||||
/*!40000 ALTER TABLE `npc_option` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `npc_option` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `npc_spellclick_spells`
|
||||
--
|
||||
|
|
@ -14087,7 +14151,7 @@ INSERT INTO `spell_bonus_data` VALUES
|
|||
(3606, 0.1667, 0, 0, 'Shaman - Searing Totem Attack'),
|
||||
/* Warlock */
|
||||
(17962, 0, 0, 0, 'Warlock - Conflagrate'),
|
||||
(172, 0, 0.3, 0, 'Warlock - Corruption'),
|
||||
(172, 0, 0.2, 0, 'Warlock - Corruption'),
|
||||
(980, 0, 0.1, 0, 'Warlock - Curse of Agony'),
|
||||
(603, 0, 2, 0, 'Warlock - Curse of Doom'),
|
||||
(18220, 0.96, 0, 0, 'Warlock - Dark Pact'),
|
||||
|
|
@ -15283,6 +15347,18 @@ INSERT INTO spell_chain VALUES
|
|||
(26801,12180,3908,5,0),
|
||||
(51309,26790,3908,6,0),
|
||||
/*------------------
|
||||
-- (202) Engineering
|
||||
------------------*/
|
||||
/*Engineering*/
|
||||
(4036,0,4036,1,0),
|
||||
(4037,4036,4036,2,0),
|
||||
(4038,4037,4036,3,0),
|
||||
(12656,4038,4036,4,0),
|
||||
(20219,12656,4036,5,0),
|
||||
(20222,12656,4036,5,0),
|
||||
(30350,12656,4036,5,0),
|
||||
(51306,30350,4036,6,0),
|
||||
/*------------------
|
||||
--(203)Pet-Spider
|
||||
--(208)Pet-Wolf
|
||||
--(212)Pet-Crocolisk
|
||||
|
|
@ -15304,18 +15380,6 @@ INSERT INTO spell_chain VALUES
|
|||
(52473,27050,17253,10,0),
|
||||
(52474,52473,17253,11,0),
|
||||
/*------------------
|
||||
-- (202) Engineering
|
||||
------------------*/
|
||||
/*Engineering*/
|
||||
(4036,0,4036,1,0),
|
||||
(4037,4036,4036,2,0),
|
||||
(4038,4037,4036,3,0),
|
||||
(12656,4038,4036,4,0),
|
||||
(20219,12656,4036,5,0),
|
||||
(20222,12656,4036,5,0),
|
||||
(30350,12656,4036,5,0),
|
||||
(51306,30350,4036,6,0),
|
||||
/*------------------
|
||||
-- (204) Pet - Voidwalker
|
||||
------------------*/
|
||||
/*Consume Shadows*/
|
||||
|
|
@ -15376,6 +15440,16 @@ INSERT INTO spell_chain VALUES
|
|||
(11785,11784,6360,4,0),
|
||||
(27275,11785,6360,5,0),
|
||||
/*------------------
|
||||
-- (208) Pet - Wolf
|
||||
------------------*/
|
||||
/* Furious Howl */
|
||||
(24604,0,24604,1,0),
|
||||
(64491,24604,24604,2,0),
|
||||
(64492,64491,24604,3,0),
|
||||
(64493,64492,24604,4,0),
|
||||
(64494,64493,24604,5,0),
|
||||
(64495,64494,24604,6,0),
|
||||
/*------------------
|
||||
-- (209) Pet - Cat
|
||||
------------------*/
|
||||
/*Prowl*/
|
||||
|
|
@ -17033,6 +17107,16 @@ INSERT INTO spell_chain VALUES
|
|||
(53597,53596,50274,5,0),
|
||||
(53598,53597,50274,6,0),
|
||||
/*------------------
|
||||
--(767)Pet - Ravager
|
||||
------------------*/
|
||||
/*Ravage*/
|
||||
(50518,0,50518,1,0),
|
||||
(53558,50518,50518,2,0),
|
||||
(53559,53558,50518,3,0),
|
||||
(53560,53559,50518,4,0),
|
||||
(53561,53560,50518,5,0),
|
||||
(53562,53561,50518,6,0),
|
||||
/*------------------
|
||||
--(768)Pet-Serpent
|
||||
------------------*/
|
||||
/*PoisonSpit*/
|
||||
|
|
@ -18168,6 +18252,7 @@ INSERT INTO `spell_proc_event` VALUES
|
|||
(49622, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 60),
|
||||
(49657, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(50781, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(50880, 0x00000010, 15, 0x00000000, 0x00000800, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51123, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51127, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51128, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
|
|
@ -18286,6 +18371,7 @@ INSERT INTO `spell_proc_event` VALUES
|
|||
(54936, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(54937, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(54939, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(55380, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(55440, 0x00000000, 11, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55640, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
|
|
@ -18322,6 +18408,7 @@ INSERT INTO `spell_proc_event` VALUES
|
|||
(57352, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00010154, 0x00000003, 0.000000, 0.000000, 45),
|
||||
(57470, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(57472, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(57499, 0x00000000, 4, 0x40000001, 0x00010000, 0x00000000, 0x00014000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(57878, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
|
||||
(57880, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
|
||||
(57881, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
|
||||
|
|
@ -18330,6 +18417,7 @@ INSERT INTO `spell_proc_event` VALUES
|
|||
(58364, 0x00000000, 4, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(58372, 0x00000000, 4, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(58386, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0.000000, 0.000000, 0),
|
||||
(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,0),
|
||||
(58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(58620, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(58626, 0x00000000, 15, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
|
|
@ -18386,7 +18474,7 @@ INSERT INTO `spell_proc_event` VALUES
|
|||
(63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(64976, 0x00000000, 4, 0x00000001, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(65661, 0x00000000, 15, 0x00400010, 0x20020004, 0x00000000, 0x00000010, 0x00000000, 0.000000, 100.000000,0),
|
||||
(65661, 0x00000000, 15, 0x00400011, 0x00020004, 0x00000000, 0x00000010, 0x00000001, 0.000000, 100.000000,0),
|
||||
(64127, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(67353, 0x00000000, 7, 0x00008000, 0x00100500, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
|
||||
|
||||
|
|
|
|||
5
sql/updates/8917_01_mangos_spell_proc_event.sql
Normal file
5
sql/updates/8917_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8912_01_mangos_spell_proc_event required_8917_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (65661);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(65661, 0x00000000, 15, 0x00400011, 0x00020004, 0x00000000, 0x00000010, 0x00000001, 0.000000, 100.000000,0);
|
||||
72
sql/updates/8923_01_mangos_gossip.sql
Normal file
72
sql/updates/8923_01_mangos_gossip.sql
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8917_01_mangos_spell_proc_event required_8923_01_mangos_gossip bit;
|
||||
|
||||
DROP TABLE IF EXISTS gossip_menu;
|
||||
CREATE TABLE gossip_menu (
|
||||
entry smallint(6) unsigned NOT NULL default '0',
|
||||
text_id mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_1_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_2_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (entry, text_id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
DROP TABLE IF EXISTS gossip_menu_option;
|
||||
CREATE TABLE gossip_menu_option (
|
||||
menu_id smallint(6) unsigned NOT NULL default '0',
|
||||
id smallint(6) unsigned NOT NULL default '0',
|
||||
option_icon mediumint(8) unsigned NOT NULL default '0',
|
||||
option_text text,
|
||||
option_id tinyint(3) unsigned NOT NULL default '0',
|
||||
npc_option_npcflag int(10) unsigned NOT NULL default '0',
|
||||
action_menu_id mediumint(8) unsigned NOT NULL default '0',
|
||||
action_poi_id mediumint(8) unsigned NOT NULL default '0',
|
||||
action_script_id mediumint(8) unsigned NOT NULL default '0',
|
||||
box_coded tinyint(3) unsigned NOT NULL default '0',
|
||||
box_money int(11) unsigned NOT NULL default '0',
|
||||
box_text text,
|
||||
cond_1 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_1_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_1_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_2_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_2_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_3 tinyint(3) unsigned NOT NULL default '0',
|
||||
cond_3_val_1 mediumint(8) unsigned NOT NULL default '0',
|
||||
cond_3_val_2 mediumint(8) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (menu_id, id)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
|
||||
DELETE FROM gossip_menu_option WHERE menu_id=0;
|
||||
INSERT INTO gossip_menu_option VALUES
|
||||
(0,0,0,'GOSSIP_OPTION_QUESTGIVER',2,2,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,1,1,'GOSSIP_OPTION_VENDOR',3,128,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,2,2,'GOSSIP_OPTION_TAXIVENDOR',4,8192,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,3,3,'GOSSIP_OPTION_TRAINER',5,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,4,4,'GOSSIP_OPTION_SPIRITHEALER',6,16384,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,5,4,'GOSSIP_OPTION_SPIRITGUIDE',7,32768,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,6,5,'GOSSIP_OPTION_INNKEEPER',8,65536,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,7,6,'GOSSIP_OPTION_BANKER',9,131072,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,8,7,'GOSSIP_OPTION_PETITIONER',10,262144,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,9,8,'GOSSIP_OPTION_TABARDDESIGNER',11,524288,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,10,9,'GOSSIP_OPTION_BATTLEFIELD',12,1048576,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,11,6,'GOSSIP_OPTION_AUCTIONEER',13,2097152,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,12,0,'GOSSIP_OPTION_STABLEPET',14,4194304,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,13,1,'GOSSIP_OPTION_ARMORER',15,4096,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,14,2,'GOSSIP_OPTION_UNLEARNTALENTS',16,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0),
|
||||
(0,15,2,'GOSSIP_OPTION_UNLEARNPETSKILLS',17,16,0,0,0,0,0,NULL,0,0,0,0,0,0,0,0,0);
|
||||
|
||||
ALTER TABLE creature_template ADD gossip_menu_id mediumint(8) unsigned NOT NULL default 0 AFTER IconName;
|
||||
|
||||
ALTER TABLE locales_npc_option CHANGE COLUMN entry id smallint(6) unsigned NOT NULL default '0';
|
||||
ALTER TABLE locales_npc_option ADD menu_id smallint(6) unsigned NOT NULL default '0' FIRST;
|
||||
|
||||
ALTER TABLE locales_npc_option DROP PRIMARY KEY;
|
||||
ALTER TABLE locales_npc_option ADD PRIMARY KEY (menu_id, id);
|
||||
|
||||
RENAME TABLE locales_npc_option TO locales_gossip_menu_option;
|
||||
|
||||
DROP TABLE IF EXISTS npc_option;
|
||||
DROP TABLE IF EXISTS npc_gossip_textid;
|
||||
15
sql/updates/8929_01_mangos_gossip_scripts.sql
Normal file
15
sql/updates/8929_01_mangos_gossip_scripts.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8923_01_mangos_gossip required_8929_01_mangos_gossip_scripts bit;
|
||||
|
||||
DROP TABLE IF EXISTS `gossip_scripts`;
|
||||
CREATE TABLE `gossip_scripts` (
|
||||
`id` mediumint(8) unsigned NOT NULL default '0',
|
||||
`delay` int(10) unsigned NOT NULL default '0',
|
||||
`command` mediumint(8) unsigned NOT NULL default '0',
|
||||
`datalong` mediumint(8) unsigned NOT NULL default '0',
|
||||
`datalong2` int(10) unsigned NOT NULL default '0',
|
||||
`dataint` int(11) NOT NULL default '0',
|
||||
`x` float NOT NULL default '0',
|
||||
`y` float NOT NULL default '0',
|
||||
`z` float NOT NULL default '0',
|
||||
`o` float NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
5
sql/updates/8930_01_mangos_spell_proc_event.sql
Normal file
5
sql/updates/8930_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8929_01_mangos_gossip_scripts required_8930_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (58597);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,0);
|
||||
5
sql/updates/8931_01_mangos_spell_bonus_data.sql
Normal file
5
sql/updates/8931_01_mangos_spell_bonus_data.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8930_01_mangos_spell_proc_event required_8931_01_mangos_spell_bonus_data bit;
|
||||
|
||||
DELETE FROM spell_bonus_data WHERE entry = 172;
|
||||
INSERT INTO spell_bonus_data (entry, direct_bonus, dot_bonus, ap_bonus, comments) VALUES
|
||||
(172, 0, 0.2, 0, 'Warlock - Corruption');
|
||||
10
sql/updates/8932_01_mangos_spell_chain.sql
Normal file
10
sql/updates/8932_01_mangos_spell_chain.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8931_01_mangos_spell_bonus_data required_8932_01_mangos_spell_chain bit;
|
||||
|
||||
DELETE FROM spell_chain WHERE spell_id IN (50518,53558,53559,53560,53561,53562);
|
||||
INSERT INTO spell_chain VALUES
|
||||
(50518,0,50518,1,0),
|
||||
(53558,50518,50518,2,0),
|
||||
(53559,53558,50518,3,0),
|
||||
(53560,53559,50518,4,0),
|
||||
(53561,53560,50518,5,0),
|
||||
(53562,53561,50518,6,0);
|
||||
5
sql/updates/8938_01_mangos_spell_proc_event.sql
Normal file
5
sql/updates/8938_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8932_01_mangos_spell_chain required_8938_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (50880);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(50880, 0x00000010, 15, 0x00000000, 0x00000800, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
|
||||
11
sql/updates/8943_01_mangos_spell_chain.sql
Normal file
11
sql/updates/8943_01_mangos_spell_chain.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8938_01_mangos_spell_proc_event required_8943_01_mangos_spell_chain bit;
|
||||
|
||||
DELETE FROM spell_chain WHERE spell_id IN (24604,64491,64492,64493,64494,64495);
|
||||
-- Furious Howl
|
||||
INSERT INTO spell_chain VALUES
|
||||
(24604,0,24604,1,0),
|
||||
(64491,24604,24604,2,0),
|
||||
(64492,64491,24604,3,0),
|
||||
(64493,64492,24604,4,0),
|
||||
(64494,64493,24604,5,0),
|
||||
(64495,64494,24604,6,0);
|
||||
5
sql/updates/8946_01_mangos_spell_proc_event.sql
Normal file
5
sql/updates/8946_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8943_01_mangos_spell_chain required_8946_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (57499);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(57499, 0x00000000, 4, 0x40000001, 0x00010000, 0x00000000, 0x00014000, 0x00000000, 0.000000, 0.000000,0);
|
||||
5
sql/updates/8950_01_mangos_spell_proc_event.sql
Normal file
5
sql/updates/8950_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8946_01_mangos_spell_proc_event required_8950_01_mangos_spell_proc_event bit;
|
||||
|
||||
DELETE FROM `spell_proc_event` WHERE `entry` IN (55166);
|
||||
INSERT INTO `spell_proc_event` VALUES
|
||||
(55166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000,0);
|
||||
6
sql/updates/8965_01_mangos_mangos_string.sql
Normal file
6
sql/updates/8965_01_mangos_mangos_string.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8950_01_mangos_spell_proc_event required_8965_01_mangos_mangos_string bit;
|
||||
|
||||
DELETE FROM mangos_string WHERE entry in (1015);
|
||||
|
||||
INSERT INTO mangos_string VALUES
|
||||
(1015,'Used not fully typed quit command, need type it fully (quit), or command used not in RA command line.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
6
sql/updates/8965_02_mangos_command.sql
Normal file
6
sql/updates/8965_02_mangos_command.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE db_version CHANGE COLUMN required_8965_01_mangos_mangos_string required_8965_02_mangos_command bit;
|
||||
|
||||
DELETE FROM command where name IN ('quit');
|
||||
|
||||
INSERT INTO `command` VALUES
|
||||
('quit',4,'Syntax: quit\r\n\r\nClose RA connection. Command must be typed fully (quit).');
|
||||
|
|
@ -188,6 +188,18 @@ pkgdata_DATA = \
|
|||
8908_01_mangos_spell_chain.sql \
|
||||
8909_01_mangos_spell_proc_event.sql \
|
||||
8912_01_mangos_spell_proc_event.sql \
|
||||
8917_01_mangos_spell_proc_event.sql \
|
||||
8923_01_mangos_gossip.sql \
|
||||
8929_01_mangos_gossip_scripts.sql \
|
||||
8930_01_mangos_spell_proc_event.sql \
|
||||
8931_01_mangos_spell_bonus_data.sql \
|
||||
8932_01_mangos_spell_chain.sql \
|
||||
8938_01_mangos_spell_proc_event.sql \
|
||||
8943_01_mangos_spell_chain.sql \
|
||||
8946_01_mangos_spell_proc_event.sql \
|
||||
8950_01_mangos_spell_proc_event.sql \
|
||||
8965_01_mangos_mangos_string.sql \
|
||||
8965_02_mangos_command.sql \
|
||||
README
|
||||
|
||||
## Additional files to include when running 'make dist'
|
||||
|
|
@ -356,4 +368,16 @@ EXTRA_DIST = \
|
|||
8908_01_mangos_spell_chain.sql \
|
||||
8909_01_mangos_spell_proc_event.sql \
|
||||
8912_01_mangos_spell_proc_event.sql \
|
||||
8917_01_mangos_spell_proc_event.sql \
|
||||
8923_01_mangos_gossip.sql \
|
||||
8929_01_mangos_gossip_scripts.sql \
|
||||
8930_01_mangos_spell_proc_event.sql \
|
||||
8931_01_mangos_spell_bonus_data.sql \
|
||||
8932_01_mangos_spell_chain.sql \
|
||||
8938_01_mangos_spell_proc_event.sql \
|
||||
8943_01_mangos_spell_chain.sql \
|
||||
8946_01_mangos_spell_proc_event.sql \
|
||||
8950_01_mangos_spell_proc_event.sql \
|
||||
8965_01_mangos_mangos_string.sql \
|
||||
8965_02_mangos_command.sql \
|
||||
README
|
||||
|
|
|
|||
|
|
@ -519,11 +519,13 @@ void BattleGround::SendPacketToAll(WorldPacket *packet)
|
|||
{
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
if (plr)
|
||||
plr->GetSession()->SendPacket(packet);
|
||||
else
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:SendPacketToAll: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -531,11 +533,12 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *
|
|||
{
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:SendPacketToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -563,11 +566,13 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
|
|||
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:PlaySoundToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -586,11 +591,13 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
|
|||
{
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:CastSpellOnTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -606,11 +613,13 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
|
|||
{
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:RewardHonorToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -631,11 +640,13 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
|
|||
|
||||
for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
continue;
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
sLog.outError("BattleGround:RewardReputationToTeam: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -721,10 +732,9 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
|
||||
for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
uint32 team = itr->second.Team;
|
||||
|
||||
if (!plr)
|
||||
if (itr->second.OfflineRemoveTime)
|
||||
{
|
||||
//if rated arena match - make member lost!
|
||||
if (isArena() && isRated() && winner_arena_team && loser_arena_team)
|
||||
|
|
@ -734,7 +744,12 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
else
|
||||
loser_arena_team->OfflineMemberLost(itr->first, winner_rating);
|
||||
}
|
||||
sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
Player *plr = sObjectMgr.GetPlayer(itr->first);
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGround:EndBattleGround Player (GUID: %u) not found!", GUID_LOPART(itr->first));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1285,14 +1300,13 @@ void BattleGround::EventPlayerLoggedOut(Player* player)
|
|||
m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME;
|
||||
if (GetStatus() == STATUS_IN_PROGRESS)
|
||||
{
|
||||
if (isBattleGround())
|
||||
EventPlayerDroppedFlag(player);
|
||||
else
|
||||
{
|
||||
//1 player is logging out, if it is the last, then end arena!
|
||||
// drop flag and handle other cleanups
|
||||
RemovePlayer(player, player->GetGUID());
|
||||
|
||||
// 1 player is logging out, if it is the last, then end arena!
|
||||
if (isArena())
|
||||
if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
|
||||
EndBattleGround(GetOtherTeam(player->GetTeam()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ void BattleGroundEY::CheckSomeoneJoinedPoint()
|
|||
Player *plr = sObjectMgr.GetPlayer(m_PlayersNearPoint[BG_EY_NODES_MAX][j]);
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[BG_EY_NODES_MAX][j]));
|
||||
sLog.outError("BattleGroundEY:CheckSomeoneJoinedPoint: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[BG_EY_NODES_MAX][j]));
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ void BattleGroundEY::CheckSomeoneLeftPoint()
|
|||
Player *plr = sObjectMgr.GetPlayer(m_PlayersNearPoint[i][j]);
|
||||
if (!plr)
|
||||
{
|
||||
sLog.outError("BattleGroundEY: Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j]));
|
||||
sLog.outError("BattleGroundEY:CheckSomeoneLeftPoint Player (GUID: %u) not found!", GUID_LOPART(m_PlayersNearPoint[i][j]));
|
||||
//move not existed player to "free space" - this will cause many error showing in log, but it is a very important bug
|
||||
m_PlayersNearPoint[BG_EY_NODES_MAX].push_back(m_PlayersNearPoint[i][j]);
|
||||
m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j);
|
||||
|
|
|
|||
|
|
@ -366,7 +366,8 @@ void WorldSession::HandleBattleFieldPortOpcode( WorldPacket &recv_data )
|
|||
//if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
|
||||
if (_player->getLevel() > bg->GetMaxLevel())
|
||||
{
|
||||
sLog.outError("Battleground: Player %s (%u) has level higher than maxlevel of battleground! Do not port him to battleground!", _player->GetName(), _player->GetGUIDLow());
|
||||
sLog.outError("Battleground: Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!",
|
||||
_player->GetName(), _player->GetGUIDLow(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID());
|
||||
action = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder)
|
|||
if(at)
|
||||
pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());
|
||||
else
|
||||
pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation());
|
||||
pCurrChar->TeleportToHomebind();
|
||||
}
|
||||
|
||||
sObjectAccessor.AddObject(pCurrChar);
|
||||
|
|
|
|||
|
|
@ -423,6 +423,8 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL },
|
||||
{ "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL },
|
||||
{ "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
|
||||
{ "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
|
||||
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL },
|
||||
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
|
||||
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
|
||||
{ "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },
|
||||
|
|
@ -439,7 +441,6 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL },
|
||||
{ "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
|
||||
{ "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
|
||||
{ "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL },
|
||||
{ "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL},
|
||||
{ "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL },
|
||||
{ "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL },
|
||||
|
|
@ -666,6 +667,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "flusharenapoints",SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
|
||||
{ "repairitems", SEC_GAMEMASTER, true, &ChatHandler::HandleRepairitemsCommand, "", NULL },
|
||||
{ "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL },
|
||||
{ "quit", SEC_CONSOLE, true, &ChatHandler::HandleQuitCommand, "", NULL },
|
||||
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -335,6 +335,8 @@ class ChatHandler
|
|||
bool HandleReloadGameGraveyardZoneCommand(const char* args);
|
||||
bool HandleReloadGameObjectScriptsCommand(const char* args);
|
||||
bool HandleReloadGameTeleCommand(const char* args);
|
||||
bool HandleReloadGossipMenuCommand(const char* args);
|
||||
bool HandleReloadGossipMenuOptionCommand(const char* args);
|
||||
bool HandleReloadGOQuestRelationsCommand(const char* args);
|
||||
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
|
||||
bool HandleReloadItemEnchantementsCommand(const char* args);
|
||||
|
|
@ -362,7 +364,6 @@ class ChatHandler
|
|||
bool HandleReloadMailLevelRewardCommand(const char* args);
|
||||
bool HandleReloadMangosStringCommand(const char* args);
|
||||
bool HandleReloadNpcGossipCommand(const char* args);
|
||||
bool HandleReloadNpcOptionCommand(const char* args);
|
||||
bool HandleReloadNpcTrainerCommand(const char* args);
|
||||
bool HandleReloadNpcVendorCommand(const char* args);
|
||||
bool HandleReloadPageTextsCommand(const char* args);
|
||||
|
|
@ -497,6 +498,7 @@ class ChatHandler
|
|||
bool HandleFlushArenaPointsCommand(const char *args);
|
||||
bool HandleRepairitemsCommand(const char* args);
|
||||
bool HandleWaterwalkCommand(const char* args);
|
||||
bool HandleQuitCommand(const char* args);
|
||||
|
||||
//! Development Commands
|
||||
bool HandleSaveAllCommand(const char* args);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ Unit(), i_AI(NULL),
|
|||
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
|
||||
m_lootMoney(0), m_lootRecipient(0),
|
||||
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
|
||||
m_gossipOptionLoaded(false), m_isPet(false), m_isVehicle(false), m_isTotem(false),
|
||||
m_isPet(false), m_isVehicle(false), m_isTotem(false),
|
||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0),
|
||||
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
|
||||
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
||||
|
|
@ -744,21 +744,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
|
|||
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class;
|
||||
}
|
||||
|
||||
void Creature::LoadGossipOptions()
|
||||
{
|
||||
if(m_gossipOptionLoaded)
|
||||
return;
|
||||
|
||||
uint32 npcflags=GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
|
||||
CacheNpcOptionList const& noList = sObjectMgr.GetNpcOptions ();
|
||||
for (CacheNpcOptionList::const_iterator i = noList.begin (); i != noList.end (); ++i)
|
||||
if(i->NpcFlag & npcflags)
|
||||
addGossipOption(*i);
|
||||
|
||||
m_gossipOptionLoaded = true;
|
||||
}
|
||||
|
||||
void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, MonsterMovementFlags flags, uint8 type)
|
||||
{
|
||||
/* uint32 timeElap = getMSTime();
|
||||
|
|
|
|||
|
|
@ -36,102 +36,6 @@ class Quest;
|
|||
class Player;
|
||||
class WorldSession;
|
||||
|
||||
enum Gossip_Option
|
||||
{
|
||||
GOSSIP_OPTION_NONE = 0, //UNIT_NPC_FLAG_NONE = 0,
|
||||
GOSSIP_OPTION_GOSSIP = 1, //UNIT_NPC_FLAG_GOSSIP = 1,
|
||||
GOSSIP_OPTION_QUESTGIVER = 2, //UNIT_NPC_FLAG_QUESTGIVER = 2,
|
||||
GOSSIP_OPTION_VENDOR = 3, //UNIT_NPC_FLAG_VENDOR = 4,
|
||||
GOSSIP_OPTION_TAXIVENDOR = 4, //UNIT_NPC_FLAG_TAXIVENDOR = 8,
|
||||
GOSSIP_OPTION_TRAINER = 5, //UNIT_NPC_FLAG_TRAINER = 16,
|
||||
GOSSIP_OPTION_SPIRITHEALER = 6, //UNIT_NPC_FLAG_SPIRITHEALER = 32,
|
||||
GOSSIP_OPTION_SPIRITGUIDE = 7, //UNIT_NPC_FLAG_SPIRITGUIDE = 64,
|
||||
GOSSIP_OPTION_INNKEEPER = 8, //UNIT_NPC_FLAG_INNKEEPER = 128,
|
||||
GOSSIP_OPTION_BANKER = 9, //UNIT_NPC_FLAG_BANKER = 256,
|
||||
GOSSIP_OPTION_PETITIONER = 10, //UNIT_NPC_FLAG_PETITIONER = 512,
|
||||
GOSSIP_OPTION_TABARDDESIGNER = 11, //UNIT_NPC_FLAG_TABARDDESIGNER = 1024,
|
||||
GOSSIP_OPTION_BATTLEFIELD = 12, //UNIT_NPC_FLAG_BATTLEFIELDPERSON = 2048,
|
||||
GOSSIP_OPTION_AUCTIONEER = 13, //UNIT_NPC_FLAG_AUCTIONEER = 4096,
|
||||
GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE = 8192,
|
||||
GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER = 16384,
|
||||
GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
|
||||
GOSSIP_OPTION_UNLEARNPETSKILLS = 17 //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
|
||||
};
|
||||
|
||||
enum Gossip_Guard
|
||||
{
|
||||
GOSSIP_GUARD_BANK = 32,
|
||||
GOSSIP_GUARD_RIDE = 33,
|
||||
GOSSIP_GUARD_GUILD = 34,
|
||||
GOSSIP_GUARD_INN = 35,
|
||||
GOSSIP_GUARD_MAIL = 36,
|
||||
GOSSIP_GUARD_AUCTION = 37,
|
||||
GOSSIP_GUARD_WEAPON = 38,
|
||||
GOSSIP_GUARD_STABLE = 39,
|
||||
GOSSIP_GUARD_BATTLE = 40,
|
||||
GOSSIP_GUARD_SPELLTRAINER = 41,
|
||||
GOSSIP_GUARD_SKILLTRAINER = 42
|
||||
};
|
||||
|
||||
enum Gossip_Guard_Spell
|
||||
{
|
||||
GOSSIP_GUARD_SPELL_WARRIOR = 64,
|
||||
GOSSIP_GUARD_SPELL_PALADIN = 65,
|
||||
GOSSIP_GUARD_SPELL_HUNTER = 66,
|
||||
GOSSIP_GUARD_SPELL_ROGUE = 67,
|
||||
GOSSIP_GUARD_SPELL_PRIEST = 68,
|
||||
GOSSIP_GUARD_SPELL_UNKNOWN1 = 69,
|
||||
GOSSIP_GUARD_SPELL_SHAMAN = 70,
|
||||
GOSSIP_GUARD_SPELL_MAGE = 71,
|
||||
GOSSIP_GUARD_SPELL_WARLOCK = 72,
|
||||
GOSSIP_GUARD_SPELL_UNKNOWN2 = 73,
|
||||
GOSSIP_GUARD_SPELL_DRUID = 74
|
||||
};
|
||||
|
||||
enum Gossip_Guard_Skill
|
||||
{
|
||||
GOSSIP_GUARD_SKILL_ALCHEMY = 80,
|
||||
GOSSIP_GUARD_SKILL_BLACKSMITH = 81,
|
||||
GOSSIP_GUARD_SKILL_COOKING = 82,
|
||||
GOSSIP_GUARD_SKILL_ENCHANT = 83,
|
||||
GOSSIP_GUARD_SKILL_FIRSTAID = 84,
|
||||
GOSSIP_GUARD_SKILL_FISHING = 85,
|
||||
GOSSIP_GUARD_SKILL_HERBALISM = 86,
|
||||
GOSSIP_GUARD_SKILL_LEATHER = 87,
|
||||
GOSSIP_GUARD_SKILL_MINING = 88,
|
||||
GOSSIP_GUARD_SKILL_SKINNING = 89,
|
||||
GOSSIP_GUARD_SKILL_TAILORING = 90,
|
||||
GOSSIP_GUARD_SKILL_ENGINERING = 91
|
||||
};
|
||||
|
||||
enum GossipOptionIcon
|
||||
{
|
||||
GOSSIP_ICON_CHAT = 0, //white chat bubble
|
||||
GOSSIP_ICON_VENDOR = 1, //brown bag
|
||||
GOSSIP_ICON_TAXI = 2, //flight
|
||||
GOSSIP_ICON_TRAINER = 3, //book
|
||||
GOSSIP_ICON_INTERACT_1 = 4, //interaction wheel
|
||||
GOSSIP_ICON_INTERACT_2 = 5, //interaction wheel
|
||||
GOSSIP_ICON_MONEY_BAG = 6, //brown bag with yellow dot
|
||||
GOSSIP_ICON_TALK = 7, //white chat bubble with black dots
|
||||
GOSSIP_ICON_TABARD = 8, //tabard
|
||||
GOSSIP_ICON_BATTLE = 9, //two swords
|
||||
GOSSIP_ICON_DOT = 10 //yellow dot
|
||||
};
|
||||
|
||||
struct GossipOption
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 GossipId;
|
||||
uint32 NpcFlag;
|
||||
uint32 Icon;
|
||||
uint32 Action;
|
||||
uint32 BoxMoney;
|
||||
bool Coded;
|
||||
std::string OptionText;
|
||||
std::string BoxText;
|
||||
};
|
||||
|
||||
enum CreatureFlagsExtra
|
||||
{
|
||||
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
|
||||
|
|
@ -165,6 +69,7 @@ struct CreatureInfo
|
|||
char* Name;
|
||||
char* SubName;
|
||||
char* IconName;
|
||||
uint32 GossipMenuId;
|
||||
uint32 minlevel;
|
||||
uint32 maxlevel;
|
||||
uint32 minhealth;
|
||||
|
|
@ -259,7 +164,7 @@ struct CreatureLocale
|
|||
std::vector<std::string> SubName;
|
||||
};
|
||||
|
||||
struct NpcOptionLocale
|
||||
struct GossipMenuItemsLocale
|
||||
{
|
||||
std::vector<std::string> OptionText;
|
||||
std::vector<std::string> BoxText;
|
||||
|
|
@ -449,8 +354,6 @@ struct TrainerSpellData
|
|||
void Clear() { spellList.clear(); }
|
||||
};
|
||||
|
||||
typedef std::list<GossipOption> GossipOptionList;
|
||||
|
||||
typedef std::map<uint32,time_t> CreatureSpellCooldowns;
|
||||
|
||||
// max different by z coordinate for creature aggro reaction
|
||||
|
|
@ -576,10 +479,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
std::string GetScriptName() const;
|
||||
uint32 GetScriptId() const;
|
||||
|
||||
void LoadGossipOptions();
|
||||
void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); }
|
||||
GossipOptionList &GetGossipOptionList() { return m_goptions; }
|
||||
|
||||
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
|
||||
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }
|
||||
void TextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(textId,TargetGuid,IsBossEmote); }
|
||||
|
|
@ -708,9 +607,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
|
||||
float m_respawnradius;
|
||||
|
||||
bool m_gossipOptionLoaded;
|
||||
GossipOptionList m_goptions;
|
||||
|
||||
bool m_isPet; // set only in Pet::Pet
|
||||
bool m_isVehicle; // set only in Vehicle::Vehicle
|
||||
bool m_isTotem; // set only in Totem::Totem
|
||||
|
|
|
|||
|
|
@ -327,26 +327,26 @@ enum TotemCategoryType
|
|||
// SummonProperties.dbc, col 1
|
||||
enum SummonPropGroup
|
||||
{
|
||||
SUMMON_PROP_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3
|
||||
SUMMON_PROP_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3
|
||||
SUMMON_PROP_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly
|
||||
SUMMON_PROP_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable
|
||||
SUMMON_PROP_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts
|
||||
SUMMON_PROP_GROUP_WILD = 0,
|
||||
SUMMON_PROP_GROUP_FRIENDLY = 1,
|
||||
SUMMON_PROP_GROUP_PETS = 2,
|
||||
SUMMON_PROP_GROUP_CONTROLLABLE = 3,
|
||||
SUMMON_PROP_GROUP_VEHICLE = 4
|
||||
};
|
||||
|
||||
// SummonProperties.dbc, col 3
|
||||
enum SummonPropType
|
||||
{
|
||||
SUMMON_PROP_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_OTHER = 0, // different summons, 1330 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3 "%s's Runeblade"
|
||||
SUMMON_PROP_TYPE_CONSTRUCT = 7, // summon bot/bomb, 4 spells in 3.0.3 "%s's Construct"
|
||||
SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 "%s's Opponent"
|
||||
SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 "%s's Vehicle"
|
||||
SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells
|
||||
SUMMON_PROP_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3
|
||||
};
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
|
|||
DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt);
|
||||
DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
|
||||
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
|
||||
//DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
|
||||
DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
|
||||
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
|
||||
TalentSpellPosMap sTalentSpellPosMap;
|
||||
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
|
||||
|
|
@ -206,7 +206,7 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
{
|
||||
std::string dbcPath = dataPath+"dbc/";
|
||||
|
||||
const uint32 DBCFilesCount = 80;
|
||||
const uint32 DBCFilesCount = 81;
|
||||
|
||||
barGoLink bar( DBCFilesCount );
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ void LoadDBCStores(const std::string& dataPath)
|
|||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
|
||||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
|
||||
|
||||
// create talent spells set
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore;
|
|||
extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
|
||||
extern DBCStorage <SpellEntry> sSpellStore;
|
||||
extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
|
||||
//extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
|
||||
extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
|
||||
extern DBCStorage <TalentEntry> sTalentStore;
|
||||
extern DBCStorage <TalentTabEntry> sTalentTabStore;
|
||||
extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
|
||||
|
|
|
|||
|
|
@ -1540,17 +1540,15 @@ struct StableSlotPricesEntry
|
|||
uint32 Price;
|
||||
};
|
||||
|
||||
/* unused currently
|
||||
struct SummonPropertiesEntry
|
||||
{
|
||||
uint32 Id; // 0
|
||||
uint32 Group; // 1, enum SummonPropGroup, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount?
|
||||
uint32 Group; // 1, enum SummonPropGroup
|
||||
uint32 FactionId; // 2, 14 rows > 0
|
||||
uint32 Type; // 3, enum SummonPropType
|
||||
uint32 Slot; // 4, 0-6
|
||||
uint32 Slot; // 4, if type = SUMMON_PROP_TYPE_TOTEM, its actual slot 0-6
|
||||
uint32 Flags; // 5, enum SummonPropFlags
|
||||
};
|
||||
*/
|
||||
|
||||
#define MAX_TALENT_RANK 5
|
||||
#define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ const char SpellRangefmt[]="nffffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
|||
const char SpellRuneCostfmt[]="niiii";
|
||||
const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx";
|
||||
const char StableSlotPricesfmt[] = "ni";
|
||||
//const char SummonPropertiesfmt[] = "niiiii";
|
||||
const char SummonPropertiesfmt[] = "niiiii";
|
||||
const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx";
|
||||
const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix";
|
||||
const char TaxiNodesEntryfmt[]="nifffssssssssssssssssxii";
|
||||
|
|
|
|||
|
|
@ -872,13 +872,13 @@ void GameObject::Use(Unit* user)
|
|||
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER: //2
|
||||
{
|
||||
if(user->GetTypeId()!=TYPEID_PLAYER)
|
||||
if (user->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Player* player = (Player*)user;
|
||||
|
||||
player->PrepareQuestMenu( GetGUID() );
|
||||
player->SendPreparedQuest( GetGUID() );
|
||||
player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID);
|
||||
player->SendPreparedGossip(this);
|
||||
return;
|
||||
}
|
||||
//Sitting: Wooden bench, chairs enzz
|
||||
|
|
@ -952,12 +952,17 @@ void GameObject::Use(Unit* user)
|
|||
Player* player = (Player*)user;
|
||||
|
||||
// show page
|
||||
if(info->goober.pageId)
|
||||
if (info->goober.pageId)
|
||||
{
|
||||
WorldPacket data(SMSG_GAMEOBJECT_PAGETEXT, 8);
|
||||
data << GetGUID();
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
else if (info->questgiver.gossipID)
|
||||
{
|
||||
player->PrepareGossipMenu(this, info->goober.gossipID);
|
||||
player->SendPreparedGossip(this);
|
||||
}
|
||||
|
||||
// possible quest objective for active quests
|
||||
player->CastedCreatureOrGO(info->id, GetGUID(), 0);
|
||||
|
|
|
|||
|
|
@ -489,6 +489,16 @@ struct GameObjectInfo
|
|||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetGossipMenuId() const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.gossipID;
|
||||
case GAMEOBJECT_TYPE_GOOBER: return goober.gossipID;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
GossipMenu::GossipMenu()
|
||||
{
|
||||
m_gItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use
|
||||
m_gMenuId = 0;
|
||||
}
|
||||
|
||||
GossipMenu::~GossipMenu()
|
||||
|
|
@ -44,13 +45,24 @@ void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSe
|
|||
gItem.m_gMessage = Message;
|
||||
gItem.m_gCoded = Coded;
|
||||
gItem.m_gSender = dtSender;
|
||||
gItem.m_gAction = dtAction;
|
||||
gItem.m_gOptionId = dtAction;
|
||||
gItem.m_gBoxMessage = BoxMessage;
|
||||
gItem.m_gBoxMoney = BoxMoney;
|
||||
|
||||
m_gItems.push_back(gItem);
|
||||
}
|
||||
|
||||
void GossipMenu::AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script)
|
||||
{
|
||||
GossipMenuItemData pItemData;
|
||||
|
||||
pItemData.m_gAction_menu = action_menu;
|
||||
pItemData.m_gAction_poi = action_poi;
|
||||
pItemData.m_gAction_script = action_script;
|
||||
|
||||
m_gItemsData.push_back(pItemData);
|
||||
}
|
||||
|
||||
void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded)
|
||||
{
|
||||
AddMenuItem( Icon, Message, 0, 0, "", 0, Coded);
|
||||
|
|
@ -77,7 +89,7 @@ uint32 GossipMenu::MenuItemAction( unsigned int ItemId )
|
|||
{
|
||||
if ( ItemId >= m_gItems.size() ) return 0;
|
||||
|
||||
return m_gItems[ ItemId ].m_gAction;
|
||||
return m_gItems[ ItemId ].m_gOptionId;
|
||||
}
|
||||
|
||||
bool GossipMenu::MenuItemCoded( unsigned int ItemId )
|
||||
|
|
@ -90,6 +102,8 @@ bool GossipMenu::MenuItemCoded( unsigned int ItemId )
|
|||
void GossipMenu::ClearMenu()
|
||||
{
|
||||
m_gItems.clear();
|
||||
m_gItemsData.clear();
|
||||
m_gMenuId = 0;
|
||||
}
|
||||
|
||||
PlayerMenu::PlayerMenu( WorldSession *session ) : pSession(session)
|
||||
|
|
@ -122,13 +136,13 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection )
|
|||
return mGossipMenu.MenuItemCoded( Selection );
|
||||
}
|
||||
|
||||
void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID )
|
||||
void PlayerMenu::SendGossipMenu(uint32 TitleTextId, uint64 objectGUID)
|
||||
{
|
||||
WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size
|
||||
data << uint64(npcGUID);
|
||||
data << uint32(0); // new 2.4.0
|
||||
data << uint32( TitleTextId );
|
||||
data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x10
|
||||
WorldPacket data(SMSG_GOSSIP_MESSAGE, (100)); // guess size
|
||||
data << uint64(objectGUID);
|
||||
data << uint32(mGossipMenu.GetMenuId()); // new 2.4.0
|
||||
data << uint32(TitleTextId);
|
||||
data << uint32(mGossipMenu.MenuItemCount()); // max count 0x10
|
||||
|
||||
for (uint32 iI = 0; iI < mGossipMenu.MenuItemCount(); ++iI )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,45 @@ class WorldSession;
|
|||
#define GOSSIP_MAX_MENU_ITEMS 64 // client supported items unknown, but provided number must be enough
|
||||
#define DEFAULT_GOSSIP_MESSAGE 0xffffff
|
||||
|
||||
enum Gossip_Option
|
||||
{
|
||||
GOSSIP_OPTION_NONE = 0, //UNIT_NPC_FLAG_NONE (0)
|
||||
GOSSIP_OPTION_GOSSIP = 1, //UNIT_NPC_FLAG_GOSSIP (1)
|
||||
GOSSIP_OPTION_QUESTGIVER = 2, //UNIT_NPC_FLAG_QUESTGIVER (2)
|
||||
GOSSIP_OPTION_VENDOR = 3, //UNIT_NPC_FLAG_VENDOR (128)
|
||||
GOSSIP_OPTION_TAXIVENDOR = 4, //UNIT_NPC_FLAG_TAXIVENDOR (8192)
|
||||
GOSSIP_OPTION_TRAINER = 5, //UNIT_NPC_FLAG_TRAINER (16)
|
||||
GOSSIP_OPTION_SPIRITHEALER = 6, //UNIT_NPC_FLAG_SPIRITHEALER (16384)
|
||||
GOSSIP_OPTION_SPIRITGUIDE = 7, //UNIT_NPC_FLAG_SPIRITGUIDE (32768)
|
||||
GOSSIP_OPTION_INNKEEPER = 8, //UNIT_NPC_FLAG_INNKEEPER (65536)
|
||||
GOSSIP_OPTION_BANKER = 9, //UNIT_NPC_FLAG_BANKER (131072)
|
||||
GOSSIP_OPTION_PETITIONER = 10, //UNIT_NPC_FLAG_PETITIONER (262144)
|
||||
GOSSIP_OPTION_TABARDDESIGNER = 11, //UNIT_NPC_FLAG_TABARDDESIGNER (524288)
|
||||
GOSSIP_OPTION_BATTLEFIELD = 12, //UNIT_NPC_FLAG_BATTLEFIELDPERSON (1048576)
|
||||
GOSSIP_OPTION_AUCTIONEER = 13, //UNIT_NPC_FLAG_AUCTIONEER (2097152)
|
||||
GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE (4194304)
|
||||
GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER (4096)
|
||||
GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (16) (bonus option for GOSSIP_OPTION_TRAINER)
|
||||
GOSSIP_OPTION_UNLEARNPETSKILLS = 17, //UNIT_NPC_FLAG_TRAINER (16) (bonus option for GOSSIP_OPTION_TRAINER)
|
||||
GOSSIP_OPTION_MAX
|
||||
};
|
||||
|
||||
enum GossipOptionIcon
|
||||
{
|
||||
GOSSIP_ICON_CHAT = 0, //white chat bubble
|
||||
GOSSIP_ICON_VENDOR = 1, //brown bag
|
||||
GOSSIP_ICON_TAXI = 2, //flight
|
||||
GOSSIP_ICON_TRAINER = 3, //book
|
||||
GOSSIP_ICON_INTERACT_1 = 4, //interaction wheel
|
||||
GOSSIP_ICON_INTERACT_2 = 5, //interaction wheel
|
||||
GOSSIP_ICON_MONEY_BAG = 6, //brown bag with yellow dot
|
||||
GOSSIP_ICON_TALK = 7, //white chat bubble with black dots
|
||||
GOSSIP_ICON_TABARD = 8, //tabard
|
||||
GOSSIP_ICON_BATTLE = 9, //two swords
|
||||
GOSSIP_ICON_DOT = 10, //yellow dot
|
||||
GOSSIP_ICON_MAX
|
||||
};
|
||||
|
||||
//POI icons. Many more exist, list not complete.
|
||||
enum Poi_Icon
|
||||
{
|
||||
|
|
@ -80,13 +119,22 @@ struct GossipMenuItem
|
|||
bool m_gCoded;
|
||||
std::string m_gMessage;
|
||||
uint32 m_gSender;
|
||||
uint32 m_gAction;
|
||||
uint32 m_gOptionId;
|
||||
std::string m_gBoxMessage;
|
||||
uint32 m_gBoxMoney;
|
||||
};
|
||||
|
||||
typedef std::vector<GossipMenuItem> GossipMenuItemList;
|
||||
|
||||
struct GossipMenuItemData
|
||||
{
|
||||
uint32 m_gAction_menu;
|
||||
uint32 m_gAction_poi;
|
||||
uint32 m_gAction_script;
|
||||
};
|
||||
|
||||
typedef std::vector<GossipMenuItemData> GossipMenuItemDataList;
|
||||
|
||||
struct QuestMenuItem
|
||||
{
|
||||
uint32 m_qId;
|
||||
|
|
@ -108,6 +156,11 @@ class MANGOS_DLL_SPEC GossipMenu
|
|||
void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false);
|
||||
void AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false);
|
||||
|
||||
void SetMenuId(uint32 menu_id) { m_gMenuId = menu_id; }
|
||||
uint32 GetMenuId() { return m_gMenuId; }
|
||||
|
||||
void AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script);
|
||||
|
||||
unsigned int MenuItemCount() const
|
||||
{
|
||||
return m_gItems.size();
|
||||
|
|
@ -123,6 +176,11 @@ class MANGOS_DLL_SPEC GossipMenu
|
|||
return m_gItems[ Id ];
|
||||
}
|
||||
|
||||
GossipMenuItemData const& GetItemData(unsigned int indexId)
|
||||
{
|
||||
return m_gItemsData[indexId];
|
||||
}
|
||||
|
||||
uint32 MenuItemSender( unsigned int ItemId );
|
||||
uint32 MenuItemAction( unsigned int ItemId );
|
||||
bool MenuItemCoded( unsigned int ItemId );
|
||||
|
|
@ -130,7 +188,10 @@ class MANGOS_DLL_SPEC GossipMenu
|
|||
void ClearMenu();
|
||||
|
||||
protected:
|
||||
GossipMenuItemList m_gItems;
|
||||
GossipMenuItemList m_gItems;
|
||||
GossipMenuItemDataList m_gItemsData;
|
||||
|
||||
uint32 m_gMenuId;
|
||||
};
|
||||
|
||||
class QuestMenu
|
||||
|
|
|
|||
|
|
@ -780,7 +780,8 @@ enum MangosStrings
|
|||
LANG_ACCOUNT_LIST_BAR = 1012,
|
||||
LANG_ACCOUNT_LIST_LINE = 1013,
|
||||
LANG_ACCOUNT_LIST_EMPTY = 1014,
|
||||
// Room for more level 4 1015-1099 not used
|
||||
LANG_QUIT_WRONG_USE_ERROR = 1015,
|
||||
// Room for more level 4 1016-1099 not used
|
||||
|
||||
// Level 3 (continue)
|
||||
LANG_ACCOUNT_SETADDON = 1100,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ bool ChatHandler::HandleReloadAllLootCommand(const char*)
|
|||
bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/)
|
||||
{
|
||||
HandleReloadNpcGossipCommand("a");
|
||||
HandleReloadNpcOptionCommand("a");
|
||||
HandleReloadNpcTrainerCommand("a");
|
||||
HandleReloadNpcVendorCommand("a");
|
||||
HandleReloadPointsOfInterestCommand("a");
|
||||
|
|
@ -252,6 +251,22 @@ bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadGossipMenuCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading `gossip_menu` Table!" );
|
||||
sObjectMgr.LoadGossipMenu();
|
||||
SendGlobalSysMessage("DB table `gossip_menu` reloaded.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading `gossip_menu_option` Table!" );
|
||||
sObjectMgr.LoadGossipMenuItems();
|
||||
SendGlobalSysMessage("DB table `gossip_menu_option` reloaded.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Loading Quests Relations... (`gameobject_questrelation`)" );
|
||||
|
|
@ -404,14 +419,6 @@ bool ChatHandler::HandleReloadMangosStringCommand(const char*)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadNpcOptionCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading `npc_option` Table!" );
|
||||
sObjectMgr.LoadNpcOptions();
|
||||
SendGlobalSysMessage("DB table `npc_option` reloaded.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadNpcGossipCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading `npc_gossip` Table!" );
|
||||
|
|
|
|||
|
|
@ -2617,7 +2617,7 @@ void InstanceMap::UnloadAll(bool pForce)
|
|||
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
|
||||
{
|
||||
Player* plr = itr->getSource();
|
||||
plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation());
|
||||
plr->TeleportToHomebind();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,12 +50,12 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
// possible errors in the coordinate validity check
|
||||
if(!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation))
|
||||
{
|
||||
sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player got's teleported far to a not valid location. (map:%u, x:%f, y:%f, z:%f) We log him out and don't save him..", loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z);
|
||||
// stop teleportation else we would try this again in the beginning of WorldSession::LogoutPlayer...
|
||||
sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player %s (%d) was teleported far to a not valid location. (map:%u, x:%f, y:%f, "
|
||||
"z:%f) We port him to his homebind instead..", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z);
|
||||
// stop teleportation else we would try this again and again in LogoutPlayer...
|
||||
GetPlayer()->SetSemaphoreTeleportFar(false);
|
||||
// player don't gets saved - so his coords will stay at the point where
|
||||
// he was last saved
|
||||
LogoutPlayer(false);
|
||||
// and teleport the player to a valid place
|
||||
GetPlayer()->TeleportToHomebind();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -81,14 +81,10 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
//if player wasn't added to map, reset his map pointer!
|
||||
GetPlayer()->ResetMap();
|
||||
|
||||
sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
|
||||
sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player %s (%d) was teleported far but couldn't be added to map. (map:%u, x:%f, y:%f, "
|
||||
"z:%f) We port him to his homebind instead..", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z);
|
||||
// teleport the player home
|
||||
if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()))
|
||||
{
|
||||
// the player must always be able to teleport home
|
||||
sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d, %f, %f, %f, %f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
|
||||
assert(false);
|
||||
}
|
||||
GetPlayer()->TeleportToHomebind();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +238,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
ReadMovementInfo(recv_data, &movementInfo);
|
||||
/*----------------*/
|
||||
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
if (!MaNGOS::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o))
|
||||
{
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data)
|
|||
if (!Script->GossipHello(_player, pCreature))
|
||||
{
|
||||
_player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
|
||||
_player->PrepareGossipMenu(pCreature);
|
||||
_player->PrepareGossipMenu(pCreature, pCreature->GetCreatureInfo()->GossipMenuId);
|
||||
_player->SendPreparedGossip(pCreature);
|
||||
}
|
||||
}
|
||||
|
|
@ -286,41 +286,58 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
|
|||
{
|
||||
sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
|
||||
|
||||
uint32 option;
|
||||
uint32 gossipListId;
|
||||
uint32 menuId;
|
||||
uint64 guid;
|
||||
std::string code = "";
|
||||
|
||||
recv_data >> guid >> menuId >> option;
|
||||
recv_data >> guid >> menuId >> gossipListId;
|
||||
|
||||
if (_player->PlayerTalkClass->GossipOptionCoded(option))
|
||||
if (_player->PlayerTalkClass->GossipOptionCoded(gossipListId))
|
||||
{
|
||||
sLog.outBasic("reading string");
|
||||
recv_data >> code;
|
||||
sLog.outBasic("string read: %s", code.c_str());
|
||||
}
|
||||
|
||||
Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
|
||||
return;
|
||||
}
|
||||
|
||||
// remove fake death
|
||||
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
||||
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
if (!code.empty())
|
||||
// TODO: determine if scriptCall is needed for GO and also if scriptCall can be same as current, with modified argument WorldObject*
|
||||
|
||||
if (IS_CREATURE_GUID(guid))
|
||||
{
|
||||
if (!Script->GossipSelectWithCode(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str()))
|
||||
_player->OnGossipSelect(pCreature, option);
|
||||
Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - Creature (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!code.empty())
|
||||
{
|
||||
if (!Script->GossipSelectWithCode(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str()))
|
||||
_player->OnGossipSelect(pCreature, gossipListId, menuId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Script->GossipSelect(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId)))
|
||||
_player->OnGossipSelect(pCreature, gossipListId, menuId);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (IS_GAMEOBJECT_GUID(guid))
|
||||
{
|
||||
if (!Script->GossipSelect(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option)))
|
||||
_player->OnGossipSelect(pCreature, option);
|
||||
GameObject *pGo = GetPlayer()->GetGameObjectIfCanInteractWith(guid);
|
||||
|
||||
if (!pGo)
|
||||
{
|
||||
sLog.outDebug("WORLD: HandleGossipSelectOptionOpcode - GameObject (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)));
|
||||
return;
|
||||
}
|
||||
|
||||
_player->OnGossipSelect(pGo, gossipListId, menuId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,13 +427,7 @@ void WorldSession::SendBindPoint(Creature *npc)
|
|||
uint32 bindspell = 3286;
|
||||
uint32 zone_id = _player->GetZoneId();
|
||||
|
||||
// update sql homebind
|
||||
CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), zone_id, _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
|
||||
_player->m_homebindMapId = _player->GetMapId();
|
||||
_player->m_homebindZoneId = zone_id;
|
||||
_player->m_homebindX = _player->GetPositionX();
|
||||
_player->m_homebindY = _player->GetPositionY();
|
||||
_player->m_homebindZ = _player->GetPositionZ();
|
||||
_player->SetHomebindToCurrentPos();
|
||||
|
||||
// send spell for bind 3286 bind magic
|
||||
npc->CastSpell(_player, bindspell, true);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "SpellAuras.h"
|
||||
#include "Util.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "GossipDef.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(ObjectMgr);
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ ScriptMapMap sQuestStartScripts;
|
|||
ScriptMapMap sSpellScripts;
|
||||
ScriptMapMap sGameObjectScripts;
|
||||
ScriptMapMap sEventScripts;
|
||||
ScriptMapMap sGossipScripts;
|
||||
|
||||
bool normalizePlayerName(std::string& name)
|
||||
{
|
||||
|
|
@ -338,16 +340,16 @@ void ObjectMgr::LoadCreatureLocales()
|
|||
sLog.outString( ">> Loaded %lu creature locale strings", (unsigned long)mCreatureLocaleMap.size() );
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadNpcOptionLocales()
|
||||
void ObjectMgr::LoadGossipMenuItemsLocales()
|
||||
{
|
||||
mNpcOptionLocaleMap.clear(); // need for reload case
|
||||
mGossipMenuItemsLocaleMap.clear(); // need for reload case
|
||||
|
||||
QueryResult *result = WorldDatabase.Query("SELECT entry,"
|
||||
QueryResult *result = WorldDatabase.Query("SELECT menu_id,id,"
|
||||
"option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2,"
|
||||
"option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4,"
|
||||
"option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6,"
|
||||
"option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 "
|
||||
"FROM locales_npc_option");
|
||||
"FROM locales_gossip_menu_option");
|
||||
|
||||
if(!result)
|
||||
{
|
||||
|
|
@ -356,7 +358,7 @@ void ObjectMgr::LoadNpcOptionLocales()
|
|||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded 0 npc_option locale strings. DB table `locales_npc_option` is empty.");
|
||||
sLog.outString(">> Loaded 0 gossip_menu_option locale strings. DB table `locales_gossip_menu_option` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -367,13 +369,14 @@ void ObjectMgr::LoadNpcOptionLocales()
|
|||
Field *fields = result->Fetch();
|
||||
bar.step();
|
||||
|
||||
uint32 entry = fields[0].GetUInt32();
|
||||
uint16 menuId = fields[0].GetUInt16();
|
||||
uint16 id = fields[1].GetUInt16();
|
||||
|
||||
NpcOptionLocale& data = mNpcOptionLocaleMap[entry];
|
||||
GossipMenuItemsLocale& data = mGossipMenuItemsLocaleMap[MAKE_PAIR32(menuId,id)];
|
||||
|
||||
for(int i = 1; i < MAX_LOCALE; ++i)
|
||||
{
|
||||
std::string str = fields[1+2*(i-1)].GetCppString();
|
||||
std::string str = fields[2+2*(i-1)].GetCppString();
|
||||
if(!str.empty())
|
||||
{
|
||||
int idx = GetOrNewIndexForLocale(LocaleConstant(i));
|
||||
|
|
@ -385,7 +388,7 @@ void ObjectMgr::LoadNpcOptionLocales()
|
|||
data.OptionText[idx] = str;
|
||||
}
|
||||
}
|
||||
str = fields[1+2*(i-1)+1].GetCppString();
|
||||
str = fields[2+2*(i-1)+1].GetCppString();
|
||||
if(!str.empty())
|
||||
{
|
||||
int idx = GetOrNewIndexForLocale(LocaleConstant(i));
|
||||
|
|
@ -403,7 +406,7 @@ void ObjectMgr::LoadNpcOptionLocales()
|
|||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %lu npc_option locale strings", (unsigned long)mNpcOptionLocaleMap.size() );
|
||||
sLog.outString( ">> Loaded %lu gossip_menu_option locale strings", (unsigned long)mGossipMenuItemsLocaleMap.size() );
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadPointOfInterestLocales()
|
||||
|
|
@ -4441,6 +4444,13 @@ void ObjectMgr::LoadEventScripts()
|
|||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadGossipScripts()
|
||||
{
|
||||
LoadScripts(sGossipScripts, "gossip_scripts");
|
||||
|
||||
// checks are done in LoadGossipMenuItems
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadItemTexts()
|
||||
{
|
||||
QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text");
|
||||
|
|
@ -7296,6 +7306,15 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
return !player->HasAura(value1, value2);
|
||||
case CONDITION_ACTIVE_EVENT:
|
||||
return sGameEventMgr.IsActiveEvent(value1);
|
||||
case CONDITION_AREA_FLAG:
|
||||
{
|
||||
if (AreaTableEntry const *pAreaEntry = GetAreaEntryByAreaID(player->GetAreaId()))
|
||||
{
|
||||
if ((!value1 || (pAreaEntry->flags & value1)) && (!value2 || !(pAreaEntry->flags & value2)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7440,6 +7459,15 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_AREA_FLAG:
|
||||
{
|
||||
if (!value1 && !value2)
|
||||
{
|
||||
sLog.outErrorDb("Area flag condition has both values like 0, skipped");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_NONE:
|
||||
break;
|
||||
}
|
||||
|
|
@ -7887,23 +7915,21 @@ void ObjectMgr::LoadNpcTextId()
|
|||
sLog.outString( ">> Loaded %d NpcTextId ", count );
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadNpcOptions()
|
||||
void ObjectMgr::LoadGossipMenu()
|
||||
{
|
||||
m_mCacheNpcOptionList.clear(); // For reload case
|
||||
m_mGossipMenusMap.clear();
|
||||
|
||||
QueryResult *result = WorldDatabase.Query(
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
"SELECT id,gossip_id,npcflag,icon,action,box_money,coded,option_text,box_text "
|
||||
"FROM npc_option");
|
||||
QueryResult* result = WorldDatabase.Query("SELECT entry, text_id, "
|
||||
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2 FROM gossip_menu");
|
||||
|
||||
if( !result )
|
||||
if (!result)
|
||||
{
|
||||
barGoLink bar( 1 );
|
||||
barGoLink bar(1);
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outErrorDb(">> Loaded `npc_option`, table is empty!");
|
||||
sLog.outErrorDb(">> Loaded gossip_menu, table is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -7917,26 +7943,186 @@ void ObjectMgr::LoadNpcOptions()
|
|||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
GossipOption go;
|
||||
go.Id = fields[0].GetUInt32();
|
||||
go.GossipId = fields[1].GetUInt32();
|
||||
go.NpcFlag = fields[2].GetUInt32();
|
||||
go.Icon = fields[3].GetUInt32();
|
||||
go.Action = fields[4].GetUInt32();
|
||||
go.BoxMoney = fields[5].GetUInt32();
|
||||
go.Coded = fields[6].GetUInt8()!=0;
|
||||
go.OptionText = fields[7].GetCppString();
|
||||
go.BoxText = fields[8].GetCppString();
|
||||
GossipMenus gMenu;
|
||||
|
||||
m_mCacheNpcOptionList.push_back(go);
|
||||
gMenu.entry = fields[0].GetUInt32();
|
||||
gMenu.text_id = fields[1].GetUInt32();
|
||||
|
||||
ConditionType cond_1 = (ConditionType)fields[2].GetUInt32();
|
||||
uint32 cond_1_val_1 = fields[3].GetUInt32();
|
||||
uint32 cond_1_val_2 = fields[4].GetUInt32();
|
||||
ConditionType cond_2 = (ConditionType)fields[5].GetUInt32();
|
||||
uint32 cond_2_val_1 = fields[6].GetUInt32();
|
||||
uint32 cond_2_val_2 = fields[7].GetUInt32();
|
||||
|
||||
if (!GetGossipText(gMenu.text_id))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u are using non-existing text_id %u", gMenu.entry, gMenu.text_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 1 for id %u", gMenu.entry, gMenu.text_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 2 for id %u", gMenu.entry, gMenu.text_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
gMenu.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
|
||||
gMenu.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
|
||||
|
||||
m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu));
|
||||
|
||||
++count;
|
||||
}
|
||||
while(result->NextRow());
|
||||
|
||||
} while (result->NextRow());
|
||||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %d npc_option entries", count );
|
||||
sLog.outString( ">> Loaded %u gossip_menu entries", count);
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadGossipMenuItems()
|
||||
{
|
||||
m_mGossipMenuItemsMap.clear();
|
||||
|
||||
QueryResult *result = WorldDatabase.Query(
|
||||
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
|
||||
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
|
||||
"cond_1, cond_1_val_1, cond_1_val_2, "
|
||||
"cond_2, cond_2_val_1, cond_2_val_2, "
|
||||
"cond_3, cond_3_val_1, cond_3_val_2 "
|
||||
"FROM gossip_menu_option");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
barGoLink bar(1);
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outErrorDb(">> Loaded gossip_menu_option, table is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
barGoLink bar(result->GetRowCount());
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
std::set<uint32> gossipScriptSet;
|
||||
|
||||
for(ScriptMapMap::const_iterator itr = sGossipScripts.begin(); itr != sGossipScripts.end(); ++itr)
|
||||
gossipScriptSet.insert(itr->first);
|
||||
|
||||
do
|
||||
{
|
||||
bar.step();
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
GossipMenuItems gMenuItem;
|
||||
|
||||
gMenuItem.menu_id = fields[0].GetUInt32();
|
||||
gMenuItem.id = fields[1].GetUInt32();
|
||||
gMenuItem.option_icon = fields[2].GetUInt8();
|
||||
gMenuItem.option_text = fields[3].GetCppString();
|
||||
gMenuItem.option_id = fields[4].GetUInt32();
|
||||
gMenuItem.npc_option_npcflag = fields[5].GetUInt32();
|
||||
gMenuItem.action_menu_id = fields[6].GetUInt32();
|
||||
gMenuItem.action_poi_id = fields[7].GetUInt32();
|
||||
gMenuItem.action_script_id = fields[8].GetUInt32();
|
||||
gMenuItem.box_coded = fields[9].GetUInt8() != 0;
|
||||
gMenuItem.box_money = fields[10].GetUInt32();
|
||||
gMenuItem.box_text = fields[11].GetCppString();
|
||||
|
||||
ConditionType cond_1 = (ConditionType)fields[12].GetUInt32();
|
||||
uint32 cond_1_val_1 = fields[13].GetUInt32();
|
||||
uint32 cond_1_val_2 = fields[14].GetUInt32();
|
||||
ConditionType cond_2 = (ConditionType)fields[15].GetUInt32();
|
||||
uint32 cond_2_val_1 = fields[16].GetUInt32();
|
||||
uint32 cond_2_val_2 = fields[17].GetUInt32();
|
||||
ConditionType cond_3 = (ConditionType)fields[18].GetUInt32();
|
||||
uint32 cond_3_val_1 = fields[19].GetUInt32();
|
||||
uint32 cond_3_val_2 = fields[20].GetUInt32();
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 1 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
}
|
||||
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 2 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
}
|
||||
if (!PlayerCondition::IsValid(cond_3, cond_3_val_1, cond_3_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 3 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gMenuItem.option_icon >= GOSSIP_ICON_MAX)
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_icon);
|
||||
gMenuItem.option_icon = GOSSIP_ICON_CHAT;
|
||||
}
|
||||
|
||||
if (gMenuItem.option_id == GOSSIP_OPTION_NONE)
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u use option id GOSSIP_OPTION_NONE. Option will never be used", gMenuItem.menu_id, gMenuItem.id);
|
||||
|
||||
if (gMenuItem.option_id >= GOSSIP_OPTION_MAX)
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_id);
|
||||
|
||||
if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_poi_id);
|
||||
gMenuItem.action_poi_id = 0;
|
||||
}
|
||||
|
||||
if (gMenuItem.action_script_id)
|
||||
{
|
||||
if (gMenuItem.option_id != GOSSIP_OPTION_GOSSIP)
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u but option_id is not GOSSIP_OPTION_GOSSIP, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sGossipScripts.find(gMenuItem.action_script_id) == sGossipScripts.end())
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `gossip_scripts`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
gossipScriptSet.erase(gMenuItem.action_script_id);
|
||||
}
|
||||
|
||||
gMenuItem.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
|
||||
gMenuItem.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
|
||||
gMenuItem.cond_3 = GetConditionId(cond_3, cond_3_val_1, cond_3_val_2);
|
||||
|
||||
m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem));
|
||||
|
||||
++count;
|
||||
|
||||
}
|
||||
while(result->NextRow());
|
||||
|
||||
delete result;
|
||||
|
||||
if (!gossipScriptSet.empty())
|
||||
{
|
||||
for(std::set<uint32>::const_iterator itr = gossipScriptSet.begin(); itr != gossipScriptSet.end(); ++itr)
|
||||
sLog.outErrorDb("Table `gossip_scripts` contain unused script, id %u.", *itr);
|
||||
}
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u gossip_menu_option entries", count);
|
||||
}
|
||||
|
||||
void ObjectMgr::AddVendorItem( uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 extendedcost )
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ extern ScriptMapMap sQuestStartScripts;
|
|||
extern ScriptMapMap sSpellScripts;
|
||||
extern ScriptMapMap sGameObjectScripts;
|
||||
extern ScriptMapMap sEventScripts;
|
||||
extern ScriptMapMap sGossipScripts;
|
||||
|
||||
struct SpellClickInfo
|
||||
{
|
||||
|
|
@ -162,7 +163,7 @@ typedef UNORDERED_MAP<uint32,QuestLocale> QuestLocaleMap;
|
|||
typedef UNORDERED_MAP<uint32,NpcTextLocale> NpcTextLocaleMap;
|
||||
typedef UNORDERED_MAP<uint32,PageTextLocale> PageTextLocaleMap;
|
||||
typedef UNORDERED_MAP<int32,MangosStringLocale> MangosStringLocaleMap;
|
||||
typedef UNORDERED_MAP<uint32,NpcOptionLocale> NpcOptionLocaleMap;
|
||||
typedef UNORDERED_MAP<uint32,GossipMenuItemsLocale> GossipMenuItemsLocaleMap;
|
||||
typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap;
|
||||
|
||||
typedef std::multimap<uint32,uint32> QuestRelations;
|
||||
|
|
@ -216,6 +217,38 @@ struct PointOfInterest
|
|||
std::string icon_name;
|
||||
};
|
||||
|
||||
struct GossipMenuItems
|
||||
{
|
||||
uint32 menu_id;
|
||||
uint32 id;
|
||||
uint8 option_icon;
|
||||
std::string option_text;
|
||||
uint32 option_id;
|
||||
uint32 npc_option_npcflag;
|
||||
uint32 action_menu_id;
|
||||
uint32 action_poi_id;
|
||||
uint32 action_script_id;
|
||||
bool box_coded;
|
||||
uint32 box_money;
|
||||
std::string box_text;
|
||||
uint16 cond_1;
|
||||
uint16 cond_2;
|
||||
uint16 cond_3;
|
||||
};
|
||||
|
||||
struct GossipMenus
|
||||
{
|
||||
uint32 entry;
|
||||
uint32 text_id;
|
||||
uint16 cond_1;
|
||||
uint16 cond_2;
|
||||
};
|
||||
|
||||
typedef std::multimap<uint32,GossipMenus> GossipMenusMap;
|
||||
typedef std::pair<GossipMenusMap::const_iterator, GossipMenusMap::const_iterator> GossipMenusMapBounds;
|
||||
typedef std::multimap<uint32,GossipMenuItems> GossipMenuItemsMap;
|
||||
typedef std::pair<GossipMenuItemsMap::const_iterator, GossipMenuItemsMap::const_iterator> GossipMenuItemsMapBounds;
|
||||
|
||||
struct QuestPOIPoint
|
||||
{
|
||||
int32 x;
|
||||
|
|
@ -223,6 +256,16 @@ struct QuestPOIPoint
|
|||
|
||||
QuestPOIPoint() : x(0), y(0) {}
|
||||
QuestPOIPoint(int32 _x, int32 _y) : x(_x), y(_y) {}
|
||||
uint32 npc_option_npcflag;
|
||||
uint32 action_menu_id;
|
||||
uint32 action_poi_id;
|
||||
uint32 action_script_id;
|
||||
bool box_coded;
|
||||
uint32 box_money;
|
||||
std::string box_text;
|
||||
uint16 cond_1;
|
||||
uint16 cond_2;
|
||||
uint16 cond_3;
|
||||
};
|
||||
|
||||
struct QuestPOI
|
||||
|
|
@ -277,9 +320,10 @@ enum ConditionType
|
|||
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD commission aura active
|
||||
CONDITION_NO_AURA = 11, // spell_id effindex
|
||||
CONDITION_ACTIVE_EVENT = 12, // event_id
|
||||
CONDITION_AREA_FLAG = 13 // area_flag area_flag_not
|
||||
};
|
||||
|
||||
#define MAX_CONDITION 13 // maximum value in ConditionType enum
|
||||
#define MAX_CONDITION 14 // maximum value in ConditionType enum
|
||||
|
||||
struct PlayerCondition
|
||||
{
|
||||
|
|
@ -301,7 +345,6 @@ struct PlayerCondition
|
|||
|
||||
// NPC gossip text id
|
||||
typedef UNORDERED_MAP<uint32, uint32> CacheNpcTextIdMap;
|
||||
typedef std::list<GossipOption> CacheNpcOptionList;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
|
||||
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
|
||||
|
|
@ -539,6 +582,7 @@ class ObjectMgr
|
|||
void LoadQuestStartScripts();
|
||||
void LoadEventScripts();
|
||||
void LoadSpellScripts();
|
||||
void LoadGossipScripts();
|
||||
|
||||
bool LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value);
|
||||
bool LoadMangosStrings() { return LoadMangosStrings(WorldDatabase,"mangos_string",MIN_MANGOS_STRING_ID,MAX_MANGOS_STRING_ID); }
|
||||
|
|
@ -559,7 +603,7 @@ class ObjectMgr
|
|||
void LoadQuestLocales();
|
||||
void LoadNpcTextLocales();
|
||||
void LoadPageTextLocales();
|
||||
void LoadNpcOptionLocales();
|
||||
void LoadGossipMenuItemsLocales();
|
||||
void LoadPointOfInterestLocales();
|
||||
void LoadInstanceTemplate();
|
||||
void LoadMailLevelRewards();
|
||||
|
|
@ -592,8 +636,11 @@ class ObjectMgr
|
|||
void LoadWeatherZoneChances();
|
||||
void LoadGameTele();
|
||||
|
||||
void LoadNpcOptions();
|
||||
void LoadNpcTextId();
|
||||
|
||||
void LoadGossipMenu();
|
||||
void LoadGossipMenuItems();
|
||||
|
||||
void LoadVendors();
|
||||
void LoadTrainerSpell();
|
||||
|
||||
|
|
@ -704,10 +751,10 @@ class ObjectMgr
|
|||
if(itr==mPageTextLocaleMap.end()) return NULL;
|
||||
return &itr->second;
|
||||
}
|
||||
NpcOptionLocale const* GetNpcOptionLocale(uint32 entry) const
|
||||
GossipMenuItemsLocale const* GetGossipMenuItemsLocale(uint32 entry) const
|
||||
{
|
||||
NpcOptionLocaleMap::const_iterator itr = mNpcOptionLocaleMap.find(entry);
|
||||
if(itr==mNpcOptionLocaleMap.end()) return NULL;
|
||||
GossipMenuItemsLocaleMap::const_iterator itr = mGossipMenuItemsLocaleMap.find(entry);
|
||||
if(itr==mGossipMenuItemsLocaleMap.end()) return NULL;
|
||||
return &itr->second;
|
||||
}
|
||||
PointOfInterestLocale const* GetPointOfInterestLocale(uint32 poi_id) const
|
||||
|
|
@ -786,8 +833,6 @@ class ObjectMgr
|
|||
bool AddGameTele(GameTele& data);
|
||||
bool DeleteGameTele(const std::string& name);
|
||||
|
||||
CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; }
|
||||
|
||||
uint32 GetNpcGossip(uint32 entry) const
|
||||
{
|
||||
CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry);
|
||||
|
|
@ -835,6 +880,16 @@ class ObjectMgr
|
|||
return ItemRequiredTargetMapBounds(m_ItemRequiredTarget.lower_bound(uiItemEntry),m_ItemRequiredTarget.upper_bound(uiItemEntry));
|
||||
}
|
||||
|
||||
GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const
|
||||
{
|
||||
return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId));
|
||||
}
|
||||
|
||||
GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const
|
||||
{
|
||||
return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// first free id for selected id type
|
||||
|
|
@ -876,7 +931,9 @@ class ObjectMgr
|
|||
|
||||
RepOnKillMap mRepOnKill;
|
||||
|
||||
PointOfInterestMap mPointsOfInterest;
|
||||
GossipMenusMap m_mGossipMenusMap;
|
||||
GossipMenuItemsMap m_mGossipMenuItemsMap;
|
||||
PointOfInterestMap mPointsOfInterest;
|
||||
|
||||
QuestPOIMap mQuestPOIMap;
|
||||
|
||||
|
|
@ -942,7 +999,7 @@ class ObjectMgr
|
|||
NpcTextLocaleMap mNpcTextLocaleMap;
|
||||
PageTextLocaleMap mPageTextLocaleMap;
|
||||
MangosStringLocaleMap mMangosStringLocaleMap;
|
||||
NpcOptionLocaleMap mNpcOptionLocaleMap;
|
||||
GossipMenuItemsLocaleMap mGossipMenuItemsLocaleMap;
|
||||
PointOfInterestLocaleMap mPointOfInterestLocaleMap;
|
||||
RespawnTimes mCreatureRespawnTimes;
|
||||
RespawnTimes mGORespawnTimes;
|
||||
|
|
@ -951,7 +1008,6 @@ class ObjectMgr
|
|||
typedef std::vector<PlayerCondition> ConditionStore;
|
||||
ConditionStore mConditions;
|
||||
|
||||
CacheNpcOptionList m_mCacheNpcOptionList;
|
||||
CacheNpcTextIdMap m_mCacheNpcTextIdMap;
|
||||
CacheVendorItemMap m_mCacheVendorItemMap;
|
||||
CacheTrainerSpellMap m_mCacheTrainerSpellMap;
|
||||
|
|
|
|||
|
|
@ -2117,14 +2117,14 @@ Creature* Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
|
|||
return unit;
|
||||
}
|
||||
|
||||
GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const
|
||||
GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, uint32 gameobject_type) const
|
||||
{
|
||||
if(GameObject *go = GetMap()->GetGameObject(guid))
|
||||
if (GameObject *go = GetMap()->GetGameObject(guid))
|
||||
{
|
||||
if(go->GetGoType() == type)
|
||||
if (uint32(go->GetGoType()) == gameobject_type || gameobject_type == MAX_GAMEOBJECT_TYPE)
|
||||
{
|
||||
float maxdist;
|
||||
switch(type)
|
||||
switch(go->GetGoType())
|
||||
{
|
||||
// TODO: find out how the client calculates the maximal usage distance to spellless working
|
||||
// gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
|
||||
|
|
@ -2140,10 +2140,10 @@ GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes
|
|||
break;
|
||||
}
|
||||
|
||||
if (go->IsWithinDistInMap(this, maxdist))
|
||||
if (go->IsWithinDistInMap(this, maxdist) && go->isSpawned())
|
||||
return go;
|
||||
|
||||
sLog.outError("IsGameObjectOfTypeInRange: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name,
|
||||
sLog.outError("GetGameObjectIfCanInteractWith: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name,
|
||||
go->GetGUIDLow(), GetName(), GetGUIDLow(), go->GetDistance(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -12178,126 +12178,151 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
|
|||
/*** GOSSIP SYSTEM ***/
|
||||
/*********************************************************/
|
||||
|
||||
void Player::PrepareGossipMenu(WorldObject *pSource, uint32 gossipid)
|
||||
void Player::PrepareGossipMenu(WorldObject *pSource, uint32 menuId)
|
||||
{
|
||||
PlayerMenu* pMenu = PlayerTalkClass;
|
||||
pMenu->ClearMenus();
|
||||
|
||||
if (pSource->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
pMenu->GetGossipMenu().SetMenuId(menuId);
|
||||
|
||||
Creature *pCreature = (Creature*)pSource;
|
||||
GossipMenuItemsMapBounds pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBounds(menuId);
|
||||
|
||||
// lazy loading single time at use
|
||||
pCreature->LoadGossipOptions();
|
||||
// if default menuId and no menu options exist for this, use options from default options
|
||||
if (pMenuItemBounds.first == pMenuItemBounds.second && menuId == GetDefaultGossipMenuForSource(pSource))
|
||||
pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBounds(0);
|
||||
|
||||
GossipOptionList &iOptList = pCreature->GetGossipOptionList();
|
||||
|
||||
for(GossipOptionList::iterator i = iOptList.begin( ); i != iOptList.end( ); ++i)
|
||||
for(GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
|
||||
{
|
||||
GossipOption* gso = &*i;
|
||||
bool bCanTalk = true;
|
||||
|
||||
if (gso->GossipId == gossipid)
|
||||
if (itr->second.cond_1 && !sObjectMgr.IsPlayerMeetToCondition(this, itr->second.cond_1))
|
||||
continue;
|
||||
|
||||
if (itr->second.cond_2 && !sObjectMgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
|
||||
continue;
|
||||
|
||||
if (itr->second.cond_3 && !sObjectMgr.IsPlayerMeetToCondition(this, itr->second.cond_3))
|
||||
continue;
|
||||
|
||||
if (pSource->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
bool cantalking = true;
|
||||
Creature *pCreature = (Creature*)pSource;
|
||||
|
||||
if (gso->Id == 1)
|
||||
uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
|
||||
if (!(itr->second.npc_option_npcflag & npcflags))
|
||||
continue;
|
||||
|
||||
switch(itr->second.option_id)
|
||||
{
|
||||
uint32 textid = GetGossipTextId(pSource);
|
||||
|
||||
GossipText const* gossiptext = sObjectMgr.GetGossipText(textid);
|
||||
|
||||
if (!gossiptext)
|
||||
cantalking = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(gso->Action)
|
||||
case GOSSIP_OPTION_QUESTGIVER:
|
||||
PrepareQuestMenu(pSource->GetGUID());
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_ARMORER:
|
||||
bCanTalk = false; // added in special mode
|
||||
break;
|
||||
case GOSSIP_OPTION_SPIRITHEALER:
|
||||
if (!isDead())
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_VENDOR:
|
||||
{
|
||||
case GOSSIP_OPTION_QUESTGIVER:
|
||||
VendorItemData const* vItems = pCreature->GetVendorItems();
|
||||
if (!vItems || vItems->Empty())
|
||||
{
|
||||
sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", pCreature->GetGUIDLow(), pCreature->GetEntry());
|
||||
bCanTalk = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GOSSIP_OPTION_TRAINER:
|
||||
if (!pCreature->isCanTrainingOf(this, false))
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_UNLEARNTALENTS:
|
||||
if (!pCreature->isCanTrainingAndResetTalentsOf(this))
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_UNLEARNPETSKILLS:
|
||||
if (!GetPet() || GetPet()->getPetType() != HUNTER_PET || GetPet()->m_spells.size() <= 1 || pCreature->GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || pCreature->GetCreatureInfo()->trainer_class != CLASS_HUNTER)
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_TAXIVENDOR:
|
||||
if (GetSession()->SendLearnNewTaxiNode(pCreature))
|
||||
return;
|
||||
break;
|
||||
case GOSSIP_OPTION_BATTLEFIELD:
|
||||
if (!pCreature->isCanInteractWithBattleMaster(this, false))
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_STABLEPET:
|
||||
if (getClass() != CLASS_HUNTER)
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_GOSSIP:
|
||||
case GOSSIP_OPTION_SPIRITGUIDE:
|
||||
case GOSSIP_OPTION_INNKEEPER:
|
||||
case GOSSIP_OPTION_BANKER:
|
||||
case GOSSIP_OPTION_PETITIONER:
|
||||
case GOSSIP_OPTION_TABARDDESIGNER:
|
||||
case GOSSIP_OPTION_AUCTIONEER:
|
||||
break; // no checks
|
||||
default:
|
||||
sLog.outErrorDb("Creature entry %u have unknown gossip option %u for menu %u", pCreature->GetEntry(), itr->second.option_id, itr->second.menu_id);
|
||||
bCanTalk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
{
|
||||
GameObject *pGo = (GameObject*)pSource;
|
||||
|
||||
switch(itr->second.option_id)
|
||||
{
|
||||
case GOSSIP_OPTION_QUESTGIVER:
|
||||
if (pGo->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER)
|
||||
PrepareQuestMenu(pSource->GetGUID());
|
||||
//if (pm->GetQuestMenu()->MenuItemCount() == 0)
|
||||
cantalking = false;
|
||||
//pm->GetQuestMenu()->ClearMenu();
|
||||
break;
|
||||
case GOSSIP_OPTION_ARMORER:
|
||||
cantalking = false; // added in special mode
|
||||
break;
|
||||
case GOSSIP_OPTION_SPIRITHEALER:
|
||||
if (!isDead())
|
||||
cantalking = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_VENDOR:
|
||||
{
|
||||
VendorItemData const* vItems = pCreature->GetVendorItems();
|
||||
if (!vItems || vItems->Empty())
|
||||
{
|
||||
sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.",
|
||||
pCreature->GetGUIDLow(), pCreature->GetEntry());
|
||||
cantalking = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GOSSIP_OPTION_TRAINER:
|
||||
if (!pCreature->isCanTrainingOf(this, false))
|
||||
cantalking = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_UNLEARNTALENTS:
|
||||
if (!pCreature->isCanTrainingAndResetTalentsOf(this))
|
||||
cantalking = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_UNLEARNPETSKILLS:
|
||||
if(!GetPet() || GetPet()->getPetType() != HUNTER_PET || GetPet()->m_spells.size() <= 1 || pCreature->GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || pCreature->GetCreatureInfo()->trainer_class != CLASS_HUNTER)
|
||||
cantalking = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_TAXIVENDOR:
|
||||
if (GetSession()->SendLearnNewTaxiNode(pCreature))
|
||||
return;
|
||||
break;
|
||||
case GOSSIP_OPTION_BATTLEFIELD:
|
||||
if (!pCreature->isCanInteractWithBattleMaster(this, false))
|
||||
cantalking = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_SPIRITGUIDE:
|
||||
case GOSSIP_OPTION_INNKEEPER:
|
||||
case GOSSIP_OPTION_BANKER:
|
||||
case GOSSIP_OPTION_PETITIONER:
|
||||
case GOSSIP_OPTION_STABLEPET:
|
||||
case GOSSIP_OPTION_TABARDDESIGNER:
|
||||
case GOSSIP_OPTION_AUCTIONEER:
|
||||
break; // no checks
|
||||
default:
|
||||
sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u", pCreature->GetDBTableGUIDLow(), pCreature->GetEntry(), gso->Action);
|
||||
break;
|
||||
}
|
||||
bCanTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_GOSSIP:
|
||||
if (pGo->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER && pGo->GetGoType() != GAMEOBJECT_TYPE_GOOBER)
|
||||
bCanTalk = false;
|
||||
break;
|
||||
default:
|
||||
bCanTalk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//note for future dev: should have database fields for BoxMessage & BoxMoney
|
||||
if (!gso->OptionText.empty() && cantalking)
|
||||
if (bCanTalk)
|
||||
{
|
||||
std::string strOptionText = itr->second.option_text;
|
||||
std::string strBoxText = itr->second.box_text;
|
||||
|
||||
int loc_idx = GetSession()->GetSessionDbLocaleIndex();
|
||||
|
||||
if (loc_idx >= 0)
|
||||
{
|
||||
std::string OptionText = gso->OptionText;
|
||||
std::string BoxText = gso->BoxText;
|
||||
int loc_idx = GetSession()->GetSessionDbLocaleIndex();
|
||||
uint32 idxEntry = MAKE_PAIR32(menuId, itr->second.id);
|
||||
|
||||
if (loc_idx >= 0)
|
||||
if (GossipMenuItemsLocale const *no = sObjectMgr.GetGossipMenuItemsLocale(idxEntry))
|
||||
{
|
||||
if (NpcOptionLocale const *no = sObjectMgr.GetNpcOptionLocale(gso->Id))
|
||||
{
|
||||
if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty())
|
||||
OptionText = no->OptionText[loc_idx];
|
||||
if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty())
|
||||
strOptionText = no->OptionText[loc_idx];
|
||||
|
||||
if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty())
|
||||
BoxText = no->BoxText[loc_idx];
|
||||
}
|
||||
if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty())
|
||||
strBoxText = no->BoxText[loc_idx];
|
||||
}
|
||||
|
||||
pMenu->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded);
|
||||
}
|
||||
|
||||
pMenu->GetGossipMenu().AddMenuItem(itr->second.option_icon, strOptionText, 0, itr->second.option_id, strBoxText, itr->second.box_money, itr->second.box_coded);
|
||||
pMenu->GetGossipMenu().AddGossipMenuItemData(itr->second.action_menu_id, itr->second.action_poi_id, itr->second.action_script_id);
|
||||
}
|
||||
}
|
||||
|
||||
///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-)
|
||||
if (pMenu->Empty())
|
||||
// some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-)
|
||||
/*if (pMenu->Empty())
|
||||
{
|
||||
if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
|
|
@ -12310,59 +12335,90 @@ void Player::PrepareGossipMenu(WorldObject *pSource, uint32 gossipid)
|
|||
// output error message if need
|
||||
pCreature->isCanInteractWithBattleMaster(this, true);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void Player::SendPreparedGossip(WorldObject *pSource)
|
||||
{
|
||||
if (!pSource || pSource->GetTypeId() != TYPEID_UNIT)
|
||||
if (!pSource)
|
||||
return;
|
||||
|
||||
// in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag)
|
||||
if (!((Creature*)pSource)->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !PlayerTalkClass->GetQuestMenu().Empty())
|
||||
if (pSource->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
SendPreparedQuest(pSource->GetGUID());
|
||||
return;
|
||||
// in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag)
|
||||
if (!((Creature*)pSource)->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !PlayerTalkClass->GetQuestMenu().Empty())
|
||||
{
|
||||
SendPreparedQuest(pSource->GetGUID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
{
|
||||
// probably need to find a better way here
|
||||
if (!PlayerTalkClass->GetGossipMenu().GetMenuId() && !PlayerTalkClass->GetQuestMenu().Empty())
|
||||
{
|
||||
SendPreparedQuest(pSource->GetGUID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// in case non empty gossip menu (that not included quests list size) show it
|
||||
// (quest entries from quest menu will be included in list)
|
||||
PlayerTalkClass->SendGossipMenu(GetGossipTextId(pSource), pSource->GetGUID());
|
||||
|
||||
uint32 textId = GetGossipTextId(pSource);
|
||||
|
||||
if (uint32 menuId = PlayerTalkClass->GetGossipMenu().GetMenuId())
|
||||
textId = GetGossipTextId(menuId);
|
||||
|
||||
PlayerTalkClass->SendGossipMenu(textId, pSource->GetGUID());
|
||||
}
|
||||
|
||||
void Player::OnGossipSelect(WorldObject* pSource, uint32 option)
|
||||
void Player::OnGossipSelect(WorldObject* pSource, uint32 gossipListId, uint32 menuId)
|
||||
{
|
||||
GossipMenu& gossipmenu = PlayerTalkClass->GetGossipMenu();
|
||||
|
||||
if (option >= gossipmenu.MenuItemCount())
|
||||
if (gossipListId >= gossipmenu.MenuItemCount())
|
||||
return;
|
||||
|
||||
uint32 action = gossipmenu.GetItem(option).m_gAction;
|
||||
uint32 zoneid = GetZoneId();
|
||||
// if not same, then something funky is going on
|
||||
if (menuId != gossipmenu.GetMenuId())
|
||||
return;
|
||||
|
||||
uint32 gossipOptionId = gossipmenu.GetItem(gossipListId).m_gOptionId;
|
||||
uint64 guid = pSource->GetGUID();
|
||||
|
||||
GossipOption const *gossip = GetGossipOption(pSource, action);
|
||||
|
||||
if (!gossip)
|
||||
if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
{
|
||||
zoneid = 0;
|
||||
gossip = GetGossipOption(pSource, action);
|
||||
|
||||
if (!gossip)
|
||||
if (gossipOptionId > GOSSIP_OPTION_QUESTGIVER)
|
||||
{
|
||||
sLog.outError("Player guid %u request invalid gossip option for GameObject entry %u", GetGUIDLow(), pSource->GetEntry());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(gossip->Action)
|
||||
GossipMenuItemData pMenuData = gossipmenu.GetItemData(gossipListId);
|
||||
|
||||
switch(gossipOptionId)
|
||||
{
|
||||
case GOSSIP_OPTION_GOSSIP:
|
||||
{
|
||||
uint32 textid = GetGossipTextId(action, zoneid);
|
||||
if (pMenuData.m_gAction_menu)
|
||||
{
|
||||
PrepareGossipMenu(pSource, pMenuData.m_gAction_menu);
|
||||
SendPreparedGossip(pSource);
|
||||
}
|
||||
|
||||
if (textid == 0)
|
||||
textid = GetGossipTextId(pSource);
|
||||
if (pMenuData.m_gAction_poi)
|
||||
PlayerTalkClass->SendPointOfInterest(pMenuData.m_gAction_poi);
|
||||
|
||||
if (pMenuData.m_gAction_script)
|
||||
{
|
||||
if (pSource->GetTypeId() == TYPEID_UNIT)
|
||||
GetMap()->ScriptsStart(sGossipScripts, pMenuData.m_gAction_script, this, pSource);
|
||||
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
GetMap()->ScriptsStart(sGossipScripts, pMenuData.m_gAction_script, pSource, this);
|
||||
}
|
||||
|
||||
PlayerTalkClass->CloseGossip();
|
||||
PlayerTalkClass->SendTalking(textid);
|
||||
break;
|
||||
}
|
||||
case GOSSIP_OPTION_SPIRITHEALER:
|
||||
|
|
@ -12413,9 +12469,7 @@ void Player::OnGossipSelect(WorldObject* pSource, uint32 option)
|
|||
GetSession()->SendAuctionHello(guid, ((Creature*)pSource));
|
||||
break;
|
||||
case GOSSIP_OPTION_SPIRITGUIDE:
|
||||
case GOSSIP_GUARD_SPELLTRAINER:
|
||||
case GOSSIP_GUARD_SKILLTRAINER:
|
||||
PrepareGossipMenu(pSource, gossip->Id);
|
||||
PrepareGossipMenu(pSource);
|
||||
SendPreparedGossip(pSource);
|
||||
break;
|
||||
case GOSSIP_OPTION_BATTLEFIELD:
|
||||
|
|
@ -12431,59 +12485,13 @@ void Player::OnGossipSelect(WorldObject* pSource, uint32 option)
|
|||
GetSession()->SendBattlegGroundList(guid, bgTypeId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
OnPoiSelect(pSource, gossip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::OnPoiSelect(WorldObject *pSource, GossipOption const *gossip)
|
||||
{
|
||||
if(gossip->GossipId==GOSSIP_GUARD_SPELLTRAINER || gossip->GossipId==GOSSIP_GUARD_SKILLTRAINER)
|
||||
{
|
||||
Poi_Icon icon = ICON_POI_BLANK;
|
||||
//need add more case.
|
||||
switch(gossip->Action)
|
||||
{
|
||||
case GOSSIP_GUARD_BANK:
|
||||
icon=ICON_POI_SMALL_HOUSE;
|
||||
break;
|
||||
case GOSSIP_GUARD_RIDE:
|
||||
icon=ICON_POI_RWHORSE;
|
||||
break;
|
||||
case GOSSIP_GUARD_GUILD:
|
||||
icon=ICON_POI_BLUETOWER;
|
||||
break;
|
||||
default:
|
||||
icon=ICON_POI_GREYTOWER;
|
||||
break;
|
||||
}
|
||||
uint32 textid = GetGossipTextId(gossip->Action, GetZoneId());
|
||||
PlayerTalkClass->SendTalking(textid);
|
||||
// std::string areaname= gossip->OptionText;
|
||||
// how this could worked player->PlayerTalkClass->SendPointOfInterest( x, y, icon, 2, 15, areaname.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Player::GetGossipTextId(uint32 action, uint32 zoneid)
|
||||
{
|
||||
QueryResult *result= WorldDatabase.PQuery("SELECT textid FROM npc_gossip_textid WHERE action = '%u' AND zoneid ='%u'", action, zoneid );
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
uint32 id = fields[0].GetUInt32();
|
||||
|
||||
delete result;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32 Player::GetGossipTextId(WorldObject *pSource)
|
||||
{
|
||||
if (!pSource || pSource->GetTypeId() != TYPEID_UNIT || !((Creature*)pSource)->GetDBTableGUIDLow())
|
||||
return DEFAULT_GOSSIP_MESSAGE;
|
||||
return 0;
|
||||
|
||||
if (uint32 pos = sObjectMgr.GetNpcGossip(((Creature*)pSource)->GetDBTableGUIDLow()))
|
||||
return pos;
|
||||
|
|
@ -12491,19 +12499,32 @@ uint32 Player::GetGossipTextId(WorldObject *pSource)
|
|||
return DEFAULT_GOSSIP_MESSAGE;
|
||||
}
|
||||
|
||||
GossipOption const* Player::GetGossipOption(WorldObject *pSource, uint32 id) const
|
||||
uint32 Player::GetGossipTextId(uint32 menuId)
|
||||
{
|
||||
uint32 textId = DEFAULT_GOSSIP_MESSAGE;
|
||||
|
||||
if (!menuId)
|
||||
return textId;
|
||||
|
||||
GossipMenusMapBounds pMenuBounds = sObjectMgr.GetGossipMenusMapBounds(menuId);
|
||||
|
||||
for(GossipMenusMap::const_iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
|
||||
{
|
||||
if (sObjectMgr.IsPlayerMeetToCondition(this, itr->second.cond_1) && sObjectMgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
|
||||
textId = itr->second.text_id;
|
||||
}
|
||||
|
||||
return textId;
|
||||
}
|
||||
|
||||
uint32 Player::GetDefaultGossipMenuForSource(WorldObject *pSource)
|
||||
{
|
||||
if (pSource->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
GossipOptionList &iOptlist = ((Creature*)pSource)->GetGossipOptionList();
|
||||
return ((Creature*)pSource)->GetCreatureInfo()->GossipMenuId;
|
||||
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
return((GameObject*)pSource)->GetGOInfo()->GetGossipMenuId();
|
||||
|
||||
for(GossipOptionList::const_iterator i = iOptlist.begin( ); i != iOptlist.end( ); ++i)
|
||||
{
|
||||
if (i->Action == id)
|
||||
return &*i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
|
|
@ -19119,7 +19140,7 @@ BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel() const
|
|||
uint32 queue_id = ( getLevel() / 10) - 1;
|
||||
if( queue_id >= MAX_BATTLEGROUND_QUEUES )
|
||||
{
|
||||
sLog.outError("BattleGround: too high queue_id %u this shouldn't happen", queue_id);
|
||||
sLog.outError("BattleGround: too high queue_id %u for player %u (acc: %u) with level %u", queue_id, GetGUIDLow(), GetSession()->GetAccountId(), getLevel());
|
||||
return QUEUE_ID_MAX_LEVEL_80;
|
||||
}
|
||||
return BGQueueIdBasedOnLevel(queue_id);
|
||||
|
|
@ -21229,3 +21250,35 @@ void Player::SendDuelCountdown(uint32 counter)
|
|||
data << uint32(counter); // seconds
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
bool Player::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
|
||||
{
|
||||
switch(spellInfo->Effect[index])
|
||||
{
|
||||
case SPELL_EFFECT_ATTACK_ME:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(spellInfo->EffectApplyAuraName[index])
|
||||
{
|
||||
case SPELL_AURA_MOD_TAUNT:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Unit::IsImmunedToSpellEffect(spellInfo, index);
|
||||
}
|
||||
|
||||
void Player::SetHomebindToCurrentPos()
|
||||
{
|
||||
m_homebindMapId = GetMapId();
|
||||
m_homebindZoneId = GetZoneId();
|
||||
m_homebindX = GetPositionX();
|
||||
m_homebindY = GetPositionY();
|
||||
m_homebindZ = GetPositionZ();
|
||||
|
||||
// update sql homebind
|
||||
CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'",
|
||||
m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ, GetGUIDLow());
|
||||
}
|
||||
|
|
@ -1067,7 +1067,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
|
||||
|
||||
Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask);
|
||||
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const;
|
||||
GameObject* GetGameObjectIfCanInteractWith(uint64 guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
|
||||
|
||||
void UpdateVisibilityForPlayer();
|
||||
|
||||
|
|
@ -1300,14 +1300,13 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
/*** GOSSIP SYSTEM ***/
|
||||
/*********************************************************/
|
||||
|
||||
void PrepareGossipMenu(WorldObject *pSource, uint32 gossipid = 0);
|
||||
void PrepareGossipMenu(WorldObject *pSource, uint32 menuId = 0);
|
||||
void SendPreparedGossip(WorldObject *pSource);
|
||||
void OnGossipSelect(WorldObject *pSource, uint32 option);
|
||||
void OnPoiSelect(WorldObject *pSource, GossipOption const *gossip);
|
||||
void OnGossipSelect(WorldObject *pSource, uint32 gossipListId, uint32 menuId);
|
||||
|
||||
uint32 GetGossipTextId(uint32 action, uint32 zoneid);
|
||||
uint32 GetGossipTextId(uint32 menuId);
|
||||
uint32 GetGossipTextId(WorldObject *pSource);
|
||||
GossipOption const* GetGossipOption(WorldObject *pSource, uint32 id) const;
|
||||
uint32 GetDefaultGossipMenuForSource(WorldObject *pSource);
|
||||
|
||||
/*********************************************************/
|
||||
/*** QUEST SYSTEM ***/
|
||||
|
|
@ -1556,6 +1555,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
|
||||
bool IsSpellFitByClassAndRace( uint32 spell_id ) const;
|
||||
bool IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const;
|
||||
bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const;
|
||||
|
||||
void SendProficiency(uint8 pr1, uint32 pr2);
|
||||
void SendInitialSpells();
|
||||
|
|
@ -2172,13 +2172,9 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
float m_recallO;
|
||||
void SaveRecallPosition();
|
||||
|
||||
// Homebind coordinates
|
||||
uint32 m_homebindMapId;
|
||||
uint16 m_homebindZoneId;
|
||||
float m_homebindX;
|
||||
float m_homebindY;
|
||||
float m_homebindZ;
|
||||
void SetHomebindToCurrentPos();
|
||||
void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); }
|
||||
bool TeleportToHomebind(uint32 options = 0) { return TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation(),options); }
|
||||
|
||||
// currently visible objects at player client
|
||||
typedef std::set<uint64> ClientGUIDs;
|
||||
|
|
@ -2537,6 +2533,13 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
GridReference<Player> m_gridRef;
|
||||
MapReference m_mapRef;
|
||||
|
||||
// Homebind coordinates
|
||||
uint32 m_homebindMapId;
|
||||
uint16 m_homebindZoneId;
|
||||
float m_homebindX;
|
||||
float m_homebindY;
|
||||
float m_homebindZ;
|
||||
|
||||
uint32 m_lastFallTime;
|
||||
float m_lastFallZ;
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data)
|
|||
if (Script->GossipHello(_player, pCreature))
|
||||
return;
|
||||
|
||||
_player->PrepareGossipMenu(pCreature);
|
||||
_player->PrepareGossipMenu(pCreature, pCreature->GetCreatureInfo()->GossipMenuId);
|
||||
_player->SendPreparedGossip(pCreature);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2442,38 +2442,6 @@ enum DiminishingGroup
|
|||
DIMINISHING_LIMITONLY
|
||||
};
|
||||
|
||||
enum SummonType
|
||||
{
|
||||
SUMMON_TYPE_CRITTER = 41,
|
||||
SUMMON_TYPE_GUARDIAN = 61,
|
||||
SUMMON_TYPE_TOTEM_SLOT1 = 63,
|
||||
SUMMON_TYPE_WILD = 64,
|
||||
SUMMON_TYPE_POSESSED = 65,
|
||||
SUMMON_TYPE_DEMON = 66,
|
||||
SUMMON_TYPE_SUMMON = 67,
|
||||
SUMMON_TYPE_TOTEM_SLOT2 = 81,
|
||||
SUMMON_TYPE_TOTEM_SLOT3 = 82,
|
||||
SUMMON_TYPE_TOTEM_SLOT4 = 83,
|
||||
SUMMON_TYPE_TOTEM = 121,
|
||||
SUMMON_TYPE_UNKNOWN3 = 181,
|
||||
SUMMON_TYPE_UNKNOWN4 = 187,
|
||||
SUMMON_TYPE_UNKNOWN1 = 247,
|
||||
SUMMON_TYPE_CRITTER2 = 407,
|
||||
SUMMON_TYPE_CRITTER3 = 307,
|
||||
SUMMON_TYPE_UNKNOWN5 = 409,
|
||||
SUMMON_TYPE_UNKNOWN2 = 427,
|
||||
SUMMON_TYPE_POSESSED2 = 428,
|
||||
SUMMON_TYPE_QUEST_CRITTER = 487,
|
||||
SUMMON_TYPE_QUEST_WILD = 587,
|
||||
SUMMON_TYPE_INFERNO = 711,
|
||||
SUMMON_TYPE_GUARDIAN2 = 713,
|
||||
SUMMON_TYPE_LIGHTWELL = 1141,
|
||||
SUMMON_TYPE_GUARDIAN3 = 1161,
|
||||
SUMMON_TYPE_CREATURE = 1302,
|
||||
SUMMON_TYPE_ELEMENTAL = 1561,
|
||||
SUMMON_TYPE_FORCE_OF_NATURE = 1562
|
||||
};
|
||||
|
||||
enum ResponseCodes
|
||||
{
|
||||
RESPONSE_SUCCESS = 0x00,
|
||||
|
|
|
|||
|
|
@ -691,8 +691,8 @@ void Spell::prepareDataForTriggerSystem()
|
|||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000060))
|
||||
m_canTrigger = true;
|
||||
break;
|
||||
case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it
|
||||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001800000000000))
|
||||
case SPELLFAMILY_PRIEST: // For Penance,Mind Sear,Mind Flay heal/damage triggers need do it
|
||||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001800000800000) || (m_spellInfo->SpellFamilyFlags2 & 0x00000040))
|
||||
m_canTrigger = true;
|
||||
break;
|
||||
case SPELLFAMILY_ROGUE: // For poisons need do it
|
||||
|
|
@ -1685,8 +1685,16 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
|
|||
}
|
||||
break;
|
||||
case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
|
||||
// Death Pact (in fact selection by player selection)
|
||||
if (m_spellInfo->Id == 48743)
|
||||
{
|
||||
// checked in Spell::CheckCast
|
||||
if (m_caster->GetTypeId()==TYPEID_PLAYER)
|
||||
if (Unit* target = m_caster->GetMap()->GetPet(((Player*)m_caster)->GetSelection()))
|
||||
TagUnitMap.push_back(target);
|
||||
}
|
||||
// Wild Growth
|
||||
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellIconID == 2864)
|
||||
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellIconID == 2864)
|
||||
{
|
||||
Unit* target = m_targets.getUnitTarget();
|
||||
if(!target)
|
||||
|
|
@ -2217,13 +2225,6 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
|
|||
}
|
||||
break;
|
||||
case SPELL_EFFECT_SUMMON:
|
||||
if (m_spellInfo->EffectMiscValueB[effIndex] == SUMMON_TYPE_POSESSED ||
|
||||
m_spellInfo->EffectMiscValueB[effIndex] == SUMMON_TYPE_POSESSED2)
|
||||
{
|
||||
if (m_targets.getUnitTarget())
|
||||
TagUnitMap.push_back(m_targets.getUnitTarget());
|
||||
}
|
||||
else
|
||||
TagUnitMap.push_back(m_caster);
|
||||
break;
|
||||
case SPELL_EFFECT_SUMMON_CHANGE_ITEM:
|
||||
|
|
@ -4299,6 +4300,34 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
// for effects of spells that have only one target
|
||||
switch(m_spellInfo->Effect[i])
|
||||
{
|
||||
case SPELL_EFFECT_INSTAKILL:
|
||||
// Death Pact
|
||||
if(m_spellInfo->Id == 48743)
|
||||
{
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return SPELL_FAILED_ERROR;
|
||||
|
||||
if (!((Player*)m_caster)->GetSelection())
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
Pet* target = m_caster->GetMap()->GetPet(((Player*)m_caster)->GetSelection());
|
||||
|
||||
// alive
|
||||
if (!target || target->isDead())
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
// undead
|
||||
if (target->GetCreatureType() != CREATURE_TYPE_UNDEAD)
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
// owned
|
||||
if (target->GetOwnerGUID() != m_caster->GetGUID())
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
|
||||
float dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
|
||||
if (!target->IsWithinDistInMap(m_caster,dist))
|
||||
return SPELL_FAILED_OUT_OF_RANGE;
|
||||
|
||||
// will set in target selection code
|
||||
}
|
||||
break;
|
||||
case SPELL_EFFECT_DUMMY:
|
||||
{
|
||||
if(m_spellInfo->SpellIconID == 1648) // Execute
|
||||
|
|
@ -4567,24 +4596,17 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
// This is generic summon effect
|
||||
case SPELL_EFFECT_SUMMON:
|
||||
{
|
||||
switch(m_spellInfo->EffectMiscValueB[i])
|
||||
if(SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]))
|
||||
{
|
||||
case SUMMON_TYPE_POSESSED:
|
||||
case SUMMON_TYPE_POSESSED2:
|
||||
case SUMMON_TYPE_DEMON:
|
||||
case SUMMON_TYPE_SUMMON:
|
||||
case SUMMON_TYPE_ELEMENTAL:
|
||||
case SUMMON_TYPE_INFERNO:
|
||||
if(summon_prop->Group == SUMMON_PROP_GROUP_PETS)
|
||||
{
|
||||
if(m_caster->GetPetGUID())
|
||||
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
||||
|
||||
if(m_caster->GetCharmGUID())
|
||||
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Not used for summon?
|
||||
case SPELL_EFFECT_SUMMON_PHANTASM:
|
||||
|
|
@ -4950,6 +4972,18 @@ SpellCastResult Spell::CheckCasterAuras() const
|
|||
prevented_reason = SPELL_FAILED_SILENCED;
|
||||
else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
|
||||
prevented_reason = SPELL_FAILED_PACIFIED;
|
||||
else if(m_caster->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY))
|
||||
{
|
||||
Unit::AuraList const& casingLimit = m_caster->GetAurasByType(SPELL_AURA_ALLOW_ONLY_ABILITY);
|
||||
for(Unit::AuraList::const_iterator itr = casingLimit.begin(); itr != casingLimit.end(); ++itr)
|
||||
{
|
||||
if(!IsAffectedByAura(*itr))
|
||||
{
|
||||
prevented_reason = SPELL_FAILED_CASTER_AURASTATE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attr must make flag drop spell totally immune from all effects
|
||||
if (prevented_reason != SPELL_CAST_OK)
|
||||
|
|
@ -5704,7 +5738,7 @@ void Spell::UpdatePointers()
|
|||
m_targets.Update(m_caster);
|
||||
}
|
||||
|
||||
bool Spell::IsAffectedByAura(Aura *aura)
|
||||
bool Spell::IsAffectedByAura(Aura *aura) const
|
||||
{
|
||||
return sSpellMgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ class Spell
|
|||
void EffectDualWield(uint32 i);
|
||||
void EffectPickPocket(uint32 i);
|
||||
void EffectAddFarsight(uint32 i);
|
||||
void EffectSummonWild(uint32 i);
|
||||
void EffectSummonGuardian(uint32 i);
|
||||
void EffectSummonWild(uint32 i, uint32 forceFaction = 0);
|
||||
void EffectSummonGuardian(uint32 i, uint32 forceFaction = 0);
|
||||
void EffectHealMechanical(uint32 i);
|
||||
void EffectJump(uint32 i);
|
||||
void EffectTeleUnitsFaceCaster(uint32 i);
|
||||
|
|
@ -277,7 +277,7 @@ class Spell
|
|||
void EffectSummonPlayer(uint32 i);
|
||||
void EffectActivateObject(uint32 i);
|
||||
void EffectApplyGlyph(uint32 i);
|
||||
void EffectSummonTotem(uint32 i);
|
||||
void EffectSummonTotem(uint32 i, uint8 slot = 0);
|
||||
void EffectEnchantHeldItem(uint32 i);
|
||||
void EffectSummonObject(uint32 i);
|
||||
void EffectResurrect(uint32 i);
|
||||
|
|
@ -299,7 +299,7 @@ class Spell
|
|||
void EffectMilling(uint32 i);
|
||||
void EffectRenamePet(uint32 i);
|
||||
void EffectSendTaxi(uint32 i);
|
||||
void EffectSummonCritter(uint32 i);
|
||||
void EffectSummonCritter(uint32 i, uint32 forceFaction = 0);
|
||||
void EffectKnockBack(uint32 i);
|
||||
void EffectPlayerPull(uint32 i);
|
||||
void EffectDispelMechanic(uint32 i);
|
||||
|
|
@ -314,7 +314,6 @@ class Spell
|
|||
void EffectAddExtraAttacks(uint32 i);
|
||||
void EffectSpiritHeal(uint32 i);
|
||||
void EffectSkinPlayerCorpse(uint32 i);
|
||||
void EffectSummonDemon(uint32 i);
|
||||
void EffectStealBeneficialBuff(uint32 i);
|
||||
void EffectUnlearnSpecialization(uint32 i);
|
||||
void EffectHealPct(uint32 i);
|
||||
|
|
@ -442,7 +441,7 @@ class Spell
|
|||
|
||||
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
|
||||
|
||||
bool IsAffectedByAura(Aura *aura);
|
||||
bool IsAffectedByAura(Aura *aura) const;
|
||||
|
||||
bool CheckTargetCreatureType(Unit* target) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ enum AuraType
|
|||
SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL = 269,
|
||||
SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
|
||||
SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
|
||||
SPELL_AURA_272 = 272,
|
||||
SPELL_AURA_MAELSTROM_WEAPON = 272,
|
||||
SPELL_AURA_X_RAY = 273,
|
||||
SPELL_AURA_274 = 274,
|
||||
SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
|
||||
|
|
@ -347,7 +347,7 @@ enum AuraType
|
|||
SPELL_AURA_302 = 302,
|
||||
SPELL_AURA_303 = 303,
|
||||
SPELL_AURA_304 = 304,
|
||||
SPELL_AURA_305 = 305,
|
||||
SPELL_AURA_MOD_MINIMUM_SPEED = 305,
|
||||
SPELL_AURA_306 = 306,
|
||||
TOTAL_AURAS = 307
|
||||
};
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING (only 2 test spels in 3.2.2a)
|
||||
&Aura::HandleNULL, //243 faction reaction override spells
|
||||
&Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
|
||||
&Aura::HandleNULL, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
|
||||
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS implemented in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNULL, //247 target to become a clone of the caster
|
||||
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
||||
|
|
@ -313,7 +313,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
|
||||
&Aura::HandlePhase, //261 SPELL_AURA_PHASE undetectable invisibility? implemented in Unit::isVisibleForOrDetect
|
||||
&Aura::HandleNULL, //262 ignore combat/aura state?
|
||||
&Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
|
||||
&Aura::HandleAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
|
||||
&Aura::HandleUnused, //264 unused (3.0.8a-3.2.2a)
|
||||
&Aura::HandleUnused, //265 unused (3.0.8a-3.2.2a)
|
||||
&Aura::HandleUnused, //266 unused (3.0.8a-3.2.2a)
|
||||
|
|
@ -322,7 +322,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL implemented in Unit::CalcNotIgnoreDamageRedunction
|
||||
&Aura::HandleUnused, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST (unused in 3.2.2a)
|
||||
&Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
|
||||
&Aura::HandleNULL, //272 reduce spell cast time?
|
||||
&Aura::HandleNoImmediateEffect, //272 SPELL_AURA_MAELSTROM_WEAPON (unclear use for aura, it used in (3.2.2a...3.3.0) in single spell 53817 that spellmode stacked and charged spell expected to be drop as stack
|
||||
&Aura::HandleNoImmediateEffect, //273 SPELL_AURA_X_RAY (client side implementation)
|
||||
&Aura::HandleNULL, //274 proc free shot?
|
||||
&Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
|
||||
|
|
@ -355,7 +355,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleUnused, //302 unused (3.2.2a)
|
||||
&Aura::HandleNULL, //303 17 spells
|
||||
&Aura::HandleNULL, //304 2 spells (alcohol effect?)
|
||||
&Aura::HandleNULL, //305 2 spells
|
||||
&Aura::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
|
||||
&Aura::HandleNULL //306 1 spell
|
||||
};
|
||||
|
||||
|
|
@ -1333,26 +1333,42 @@ bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
|
|||
|
||||
void Aura::ReapplyAffectedPassiveAuras( Unit* target )
|
||||
{
|
||||
std::set<uint32> affectedPassives;
|
||||
std::set<uint32> affectedSelf;
|
||||
std::set<uint32> affectedAuraCaster;
|
||||
|
||||
for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr)
|
||||
{
|
||||
// permanent passive
|
||||
if (itr->second->IsPassive() && itr->second->IsPermanent() &&
|
||||
// permanent passive or permanent area aura
|
||||
if (itr->second->IsPermanent() && (itr->second->IsPassive() || itr->second->IsAreaAura()) &&
|
||||
// non deleted and not same aura (any with same spell id)
|
||||
!itr->second->IsDeleted() && itr->second->GetId() != GetId() &&
|
||||
// only applied by self and affected by aura
|
||||
itr->second->GetCasterGUID() == target->GetGUID() && isAffectedOnSpell(itr->second->GetSpellProto()))
|
||||
// and affected by aura
|
||||
isAffectedOnSpell(itr->second->GetSpellProto()))
|
||||
{
|
||||
affectedPassives.insert(itr->second->GetId());
|
||||
// only applied by self or aura caster
|
||||
if(itr->second->GetCasterGUID() == target->GetGUID())
|
||||
affectedSelf.insert(itr->second->GetId());
|
||||
else if(itr->second->GetCasterGUID() == GetCasterGUID())
|
||||
affectedAuraCaster.insert(itr->second->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
for(std::set<uint32>::const_iterator set_itr = affectedPassives.begin(); set_itr != affectedPassives.end(); ++set_itr)
|
||||
for(std::set<uint32>::const_iterator set_itr = affectedSelf.begin(); set_itr != affectedSelf.end(); ++set_itr)
|
||||
{
|
||||
target->RemoveAurasDueToSpell(*set_itr);
|
||||
target->CastSpell(m_target, *set_itr, true);
|
||||
}
|
||||
|
||||
if (!affectedAuraCaster.empty())
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
for(std::set<uint32>::const_iterator set_itr = affectedAuraCaster.begin(); set_itr != affectedAuraCaster.end(); ++set_itr)
|
||||
{
|
||||
target->RemoveAurasDueToSpell(*set_itr);
|
||||
if (caster)
|
||||
caster->CastSpell(m_target, *set_itr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
|
|
@ -1402,7 +1418,10 @@ void Aura::HandleAddModifier(bool apply, bool Real)
|
|||
|
||||
mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32;
|
||||
mod->mask2= (uint64)ptr[2];
|
||||
mod->charges = m_procCharges;
|
||||
|
||||
// prevent expire spell mods with (charges > 0 && m_stackAmount > 1)
|
||||
// all this spell expected expire not at use but at spell proc event check
|
||||
mod->charges = m_spellProto->StackAmount > 1 ? 0 : m_procCharges;
|
||||
|
||||
m_spellmod = mod;
|
||||
}
|
||||
|
|
@ -1412,14 +1431,22 @@ void Aura::HandleAddModifier(bool apply, bool Real)
|
|||
// reapply talents to own passive persistent auras
|
||||
ReapplyAffectedPassiveAuras(m_target);
|
||||
|
||||
// re-aplly talents and passives applied to pet (it affected by player spellmods)
|
||||
// re-apply talents/passives/area auras applied to pet (it affected by player spellmods)
|
||||
if(Pet* pet = m_target->GetPet())
|
||||
ReapplyAffectedPassiveAuras(pet);
|
||||
|
||||
// re-apply talents/passives/area auras applied to totems (it affected by player spellmods)
|
||||
for(int i = 0; i < MAX_TOTEM; ++i)
|
||||
if(m_target->m_TotemSlot[i])
|
||||
if(Creature* totem = m_target->GetMap()->GetCreature(m_target->m_TotemSlot[i]))
|
||||
ReapplyAffectedPassiveAuras(totem);
|
||||
|
||||
// re-apply talents/passives/area auras applied to group members (it affected by player spellmods)
|
||||
if (Group* group = ((Player*)m_target)->GetGroup())
|
||||
for(GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
if (Player* member = itr->getSource())
|
||||
if (member != m_target && member->IsInMap(m_target))
|
||||
ReapplyAffectedPassiveAuras(member);
|
||||
}
|
||||
void Aura::HandleAddTargetTrigger(bool apply, bool /*Real*/)
|
||||
{
|
||||
|
|
@ -2212,56 +2239,107 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
// AT APPLY
|
||||
if(apply)
|
||||
{
|
||||
switch(GetId())
|
||||
switch(m_spellProto->SpellFamilyName)
|
||||
{
|
||||
case 1515: // Tame beast
|
||||
// FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
|
||||
if (m_target->CanHaveThreatList())
|
||||
if (Unit* caster = GetCaster())
|
||||
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||
return;
|
||||
case 13139: // net-o-matic
|
||||
// root to self part of (root_target->charge->root_self sequence
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(caster, 13138, true, NULL, this);
|
||||
return;
|
||||
case 39850: // Rocket Blast
|
||||
if(roll_chance_i(20)) // backfire stun
|
||||
m_target->CastSpell(m_target, 51581, true, NULL, this);
|
||||
return;
|
||||
case 43873: // Headless Horseman Laugh
|
||||
m_target->PlayDistanceSound(11965);
|
||||
return;
|
||||
case 46354: // Blood Elf Illusion
|
||||
if (Unit* caster = GetCaster())
|
||||
case SPELLFAMILY_GENERIC:
|
||||
switch(GetId())
|
||||
{
|
||||
switch(caster->getGender())
|
||||
{
|
||||
case GENDER_FEMALE:
|
||||
caster->CastSpell(m_target, 46356, true, NULL, this);
|
||||
break;
|
||||
case GENDER_MALE:
|
||||
caster->CastSpell(m_target, 46355, true, NULL, this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case 1515: // Tame beast
|
||||
// FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
|
||||
if (m_target->CanHaveThreatList())
|
||||
if (Unit* caster = GetCaster())
|
||||
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||
return;
|
||||
case 13139: // net-o-matic
|
||||
// root to self part of (root_target->charge->root_self sequence
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(caster, 13138, true, NULL, this);
|
||||
return;
|
||||
case 39850: // Rocket Blast
|
||||
if(roll_chance_i(20)) // backfire stun
|
||||
m_target->CastSpell(m_target, 51581, true, NULL, this);
|
||||
return;
|
||||
case 43873: // Headless Horseman Laugh
|
||||
m_target->PlayDistanceSound(11965);
|
||||
return;
|
||||
case 46354: // Blood Elf Illusion
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
switch(caster->getGender())
|
||||
{
|
||||
case GENDER_FEMALE:
|
||||
caster->CastSpell(m_target, 46356, true, NULL, this);
|
||||
break;
|
||||
case GENDER_MALE:
|
||||
caster->CastSpell(m_target, 46355, true, NULL, this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 46699: // Requires No Ammo
|
||||
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case 46699: // Requires No Ammo
|
||||
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_WARRIOR:
|
||||
// Overpower
|
||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004))
|
||||
{
|
||||
// Must be casting target
|
||||
if (!m_target->IsNonMeleeSpellCasted(false))
|
||||
return;
|
||||
|
||||
// Earth Shield
|
||||
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x40000000000)))
|
||||
{
|
||||
// prevent double apply bonuses
|
||||
if(m_target->GetTypeId() != TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
|
||||
if (Unit* caster = GetCaster())
|
||||
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
|
||||
return;
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
Unit::AuraList const& modifierAuras = caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
|
||||
for(Unit::AuraList::const_iterator itr = modifierAuras.begin(); itr != modifierAuras.end(); ++itr)
|
||||
{
|
||||
// Unrelenting Assault
|
||||
if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARRIOR && (*itr)->GetSpellProto()->SpellIconID == 2775)
|
||||
{
|
||||
switch ((*itr)->GetSpellProto()->Id)
|
||||
{
|
||||
case 46859: // Unrelenting Assault, rank 1
|
||||
m_target->CastSpell(m_target,64849,true,NULL,(*itr));
|
||||
break;
|
||||
case 46860: // Unrelenting Assault, rank 2
|
||||
m_target->CastSpell(m_target,64850,true,NULL,(*itr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_SHAMAN:
|
||||
// Tidal Force
|
||||
if (GetId() == 55198)
|
||||
{
|
||||
// apply max stack bufs
|
||||
SpellEntry const* buffEntry = sSpellStore.LookupEntry(55166);
|
||||
if (!buffEntry)
|
||||
return;
|
||||
for(int k = 0; k < buffEntry->StackAmount; ++k)
|
||||
m_target->CastSpell(m_target, buffEntry, true, NULL, this);
|
||||
}
|
||||
// Earth Shield
|
||||
else if ((GetSpellProto()->SpellFamilyFlags & UI64LIT(0x40000000000)))
|
||||
{
|
||||
// prevent double apply bonuses
|
||||
if(m_target->GetTypeId() != TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
|
||||
if (Unit* caster = GetCaster())
|
||||
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// AT REMOVE
|
||||
|
|
@ -2668,6 +2746,18 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
case SPELLFAMILY_HUNTER:
|
||||
break;
|
||||
case SPELLFAMILY_PALADIN:
|
||||
switch(GetId())
|
||||
{
|
||||
case 20911: // Blessing of Sanctuary
|
||||
case 25899: // Greater Blessing of Sanctuary
|
||||
{
|
||||
if (apply)
|
||||
m_target->CastSpell(m_target, 67480, true, NULL, this);
|
||||
else
|
||||
m_target->RemoveAurasDueToSpell(67480);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELLFAMILY_SHAMAN:
|
||||
{
|
||||
|
|
@ -3148,6 +3238,22 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
|
|||
}
|
||||
// Murloc costume
|
||||
case 42365: m_target->SetDisplayId(21723); break;
|
||||
// Honor the Dead
|
||||
case 65386:
|
||||
case 65495:
|
||||
{
|
||||
switch(m_target->getGender())
|
||||
{
|
||||
case GENDER_MALE:
|
||||
m_target->SetDisplayId(29203); // Chapman
|
||||
break;
|
||||
case GENDER_FEMALE:
|
||||
case GENDER_NONE:
|
||||
m_target->SetDisplayId(29204); // Catrina
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
@ -5662,6 +5768,8 @@ void Aura::HandleShapeshiftBoosts(bool apply)
|
|||
((Player*)m_target)->RemoveSpellCooldown(49868);
|
||||
break;
|
||||
case FORM_GHOSTWOLF:
|
||||
spellId1 = 67116;
|
||||
break;
|
||||
case FORM_AMBIENT:
|
||||
case FORM_GHOUL:
|
||||
case FORM_STEALTH:
|
||||
|
|
@ -5789,6 +5897,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
|
|||
|
||||
void Aura::HandleSpellSpecificBoosts(bool apply)
|
||||
{
|
||||
bool cast_at_remove = false; // if spell must be casted at aura remove
|
||||
uint32 spellId1 = 0;
|
||||
uint32 spellId2 = 0;
|
||||
uint32 spellId3 = 0;
|
||||
|
|
@ -5796,6 +5905,33 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
|
||||
switch(GetSpellProto()->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_MAGE:
|
||||
{
|
||||
// Ice Barrier
|
||||
if (m_spellProto->SpellIconID == 32)
|
||||
{
|
||||
if (!apply && (m_removeMode == AURA_REMOVE_BY_DISPEL || (m_removeMode == AURA_REMOVE_BY_DEFAULT && !GetModifier()->m_amount)))
|
||||
{
|
||||
Unit::AuraList const& dummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
|
||||
{
|
||||
// Shattered Barrier
|
||||
if ((*itr)->GetSpellProto()->SpellIconID == 2945)
|
||||
{
|
||||
cast_at_remove = true;
|
||||
// first rank have 50% chance
|
||||
if ((*itr)->GetId() != 44745 || roll_chance_i(50))
|
||||
spellId1 = 55080;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
case SPELLFAMILY_WARRIOR:
|
||||
{
|
||||
if(!apply)
|
||||
|
|
@ -5817,14 +5953,72 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_WARLOCK:
|
||||
// Fear
|
||||
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000040000000000))
|
||||
{
|
||||
if(!apply)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if(!caster)
|
||||
return;
|
||||
|
||||
Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
|
||||
{
|
||||
SpellEntry const* dummyEntry = (*itr)->GetSpellProto();
|
||||
// Improved Fear
|
||||
if (dummyEntry->SpellFamilyName == SPELLFAMILY_WARLOCK && dummyEntry->SpellIconID == 98)
|
||||
{
|
||||
cast_at_remove = true;
|
||||
switch((*itr)->GetModifier()->m_amount)
|
||||
{
|
||||
// Rank 1
|
||||
case 0: spellId1 = 60946; break;
|
||||
// Rank 1
|
||||
case 1: spellId1 = 60947; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
break;
|
||||
case SPELLFAMILY_PRIEST:
|
||||
{
|
||||
// Shadow Word: Pain (need visual check fro skip improvement talent) or Vampiric Touch
|
||||
if (m_spellProto->SpellIconID == 234 && m_spellProto->SpellVisual[0] || m_spellProto->SpellIconID == 2213)
|
||||
{
|
||||
if (!apply && m_removeMode == AURA_REMOVE_BY_DISPEL)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if(!caster)
|
||||
return;
|
||||
|
||||
Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
|
||||
{
|
||||
// Shadow Affinity
|
||||
if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST
|
||||
&& (*itr)->GetSpellProto()->SpellIconID == 178)
|
||||
{
|
||||
// custom cast code
|
||||
int32 basepoints0 = (*itr)->GetModifier()->m_amount * caster->GetCreateMana() / 100;
|
||||
caster->CastCustomSpell(caster, 64103, &basepoints0, NULL, NULL, true, NULL, this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
switch(GetId())
|
||||
{
|
||||
// Dispersion mana reg and immunity
|
||||
case 47585:
|
||||
spellId1 = 60069; // Dispersion
|
||||
spellId2 = 63230; // Dispersion
|
||||
break;
|
||||
// Abolish Disease (remove 1 more poison effect with Body and Soul)
|
||||
case 552:
|
||||
{
|
||||
|
|
@ -5851,10 +6045,16 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
spellId1 = 64134; // Body and Soul (periodic dispel effect)
|
||||
break;
|
||||
}
|
||||
// Dispersion mana reg and immunity
|
||||
case 47585:
|
||||
spellId1 = 60069; // Dispersion
|
||||
spellId2 = 63230; // Dispersion
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_ROGUE:
|
||||
// Sprint (skip non player casted spells by category)
|
||||
if (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000040) && GetSpellProto()->Category == 44)
|
||||
|
|
@ -5963,7 +6163,7 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
// prevent aura deletion, specially in multi-boost case
|
||||
SetInUse(true);
|
||||
|
||||
if (apply)
|
||||
if (apply || cast_at_remove)
|
||||
{
|
||||
if (spellId1)
|
||||
m_target->CastSpell(m_target, spellId1, true, NULL, this);
|
||||
|
|
@ -6259,47 +6459,10 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
|
|||
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
|
||||
|
||||
m_modifier.m_amount += (int32)DoneActualBenefit;
|
||||
|
||||
// now that the correct amount is computed, apply caster aura, if any
|
||||
switch(m_spellProto->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_PRIEST:
|
||||
// Power Word: Shield
|
||||
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000001))
|
||||
{
|
||||
// Glyph of Power Word: Shield
|
||||
if(Aura* glyph = caster->GetAura(55672,0))
|
||||
{
|
||||
// instant heal glyph m_amount% of the absorbed amount
|
||||
int32 heal = (glyph->GetModifier()->m_amount * m_modifier.m_amount)/100;
|
||||
caster->CastCustomSpell(m_target, 56160, &heal, NULL, NULL, true, 0, this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ice Barrier (remove effect from Shattered Barrier)
|
||||
if (m_spellProto->SpellIconID == 32 && m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE)
|
||||
{
|
||||
if (!((m_removeMode == AURA_REMOVE_BY_DEFAULT && !m_modifier.m_amount) || m_removeMode == AURA_REMOVE_BY_DISPEL))
|
||||
return;
|
||||
|
||||
if (m_target->HasAura(44745,0)) // Shattered Barrier, rank 1
|
||||
{
|
||||
if(roll_chance_i(50))
|
||||
m_target->CastSpell(m_target, 55080, true, NULL, this);
|
||||
}
|
||||
else if (m_target->HasAura(54787,0)) // Shattered Barrier, rank 2
|
||||
{
|
||||
m_target->CastSpell(m_target, 55080, true, NULL, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (caster &&
|
||||
// Power Word: Shield
|
||||
m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->Mechanic == MECHANIC_SHIELD &&
|
||||
|
|
@ -7539,3 +7702,26 @@ void Aura::HandleAuraModAllCritChance(bool apply, bool Real)
|
|||
// included in Player::UpdateSpellCritChance calculation
|
||||
((Player*)m_target)->UpdateAllSpellCritChances();
|
||||
}
|
||||
|
||||
void Aura::HandleAllowOnlyAbility(bool apply, bool Real)
|
||||
{
|
||||
if(!Real)
|
||||
return;
|
||||
|
||||
if(apply)
|
||||
{
|
||||
m_target->setAttackTimer(BASE_ATTACK,m_duration);
|
||||
m_target->setAttackTimer(RANGED_ATTACK,m_duration);
|
||||
m_target->setAttackTimer(OFF_ATTACK,m_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_target->resetAttackTimer(BASE_ATTACK);
|
||||
m_target->resetAttackTimer(RANGED_ATTACK);
|
||||
m_target->resetAttackTimer(OFF_ATTACK);
|
||||
}
|
||||
|
||||
m_target->UpdateDamagePhysical(BASE_ATTACK);
|
||||
m_target->UpdateDamagePhysical(RANGED_ATTACK);
|
||||
m_target->UpdateDamagePhysical(OFF_ATTACK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ class MANGOS_DLL_SPEC Aura
|
|||
void HandlePhase(bool Apply, bool Real);
|
||||
void HandleModTargetArmorPct(bool Apply, bool Real);
|
||||
void HandleAuraModAllCritChance(bool Apply, bool Real);
|
||||
void HandleAllowOnlyAbility(bool Apply, bool Real);
|
||||
|
||||
virtual ~Aura();
|
||||
|
||||
|
|
@ -268,6 +269,13 @@ class MANGOS_DLL_SPEC Aura
|
|||
{
|
||||
if (m_procCharges == 0)
|
||||
return false;
|
||||
|
||||
// exist spells that have maxStack > 1 and m_procCharges > 0 (==1 in fact)
|
||||
// all like stacks have 1 value in one from this fields
|
||||
// so return true for allow remove one aura from stacks as expired
|
||||
if (GetStackAmount() > 1)
|
||||
return true;
|
||||
|
||||
m_procCharges--;
|
||||
SendAuraUpdate(false);
|
||||
return m_procCharges == 0;
|
||||
|
|
|
|||
|
|
@ -515,12 +515,14 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
|
|||
// Ferocious Bite
|
||||
if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000800000)) && m_spellInfo->SpellVisual[0]==6587)
|
||||
{
|
||||
// converts each extra point of energy into ($f1+$AP/410) additional damage
|
||||
// converts up to 30 points of energy into ($f1+$AP/410) additional damage
|
||||
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
|
||||
damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
|
||||
damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
|
||||
m_caster->SetPower(POWER_ENERGY,0);
|
||||
uint32 energy = m_caster->GetPower(POWER_ENERGY);
|
||||
uint32 used_energy = energy > 30 ? 30 : energy;
|
||||
damage += int32(used_energy * multiple);
|
||||
m_caster->SetPower(POWER_ENERGY,energy-used_energy);
|
||||
}
|
||||
// Rake
|
||||
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS)
|
||||
|
|
@ -1441,14 +1443,14 @@ void Spell::EffectDummy(uint32 i)
|
|||
uint32 rage = m_caster->GetPower(POWER_RAGE);
|
||||
|
||||
// up to max 30 rage cost
|
||||
if(rage > 30)
|
||||
rage = 30;
|
||||
if(rage > 300)
|
||||
rage = 300;
|
||||
|
||||
// Glyph of Execution bonus
|
||||
uint32 rage_modified = rage;
|
||||
|
||||
if (Aura *aura = m_caster->GetDummyAura(58367))
|
||||
rage_modified += aura->GetModifier()->m_amount;
|
||||
rage_modified += aura->GetModifier()->m_amount*10;
|
||||
|
||||
int32 basePoints0 = damage+int32(rage_modified * m_spellInfo->DmgMultiplier[i] +
|
||||
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
|
||||
|
|
@ -1465,7 +1467,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
if ((*itr)->GetSpellProto()->SpellIconID == 1989)
|
||||
{
|
||||
// saved rage top stored in next affect
|
||||
uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(1);
|
||||
uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(1)*10;
|
||||
if(lastrage < rage)
|
||||
rage -= lastrage;
|
||||
break;
|
||||
|
|
@ -1491,6 +1493,7 @@ void Spell::EffectDummy(uint32 i)
|
|||
m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(m_spellInfo->Id)
|
||||
{
|
||||
// Warrior's Wrath
|
||||
|
|
@ -2337,7 +2340,7 @@ void Spell::EffectTeleportUnits(uint32 i)
|
|||
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
|
||||
((Player*)unitTarget)->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
|
||||
return;
|
||||
}
|
||||
case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
|
||||
|
|
@ -2675,6 +2678,9 @@ void Spell::EffectHeal( uint32 /*i*/ )
|
|||
|
||||
addhealth += damageAmount;
|
||||
}
|
||||
// Death Pact (percent heal)
|
||||
else if (m_spellInfo->Id==48743)
|
||||
addhealth = addhealth * unitTarget->GetMaxHealth() / 100;
|
||||
// Swiftmend - consumes Regrowth or Rejuvenation
|
||||
else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
|
||||
{
|
||||
|
|
@ -2770,21 +2776,21 @@ void Spell::EffectHealthLeech(uint32 i)
|
|||
|
||||
sLog.outDebug("HealthLeech :%i", damage);
|
||||
|
||||
uint32 curHealth = unitTarget->GetHealth();
|
||||
damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage );
|
||||
if (curHealth < damage)
|
||||
damage = curHealth;
|
||||
|
||||
float multiplier = m_spellInfo->EffectMultipleValue[i];
|
||||
|
||||
if (Player *modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
|
||||
|
||||
int32 new_damage = int32(damage*multiplier);
|
||||
uint32 curHealth = unitTarget->GetHealth();
|
||||
new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage );
|
||||
if (curHealth < new_damage)
|
||||
new_damage = curHealth;
|
||||
|
||||
uint32 heal = uint32(damage*multiplier);
|
||||
if (m_caster->isAlive())
|
||||
{
|
||||
new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL);
|
||||
m_caster->DealHeal(m_caster, uint32(new_damage), m_spellInfo);
|
||||
heal = m_caster->SpellHealingBonus(m_caster, m_spellInfo, heal, HEAL);
|
||||
m_caster->DealHeal(m_caster, heal, m_spellInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3392,54 +3398,99 @@ void Spell::EffectApplyAreaAura(uint32 i)
|
|||
|
||||
void Spell::EffectSummonType(uint32 i)
|
||||
{
|
||||
switch(m_spellInfo->EffectMiscValueB[i])
|
||||
uint32 prop_id = m_spellInfo->EffectMiscValueB[i];
|
||||
SummonPropertiesEntry const *summon_prop = sSummonPropertiesStore.LookupEntry(prop_id);
|
||||
if(!summon_prop)
|
||||
{
|
||||
case SUMMON_TYPE_GUARDIAN:
|
||||
case SUMMON_TYPE_POSESSED:
|
||||
case SUMMON_TYPE_POSESSED2:
|
||||
case SUMMON_TYPE_FORCE_OF_NATURE:
|
||||
case SUMMON_TYPE_GUARDIAN2:
|
||||
case SUMMON_TYPE_GUARDIAN3:
|
||||
// Jewelery statue case (totem like)
|
||||
if(m_spellInfo->SpellIconID == 2056)
|
||||
EffectSummonTotem(i);
|
||||
sLog.outError("EffectSummonType: Unhandled summon type %u", prop_id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(summon_prop->Group)
|
||||
{
|
||||
// faction handled later on, or loaded from template
|
||||
case SUMMON_PROP_GROUP_WILD:
|
||||
case SUMMON_PROP_GROUP_FRIENDLY:
|
||||
{
|
||||
switch(summon_prop->Type)
|
||||
{
|
||||
case SUMMON_PROP_TYPE_SIEGE_VEH:
|
||||
case SUMMON_PROP_TYPE_DRAKE_VEH:
|
||||
{
|
||||
// TODO
|
||||
// EffectSummonVehicle(i);
|
||||
break;
|
||||
}
|
||||
case SUMMON_PROP_TYPE_TOTEM:
|
||||
{
|
||||
EffectSummonTotem(i, summon_prop->Slot);
|
||||
break;
|
||||
}
|
||||
case SUMMON_PROP_TYPE_SUMMON:
|
||||
case SUMMON_PROP_TYPE_GUARDIAN:
|
||||
case SUMMON_PROP_TYPE_ARMY:
|
||||
case SUMMON_PROP_TYPE_DK:
|
||||
case SUMMON_PROP_TYPE_CONSTRUCT:
|
||||
{
|
||||
// JC golems - 32804, etc -- fits much better totem AI
|
||||
if(m_spellInfo->SpellIconID == 2056)
|
||||
EffectSummonTotem(i);
|
||||
if(prop_id == 832) // scrapbot
|
||||
EffectSummonWild(i, summon_prop->FactionId);
|
||||
else
|
||||
EffectSummonGuardian(i, summon_prop->FactionId);
|
||||
break;
|
||||
}
|
||||
case SUMMON_PROP_TYPE_CRITTER:
|
||||
{
|
||||
EffectSummonCritter(i, summon_prop->FactionId);
|
||||
break;
|
||||
}
|
||||
case SUMMON_PROP_TYPE_OTHER:
|
||||
case SUMMON_PROP_TYPE_PHASING:
|
||||
case SUMMON_PROP_TYPE_LIGHTWELL:
|
||||
{
|
||||
// those are classical totems - effectbasepoints is their hp and not summon ammount!
|
||||
//SUMMON_TYPE_TOTEM = 121: 23035, battlestands
|
||||
//SUMMON_TYPE_TOTEM2 = 647: 52893, Anti-Magic Zone (npc used)
|
||||
if(prop_id == 121 || prop_id == 647)
|
||||
EffectSummonTotem(i);
|
||||
else
|
||||
EffectSummonWild(i, summon_prop->FactionId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("EffectSummonType: Unhandled summon type %u", summon_prop->Type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SUMMON_PROP_GROUP_PETS:
|
||||
{
|
||||
// FIXME : multiple summons - not yet supported as pet
|
||||
//1562 - force of nature - sid 33831
|
||||
//1161 - feral spirit - sid 51533
|
||||
if(prop_id == 1562) // 3 uncontrolable instead of one controllable :/
|
||||
EffectSummonGuardian(i, summon_prop->FactionId);
|
||||
else
|
||||
EffectSummonGuardian(i);
|
||||
EffectSummon(i);
|
||||
break;
|
||||
case SUMMON_TYPE_WILD:
|
||||
case SUMMON_TYPE_QUEST_WILD:
|
||||
case SUMMON_TYPE_CREATURE:
|
||||
EffectSummonWild(i);
|
||||
}
|
||||
case SUMMON_PROP_GROUP_CONTROLLABLE:
|
||||
{
|
||||
// no type here
|
||||
// maybe wrong - but thats the handler currently used for those
|
||||
EffectSummonGuardian(i, summon_prop->FactionId);
|
||||
break;
|
||||
case SUMMON_TYPE_DEMON:
|
||||
case SUMMON_TYPE_INFERNO:
|
||||
EffectSummonDemon(i);
|
||||
break;
|
||||
case SUMMON_TYPE_SUMMON:
|
||||
case SUMMON_TYPE_ELEMENTAL:
|
||||
EffectSummon(i);
|
||||
break;
|
||||
case SUMMON_TYPE_CRITTER:
|
||||
case SUMMON_TYPE_CRITTER2:
|
||||
case SUMMON_TYPE_CRITTER3:
|
||||
case SUMMON_TYPE_QUEST_CRITTER:
|
||||
EffectSummonCritter(i);
|
||||
break;
|
||||
case SUMMON_TYPE_TOTEM_SLOT1:
|
||||
case SUMMON_TYPE_TOTEM_SLOT2:
|
||||
case SUMMON_TYPE_TOTEM_SLOT3:
|
||||
case SUMMON_TYPE_TOTEM_SLOT4:
|
||||
case SUMMON_TYPE_TOTEM:
|
||||
EffectSummonTotem(i);
|
||||
break;
|
||||
case SUMMON_TYPE_UNKNOWN1:
|
||||
case SUMMON_TYPE_UNKNOWN2:
|
||||
case SUMMON_TYPE_UNKNOWN3:
|
||||
case SUMMON_TYPE_UNKNOWN4:
|
||||
case SUMMON_TYPE_UNKNOWN5:
|
||||
}
|
||||
case SUMMON_PROP_GROUP_VEHICLE:
|
||||
{
|
||||
// TODO
|
||||
// EffectSummonVehicle(i);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
|
||||
sLog.outError("EffectSummonType: Unhandled summon group type %u", summon_prop->Group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -3457,6 +3508,10 @@ void Spell::EffectSummon(uint32 i)
|
|||
uint32 level = m_caster->getLevel();
|
||||
Pet* spawnCreature = new Pet(SUMMON_PET);
|
||||
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
if(Player* modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
|
||||
if (m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry))
|
||||
{
|
||||
// Summon in dest location
|
||||
|
|
@ -3470,7 +3525,6 @@ void Spell::EffectSummon(uint32 i)
|
|||
}
|
||||
|
||||
// set timer for unsummon
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
if (duration > 0)
|
||||
spawnCreature->SetDuration(duration);
|
||||
|
||||
|
|
@ -3509,7 +3563,6 @@ void Spell::EffectSummon(uint32 i)
|
|||
}
|
||||
|
||||
// set timer for unsummon
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
if (duration > 0)
|
||||
spawnCreature->SetDuration(duration);
|
||||
|
||||
|
|
@ -3780,7 +3833,7 @@ void Spell::EffectAddFarsight(uint32 i)
|
|||
((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
|
||||
}
|
||||
|
||||
void Spell::EffectSummonWild(uint32 i)
|
||||
void Spell::EffectSummonWild(uint32 i, uint32 forceFaction)
|
||||
{
|
||||
uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
|
||||
if (!creature_entry)
|
||||
|
|
@ -3796,9 +3849,7 @@ void Spell::EffectSummonWild(uint32 i)
|
|||
{
|
||||
uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
|
||||
if (skill202)
|
||||
{
|
||||
level = skill202/5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3808,6 +3859,8 @@ void Spell::EffectSummonWild(uint32 i)
|
|||
float center_z = m_targets.m_destZ;
|
||||
|
||||
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
|
||||
|
||||
int32 amount = damage > 0 ? damage : 1;
|
||||
|
||||
|
|
@ -3832,30 +3885,23 @@ void Spell::EffectSummonWild(uint32 i)
|
|||
else
|
||||
m_caster->GetClosePoint(px, py, pz, 3.0f);
|
||||
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
if(Creature *summon = m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration))
|
||||
{
|
||||
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
summon->SetCreatorGUID(m_caster->GetGUID());
|
||||
|
||||
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
|
||||
|
||||
m_caster->SummonCreature(creature_entry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
|
||||
if(forceFaction)
|
||||
summon->setFaction(forceFaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectSummonGuardian(uint32 i)
|
||||
void Spell::EffectSummonGuardian(uint32 i, uint32 forceFaction)
|
||||
{
|
||||
uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
|
||||
if (!pet_entry)
|
||||
return;
|
||||
|
||||
// set timer for unsummon
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
|
||||
// Search old Guardian only for players (if casted spell not have duration or cooldown)
|
||||
// FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
|
||||
// so this code hack in fact
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo) == 0))
|
||||
if(m_caster->FindGuardianWithEntry(pet_entry))
|
||||
return; // find old guardian, ignore summon
|
||||
|
||||
// in another case summon new
|
||||
uint32 level = m_caster->getLevel();
|
||||
|
||||
|
|
@ -3879,6 +3925,9 @@ void Spell::EffectSummonGuardian(uint32 i)
|
|||
float center_z = m_targets.m_destZ;
|
||||
|
||||
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
if(Player* modOwner = m_caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
|
||||
int32 amount = damage > 0 ? damage : 1;
|
||||
|
||||
|
|
@ -3930,8 +3979,8 @@ void Spell::EffectSummonGuardian(uint32 i)
|
|||
|
||||
spawnCreature->SetOwnerGUID(m_caster->GetGUID());
|
||||
spawnCreature->setPowerType(POWER_MANA);
|
||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
spawnCreature->setFaction(m_caster->getFaction());
|
||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
|
||||
spawnCreature->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
|
||||
spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
|
||||
spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
|
||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
||||
|
|
@ -5350,6 +5399,14 @@ void Spell::EffectScriptEffect(uint32 effIndex)
|
|||
}
|
||||
return;
|
||||
}
|
||||
// Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
|
||||
case 63521:
|
||||
{
|
||||
// Divine Plea, refresh on target (3 aura slots)
|
||||
if (Aura* aura = unitTarget->GetAura(54428,0))
|
||||
aura->RefreshAura();
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -5745,7 +5802,7 @@ void Spell::EffectStuck(uint32 /*i*/)
|
|||
return;
|
||||
|
||||
// homebind location is loaded always
|
||||
pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
|
||||
pTarget->TeleportToHomebind(unitTarget==m_caster ? TELE_TO_SPELL : 0);
|
||||
|
||||
// Stuck spell trigger Hearthstone cooldown
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
|
||||
|
|
@ -5833,21 +5890,9 @@ void Spell::EffectApplyGlyph(uint32 i)
|
|||
}
|
||||
}
|
||||
|
||||
void Spell::EffectSummonTotem(uint32 i)
|
||||
void Spell::EffectSummonTotem(uint32 i, uint8 slot)
|
||||
{
|
||||
uint8 slot = 0;
|
||||
switch(m_spellInfo->EffectMiscValueB[i])
|
||||
{
|
||||
case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
|
||||
case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
|
||||
case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
|
||||
case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
|
||||
// Battle standard case
|
||||
case SUMMON_TYPE_TOTEM: slot = 254; break;
|
||||
// jewelery statue case, like totem without slot
|
||||
case SUMMON_TYPE_GUARDIAN: slot = 255; break;
|
||||
default: return;
|
||||
}
|
||||
slot = slot ? (slot - 1): 255;
|
||||
|
||||
if(slot < MAX_TOTEM)
|
||||
{
|
||||
|
|
@ -6339,7 +6384,7 @@ void Spell::EffectCharge2(uint32 /*i*/)
|
|||
m_caster->Attack(unitTarget,true);
|
||||
}
|
||||
|
||||
void Spell::EffectSummonCritter(uint32 i)
|
||||
void Spell::EffectSummonCritter(uint32 i, uint32 forceFaction)
|
||||
{
|
||||
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
|
@ -6399,9 +6444,9 @@ void Spell::EffectSummonCritter(uint32 i)
|
|||
|
||||
critter->SetOwnerGUID(m_caster->GetGUID());
|
||||
critter->SetCreatorGUID(m_caster->GetGUID());
|
||||
critter->setFaction(m_caster->getFaction());
|
||||
critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
|
||||
critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
critter->setFaction(forceFaction ? forceFaction : m_caster->getFaction());
|
||||
critter->AIM_Initialize();
|
||||
critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
|
||||
//critter->InitLevelupSpellsForLevel(); // none?
|
||||
|
|
@ -6764,65 +6809,6 @@ void Spell::EffectSkill(uint32 /*i*/)
|
|||
sLog.outDebug("WORLD: SkillEFFECT");
|
||||
}
|
||||
|
||||
void Spell::EffectSummonDemon(uint32 i)
|
||||
{
|
||||
// select center of summon position
|
||||
float center_x = m_targets.m_destX;
|
||||
float center_y = m_targets.m_destY;
|
||||
float center_z = m_targets.m_destZ;
|
||||
|
||||
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
|
||||
|
||||
int32 amount = damage > 0 ? damage : 1;
|
||||
|
||||
if (m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_INFERNO)
|
||||
amount = 1;
|
||||
|
||||
for(int32 count = 0; count < amount; ++count)
|
||||
{
|
||||
float px, py, pz;
|
||||
// If dest location if present
|
||||
if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
||||
{
|
||||
// Summon 1 unit in dest location
|
||||
if (count == 0)
|
||||
{
|
||||
px = m_targets.m_destX;
|
||||
py = m_targets.m_destY;
|
||||
pz = m_targets.m_destZ;
|
||||
}
|
||||
// Summon in random point all other units if location present
|
||||
else
|
||||
m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
|
||||
}
|
||||
// Summon if dest location not present near caster
|
||||
else
|
||||
m_caster->GetClosePoint(px,py,pz,3.0f);
|
||||
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
|
||||
Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);
|
||||
if (!Charmed) // something fatal, not attempt more
|
||||
return;
|
||||
|
||||
// might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
|
||||
Charmed->SetLevel(m_caster->getLevel());
|
||||
|
||||
// TODO: Add damage/mana/hp according to level
|
||||
|
||||
// Enslave demon effect, without mana cost and cooldown
|
||||
if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon
|
||||
{
|
||||
// Enslave demon effect, without mana cost and cooldown
|
||||
m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
|
||||
|
||||
// Inferno effect for non player calls
|
||||
if (m_spellInfo->EffectMiscValueB[i]!=SUMMON_TYPE_INFERNO)
|
||||
Charmed->CastSpell(Charmed, 22703, true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectSpiritHeal(uint32 /*i*/)
|
||||
{
|
||||
// TODO player can't see the heal-animation - he should respawn some ticks later
|
||||
|
|
|
|||
|
|
@ -1329,10 +1329,8 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
spellInfo_2->SpellVisual[0] == 99 && spellInfo_1->SpellVisual[0] == 0 ) )
|
||||
return false;
|
||||
|
||||
// Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
|
||||
if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && (
|
||||
spellInfo_1->SpellVisual[0] == 0 && spellInfo_2->SpellVisual[0] == 78 ||
|
||||
spellInfo_2->SpellVisual[0] == 0 && spellInfo_1->SpellVisual[0] == 78 ) )
|
||||
// Heart of the Wild, Agility and various Idol Triggers
|
||||
if(spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240)
|
||||
return false;
|
||||
|
||||
// Personalized Weather (thunder effect should overwrite rainy aura)
|
||||
|
|
@ -1414,6 +1412,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual[0]==7992)
|
||||
return false;
|
||||
|
||||
// Blessing of Sanctuary (multi-family check, some from 16 spell icon spells)
|
||||
if (spellInfo_1->Id == 67480 && spellInfo_2->Id == 20911)
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1642,8 +1644,13 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
// Concentration Aura and Improved Concentration Aura and Aura Mastery
|
||||
if ((spellInfo_1->SpellIconID == 1487) && (spellInfo_2->SpellIconID == 1487))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Blessing of Sanctuary (multi-family check, some from 16 spell icon spells)
|
||||
if (spellInfo_2->Id == 67480 && spellInfo_1->Id == 20911)
|
||||
return false;
|
||||
|
||||
// Combustion and Fire Protection Aura (multi-family check)
|
||||
if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 )
|
||||
return false;
|
||||
|
|
@ -1663,6 +1670,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
|
||||
spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags )
|
||||
return false;
|
||||
|
||||
// Ghost Wolf
|
||||
if (spellInfo_1->SpellIconID == 67 && spellInfo_2->SpellIconID == 67)
|
||||
return false;
|
||||
}
|
||||
// Bloodlust and Bloodthirst (multi-family check)
|
||||
if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 )
|
||||
|
|
@ -1711,13 +1722,22 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
|
||||
return false;
|
||||
|
||||
bool dummy_only = true;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (spellInfo_1->Effect[i] != spellInfo_2->Effect[i] ||
|
||||
spellInfo_1->EffectItemType[i] != spellInfo_2->EffectItemType[i] ||
|
||||
spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i] ||
|
||||
spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i])
|
||||
return false;
|
||||
|
||||
// ignore dummy only spells
|
||||
if(spellInfo_1->Effect[i] && spellInfo_1->Effect[i] != SPELL_EFFECT_DUMMY && spellInfo_1->EffectApplyAuraName[i] != SPELL_AURA_DUMMY)
|
||||
dummy_only = false;
|
||||
}
|
||||
if (dummy_only)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,20 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto)
|
|||
bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
|
||||
{
|
||||
// TODO: possibly all negative auras immune?
|
||||
switch(spellInfo->Effect[index])
|
||||
{
|
||||
case SPELL_EFFECT_ATTACK_ME:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(spellInfo->EffectApplyAuraName[index])
|
||||
{
|
||||
case SPELL_AURA_PERIODIC_DAMAGE:
|
||||
case SPELL_AURA_PERIODIC_LEECH:
|
||||
case SPELL_AURA_MOD_FEAR:
|
||||
case SPELL_AURA_TRANSFORM:
|
||||
case SPELL_AURA_MOD_TAUNT:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1693,8 +1693,47 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
|
|||
// Death Prevention Aura
|
||||
SpellEntry const* preventDeathSpell = NULL;
|
||||
int32 preventDeathAmount = 0;
|
||||
|
||||
// full absorb cases (by chance)
|
||||
AuraList const& vAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
|
||||
for(AuraList::const_iterator i = vAbsorb.begin(); i != vAbsorb.end() && RemainingDamage > 0; ++i)
|
||||
{
|
||||
// only work with proper school mask damage
|
||||
Modifier* i_mod = (*i)->GetModifier();
|
||||
if (!(i_mod->m_miscvalue & schoolMask))
|
||||
continue;
|
||||
|
||||
SpellEntry const* i_spellProto = (*i)->GetSpellProto();
|
||||
// Fire Ward or Frost Ward
|
||||
if(i_spellProto->SpellFamilyName == SPELLFAMILY_MAGE && i_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000108))
|
||||
{
|
||||
int chance = 0;
|
||||
Unit::AuraList const& auras = pVictim->GetAurasByType(SPELL_AURA_ADD_PCT_MODIFIER);
|
||||
for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
{
|
||||
SpellEntry const* itr_spellProto = (*itr)->GetSpellProto();
|
||||
// Frost Warding (chance full absorb)
|
||||
if (itr_spellProto->SpellFamilyName == SPELLFAMILY_MAGE && itr_spellProto->SpellIconID == 501)
|
||||
{
|
||||
// chance stored in next dummy effect
|
||||
chance = itr_spellProto->CalculateSimpleValue(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(roll_chance_i(chance))
|
||||
{
|
||||
int32 amount = RemainingDamage;
|
||||
RemainingDamage = 0;
|
||||
// Frost Warding (mana regen)
|
||||
pVictim->CastCustomSpell(pVictim, 57776, &amount, NULL, NULL, true, NULL, *i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need remove expired auras after
|
||||
bool existExpired = false;
|
||||
|
||||
// absorb without mana cost
|
||||
AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
|
||||
for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i)
|
||||
|
|
@ -1802,7 +1841,17 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
|
|||
preventDeathAmount = (*i)->GetModifier()->m_amount;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Power Word: Shield
|
||||
if (spellProto->SpellFamilyFlags & UI64LIT(00000001) && spellProto->Mechanic == MECHANIC_SHIELD)
|
||||
{
|
||||
// Glyph of Power Word: Shield
|
||||
if (Aura *glyph = pVictim->GetAura(55672,0))
|
||||
{
|
||||
int32 heal = int32(glyph->GetModifier()->m_amount *
|
||||
(RemainingDamage >= currentAbsorb ? currentAbsorb : RemainingDamage) / 100);
|
||||
pVictim->CastCustomSpell(pVictim, 56160, &heal, NULL, NULL, true, 0, *i);
|
||||
}
|
||||
}
|
||||
// Reflective Shield
|
||||
if (spellProto->SpellFamilyFlags == 0x1 && canReflect)
|
||||
{
|
||||
|
|
@ -1945,13 +1994,18 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
|
|||
else
|
||||
currentAbsorb = RemainingDamage;
|
||||
|
||||
float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()];
|
||||
if(Player *modOwner = pVictim->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
|
||||
if (float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()])
|
||||
{
|
||||
if(Player *modOwner = pVictim->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
|
||||
|
||||
int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier);
|
||||
if (currentAbsorb > maxAbsorb)
|
||||
currentAbsorb = maxAbsorb;
|
||||
int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier);
|
||||
if (currentAbsorb > maxAbsorb)
|
||||
currentAbsorb = maxAbsorb;
|
||||
|
||||
int32 manaReduction = int32(currentAbsorb * manaMultiplier);
|
||||
pVictim->ApplyPowerMod(POWER_MANA, manaReduction, false);
|
||||
}
|
||||
|
||||
(*i)->GetModifier()->m_amount -= currentAbsorb;
|
||||
if((*i)->GetModifier()->m_amount <= 0)
|
||||
|
|
@ -1960,12 +2014,40 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
|
|||
next = vManaShield.begin();
|
||||
}
|
||||
|
||||
int32 manaReduction = int32(currentAbsorb * manaMultiplier);
|
||||
pVictim->ApplyPowerMod(POWER_MANA, manaReduction, false);
|
||||
|
||||
RemainingDamage -= currentAbsorb;
|
||||
}
|
||||
|
||||
// effects dependent from full absorb amount
|
||||
if (int32 full_absorb = damage - RemainingDamage - *resist)
|
||||
{
|
||||
Unit::AuraList const& auras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
{
|
||||
SpellEntry const* itr_spellProto = (*itr)->GetSpellProto();
|
||||
|
||||
// Incanter's Absorption
|
||||
if (itr_spellProto->SpellFamilyName == SPELLFAMILY_GENERIC &&
|
||||
itr_spellProto->SpellIconID == 2941)
|
||||
{
|
||||
|
||||
int32 amount = int32(full_absorb * (*itr)->GetModifier()->m_amount / 100);
|
||||
|
||||
// apply normalized part of already accumulated amount in aura
|
||||
if (Aura* spdAura = pVictim->GetAura(44413,0))
|
||||
amount += spdAura->GetModifier()->m_amount * spdAura->GetAuraDuration() / spdAura->GetAuraMaxDuration();
|
||||
|
||||
// limit 5 health percents
|
||||
int32 health_5percent = pVictim->GetMaxHealth()*5/100;
|
||||
if(amount > health_5percent)
|
||||
amount = health_5percent;
|
||||
|
||||
// Incanter's Absorption (triggered absorb based spell power, will replace existed if any)
|
||||
pVictim->CastCustomSpell(pVictim, 44413, &amount, NULL, NULL, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only split damage if not damaging yourself
|
||||
if(pVictim != this)
|
||||
{
|
||||
|
|
@ -3867,7 +3949,7 @@ void Unit::RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID,
|
|||
{
|
||||
SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId);
|
||||
|
||||
// Custom dispel case
|
||||
// Custom dispel cases
|
||||
// Unstable Affliction
|
||||
if(spellEntry->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellEntry->SpellFamilyFlags & UI64LIT(0x010000000000)))
|
||||
{
|
||||
|
|
@ -3881,9 +3963,43 @@ void Unit::RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID,
|
|||
// backfire damage and silence
|
||||
dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,casterGUID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
// Flame Shock
|
||||
if (spellEntry->SpellFamilyName == SPELLFAMILY_SHAMAN && (spellEntry->SpellFamilyFlags & UI64LIT(0x10000000)))
|
||||
{
|
||||
Unit* caster = NULL;
|
||||
uint32 triggeredSpell = 0;
|
||||
|
||||
if (Aura* dotAura = GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, UI64LIT(0x10000000), 0x00000000, casterGUID))
|
||||
caster = dotAura->GetCaster();
|
||||
|
||||
if (caster && !caster->isDead())
|
||||
{
|
||||
Unit::AuraList const& auras = caster->GetAurasByType(SPELL_AURA_DUMMY);
|
||||
for (Unit::AuraList::const_iterator i = auras.begin(); i != auras.end(); ++i)
|
||||
{
|
||||
switch((*i)->GetId())
|
||||
{
|
||||
case 51480: triggeredSpell=64694; break;// Lava Flows, Rank 1
|
||||
case 51481: triggeredSpell=65263; break;// Lava Flows, Rank 2
|
||||
case 51482: triggeredSpell=65264; break;// Lava Flows, Rank 3
|
||||
default: continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove spell auras from stack
|
||||
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
|
||||
|
||||
// Haste
|
||||
if (triggeredSpell)
|
||||
caster->CastSpell(caster, triggeredSpell, true);
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
|
||||
}
|
||||
|
||||
void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer)
|
||||
|
|
@ -5600,6 +5716,34 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
{
|
||||
switch(dummySpell->Id)
|
||||
{
|
||||
// Leader of the Pack
|
||||
case 24932:
|
||||
{
|
||||
// dummy m_amount store health percent (!=0 if Improved Leader of the Pack applied)
|
||||
int32 heal_percent = triggeredByAura->GetModifier()->m_amount;
|
||||
if (!heal_percent)
|
||||
return false;
|
||||
|
||||
// check explicitly only to prevent mana cast when halth cast cooldown
|
||||
if (cooldown && ((Player*)this)->HasSpellCooldown(34299))
|
||||
return false;
|
||||
|
||||
// health
|
||||
triggered_spell_id = 34299;
|
||||
basepoints0 = GetMaxHealth() * heal_percent / 100;
|
||||
target = this;
|
||||
|
||||
// mana to caster
|
||||
if (triggeredByAura->GetCasterGUID() == GetGUID())
|
||||
{
|
||||
if (SpellEntry const* manaCastEntry = sSpellStore.LookupEntry(60889))
|
||||
{
|
||||
int32 mana_percent = manaCastEntry->CalculateSimpleValue(0) * heal_percent;
|
||||
CastCustomSpell(this, manaCastEntry, &mana_percent, NULL, NULL, true, castItem, triggeredByAura);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Healing Touch (Dreamwalker Raiment set)
|
||||
case 28719:
|
||||
{
|
||||
|
|
@ -5825,13 +5969,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
|
||||
break;
|
||||
}
|
||||
// Sacred Shield
|
||||
if (dummySpell->SpellFamilyFlags & UI64LIT(0x0008000000000000))
|
||||
{
|
||||
triggered_spell_id = 58597;
|
||||
target = this;
|
||||
break;
|
||||
}
|
||||
// Righteous Vengeance
|
||||
if (dummySpell->SpellIconID == 3025)
|
||||
{
|
||||
|
|
@ -5853,14 +5990,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
// Judgement of Light
|
||||
case 20185:
|
||||
{
|
||||
// Get judgement caster
|
||||
Unit *caster = triggeredByAura->GetCaster();
|
||||
if (!caster)
|
||||
return false;
|
||||
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
|
||||
caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this);
|
||||
basepoints0 = int32(ap*0.10f + 0.10f*holy);
|
||||
basepoints0 = int32( pVictim->GetMaxHealth() * triggeredByAura->GetModifier()->m_amount / 100 );
|
||||
pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5932,6 +6062,20 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
}
|
||||
break;
|
||||
}
|
||||
// Spiritual Attunement
|
||||
case 31785:
|
||||
case 33776:
|
||||
{
|
||||
// if healed by another unit (pVictim)
|
||||
if(this == pVictim)
|
||||
return false;
|
||||
|
||||
// heal amount
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
target = this;
|
||||
triggered_spell_id = 31786;
|
||||
break;
|
||||
}
|
||||
// Seal of Vengeance (damage calc on apply aura)
|
||||
case 31801:
|
||||
{
|
||||
|
|
@ -5969,20 +6113,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
// Replenishment
|
||||
CastSpell(this, 57669, true, NULL, triggeredByAura);
|
||||
break;
|
||||
// Spiritual Attunement
|
||||
case 31785:
|
||||
case 33776:
|
||||
{
|
||||
// if healed by another unit (pVictim)
|
||||
if(this == pVictim)
|
||||
return false;
|
||||
|
||||
// heal amount
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
target = this;
|
||||
triggered_spell_id = 31786;
|
||||
break;
|
||||
}
|
||||
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
|
||||
case 40470:
|
||||
{
|
||||
|
|
@ -6011,29 +6141,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
|
||||
break;
|
||||
}
|
||||
// Seal of Corruption (damage calc on apply aura)
|
||||
case 53736:
|
||||
{
|
||||
if(effIndex != 0) // effect 1,2 used by seal unleashing code
|
||||
return false;
|
||||
|
||||
triggered_spell_id = 53742;
|
||||
|
||||
// Add 5-stack effect
|
||||
int8 stacks = 0;
|
||||
AuraList const& auras = target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
|
||||
{
|
||||
if( ((*itr)->GetId() == 53742) && (*itr)->GetCasterGUID()==GetGUID())
|
||||
{
|
||||
stacks = (*itr)->GetStackAmount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stacks >= 5)
|
||||
CastSpell(target,53739,true,NULL,triggeredByAura);
|
||||
break;
|
||||
}
|
||||
// Light's Beacon (heal target area aura)
|
||||
case 53651:
|
||||
{
|
||||
|
|
@ -6069,6 +6176,43 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
beacon->CastCustomSpell(beacon,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura,pVictim->GetGUID());
|
||||
return true;
|
||||
}
|
||||
// Seal of Corruption (damage calc on apply aura)
|
||||
case 53736:
|
||||
{
|
||||
if(effIndex != 0) // effect 1,2 used by seal unleashing code
|
||||
return false;
|
||||
|
||||
triggered_spell_id = 53742;
|
||||
|
||||
// Add 5-stack effect
|
||||
int8 stacks = 0;
|
||||
AuraList const& auras = target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
|
||||
for(AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
|
||||
{
|
||||
if( ((*itr)->GetId() == 53742) && (*itr)->GetCasterGUID()==GetGUID())
|
||||
{
|
||||
stacks = (*itr)->GetStackAmount();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stacks >= 5)
|
||||
CastSpell(target,53739,true,NULL,triggeredByAura);
|
||||
break;
|
||||
}
|
||||
// Glyph of Flash of Light
|
||||
case 54936:
|
||||
{
|
||||
triggered_spell_id = 54957;
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
break;
|
||||
}
|
||||
// Glyph of Holy Light
|
||||
case 54937:
|
||||
{
|
||||
triggered_spell_id = 54968;
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
break;
|
||||
}
|
||||
// Glyph of Divinity
|
||||
case 54939:
|
||||
{
|
||||
|
|
@ -6082,18 +6226,23 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
}
|
||||
return true;
|
||||
}
|
||||
// Glyph of Flash of Light
|
||||
case 54936:
|
||||
// Sacred Shield (buff)
|
||||
case 58597:
|
||||
{
|
||||
triggered_spell_id = 54957;
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
triggered_spell_id = 66922;
|
||||
SpellEntry const* triggeredEntry = sSpellStore.LookupEntry(triggered_spell_id);
|
||||
if (!triggeredEntry)
|
||||
return false;
|
||||
|
||||
basepoints0 = int32(damage / (GetSpellDuration(triggeredEntry) / triggeredEntry->EffectAmplitude[0]));
|
||||
target = this;
|
||||
break;
|
||||
}
|
||||
// Glyph of Holy Light
|
||||
case 54937:
|
||||
// Sacred Shield (talent rank)
|
||||
case 53601:
|
||||
{
|
||||
triggered_spell_id = 54968;
|
||||
basepoints0 = triggerAmount*damage/100;
|
||||
triggered_spell_id = 58597;
|
||||
target = this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -6324,7 +6473,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()];
|
||||
CastSpell(this, spell, true, castItem, triggeredByAura);
|
||||
if ((*itr)->DropAuraCharge())
|
||||
RemoveAurasDueToSpell((*itr)->GetId());
|
||||
RemoveSingleSpellAurasFromStack((*itr)->GetId());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -6426,7 +6575,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
|||
}
|
||||
CastSpell(target, spell, true, castItem, triggeredByAura);
|
||||
if ((*itr)->DropAuraCharge())
|
||||
RemoveAurasDueToSpell((*itr)->GetId());
|
||||
RemoveSingleSpellAurasFromStack((*itr)->GetId());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -6919,16 +7068,8 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
|
|||
}
|
||||
case SPELLFAMILY_DRUID:
|
||||
{
|
||||
// Leader of the Pack
|
||||
if (auraSpellInfo->Id == 24932)
|
||||
{
|
||||
if (triggerAmount == 0)
|
||||
return false;
|
||||
basepoints[0] = triggerAmount * GetMaxHealth() / 100;
|
||||
trigger_spell_id = 34299;
|
||||
}
|
||||
// Druid Forms Trinket
|
||||
else if (auraSpellInfo->Id==37336)
|
||||
if (auraSpellInfo->Id==37336)
|
||||
{
|
||||
switch(m_form)
|
||||
{
|
||||
|
|
@ -7152,7 +7293,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
|
|||
case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break;
|
||||
case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break;
|
||||
case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break;
|
||||
case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
|
||||
case SPELL_SCHOOL_ARCANE: trigger_spell_id = 50486; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7525,6 +7666,9 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura
|
|||
case 5497: // Improved Mana Gems (Serpent-Coil Braid)
|
||||
triggered_spell_id = 37445; // Mana Surge
|
||||
break;
|
||||
case 6953: // Warbringer
|
||||
RemoveAurasAtMechanicImmunity(IMMUNE_TO_ROOT_AND_SNARE_MASK,0,true);
|
||||
return true;
|
||||
case 8152: // Serendipity
|
||||
{
|
||||
// if heal your target over maximum health
|
||||
|
|
@ -8904,10 +9048,9 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
|
|||
case SPELL_DAMAGE_CLASS_RANGED:
|
||||
{
|
||||
if (pVictim)
|
||||
{
|
||||
crit_chance = GetUnitCriticalChance(attackType, pVictim);
|
||||
crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
|
||||
}
|
||||
|
||||
crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -10252,7 +10395,12 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
|
|||
// Apply strongest slow aura mod to speed
|
||||
int32 slow = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
|
||||
if (slow)
|
||||
{
|
||||
speed *=(100.0f + slow)/100.0f;
|
||||
float min_speed = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED) / 100.0f;
|
||||
if (speed < min_speed)
|
||||
speed = min_speed;
|
||||
}
|
||||
SetSpeed(mtype, speed, forced);
|
||||
}
|
||||
|
||||
|
|
@ -10710,6 +10858,9 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in
|
|||
durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel);
|
||||
// Find max mod (negative bonus)
|
||||
int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic);
|
||||
|
||||
if (!IsPositiveSpell(spellProto->Id))
|
||||
durationMod_always += target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS, spellProto->DmgClass);
|
||||
|
||||
int32 durationMod = 0;
|
||||
// Select strongest negative mod
|
||||
|
|
@ -11578,6 +11729,7 @@ bool InitTriggerAuraData()
|
|||
isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true;
|
||||
isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true;
|
||||
isTriggerAura[SPELL_AURA_MOD_SPELL_CRIT_CHANCE] = true;
|
||||
isTriggerAura[SPELL_AURA_MAELSTROM_WEAPON] = true;
|
||||
|
||||
isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true;
|
||||
isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true;
|
||||
|
|
@ -11868,6 +12020,13 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
|||
continue;
|
||||
}
|
||||
break;
|
||||
case SPELL_AURA_MAELSTROM_WEAPON:
|
||||
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s maelstrom aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
|
||||
|
||||
// remove all stack;
|
||||
RemoveSpellsCausingAura(SPELL_AURA_MAELSTROM_WEAPON);
|
||||
triggeredByAura->SetInUse(false); // this safe, aura locked
|
||||
continue; // avoid re-remove attempts
|
||||
default:
|
||||
// nothing do, just charges counter
|
||||
break;
|
||||
|
|
@ -11890,7 +12049,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
|
|||
removedSpells.unique();
|
||||
// Remove auras from removedAuras
|
||||
for(RemoveSpellList::const_iterator i = removedSpells.begin(); i != removedSpells.end();++i)
|
||||
RemoveAurasDueToSpell(*i);
|
||||
RemoveSingleSpellAurasFromStack(*i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1176,7 +1176,7 @@ void World::SetInitialWorldSettings()
|
|||
sObjectMgr.LoadQuestLocales();
|
||||
sObjectMgr.LoadNpcTextLocales();
|
||||
sObjectMgr.LoadPageTextLocales();
|
||||
sObjectMgr.LoadNpcOptionLocales();
|
||||
sObjectMgr.LoadGossipMenuItemsLocales();
|
||||
sObjectMgr.LoadPointOfInterestLocales();
|
||||
sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
|
||||
sLog.outString( ">>> Localization strings loaded" );
|
||||
|
|
@ -1405,8 +1405,14 @@ void World::SetInitialWorldSettings()
|
|||
sLog.outString( "Loading Npc Text Id..." );
|
||||
sObjectMgr.LoadNpcTextId(); // must be after load Creature and NpcText
|
||||
|
||||
sLog.outString( "Loading Npc Options..." );
|
||||
sObjectMgr.LoadNpcOptions();
|
||||
sLog.outString( "Loading Gossip scripts..." );
|
||||
sObjectMgr.LoadGossipScripts(); // must be before gossip menu options
|
||||
|
||||
sLog.outString( "Loading Gossip menus..." );
|
||||
sObjectMgr.LoadGossipMenu();
|
||||
|
||||
sLog.outString( "Loading Gossip menu options..." );
|
||||
sObjectMgr.LoadGossipMenuItems();
|
||||
|
||||
sLog.outString( "Loading Vendors..." );
|
||||
sObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ void WorldSession::LogoutPlayer(bool Save)
|
|||
///- Teleport to home if the player is in an invalid instance
|
||||
if(!_player->m_InstanceValid && !_player->isGameMaster())
|
||||
{
|
||||
_player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation());
|
||||
_player->TeleportToHomebind();
|
||||
//this is a bad place to call for far teleport because we need player to be in world for successful logout
|
||||
//maybe we should implement delayed far teleport logout?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,6 +152,14 @@ bool ChatHandler::HandleCharacterDeleteCommand(const char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Close RA connection
|
||||
bool ChatHandler::HandleQuitCommand(const char* /*args*/)
|
||||
{
|
||||
// processed in RASocket
|
||||
SendSysMessage(LANG_QUIT_WRONG_USE_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Exit the realm
|
||||
bool ChatHandler::HandleServerExitCommand(const char* /*args*/)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -225,7 +225,10 @@ void RASocket::OnRead()
|
|||
if (strlen(buff))
|
||||
{
|
||||
sLog.outRALog("Got '%s' cmd.\n",buff);
|
||||
sWorld.QueueCliCommand(&RASocket::zprint , buff);
|
||||
if (strncmp(buff,"quit",4)==0)
|
||||
SetCloseAndDelete();
|
||||
else
|
||||
sWorld.QueueCliCommand(&RASocket::zprint, buff);
|
||||
}
|
||||
else
|
||||
Sendf("mangos>");
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ extern DatabasePostgre WorldDatabase;
|
|||
extern DatabaseMysql WorldDatabase;
|
||||
#endif
|
||||
|
||||
const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis";
|
||||
const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii";
|
||||
const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis";
|
||||
const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiiffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii";
|
||||
const char CreatureDataAddonInfofmt[]="iiiiiis";
|
||||
const char CreatureModelfmt[]="iffbi";
|
||||
const char CreatureInfoAddonInfofmt[]="iiiiiis";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8913"
|
||||
#define REVISION_NR "8971"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __REVISION_SQL_H__
|
||||
#define __REVISION_SQL_H__
|
||||
#define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills"
|
||||
#define REVISION_DB_MANGOS "required_8912_01_mangos_spell_proc_event"
|
||||
#define REVISION_DB_MANGOS "required_8965_02_mangos_command"
|
||||
#define REVISION_DB_REALMD "required_8728_01_realmd_account"
|
||||
#endif // __REVISION_SQL_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue