Merge remote branch 'origin/master' into 330

This commit is contained in:
tomrus88 2009-12-03 18:10:28 +03:00
commit 922544739b
27 changed files with 756 additions and 531 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_8891_01_mangos_spell_proc_event` bit(1) default NULL `required_8912_01_mangos_spell_proc_event` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -3081,7 +3081,7 @@ INSERT INTO `mangos_string` VALUES
(352,'Invalid title id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (352,'Invalid title id: %u',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(353,'Title %u (%s) added to known titles list for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (353,'Title %u (%s) added to known titles list for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(354,'Title %u (%s) removed from known titles list for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (354,'Title %u (%s) removed from known titles list for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(355,'Title %u (%s) set as current seelcted title for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (355,'Title %u (%s) set as current selected title for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(356,'Current selected title for player %s reset as not known now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (356,'Current selected title for player %s reset as not known now.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -16934,9 +16934,9 @@ INSERT INTO spell_chain VALUES
(25392,21564,21562,3,0), (25392,21564,21562,3,0),
(48162,25392,21562,4,0), (48162,25392,21562,4,0),
/*Prayer of Spirit*/ /*Prayer of Spirit*/
(27681,0,27681,1,14752), (27681,14752,14752,2,0),
(32999,27681,27681,2,0), (32999,27681,14752,3,0),
(48074,32999,27681,3,0), (48074,32999,14752,4,0),
/*Rapture*/ /*Rapture*/
(47535,0,47535,1,0), (47535,0,47535,1,0),
(47536,47535,47535,2,0), (47536,47535,47535,2,0),
@ -17774,7 +17774,7 @@ INSERT INTO `spell_proc_event` VALUES
(20215, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (20215, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(20234, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20234, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(20235, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20235, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(20335, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00000100, 0x00000000, 0.000000, 100.000000, 0), (20335, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00000100, 0x00000000, 0.000000, 100.000000,0),
(20375, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 7.000000, 0.000000, 0), (20375, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 7.000000, 0.000000, 0),
(20500, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20500, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(20501, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20501, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
@ -17884,7 +17884,7 @@ INSERT INTO `spell_proc_event` VALUES
(30805, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (30805, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(30808, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (30808, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(30809, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (30809, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(30823, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 10.500000, 0.000000, 0), (30823, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 10.500000, 0.000000, 0),
(30881, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5), (30881, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5),
(30883, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5), (30883, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5),
(30884, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5), (30884, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5),
@ -18325,6 +18325,7 @@ INSERT INTO `spell_proc_event` VALUES
(57878, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 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), (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), (57881, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
(57989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0.000000, 0.000000, 0),
(58357, 0x00000000, 4, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (58357, 0x00000000, 4, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(58364, 0x00000000, 4, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (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), (58372, 0x00000000, 4, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
@ -18385,7 +18386,9 @@ INSERT INTO `spell_proc_event` VALUES
(63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (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), (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), (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, 0x00400010, 0x20020004, 0x00000000, 0x00000010, 0x00000000, 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);
/*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;

View file

@ -300,6 +300,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(52042,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Healing Stream Totem', 'Spell::EffectDummy'), (52042,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Healing Stream Totem', 'Spell::EffectDummy'),
(52308, 0, -1, -1, -1, -1, -1, 3, -1, 0,'Take Sputum Sample', 'Spell::EffectDummy'), (52308, 0, -1, -1, -1, -1, -1, 3, -1, 0,'Take Sputum Sample', 'Spell::EffectDummy'),
(52308, 0, -1, -1, -1, -1, -1, 3, -1, 1,'Take Sputum Sample', 'Spell::EffectDummy'), (52308, 0, -1, -1, -1, -1, -1, 3, -1, 1,'Take Sputum Sample', 'Spell::EffectDummy'),
(52437,-1, -1, -1, -1, -1, -1, 6, -1, 0,'Sudden Death', 'Spell::EffectDummy'),
(52752,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Ancestral Awakening', 'Spell::EffectDummy'), (52752,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Ancestral Awakening', 'Spell::EffectDummy'),
(52759, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Ancestral Awakening', 'Spell::EffectDummy'), (52759, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Ancestral Awakening', 'Spell::EffectDummy'),
(52845,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Brewfest Mount Transformation (Faction Swap)','Spell::EffectDummy'), (52845,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Brewfest Mount Transformation (Faction Swap)','Spell::EffectDummy'),
@ -438,6 +439,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 2, -1,-1,'Steady Shot', 'Spell::EffectSchoolDMG'), ( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 2, -1,-1,'Steady Shot', 'Spell::EffectSchoolDMG'),
( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 3, -1,-1,'Steady Shot', 'Spell::EffectDummy'), ( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 3, -1,-1,'Steady Shot', 'Spell::EffectDummy'),
( 0, 8,0x0000000000400000,0x00000000, -1, -1, -1, -1, -1,-1,'Stealth', 'Spell::EffectTriggerSpell'), ( 0, 8,0x0000000000400000,0x00000000, -1, -1, -1, -1, -1,-1,'Stealth', 'Spell::EffectTriggerSpell'),
( 0,-1, -1, -1,1989, -1, -1, -1, 42, 0,'Sudden Death', 'Spell::EffectDummy'),
( 0, 7,0x0010000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Swipe', 'Spell::EffectSchoolDMG'), ( 0, 7,0x0010000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Swipe', 'Spell::EffectSchoolDMG'),
( 0, 4,0x0000000000000080,0x00000000, -1, -1, -1, 2, -1,-1,'Thunder Clap', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000000000000080,0x00000000, -1, -1, -1, 2, -1,-1,'Thunder Clap', 'Spell::EffectSchoolDMG'),
( 0, 4,0x0000010000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Victory Rush', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000010000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Victory Rush', 'Spell::EffectSchoolDMG'),

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8891_01_mangos_spell_proc_event required_8893_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry in (355);
INSERT INTO mangos_string VALUES
(355,'Title %u (%s) set as current selected title for player %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8893_01_mangos_mangos_string required_8899_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` IN (57989);
INSERT INTO `spell_proc_event` VALUES
(57989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,7 @@
ALTER TABLE db_version CHANGE COLUMN required_8899_01_mangos_spell_proc_event required_8908_01_mangos_spell_chain bit;
DELETE FROM spell_chain WHERE spell_id IN (27681,32999,48074);
INSERT INTO spell_chain VALUES
(27681,14752,14752,2,0),
(32999,27681,14752,3,0),
(48074,32999,14752,4,0);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8908_01_mangos_spell_chain required_8909_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` IN (64127);
INSERT INTO `spell_proc_event` VALUES
(64127, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8909_01_mangos_spell_proc_event required_8912_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` IN (67353);
INSERT INTO `spell_proc_event` VALUES
(67353, 0x00000000, 7, 0x00008000, 0x00100500, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -183,6 +183,11 @@ pkgdata_DATA = \
8886_01_mangos_string.sql \ 8886_01_mangos_string.sql \
8889_01_mangos_spell_pet_auras.sql \ 8889_01_mangos_spell_pet_auras.sql \
8891_01_mangos_spell_proc_event.sql \ 8891_01_mangos_spell_proc_event.sql \
8893_01_mangos_mangos_string.sql \
8899_01_mangos_spell_proc_event.sql \
8908_01_mangos_spell_chain.sql \
8909_01_mangos_spell_proc_event.sql \
8912_01_mangos_spell_proc_event.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -346,4 +351,9 @@ EXTRA_DIST = \
8886_01_mangos_string.sql \ 8886_01_mangos_string.sql \
8889_01_mangos_spell_pet_auras.sql \ 8889_01_mangos_spell_pet_auras.sql \
8891_01_mangos_spell_proc_event.sql \ 8891_01_mangos_spell_proc_event.sql \
8893_01_mangos_mangos_string.sql \
8899_01_mangos_spell_proc_event.sql \
8908_01_mangos_spell_chain.sql \
8909_01_mangos_spell_proc_event.sql \
8912_01_mangos_spell_proc_event.sql \
README README

View file

@ -744,309 +744,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class; && pPlayer->getClass() == GetCreatureInfo()->trainer_class;
} }
void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid )
{
PlayerMenu* pm=pPlayer->PlayerTalkClass;
pm->ClearMenus();
// lazy loading single time at use
LoadGossipOptions();
for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); ++i )
{
GossipOption* gso=&*i;
if(gso->GossipId == gossipid)
{
bool cantalking=true;
if(gso->Id==1)
{
uint32 textid=GetNpcTextId();
GossipText const* gossiptext=sObjectMgr.GetGossipText(textid);
if(!gossiptext)
cantalking=false;
}
else
{
switch (gso->Action)
{
case GOSSIP_OPTION_QUESTGIVER:
pPlayer->PrepareQuestMenu(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( !pPlayer->isDead() )
cantalking=false;
break;
case GOSSIP_OPTION_VENDOR:
{
VendorItemData const* vItems = GetVendorItems();
if(!vItems || vItems->Empty())
{
sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.",
GetGUIDLow(),GetEntry());
cantalking=false;
}
break;
}
case GOSSIP_OPTION_TRAINER:
if(!isCanTrainingOf(pPlayer,false))
cantalking=false;
break;
case GOSSIP_OPTION_UNLEARNTALENTS:
if(!isCanTrainingAndResetTalentsOf(pPlayer))
cantalking=false;
break;
case GOSSIP_OPTION_UNLEARNPETSKILLS:
if(!pPlayer->GetPet() || pPlayer->GetPet()->getPetType() != HUNTER_PET || pPlayer->GetPet()->m_spells.size() <= 1 || GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || GetCreatureInfo()->trainer_class != CLASS_HUNTER)
cantalking=false;
break;
case GOSSIP_OPTION_TAXIVENDOR:
if ( pPlayer->GetSession()->SendLearnNewTaxiNode(this) )
return;
break;
case GOSSIP_OPTION_BATTLEFIELD:
if(!isCanInteractWithBattleMaster(pPlayer,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",GetDBTableGUIDLow(),GetEntry(),gso->Action);
break;
}
}
//note for future dev: should have database fields for BoxMessage & BoxMoney
if(!gso->OptionText.empty() && cantalking)
{
std::string OptionText = gso->OptionText;
std::string BoxText = gso->BoxText;
int loc_idx = pPlayer->GetSession()->GetSessionDbLocaleIndex();
if (loc_idx >= 0)
{
NpcOptionLocale const *no = sObjectMgr.GetNpcOptionLocale(gso->Id);
if (no)
{
if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty())
OptionText=no->OptionText[loc_idx];
if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty())
BoxText=no->BoxText[loc_idx];
}
}
pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded);
}
}
}
///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-)
if(pm->Empty())
{
if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER))
{
isCanTrainingOf(pPlayer,true); // output error message if need
}
if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER))
{
isCanInteractWithBattleMaster(pPlayer,true); // output error message if need
}
}
}
void Creature::sendPreparedGossip(Player* player)
{
if(!player)
return;
// in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag)
if (!HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !player->PlayerTalkClass->GetQuestMenu().Empty())
{
player->SendPreparedQuest(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)
player->PlayerTalkClass->SendGossipMenu(GetNpcTextId(), GetGUID());
}
void Creature::OnGossipSelect(Player* player, uint32 option)
{
GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu();
if(option >= gossipmenu.MenuItemCount())
return;
uint32 action=gossipmenu.GetItem(option).m_gAction;
uint32 zoneid=GetZoneId();
uint64 guid=GetGUID();
GossipOption const *gossip=GetGossipOption( action );
if(!gossip)
{
zoneid=0;
gossip=GetGossipOption( action );
if(!gossip)
return;
}
switch (gossip->Action)
{
case GOSSIP_OPTION_GOSSIP:
{
uint32 textid = GetGossipTextId(action, zoneid);
if (textid == 0)
textid=GetNpcTextId();
player->PlayerTalkClass->CloseGossip();
player->PlayerTalkClass->SendTalking(textid);
break;
}
case GOSSIP_OPTION_SPIRITHEALER:
if (player->isDead())
CastSpell(this,17251,true,NULL,NULL,player->GetGUID());
break;
case GOSSIP_OPTION_QUESTGIVER:
player->PrepareQuestMenu( guid );
player->SendPreparedQuest( guid );
break;
case GOSSIP_OPTION_VENDOR:
case GOSSIP_OPTION_ARMORER:
player->GetSession()->SendListInventory(guid);
break;
case GOSSIP_OPTION_STABLEPET:
player->GetSession()->SendStablePet(guid);
break;
case GOSSIP_OPTION_TRAINER:
player->GetSession()->SendTrainerList(guid);
break;
case GOSSIP_OPTION_UNLEARNTALENTS:
player->PlayerTalkClass->CloseGossip();
player->SendTalentWipeConfirm(guid);
break;
case GOSSIP_OPTION_UNLEARNPETSKILLS:
player->PlayerTalkClass->CloseGossip();
player->SendPetSkillWipeConfirm();
break;
case GOSSIP_OPTION_TAXIVENDOR:
player->GetSession()->SendTaxiMenu(this);
break;
case GOSSIP_OPTION_INNKEEPER:
player->PlayerTalkClass->CloseGossip();
player->SetBindPoint( guid );
break;
case GOSSIP_OPTION_BANKER:
player->GetSession()->SendShowBank( guid );
break;
case GOSSIP_OPTION_PETITIONER:
player->PlayerTalkClass->CloseGossip();
player->GetSession()->SendPetitionShowList( guid );
break;
case GOSSIP_OPTION_TABARDDESIGNER:
player->PlayerTalkClass->CloseGossip();
player->GetSession()->SendTabardVendorActivate( guid );
break;
case GOSSIP_OPTION_AUCTIONEER:
player->GetSession()->SendAuctionHello( guid, this );
break;
case GOSSIP_OPTION_SPIRITGUIDE:
case GOSSIP_GUARD_SPELLTRAINER:
case GOSSIP_GUARD_SKILLTRAINER:
prepareGossipMenu( player,gossip->Id );
sendPreparedGossip( player );
break;
case GOSSIP_OPTION_BATTLEFIELD:
{
BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry());
if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
sLog.outError("a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", player->GetGUIDLow());
return;
}
player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId );
break;
}
default:
OnPoiSelect( player, gossip );
break;
}
}
void Creature::OnPoiSelect(Player* player, 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() );
player->PlayerTalkClass->SendTalking(textid);
// std::string areaname= gossip->OptionText;
// how this could worked player->PlayerTalkClass->SendPointOfInterest( x, y, icon, 2, 15, areaname.c_str() );
}
}
uint32 Creature::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 Creature::GetNpcTextId()
{
if (!m_DBTableGuid)
return DEFAULT_GOSSIP_MESSAGE;
if(uint32 pos = sObjectMgr.GetNpcGossip(m_DBTableGuid))
return pos;
return DEFAULT_GOSSIP_MESSAGE;
}
GossipOption const* Creature::GetGossipOption( uint32 id ) const
{
for( GossipOptionList::const_iterator i = m_goptions.begin( ); i != m_goptions.end( ); ++i )
{
if(i->Action==id )
return &*i;
}
return NULL;
}
void Creature::LoadGossipOptions() void Creature::LoadGossipOptions()
{ {
if(m_gossipOptionLoaded) if(m_gossipOptionLoaded)

View file

@ -576,16 +576,9 @@ class MANGOS_DLL_SPEC Creature : public Unit
std::string GetScriptName() const; std::string GetScriptName() const;
uint32 GetScriptId() const; uint32 GetScriptId() const;
void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 );
void sendPreparedGossip( Player* player );
void OnGossipSelect(Player* player, uint32 option);
void OnPoiSelect(Player* player, GossipOption const *gossip);
uint32 GetGossipTextId(uint32 action, uint32 zoneid);
uint32 GetNpcTextId();
void LoadGossipOptions(); void LoadGossipOptions();
GossipOption const* GetGossipOption( uint32 id ) const;
void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); } 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 Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }

View file

@ -44,13 +44,13 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
if (count == 0) if (count == 0)
return; //check count - if zero it's fake packet return; //check count - if zero it's fake packet
if(!_player->IsValidPos(srcbag, srcslot)) if(!_player->IsValidPos(srcbag, srcslot, true))
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return; return;
} }
if(!_player->IsValidPos(dstbag, dstslot)) if(!_player->IsValidPos(dstbag, dstslot, false)) // can be autostore pos
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
return; return;
@ -71,13 +71,13 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
if(srcslot == dstslot) if(srcslot == dstslot)
return; return;
if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot)) if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true))
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return; return;
} }
if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, true))
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
return; return;
@ -123,13 +123,13 @@ void WorldSession::HandleSwapItem( WorldPacket & recv_data )
if(src == dst) if(src == dst)
return; return;
if(!_player->IsValidPos(srcbag, srcslot)) if(!_player->IsValidPos(srcbag, srcslot, true))
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return; return;
} }
if(!_player->IsValidPos(dstbag, dstslot)) if(!_player->IsValidPos(dstbag, dstslot, true))
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
return; return;
@ -425,7 +425,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->GemProperties; data << pProto->GemProperties;
data << pProto->RequiredDisenchantSkill; data << pProto->RequiredDisenchantSkill;
data << pProto->ArmorDamageModifier; data << pProto->ArmorDamageModifier;
data << pProto->Duration; // added in 2.4.2.8209, duration (seconds) data << abs(pProto->Duration); // added in 2.4.2.8209, duration (seconds)
data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
data << pProto->HolidayId; // Holiday.dbc? data << pProto->HolidayId; // Holiday.dbc?
SendPacket( &data ); SendPacket( &data );
@ -783,7 +783,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
if( !pItem ) if( !pItem )
return; return;
if(!_player->IsValidPos(dstbag, NULL_SLOT)) if(!_player->IsValidPos(dstbag, NULL_SLOT, false)) // can be autostore pos
{ {
_player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
return; return;

View file

@ -2011,10 +2011,11 @@ bool ChatHandler::HandleItemMoveCommand(const char* args)
if(srcslot==dstslot) if(srcslot==dstslot)
return true; return true;
if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true))
return false; return false;
if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) // can be autostore pos
if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot, false))
return false; return false;
uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);

View file

@ -277,8 +277,8 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data)
if (!Script->GossipHello(_player, pCreature)) if (!Script->GossipHello(_player, pCreature))
{ {
_player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); _player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
pCreature->prepareGossipMenu(_player); _player->PrepareGossipMenu(pCreature);
pCreature->sendPreparedGossip(_player); _player->SendPreparedGossip(pCreature);
} }
} }
@ -287,39 +287,40 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
uint32 option; uint32 option;
uint32 unk; uint32 menuId;
uint64 guid; uint64 guid;
std::string code = ""; std::string code = "";
recv_data >> guid >> unk >> option; recv_data >> guid >> menuId >> option;
if(_player->PlayerTalkClass->GossipOptionCoded( option )) if (_player->PlayerTalkClass->GossipOptionCoded(option))
{ {
sLog.outBasic("reading string"); sLog.outBasic("reading string");
recv_data >> code; recv_data >> code;
sLog.outBasic("string read: %s", code.c_str()); sLog.outBasic("string read: %s", code.c_str());
} }
Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
if (!unit)
if (!pCreature)
{ {
sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
return; return;
} }
// remove fake death // remove fake death
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
if(!code.empty()) if (!code.empty())
{ {
if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str())) if (!Script->GossipSelectWithCode(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str()))
unit->OnGossipSelect (_player, option); _player->OnGossipSelect(pCreature, option);
} }
else else
{ {
if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) if (!Script->GossipSelect(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option)))
unit->OnGossipSelect (_player, option); _player->OnGossipSelect(pCreature, option);
} }
} }

View file

@ -4044,6 +4044,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",guid);
@ -8644,16 +8645,16 @@ bool Player::IsBagPos( uint16 pos )
return false; return false;
} }
bool Player::IsValidPos( uint8 bag, uint8 slot ) bool Player::IsValidPos( uint8 bag, uint8 slot, bool explicit_pos )
{ {
// post selected // post selected
if(bag == NULL_BAG) if(bag == NULL_BAG && !explicit_pos)
return true; return true;
if (bag == INVENTORY_SLOT_BAG_0) if (bag == INVENTORY_SLOT_BAG_0)
{ {
// any post selected // any post selected
if (slot == NULL_SLOT) if (slot == NULL_SLOT && !explicit_pos)
return true; return true;
// equipment // equipment
@ -8691,7 +8692,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
return false; return false;
// any post selected // any post selected
if (slot == NULL_SLOT) if (slot == NULL_SLOT && !explicit_pos)
return true; return true;
return slot < pBag->GetBagSize(); return slot < pBag->GetBagSize();
@ -8705,7 +8706,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
return false; return false;
// any post selected // any post selected
if (slot == NULL_SLOT) if (slot == NULL_SLOT && !explicit_pos)
return true; return true;
return slot < pBag->GetBagSize(); return slot < pBag->GetBagSize();
@ -8997,8 +8998,9 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
if (bag==skip_bag) if (bag==skip_bag)
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
// skip not existed bag or self targeted bag
Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag ); Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag );
if (!pBag) if (!pBag || pBag==pSrcItem)
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
ItemPrototype const* pBagProto = pBag->GetProto(); ItemPrototype const* pBagProto = pBag->GetProto();
@ -12172,6 +12174,338 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }
/*********************************************************/
/*** GOSSIP SYSTEM ***/
/*********************************************************/
void Player::PrepareGossipMenu(WorldObject *pSource, uint32 gossipid)
{
PlayerMenu* pMenu = PlayerTalkClass;
pMenu->ClearMenus();
if (pSource->GetTypeId() != TYPEID_UNIT)
return;
Creature *pCreature = (Creature*)pSource;
// lazy loading single time at use
pCreature->LoadGossipOptions();
GossipOptionList &iOptList = pCreature->GetGossipOptionList();
for(GossipOptionList::iterator i = iOptList.begin( ); i != iOptList.end( ); ++i)
{
GossipOption* gso = &*i;
if (gso->GossipId == gossipid)
{
bool cantalking = true;
if (gso->Id == 1)
{
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());
//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;
}
}
//note for future dev: should have database fields for BoxMessage & BoxMoney
if (!gso->OptionText.empty() && cantalking)
{
std::string OptionText = gso->OptionText;
std::string BoxText = gso->BoxText;
int loc_idx = GetSession()->GetSessionDbLocaleIndex();
if (loc_idx >= 0)
{
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->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty())
BoxText = no->BoxText[loc_idx];
}
}
pMenu->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded);
}
}
}
///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))
{
// output error message if need
pCreature->isCanTrainingOf(this, true);
}
if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER))
{
// output error message if need
pCreature->isCanInteractWithBattleMaster(this, true);
}
}
}
void Player::SendPreparedGossip(WorldObject *pSource)
{
if (!pSource || pSource->GetTypeId() != TYPEID_UNIT)
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;
}
// 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());
}
void Player::OnGossipSelect(WorldObject* pSource, uint32 option)
{
GossipMenu& gossipmenu = PlayerTalkClass->GetGossipMenu();
if (option >= gossipmenu.MenuItemCount())
return;
uint32 action = gossipmenu.GetItem(option).m_gAction;
uint32 zoneid = GetZoneId();
uint64 guid = pSource->GetGUID();
GossipOption const *gossip = GetGossipOption(pSource, action);
if (!gossip)
{
zoneid = 0;
gossip = GetGossipOption(pSource, action);
if (!gossip)
return;
}
switch(gossip->Action)
{
case GOSSIP_OPTION_GOSSIP:
{
uint32 textid = GetGossipTextId(action, zoneid);
if (textid == 0)
textid = GetGossipTextId(pSource);
PlayerTalkClass->CloseGossip();
PlayerTalkClass->SendTalking(textid);
break;
}
case GOSSIP_OPTION_SPIRITHEALER:
if (isDead())
((Creature*)pSource)->CastSpell(((Creature*)pSource),17251,true,NULL,NULL,GetGUID());
break;
case GOSSIP_OPTION_QUESTGIVER:
PrepareQuestMenu(guid);
SendPreparedQuest(guid);
break;
case GOSSIP_OPTION_VENDOR:
case GOSSIP_OPTION_ARMORER:
GetSession()->SendListInventory(guid);
break;
case GOSSIP_OPTION_STABLEPET:
GetSession()->SendStablePet(guid);
break;
case GOSSIP_OPTION_TRAINER:
GetSession()->SendTrainerList(guid);
break;
case GOSSIP_OPTION_UNLEARNTALENTS:
PlayerTalkClass->CloseGossip();
SendTalentWipeConfirm(guid);
break;
case GOSSIP_OPTION_UNLEARNPETSKILLS:
PlayerTalkClass->CloseGossip();
SendPetSkillWipeConfirm();
break;
case GOSSIP_OPTION_TAXIVENDOR:
GetSession()->SendTaxiMenu(((Creature*)pSource));
break;
case GOSSIP_OPTION_INNKEEPER:
PlayerTalkClass->CloseGossip();
SetBindPoint(guid);
break;
case GOSSIP_OPTION_BANKER:
GetSession()->SendShowBank(guid);
break;
case GOSSIP_OPTION_PETITIONER:
PlayerTalkClass->CloseGossip();
GetSession()->SendPetitionShowList(guid);
break;
case GOSSIP_OPTION_TABARDDESIGNER:
PlayerTalkClass->CloseGossip();
GetSession()->SendTabardVendorActivate(guid);
break;
case GOSSIP_OPTION_AUCTIONEER:
GetSession()->SendAuctionHello(guid, ((Creature*)pSource));
break;
case GOSSIP_OPTION_SPIRITGUIDE:
case GOSSIP_GUARD_SPELLTRAINER:
case GOSSIP_GUARD_SKILLTRAINER:
PrepareGossipMenu(pSource, gossip->Id);
SendPreparedGossip(pSource);
break;
case GOSSIP_OPTION_BATTLEFIELD:
{
BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(pSource->GetEntry());
if (bgTypeId == BATTLEGROUND_TYPE_NONE)
{
sLog.outError("a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", GetGUIDLow());
return;
}
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;
if (uint32 pos = sObjectMgr.GetNpcGossip(((Creature*)pSource)->GetDBTableGUIDLow()))
return pos;
return DEFAULT_GOSSIP_MESSAGE;
}
GossipOption const* Player::GetGossipOption(WorldObject *pSource, uint32 id) const
{
if (pSource->GetTypeId() == TYPEID_UNIT)
{
GossipOptionList &iOptlist = ((Creature*)pSource)->GetGossipOptionList();
for(GossipOptionList::const_iterator i = iOptlist.begin( ); i != iOptlist.end( ); ++i)
{
if (i->Action == id)
return &*i;
}
}
return NULL;
}
/*********************************************************/ /*********************************************************/
/*** QUEST SYSTEM ***/ /*** QUEST SYSTEM ***/
/*********************************************************/ /*********************************************************/
@ -12279,7 +12613,8 @@ void Player::SendPreparedQuest(uint64 guid)
// need pet case for some quests // need pet case for some quests
if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid)) if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid))
{ {
uint32 textid = pCreature->GetNpcTextId(); uint32 textid = GetGossipTextId(pCreature);
GossipText const* gossiptext = sObjectMgr.GetGossipText(textid); GossipText const* gossiptext = sObjectMgr.GetGossipText(textid);
if (!gossiptext) if (!gossiptext)
{ {
@ -14954,9 +15289,9 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
bool success = true; bool success = true;
// the item/bag is not in a bag
if (!bag_guid) if (!bag_guid)
{ {
// the item is not in a bag
item->SetContainer( NULL ); item->SetContainer( NULL );
item->SetSlot(slot); item->SetSlot(slot);
@ -14992,13 +15327,20 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
bagMap[item_guid] = (Bag*)item; bagMap[item_guid] = (Bag*)item;
} }
} }
// the item/bag in a bag
else else
{ {
item->SetSlot(NULL_SLOT); item->SetSlot(NULL_SLOT);
// the item is in a bag, find the bag // the item is in a bag, find the bag
std::map<uint64, Bag*>::const_iterator itr = bagMap.find(bag_guid); std::map<uint64, Bag*>::const_iterator itr = bagMap.find(bag_guid);
if(itr != bagMap.end() && slot < itr->second->GetBagSize()) if(itr != bagMap.end() && slot < itr->second->GetBagSize())
itr->second->StoreItem(slot, item, true ); {
ItemPosCountVec dest;
if( CanStoreItem( itr->second->GetSlot(), slot, dest, item, false ) == EQUIP_ERR_OK )
item = StoreItem(dest, item, true);
else
success = false;
}
else else
success = false; success = false;
} }

View file

@ -1174,8 +1174,8 @@ class MANGOS_DLL_SPEC Player : public Unit
static bool IsBagPos( uint16 pos ); static bool IsBagPos( uint16 pos );
static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8, pos & 255); } static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8, pos & 255); }
static bool IsBankPos( uint8 bag, uint8 slot ); static bool IsBankPos( uint8 bag, uint8 slot );
bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8, pos & 255); } bool IsValidPos( uint16 pos, bool explicit_pos ) { return IsValidPos(pos >> 8, pos & 255, explicit_pos); }
bool IsValidPos( uint8 bag, uint8 slot ); bool IsValidPos( uint8 bag, uint8 slot, bool explicit_pos );
uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); } uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); }
void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); } void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); }
bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const;
@ -1296,6 +1296,19 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_stableSlots; uint32 m_stableSlots;
/*********************************************************/
/*** GOSSIP SYSTEM ***/
/*********************************************************/
void PrepareGossipMenu(WorldObject *pSource, uint32 gossipid = 0);
void SendPreparedGossip(WorldObject *pSource);
void OnGossipSelect(WorldObject *pSource, uint32 option);
void OnPoiSelect(WorldObject *pSource, GossipOption const *gossip);
uint32 GetGossipTextId(uint32 action, uint32 zoneid);
uint32 GetGossipTextId(WorldObject *pSource);
GossipOption const* GetGossipOption(WorldObject *pSource, uint32 id) const;
/*********************************************************/ /*********************************************************/
/*** QUEST SYSTEM ***/ /*** QUEST SYSTEM ***/
/*********************************************************/ /*********************************************************/

View file

@ -24,15 +24,16 @@
#include "ObjectMgr.h" #include "ObjectMgr.h"
// Character Dump tables // Character Dump tables
#define DUMP_TABLE_COUNT 21
struct DumpTable struct DumpTable
{ {
char const* name; char const* name;
DumpTableType type; DumpTableType type;
// helpers
bool isValid() const { return name != NULL; }
}; };
static DumpTable dumpTables[DUMP_TABLE_COUNT] = static DumpTable dumpTables[] =
{ {
{ "characters", DTT_CHARACTER }, { "characters", DTT_CHARACTER },
{ "character_achievement", DTT_CHAR_TABLE }, { "character_achievement", DTT_CHAR_TABLE },
@ -44,6 +45,7 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_action", DTT_CHAR_TABLE }, { "character_action", DTT_CHAR_TABLE },
{ "character_aura", DTT_CHAR_TABLE }, { "character_aura", DTT_CHAR_TABLE },
{ "character_homebind", DTT_CHAR_TABLE }, { "character_homebind", DTT_CHAR_TABLE },
{ "character_skills", DTT_CHAR_TABLE },
{ "character_ticket", DTT_CHAR_TABLE }, { "character_ticket", DTT_CHAR_TABLE },
{ "character_inventory", DTT_INVENTORY }, { "character_inventory", DTT_INVENTORY },
{ "mail", DTT_MAIL }, { "mail", DTT_MAIL },
@ -55,6 +57,7 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "pet_aura", DTT_PET_TABLE }, { "pet_aura", DTT_PET_TABLE },
{ "pet_spell", DTT_PET_TABLE }, { "pet_spell", DTT_PET_TABLE },
{ "pet_spell_cooldown", DTT_PET_TABLE }, { "pet_spell_cooldown", DTT_PET_TABLE },
{ NULL, DTT_CHAR_TABLE }, // end marker
}; };
// Low level functions // Low level functions
@ -258,7 +261,7 @@ void StoreGUID(QueryResult *result,uint32 data,uint32 field, std::set<uint32>& g
} }
// Writing - High-level functions // Writing - High-level functions
void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) void PlayerDumpWriter::DumpTableContent(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type)
{ {
GUIDs const* guids = NULL; GUIDs const* guids = NULL;
char const* fieldname = NULL; char const* fieldname = NULL;
@ -362,8 +365,8 @@ std::string PlayerDumpWriter::GetDump(uint32 guid)
else else
sLog.outError("Character DB not have 'character_db_version' table, revision guard query not added to pdump."); sLog.outError("Character DB not have 'character_db_version' table, revision guard query not added to pdump.");
for(int i = 0; i < DUMP_TABLE_COUNT; ++i) for(DumpTable* itr = &dumpTables[0]; itr->isValid(); ++itr)
DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type); DumpTableContent(dump, guid, itr->name, itr->name, itr->type);
// TODO: Add instance/group.. // TODO: Add instance/group..
// TODO: Add a dump level option to skip some non-important tables // TODO: Add a dump level option to skip some non-important tables
@ -497,17 +500,17 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
} }
DumpTableType type; DumpTableType type;
uint8 i; DumpTable* dTable = &dumpTables[0];
for(i = 0; i < DUMP_TABLE_COUNT; ++i) for(; dTable->isValid(); ++dTable)
{ {
if (tn == dumpTables[i].name) if (tn == dTable->name)
{ {
type = dumpTables[i].type; type = dTable->type;
break; break;
} }
} }
if (i == DUMP_TABLE_COUNT) if (!dTable->isValid())
{ {
sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str());
ROLLBACK(DUMP_FILE_BROKEN); ROLLBACK(DUMP_FILE_BROKEN);

View file

@ -75,7 +75,7 @@ class PlayerDumpWriter : public PlayerDump
private: private:
typedef std::set<uint32> GUIDs; typedef std::set<uint32> GUIDs;
void DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type); void DumpTableContent(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type);
std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr); std::string GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr);
std::string GenerateWhereStr(char const* field, uint32 guid); std::string GenerateWhereStr(char const* field, uint32 guid);

View file

@ -102,8 +102,8 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data)
if (Script->GossipHello(_player, pCreature)) if (Script->GossipHello(_player, pCreature))
return; return;
pCreature->prepareGossipMenu(_player); _player->PrepareGossipMenu(pCreature);
pCreature->sendPreparedGossip(_player); _player->SendPreparedGossip(pCreature);
} }
void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data ) void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data )

View file

@ -2532,8 +2532,14 @@ void Spell::cast(bool skipCheck)
break; break;
case SPELLFAMILY_PALADIN: case SPELLFAMILY_PALADIN:
{ {
// Hand of Reckoning
if (m_spellInfo->Id == 62124)
{
if (m_targets.getUnitTarget() && m_targets.getUnitTarget()->getVictim() != m_caster)
AddPrecastSpell(67485); // Hand of Rekoning (no typos in name ;) )
}
// Divine Shield, Divine Protection or Hand of Protection // Divine Shield, Divine Protection or Hand of Protection
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080)) else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080))
{ {
AddPrecastSpell(25771); // Forbearance AddPrecastSpell(25771); // Forbearance
AddPrecastSpell(61987); // Avenging Wrath Marker AddPrecastSpell(61987); // Avenging Wrath Marker
@ -3795,7 +3801,7 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
damage = int32(CalculateDamage((uint8)i, unitTarget) * DamageMultiplier); damage = int32(CalculateDamage((uint8)i, unitTarget) * DamageMultiplier);
sLog.outDebug( "Spell: Effect : %u", eff); sLog.outDebug( "Spell %u Effect%d : %u", m_spellInfo->Id, i, eff);
if(eff<TOTAL_SPELL_EFFECTS) if(eff<TOTAL_SPELL_EFFECTS)
{ {

View file

@ -2209,8 +2209,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
if(!Real) if(!Real)
return; return;
Unit* caster = GetCaster();
// AT APPLY // AT APPLY
if(apply) if(apply)
{ {
@ -2218,12 +2216,13 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
{ {
case 1515: // Tame beast 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 // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
if( caster && m_target->CanHaveThreatList()) if (m_target->CanHaveThreatList())
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); if (Unit* caster = GetCaster())
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
return; return;
case 13139: // net-o-matic case 13139: // net-o-matic
// root to self part of (root_target->charge->root_self sequence // root to self part of (root_target->charge->root_self sequence
if(caster) if (Unit* caster = GetCaster())
caster->CastSpell(caster, 13138, true, NULL, this); caster->CastSpell(caster, 13138, true, NULL, this);
return; return;
case 39850: // Rocket Blast case 39850: // Rocket Blast
@ -2234,7 +2233,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->PlayDistanceSound(11965); m_target->PlayDistanceSound(11965);
return; return;
case 46354: // Blood Elf Illusion case 46354: // Blood Elf Illusion
if(caster) if (Unit* caster = GetCaster())
{ {
switch(caster->getGender()) switch(caster->getGender())
{ {
@ -2256,11 +2255,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
} }
// Earth Shield // Earth Shield
if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x40000000000))) if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x40000000000)))
{ {
// prevent double apply bonuses // prevent double apply bonuses
if(m_target->GetTypeId() != TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) if(m_target->GetTypeId() != TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); if (Unit* caster = GetCaster())
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
return; return;
} }
} }
@ -2278,8 +2278,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
return; return;
} }
if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive()) if (IsQuestTameSpell(GetId()) && m_target->isAlive())
{ {
Unit* caster = GetCaster();
if (!caster || !caster->isAlive())
return;
uint32 finalSpelId = 0; uint32 finalSpelId = 0;
switch(GetId()) switch(GetId())
{ {
@ -2340,23 +2344,24 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
} }
} }
if (caster && m_removeMode == AURA_REMOVE_BY_DEATH) if (m_removeMode == AURA_REMOVE_BY_DEATH)
{ {
// Stop caster Arcane Missle chanelling on death // Stop caster Arcane Missle chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE && if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000800))) (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000800)))
{ {
caster->InterruptSpell(CURRENT_CHANNELED_SPELL); if (Unit* caster = GetCaster())
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return; return;
} }
// Stop caster Penance chanelling on death // Stop caster Penance chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
(m_spellProto->SpellFamilyFlags2 & UI64LIT(0x00000080))) (m_spellProto->SpellFamilyFlags2 & UI64LIT(0x00000080)))
{ {
caster->InterruptSpell(CURRENT_CHANNELED_SPELL); if (Unit* caster = GetCaster())
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return; return;
} }
} }
} }
@ -2376,14 +2381,15 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
case 24658: case 24658:
{ {
uint32 spellId = 24659; uint32 spellId = 24659;
if (apply && caster) if (apply)
{ {
const SpellEntry *spell = sSpellStore.LookupEntry(spellId); SpellEntry const *spell = sSpellStore.LookupEntry(spellId);
if (!spell) Unit* caster = GetCaster();
if (!spell || !caster)
return; return;
for (int i=0; i < spell->StackAmount; ++i) for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); caster->CastSpell(m_target, spellId, true, NULL, NULL, GetCasterGUID());
return; return;
} }
m_target->RemoveAurasDueToSpell(spellId); m_target->RemoveAurasDueToSpell(spellId);
@ -2393,10 +2399,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
case 24661: case 24661:
{ {
uint32 spellId = 24662; uint32 spellId = 24662;
if (apply && caster) if (apply)
{ {
const SpellEntry *spell = sSpellStore.LookupEntry(spellId); SpellEntry const* spell = sSpellStore.LookupEntry(spellId);
if (!spell) Unit* caster = GetCaster();
if (!spell || !caster)
return; return;
for (int i=0; i < spell->StackAmount; ++i) for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
@ -2408,6 +2415,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
//Summon Fire Elemental //Summon Fire Elemental
case 40133: case 40133:
{ {
Unit* caster = GetCaster();
if (!caster) if (!caster)
return; return;
@ -2424,6 +2432,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
//Summon Earth Elemental //Summon Earth Elemental
case 40132 : case 40132 :
{ {
Unit* caster = GetCaster();
if (!caster) if (!caster)
return; return;
@ -2499,7 +2508,9 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
else else
{ {
int32 bp0 = m_modifier.m_amount; int32 bp0 = m_modifier.m_amount;
m_target->CastCustomSpell(caster,48210,&bp0,NULL,NULL,true);
if (Unit* caster = GetCaster())
m_target->CastCustomSpell(caster,48210,&bp0,NULL,NULL,true);
} }
} }
break; break;
@ -2586,7 +2597,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
{ {
if ( apply ) if ( apply )
{ {
if ( caster ) if (Unit* caster = GetCaster())
// prevent double apply bonuses // prevent double apply bonuses
if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE);
@ -2610,7 +2621,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
int32 amount = m_modifier.m_amount / m_stackAmount; int32 amount = m_modifier.m_amount / m_stackAmount;
m_target->CastCustomSpell(m_target, 33778, &amount, NULL, NULL, true, NULL, this, GetCasterGUID()); m_target->CastCustomSpell(m_target, 33778, &amount, NULL, NULL, true, NULL, this, GetCasterGUID());
if (caster) if (Unit* caster = GetCaster())
{ {
int32 returnmana = (GetSpellProto()->ManaCostPercentage * caster->GetCreateMana() / 100) * m_stackAmount / 2; int32 returnmana = (GetSpellProto()->ManaCostPercentage * caster->GetCreateMana() / 100) * m_stackAmount / 2;
caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID()); caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID());
@ -3269,9 +3280,7 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real)
{ {
if(Real && !apply) if(Real && !apply)
{ {
Unit* caster = GetCaster(); if(m_removeMode != AURA_REMOVE_BY_DEATH)
Unit* victim = GetTarget();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode != AURA_REMOVE_BY_DEATH)
return; return;
// Item amount // Item amount
if (m_modifier.m_amount <= 0) if (m_modifier.m_amount <= 0)
@ -3281,6 +3290,11 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real)
if(spellInfo->EffectItemType[m_effIndex] == 0) if(spellInfo->EffectItemType[m_effIndex] == 0)
return; return;
Unit* victim = GetTarget();
Unit* caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
// Soul Shard only from non-grey units // Soul Shard only from non-grey units
if( spellInfo->EffectItemType[m_effIndex] == 6265 && if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
(victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) || (victim->getLevel() <= MaNGOS::XP::GetGrayLevel(caster->getLevel()) ||
@ -4437,20 +4451,21 @@ void Aura::HandlePeriodicEnergize(bool apply, bool Real)
{ {
case 54833: // Glyph of Innervate (value%/2 of casters base mana) case 54833: // Glyph of Innervate (value%/2 of casters base mana)
{ {
Unit* caster = GetCaster(); if (Unit* caster = GetCaster())
m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (200 * m_maxduration / m_periodicTimer)); m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (200 * m_maxduration / m_periodicTimer));
break; break;
} }
case 29166: // Innervate (value% of casters base mana) case 29166: // Innervate (value% of casters base mana)
{ {
Unit* caster = GetCaster(); if (Unit* caster = GetCaster())
{
// Glyph of Innervate
if (caster->HasAura(54832))
caster->CastSpell(caster,54833,true,NULL,this);
// Glyph of Innervate m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (100 * m_maxduration / m_periodicTimer));
if (caster && caster->HasAura(54832)) }
caster->CastSpell(caster,54833,true,NULL,this);
m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (100 * m_maxduration / m_periodicTimer));
break; break;
} }
case 48391: // Owlkin Frenzy 2% base mana case 48391: // Owlkin Frenzy 2% base mana
@ -5797,17 +5812,47 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
(*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED) (*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED)
return; return;
spellId1 = 30069; spellId1 = 30069; // Blood Frenzy (Rank 1)
spellId2 = 30070; spellId2 = 30070; // Blood Frenzy (Rank 2)
} }
break; break;
} }
case SPELLFAMILY_PRIEST: case SPELLFAMILY_PRIEST:
// Dispersion mana reg and immunity switch(GetId())
if (GetSpellProto()->Id == 47585)
{ {
spellId1 = 60069; // Dispersion mana reg and immunity
spellId2 = 63230; case 47585:
spellId1 = 60069; // Dispersion
spellId2 = 63230; // Dispersion
break;
// Abolish Disease (remove 1 more poison effect with Body and Soul)
case 552:
{
if(apply)
{
int chance =0;
Unit::AuraList const& dummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
{
SpellEntry const* dummyEntry = (*itr)->GetSpellProto();
// Body and Soul (talent ranks)
if (dummyEntry->SpellFamilyName == SPELLFAMILY_PRIEST && dummyEntry->SpellIconID == 2218 &&
dummyEntry->SpellVisual[0]==0)
{
chance = (*itr)->GetSpellProto()->CalculateSimpleValue(1);
break;
}
}
if(roll_chance_i(chance))
spellId1 = 64134; // Body and Soul (periodic dispel effect)
}
else
spellId1 = 64134; // Body and Soul (periodic dispel effect)
break;
}
default:
return;
} }
break; break;
case SPELLFAMILY_ROGUE: case SPELLFAMILY_ROGUE:

View file

@ -358,6 +358,10 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = unitTarget->GetMaxHealth() / 10; damage = unitTarget->GetMaxHealth() / 10;
break; break;
} }
// Hand of Rekoning (name not have typos ;) )
case 67485:
damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
break;
} }
break; break;
} }
@ -1450,7 +1454,26 @@ void Spell::EffectDummy(uint32 i)
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
m_caster->SetPower(POWER_RAGE, m_caster->GetPower(POWER_RAGE)-rage);
// Sudden Death
if(m_caster->HasAura(52437))
{
Unit::AuraList const& auras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
for (Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
// Only Sudden Death have this SpellIconID with SPELL_AURA_PROC_TRIGGER_SPELL
if ((*itr)->GetSpellProto()->SpellIconID == 1989)
{
// saved rage top stored in next affect
uint32 lastrage = (*itr)->GetSpellProto()->CalculateSimpleValue(1);
if(lastrage < rage)
rage -= lastrage;
break;
}
}
}
m_caster->SetPower(POWER_RAGE,m_caster->GetPower(POWER_RAGE)-rage);
return; return;
} }
// Slam // Slam
@ -3580,8 +3603,9 @@ void Spell::EffectDispel(uint32 i)
if (positive == unitTarget->IsFriendlyTo(m_caster)) if (positive == unitTarget->IsFriendlyTo(m_caster))
continue; continue;
} }
// Add aura to dispel list // Add aura to dispel list (all stack cases)
dispel_list.push_back(aur); for(int k = 0; k < aur->GetStackAmount(); ++k)
dispel_list.push_back(aur);
} }
} }
// Ok if exist some buffs for dispel try dispel it // Ok if exist some buffs for dispel try dispel it
@ -3589,17 +3613,22 @@ void Spell::EffectDispel(uint32 i)
{ {
std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid) std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
std::list < uint32 > fail_list; // spell_id std::list < uint32 > fail_list; // spell_id
int32 list_size = dispel_list.size();
// some spells have effect value = 0 and all from its by meaning expect 1 // some spells have effect value = 0 and all from its by meaning expect 1
if(!damage) if(!damage)
damage = 1; damage = 1;
// Dispell N = damage buffs (or while exist buffs for dispel) // Dispell N = damage buffs (or while exist buffs for dispel)
for (int32 count=0; count < damage && list_size > 0; ++count) for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
{ {
// Random select buff for dispel // Random select buff for dispel
Aura *aur = dispel_list[urand(0, list_size-1)]; std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
std::advance(dispel_itr,urand(0, dispel_list.size()-1));
Aura *aur = *dispel_itr;
// remove entry from dispel_list
dispel_list.erase(dispel_itr);
SpellEntry const* spellInfo = aur->GetSpellProto(); SpellEntry const* spellInfo = aur->GetSpellProto();
// Base dispel chance // Base dispel chance
@ -3613,21 +3642,9 @@ void Spell::EffectDispel(uint32 i)
} }
// Try dispel // Try dispel
if (roll_chance_i(miss_chance)) if (roll_chance_i(miss_chance))
fail_list.push_back(aur->GetId()); fail_list.push_back(spellInfo->Id);
else else
success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
// Remove buff from list for prevent doubles
for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
{
Aura *dispeled = *j;
if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
{
j = dispel_list.erase(j);
--list_size;
}
else
++j;
}
} }
// Send success log and really remove auras // Send success log and really remove auras
if (!success_list.empty()) if (!success_list.empty())
@ -3636,7 +3653,7 @@ void Spell::EffectDispel(uint32 i)
WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5); WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
data.append(unitTarget->GetPackGUID()); // Victim GUID data.append(unitTarget->GetPackGUID()); // Victim GUID
data.append(m_caster->GetPackGUID()); // Caster GUID data.append(m_caster->GetPackGUID()); // Caster GUID
data << uint32(m_spellInfo->Id); // Dispell spell id data << uint32(m_spellInfo->Id); // Dispel spell id
data << uint8(0); // not used data << uint8(0); // not used
data << uint32(count); // count data << uint32(count); // count
for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j) for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
@ -3644,7 +3661,7 @@ void Spell::EffectDispel(uint32 i)
SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
data << uint32(spellInfo->Id); // Spell Id data << uint32(spellInfo->Id); // Spell Id
data << uint8(0); // 0 - dispeled !=0 cleansed data << uint8(0); // 0 - dispeled !=0 cleansed
unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
} }
m_caster->SendMessageToSet(&data, true); m_caster->SendMessageToSet(&data, true);

View file

@ -224,9 +224,12 @@ void Player::UpdateMaxPower(Powers power)
{ {
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
float bonusPower = (power == POWER_MANA) ? GetManaBonusFromIntellect() : 0; uint32 create_power = GetCreatePowers(power);
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); // ignore classes without mana
float bonusPower = (power == POWER_MANA && create_power > 0) ? GetManaBonusFromIntellect() : 0;
float value = GetModifierValue(unitMod, BASE_VALUE) + create_power;
value *= GetModifierValue(unitMod, BASE_PCT); value *= GetModifierValue(unitMod, BASE_PCT);
value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
value *= GetModifierValue(unitMod, TOTAL_PCT); value *= GetModifierValue(unitMod, TOTAL_PCT);

View file

@ -3466,6 +3466,23 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
return modifier; return modifier;
} }
float Unit::GetTotalAuraMultiplierByMiscValueForMask(AuraType auratype, uint32 mask) const
{
if(!mask)
return 1.0f;
float multiplier = 1.0f;
AuraList const& mTotalAuraList = GetAurasByType(auratype);
for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if (mask & (1 << (mod->m_miscvalue -1)))
multiplier *= (100.0f + mod->m_amount)/100.0f;
}
return multiplier;
}
bool Unit::AddAura(Aura *Aur) bool Unit::AddAura(Aura *Aur)
{ {
SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
@ -3846,34 +3863,27 @@ void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 cast
} }
} }
void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler) void Unit::RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler)
{ {
for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId);
// Custom dispel case
// Unstable Affliction
if(spellEntry->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellEntry->SpellFamilyFlags & UI64LIT(0x010000000000)))
{ {
Aura *aur = iter->second; if (Aura* dotAura = GetAura(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_WARLOCK,UI64LIT(0x010000000000),0x00000000,casterGUID))
if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
{ {
// Custom dispel case int32 damage = dotAura->GetModifier()->m_amount*9;
// Unstable Affliction
if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x010000000000)))
{
int32 damage = aur->GetModifier()->m_amount*9;
uint64 caster_guid = aur->GetCasterGUID();
// Remove aura // Remove spell auras from stack
RemoveAura(iter, AURA_REMOVE_BY_DISPEL); RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
// backfire damage and silence // backfire damage and silence
dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid); dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,casterGUID);
iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel
}
else
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
} }
else
++iter;
} }
else
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
} }
void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer) void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer)
@ -3943,21 +3953,46 @@ void Unit::RemoveAurasWithDispelType( DispelType type )
} }
} }
void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex) void Unit::RemoveSingleAuraFromStack(AuraMap::iterator &i, AuraRemoveMode mode)
{
if (i->second->modStackAmount(-1))
RemoveAura(i,mode);
}
void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex, AuraRemoveMode mode)
{ {
AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
if(iter != m_Auras.end()) if(iter != m_Auras.end())
RemoveSingleAuraFromStack(iter,mode);
}
void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId, AuraRemoveMode mode)
{
for (int i=0; i<3; ++i)
RemoveSingleAuraFromStack(spellId, i, mode);
}
void Unit::RemoveSingleSpellAurasByCasterSpell(uint32 spellId, uint64 casterGUID, AuraRemoveMode mode)
{
for (int i=0; i<3; ++i)
RemoveSingleAuraByCasterSpell(spellId, i, casterGUID, mode);
}
void Unit::RemoveSingleAuraByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID, AuraRemoveMode mode)
{
spellEffectPair spair = spellEffectPair(spellId, effindex);
for(AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair); ++iter)
{ {
if (iter->second->modStackAmount(-1)) Aura *aur = iter->second;
RemoveAura(iter); if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
{
RemoveSingleAuraFromStack(iter,mode);
break;
}
} }
} }
void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId)
{
for (int i=0; i<3; ++i)
RemoveSingleAuraFromStack(spellId, i);
}
void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except)
{ {
@ -4745,6 +4780,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 26654; triggered_spell_id = 26654;
break; break;
} }
// Twisted Reflection (boss spell)
case 21063:
triggered_spell_id = 21064;
break;
// Unstable Power // Unstable Power
case 24658: case 24658:
{ {
@ -4835,6 +4874,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 34650; triggered_spell_id = 34650;
break; break;
} }
// Divine purpose
case 31871:
case 31872:
{
// Roll chane
if (!roll_chance_i(triggerAmount))
return false;
// Remove any stun effect on target
AuraMap& Auras = pVictim->GetAuras();
for(AuraMap::const_iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetSpellProto();
if( spell->Mechanic == MECHANIC_STUN ||
spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
{
pVictim->RemoveAurasDueToSpell(spell->Id);
iter = Auras.begin();
}
else
++iter;
}
return true;
}
// Mark of Malice // Mark of Malice
case 33493: case 33493:
{ {
@ -4846,10 +4909,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 33494; triggered_spell_id = 33494;
break; break;
} }
// Twisted Reflection (boss spell)
case 21063:
triggered_spell_id = 21064;
break;
// Vampiric Aura (boss spell) // Vampiric Aura (boss spell)
case 38196: case 38196:
{ {
@ -4919,12 +4978,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
((Player*)this)->Say("This is Madness!", LANG_UNIVERSAL); ((Player*)this)->Say("This is Madness!", LANG_UNIVERSAL);
break; break;
} }
/*
// Sunwell Exalted Caster Neck (??? neck)
// cast ??? Light's Wrath if Exalted by Aldor
// cast ??? Arcane Bolt if Exalted by Scryers*/
case 46569:
return false; // old unused version
// Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck) // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck)
// cast 45479 Light's Wrath if Exalted by Aldor // cast 45479 Light's Wrath if Exalted by Aldor
// cast 45429 Arcane Bolt if Exalted by Scryers // cast 45429 Arcane Bolt if Exalted by Scryers
@ -5033,6 +5086,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
} }
return false; return false;
} }
/*
// Sunwell Exalted Caster Neck (??? neck)
// cast ??? Light's Wrath if Exalted by Aldor
// cast ??? Arcane Bolt if Exalted by Scryers*/
case 46569:
return false; // old unused version
// Living Seed // Living Seed
case 48504: case 48504:
{ {
@ -5050,28 +5109,15 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this; target = this;
break; break;
} }
// Divine purpose // Shadowfiend Death (Gain mana if pet dies with Glyph of Shadowfiend)
case 31871: case 57989:
case 31872:
{ {
// Roll chane Unit *owner = GetOwner();
if (!roll_chance_i(triggerAmount)) if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
return false; return false;
// Remove any stun effect on target // Glyph of Shadowfiend (need cast as self cast for owner, no hidden cooldown)
AuraMap& Auras = pVictim->GetAuras(); owner->CastSpell(owner,58227,true,castItem,triggeredByAura);
for(AuraMap::const_iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetSpellProto();
if( spell->Mechanic == MECHANIC_STUN ||
spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
{
pVictim->RemoveAurasDueToSpell(spell->Id);
iter = Auras.begin();
}
else
++iter;
}
return true; return true;
} }
} }
@ -6873,8 +6919,16 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
} }
case SPELLFAMILY_DRUID: 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 // Druid Forms Trinket
if (auraSpellInfo->Id==37336) else if (auraSpellInfo->Id==37336)
{ {
switch(m_form) switch(m_form)
{ {
@ -6888,15 +6942,17 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false; return false;
} }
} }
//else if (auraSpellInfo->Id==40363)// Entangling Roots () // Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred)
// trigger_spell_id = ????; else if (auraSpellInfo->Id==67353)
// Leader of the Pack
else if (auraSpellInfo->Id == 24932)
{ {
if (triggerAmount == 0) switch(m_form)
return false; {
basepoints[0] = triggerAmount * GetMaxHealth() / 100; case FORM_CAT: trigger_spell_id = 67355; break;
trigger_spell_id = 34299; case FORM_BEAR:
case FORM_DIREBEAR: trigger_spell_id = 67354; break;
default:
return false;
}
} }
break; break;
} }
@ -8571,15 +8627,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
} }
// Mod damage from spell mechanic // Mod damage from spell mechanic
if (uint32 mechanicMask = GetAllSpellMechanicMask(spellProto)) TakenTotalMod *= pVictim->GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,GetAllSpellMechanicMask(spellProto));
{
AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
{
if (mechanicMask & uint32(1 << ((*i)->GetModifier()->m_miscvalue)))
TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
}
}
// Mod damage taken from AoE spells // Mod damage taken from AoE spells
if(IsAreaOfEffectSpell(spellProto)) if(IsAreaOfEffectSpell(spellProto))
@ -9388,16 +9436,7 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att
TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask); TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask);
// ..taken pct (by mechanic mask) // ..taken pct (by mechanic mask)
if (mechanicMask) TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,mechanicMask);
{
AuraList const& mTotalAuraList = GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
for(AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
{
Modifier* mod = (*i)->GetModifier();
if ((1<<(mod->m_miscvalue-1)) & mechanicMask)
TakenPercent *= (100.0f + mod->m_amount)/100.0f;
}
}
// ..taken pct (melee/ranged) // ..taken pct (melee/ranged)
if(attType == RANGED_ATTACK) if(attType == RANGED_ATTACK)

View file

@ -1235,31 +1235,42 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool AddAura(Aura *aur); bool AddAura(Aura *aur);
// removing specific aura stack
void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
void RemoveSingleSpellAurasFromStack(uint32 spellId);
void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); // removing specific aura stacks by diff reasons and selections
void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL);
void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID); void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID);
void RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID); void RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID);
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
void RemoveAurasDueToSpellByCancel(uint32 spellId); void RemoveAurasDueToSpellByCancel(uint32 spellId);
void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo); void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
// removing unknown aura stacks by diff reasons and selections
void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0); void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
void RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId, bool non_positive = false); void RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId, bool non_positive = false);
void RemoveSpellsCausingAura(AuraType auraType); void RemoveSpellsCausingAura(AuraType auraType);
void RemoveRankAurasDueToSpell(uint32 spellId); void RemoveRankAurasDueToSpell(uint32 spellId);
bool RemoveNoStackAurasDueToAura(Aura *Aur); bool RemoveNoStackAurasDueToAura(Aura *Aur);
void RemoveAurasWithInterruptFlags(uint32 flags); void RemoveAurasWithInterruptFlags(uint32 flags);
void RemoveAurasWithDispelType( DispelType type ); void RemoveAurasWithDispelType( DispelType type );
void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveArenaAuras(bool onleave = false); void RemoveArenaAuras(bool onleave = false);
void RemoveAllAurasOnDeath(); void RemoveAllAurasOnDeath();
// removing specific aura FROM stack
void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraFromStack(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
// removing specific aura FROM stack by diff reasons and selections
void RemoveSingleSpellAurasFromStack(uint32 spellId, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleSpellAurasByCasterSpell(uint32 spellId, uint64 casterGUID, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);
float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); }
@ -1424,6 +1435,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
// misc have plain value but we check it fit to provided values mask (mask & (1 << (misc-1)))
float GetTotalAuraMultiplierByMiscValueForMask(AuraType auratype, uint32 mask) const;
Aura* GetDummyAura(uint32 spell_id) const; Aura* GetDummyAura(uint32 spell_id) const;
uint32 m_AuraFlags; uint32 m_AuraFlags;

View file

@ -292,12 +292,13 @@ int Master::Run()
realCurrTime = realPrevTime = getMSTime(); realCurrTime = realPrevTime = getMSTime();
///- Start up freeze catcher thread ///- Start up freeze catcher thread
ACE_Based::Thread* freeze_thread = NULL;
if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0)) if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0))
{ {
FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable(); FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
fdr->SetDelayTime(freeze_delay*1000); fdr->SetDelayTime(freeze_delay*1000);
ACE_Based::Thread freeze_thread(fdr); freeze_thread = new ACE_Based::Thread(fdr);
freeze_thread.setPriority(ACE_Based::Highest); freeze_thread->setPriority(ACE_Based::Highest);
} }
///- Launch the world listener socket ///- Launch the world listener socket
@ -313,7 +314,14 @@ int Master::Run()
sWorldSocketMgr->Wait (); sWorldSocketMgr->Wait ();
// set server offline ///- Stop freeze protection before shutdown tasks
if (freeze_thread)
{
freeze_thread->destroy();
delete freeze_thread;
}
///- Set server offline in realmlist
loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID); loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);
///- Remove signal handling before leaving ///- Remove signal handling before leaving
@ -324,10 +332,10 @@ int Master::Run()
world_thread.wait(); world_thread.wait();
rar_thread.wait (); rar_thread.wait ();
///- Clean database before leaving ///- Clean account database before leaving
clearOnlineAccounts(); clearOnlineAccounts();
///- Wait for delay threads to end ///- Wait for DB delay threads to end
CharacterDatabase.HaltDelayThread(); CharacterDatabase.HaltDelayThread();
WorldDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread();
loginDatabase.HaltDelayThread(); loginDatabase.HaltDelayThread();
@ -388,7 +396,7 @@ int Master::Run()
// fixes a memory leak related to detaching threads from the module // fixes a memory leak related to detaching threads from the module
UnloadScriptingModule(); UnloadScriptingModule();
// Exit the process with specified return value ///- Exit the process with specified return value
return World::GetExitCode(); return World::GetExitCode();
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8892" #define REVISION_NR "8913"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills" #define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills"
#define REVISION_DB_MANGOS "required_8891_01_mangos_spell_proc_event" #define REVISION_DB_MANGOS "required_8912_01_mangos_spell_proc_event"
#define REVISION_DB_REALMD "required_8728_01_realmd_account" #define REVISION_DB_REALMD "required_8728_01_realmd_account"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__