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,
`creature_ai_version` varchar(120) default NULL,
`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';
--
@ -3081,7 +3081,7 @@ INSERT INTO `mangos_string` VALUES
(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),
(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),
(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),
@ -16934,9 +16934,9 @@ INSERT INTO spell_chain VALUES
(25392,21564,21562,3,0),
(48162,25392,21562,4,0),
/*Prayer of Spirit*/
(27681,0,27681,1,14752),
(32999,27681,27681,2,0),
(48074,32999,27681,3,0),
(27681,14752,14752,2,0),
(32999,27681,14752,3,0),
(48074,32999,14752,4,0),
/*Rapture*/
(47535,0,47535,1,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),
(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),
(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),
(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),
@ -18325,6 +18325,7 @@ INSERT INTO `spell_proc_event` VALUES
(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),
(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),
(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),
@ -18385,7 +18386,9 @@ 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, 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 */;
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'),
(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'),
(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'),
(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'),
@ -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, 3, -1,-1,'Steady Shot', 'Spell::EffectDummy'),
( 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, 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'),

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 \
8889_01_mangos_spell_pet_auras.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
## Additional files to include when running 'make dist'
@ -346,4 +351,9 @@ EXTRA_DIST = \
8886_01_mangos_string.sql \
8889_01_mangos_spell_pet_auras.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

View file

@ -744,309 +744,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
&& 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()
{
if(m_gossipOptionLoaded)

View file

@ -576,16 +576,9 @@ class MANGOS_DLL_SPEC Creature : public Unit
std::string GetScriptName() 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();
GossipOption const* GetGossipOption( uint32 id ) const;
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); }

View file

@ -44,13 +44,13 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
if (count == 0)
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 );
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 );
return;
@ -71,13 +71,13 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
if(srcslot == dstslot)
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 );
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 );
return;
@ -123,13 +123,13 @@ void WorldSession::HandleSwapItem( WorldPacket & recv_data )
if(src == dst)
return;
if(!_player->IsValidPos(srcbag, srcslot))
if(!_player->IsValidPos(srcbag, srcslot, true))
{
_player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
if(!_player->IsValidPos(dstbag, dstslot))
if(!_player->IsValidPos(dstbag, dstslot, true))
{
_player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
return;
@ -425,7 +425,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
data << pProto->GemProperties;
data << pProto->RequiredDisenchantSkill;
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->HolidayId; // Holiday.dbc?
SendPacket( &data );
@ -783,7 +783,7 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
if( !pItem )
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 );
return;

View file

@ -2011,10 +2011,11 @@ bool ChatHandler::HandleItemMoveCommand(const char* args)
if(srcslot==dstslot)
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;
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;
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))
{
_player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
pCreature->prepareGossipMenu(_player);
pCreature->sendPreparedGossip(_player);
_player->PrepareGossipMenu(pCreature);
_player->SendPreparedGossip(pCreature);
}
}
@ -287,39 +287,40 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
uint32 option;
uint32 unk;
uint32 menuId;
uint64 guid;
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");
recv_data >> code;
sLog.outBasic("string read: %s", code.c_str());
}
Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
if (!unit)
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))
if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
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()))
unit->OnGossipSelect (_player, option);
if (!Script->GossipSelectWithCode(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str()))
_player->OnGossipSelect(pCreature, option);
}
else
{
if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
unit->OnGossipSelect (_player, option);
if (!Script->GossipSelect(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(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_queststatus 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_cooldown 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;
}
bool Player::IsValidPos( uint8 bag, uint8 slot )
bool Player::IsValidPos( uint8 bag, uint8 slot, bool explicit_pos )
{
// post selected
if(bag == NULL_BAG)
if(bag == NULL_BAG && !explicit_pos)
return true;
if (bag == INVENTORY_SLOT_BAG_0)
{
// any post selected
if (slot == NULL_SLOT)
if (slot == NULL_SLOT && !explicit_pos)
return true;
// equipment
@ -8691,7 +8692,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
return false;
// any post selected
if (slot == NULL_SLOT)
if (slot == NULL_SLOT && !explicit_pos)
return true;
return slot < pBag->GetBagSize();
@ -8705,7 +8706,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
return false;
// any post selected
if (slot == NULL_SLOT)
if (slot == NULL_SLOT && !explicit_pos)
return true;
return slot < pBag->GetBagSize();
@ -8997,8 +8998,9 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
if (bag==skip_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 );
if (!pBag)
if (!pBag || pBag==pSrcItem)
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
ItemPrototype const* pBagProto = pBag->GetProto();
@ -12172,6 +12174,338 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
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 ***/
/*********************************************************/
@ -12279,7 +12613,8 @@ void Player::SendPreparedQuest(uint64 guid)
// need pet case for some quests
if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid))
{
uint32 textid = pCreature->GetNpcTextId();
uint32 textid = GetGossipTextId(pCreature);
GossipText const* gossiptext = sObjectMgr.GetGossipText(textid);
if (!gossiptext)
{
@ -14954,9 +15289,9 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
bool success = true;
// the item/bag is not in a bag
if (!bag_guid)
{
// the item is not in a bag
item->SetContainer( NULL );
item->SetSlot(slot);
@ -14992,13 +15327,20 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
bagMap[item_guid] = (Bag*)item;
}
}
// the item/bag in a bag
else
{
item->SetSlot(NULL_SLOT);
// the item is in a bag, find the bag
std::map<uint64, Bag*>::const_iterator itr = bagMap.find(bag_guid);
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
success = false;
}

View file

@ -1174,8 +1174,8 @@ class MANGOS_DLL_SPEC Player : public Unit
static bool IsBagPos( uint16 pos );
static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8, pos & 255); }
static bool IsBankPos( uint8 bag, uint8 slot );
bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8, pos & 255); }
bool IsValidPos( uint8 bag, uint8 slot );
bool IsValidPos( uint16 pos, bool explicit_pos ) { return IsValidPos(pos >> 8, pos & 255, explicit_pos); }
bool IsValidPos( uint8 bag, uint8 slot, bool explicit_pos );
uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); }
void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); }
bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const;
@ -1296,6 +1296,19 @@ class MANGOS_DLL_SPEC Player : public Unit
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 ***/
/*********************************************************/

View file

@ -24,15 +24,16 @@
#include "ObjectMgr.h"
// Character Dump tables
#define DUMP_TABLE_COUNT 21
struct DumpTable
{
char const* name;
DumpTableType type;
// helpers
bool isValid() const { return name != NULL; }
};
static DumpTable dumpTables[DUMP_TABLE_COUNT] =
static DumpTable dumpTables[] =
{
{ "characters", DTT_CHARACTER },
{ "character_achievement", DTT_CHAR_TABLE },
@ -44,6 +45,7 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "character_action", DTT_CHAR_TABLE },
{ "character_aura", DTT_CHAR_TABLE },
{ "character_homebind", DTT_CHAR_TABLE },
{ "character_skills", DTT_CHAR_TABLE },
{ "character_ticket", DTT_CHAR_TABLE },
{ "character_inventory", DTT_INVENTORY },
{ "mail", DTT_MAIL },
@ -55,6 +57,7 @@ static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{ "pet_aura", DTT_PET_TABLE },
{ "pet_spell", DTT_PET_TABLE },
{ "pet_spell_cooldown", DTT_PET_TABLE },
{ NULL, DTT_CHAR_TABLE }, // end marker
};
// Low level functions
@ -258,7 +261,7 @@ void StoreGUID(QueryResult *result,uint32 data,uint32 field, std::set<uint32>& g
}
// 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;
char const* fieldname = NULL;
@ -362,8 +365,8 @@ std::string PlayerDumpWriter::GetDump(uint32 guid)
else
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)
DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type);
for(DumpTable* itr = &dumpTables[0]; itr->isValid(); ++itr)
DumpTableContent(dump, guid, itr->name, itr->name, itr->type);
// TODO: Add instance/group..
// 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;
uint8 i;
for(i = 0; i < DUMP_TABLE_COUNT; ++i)
DumpTable* dTable = &dumpTables[0];
for(; dTable->isValid(); ++dTable)
{
if (tn == dumpTables[i].name)
if (tn == dTable->name)
{
type = dumpTables[i].type;
type = dTable->type;
break;
}
}
if (i == DUMP_TABLE_COUNT)
if (!dTable->isValid())
{
sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str());
ROLLBACK(DUMP_FILE_BROKEN);

View file

@ -75,7 +75,7 @@ class PlayerDumpWriter : public PlayerDump
private:
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, uint32 guid);

View file

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

View file

@ -2532,8 +2532,14 @@ void Spell::cast(bool skipCheck)
break;
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
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080))
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080))
{
AddPrecastSpell(25771); // Forbearance
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);
sLog.outDebug( "Spell: Effect : %u", eff);
sLog.outDebug( "Spell %u Effect%d : %u", m_spellInfo->Id, i, eff);
if(eff<TOTAL_SPELL_EFFECTS)
{

View file

@ -2209,8 +2209,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
if(!Real)
return;
Unit* caster = GetCaster();
// AT APPLY
if(apply)
{
@ -2218,12 +2216,13 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
{
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( caster && m_target->CanHaveThreatList())
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(caster)
if (Unit* caster = GetCaster())
caster->CastSpell(caster, 13138, true, NULL, this);
return;
case 39850: // Rocket Blast
@ -2234,7 +2233,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
m_target->PlayDistanceSound(11965);
return;
case 46354: // Blood Elf Illusion
if(caster)
if (Unit* caster = GetCaster())
{
switch(caster->getGender())
{
@ -2256,10 +2255,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
// 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
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;
}
@ -2278,8 +2278,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
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;
switch(GetId())
{
@ -2340,12 +2344,13 @@ 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
if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000800)))
{
if (Unit* caster = GetCaster())
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}
@ -2353,10 +2358,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
(m_spellProto->SpellFamilyFlags2 & UI64LIT(0x00000080)))
{
if (Unit* caster = GetCaster())
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}
}
}
@ -2376,14 +2381,15 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
case 24658:
{
uint32 spellId = 24659;
if (apply && caster)
if (apply)
{
const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
if (!spell)
SpellEntry const *spell = sSpellStore.LookupEntry(spellId);
Unit* caster = GetCaster();
if (!spell || !caster)
return;
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;
}
m_target->RemoveAurasDueToSpell(spellId);
@ -2393,10 +2399,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
case 24661:
{
uint32 spellId = 24662;
if (apply && caster)
if (apply)
{
const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
if (!spell)
SpellEntry const* spell = sSpellStore.LookupEntry(spellId);
Unit* caster = GetCaster();
if (!spell || !caster)
return;
for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
@ -2408,6 +2415,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
//Summon Fire Elemental
case 40133:
{
Unit* caster = GetCaster();
if (!caster)
return;
@ -2424,6 +2432,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
//Summon Earth Elemental
case 40132 :
{
Unit* caster = GetCaster();
if (!caster)
return;
@ -2499,6 +2508,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
else
{
int32 bp0 = m_modifier.m_amount;
if (Unit* caster = GetCaster())
m_target->CastCustomSpell(caster,48210,&bp0,NULL,NULL,true);
}
}
@ -2586,7 +2597,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
{
if ( apply )
{
if ( caster )
if (Unit* caster = GetCaster())
// prevent double apply bonuses
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);
@ -2610,7 +2621,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
int32 amount = m_modifier.m_amount / m_stackAmount;
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;
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)
{
Unit* caster = GetCaster();
Unit* victim = GetTarget();
if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode != AURA_REMOVE_BY_DEATH)
if(m_removeMode != AURA_REMOVE_BY_DEATH)
return;
// Item amount
if (m_modifier.m_amount <= 0)
@ -3281,6 +3290,11 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real)
if(spellInfo->EffectItemType[m_effIndex] == 0)
return;
Unit* victim = GetTarget();
Unit* caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
// Soul Shard only from non-grey units
if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
(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)
{
Unit* caster = GetCaster();
if (Unit* caster = GetCaster())
m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (200 * m_maxduration / m_periodicTimer));
break;
}
case 29166: // Innervate (value% of casters base mana)
{
Unit* caster = GetCaster();
if (Unit* caster = GetCaster())
{
// Glyph of Innervate
if (caster && caster->HasAura(54832))
if (caster->HasAura(54832))
caster->CastSpell(caster,54833,true,NULL,this);
m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (100 * m_maxduration / m_periodicTimer));
}
break;
}
case 48391: // Owlkin Frenzy 2% base mana
@ -5797,17 +5812,47 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
(*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED)
return;
spellId1 = 30069;
spellId2 = 30070;
spellId1 = 30069; // Blood Frenzy (Rank 1)
spellId2 = 30070; // Blood Frenzy (Rank 2)
}
break;
}
case SPELLFAMILY_PRIEST:
// Dispersion mana reg and immunity
if (GetSpellProto()->Id == 47585)
switch(GetId())
{
spellId1 = 60069;
spellId2 = 63230;
// 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:
{
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;
case SPELLFAMILY_ROGUE:

View file

@ -358,6 +358,10 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = unitTarget->GetMaxHealth() / 10;
break;
}
// Hand of Rekoning (name not have typos ;) )
case 67485:
damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
break;
}
break;
}
@ -1450,7 +1454,26 @@ void Spell::EffectDummy(uint32 i)
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
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;
}
// Slam
@ -3580,7 +3603,8 @@ void Spell::EffectDispel(uint32 i)
if (positive == unitTarget->IsFriendlyTo(m_caster))
continue;
}
// Add aura to dispel list
// Add aura to dispel list (all stack cases)
for(int k = 0; k < aur->GetStackAmount(); ++k)
dispel_list.push_back(aur);
}
}
@ -3589,17 +3613,22 @@ void Spell::EffectDispel(uint32 i)
{
std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
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
if(!damage)
damage = 1;
// 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
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();
// Base dispel chance
@ -3613,21 +3642,9 @@ void Spell::EffectDispel(uint32 i)
}
// Try dispel
if (roll_chance_i(miss_chance))
fail_list.push_back(aur->GetId());
fail_list.push_back(spellInfo->Id);
else
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
if (!success_list.empty())
@ -3636,7 +3653,7 @@ void Spell::EffectDispel(uint32 i)
WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
data.append(unitTarget->GetPackGUID()); // Victim 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 << uint32(count); // count
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);
data << uint32(spellInfo->Id); // Spell Id
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);

View file

@ -224,9 +224,12 @@ void Player::UpdateMaxPower(Powers 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, TOTAL_VALUE) + bonusPower;
value *= GetModifierValue(unitMod, TOTAL_PCT);

View file

@ -3466,6 +3466,23 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_
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)
{
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(); )
{
Aura *aur = iter->second;
if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
{
SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId);
// Custom dispel case
// Unstable Affliction
if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x010000000000)))
if(spellEntry->SpellFamilyName == SPELLFAMILY_WARLOCK && (spellEntry->SpellFamilyFlags & UI64LIT(0x010000000000)))
{
int32 damage = aur->GetModifier()->m_amount*9;
uint64 caster_guid = aur->GetCasterGUID();
if (Aura* dotAura = GetAura(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_WARLOCK,UI64LIT(0x010000000000),0x00000000,casterGUID))
{
int32 damage = dotAura->GetModifier()->m_amount*9;
// Remove aura
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
// Remove spell auras from stack
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
// backfire damage and silence
dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid);
iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel
dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,casterGUID);
}
}
else
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
}
else
++iter;
}
RemoveSingleSpellAurasByCasterSpell(spellId, casterGUID, AURA_REMOVE_BY_DISPEL);
}
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));
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))
RemoveAura(iter);
Aura *aur = iter->second;
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)
{
@ -4745,6 +4780,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 26654;
break;
}
// Twisted Reflection (boss spell)
case 21063:
triggered_spell_id = 21064;
break;
// Unstable Power
case 24658:
{
@ -4835,6 +4874,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 34650;
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
case 33493:
{
@ -4846,10 +4909,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 33494;
break;
}
// Twisted Reflection (boss spell)
case 21063:
triggered_spell_id = 21064;
break;
// Vampiric Aura (boss spell)
case 38196:
{
@ -4919,12 +4978,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
((Player*)this)->Say("This is Madness!", LANG_UNIVERSAL);
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)
// cast 45479 Light's Wrath if Exalted by Aldor
// cast 45429 Arcane Bolt if Exalted by Scryers
@ -5033,6 +5086,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
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
case 48504:
{
@ -5050,28 +5109,15 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
// Divine purpose
case 31871:
case 31872:
// Shadowfiend Death (Gain mana if pet dies with Glyph of Shadowfiend)
case 57989:
{
// Roll chane
if (!roll_chance_i(triggerAmount))
Unit *owner = GetOwner();
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
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;
}
// Glyph of Shadowfiend (need cast as self cast for owner, no hidden cooldown)
owner->CastSpell(owner,58227,true,castItem,triggeredByAura);
return true;
}
}
@ -6873,8 +6919,16 @@ 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
if (auraSpellInfo->Id==37336)
else if (auraSpellInfo->Id==37336)
{
switch(m_form)
{
@ -6888,15 +6942,17 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false;
}
}
//else if (auraSpellInfo->Id==40363)// Entangling Roots ()
// trigger_spell_id = ????;
// Leader of the Pack
else if (auraSpellInfo->Id == 24932)
// Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred)
else if (auraSpellInfo->Id==67353)
{
if (triggerAmount == 0)
switch(m_form)
{
case FORM_CAT: trigger_spell_id = 67355; break;
case FORM_BEAR:
case FORM_DIREBEAR: trigger_spell_id = 67354; break;
default:
return false;
basepoints[0] = triggerAmount * GetMaxHealth() / 100;
trigger_spell_id = 34299;
}
}
break;
}
@ -8571,15 +8627,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
}
// Mod damage from spell mechanic
if (uint32 mechanicMask = 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;
}
}
TakenTotalMod *= pVictim->GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,GetAllSpellMechanicMask(spellProto));
// Mod damage taken from AoE spells
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);
// ..taken pct (by mechanic mask)
if (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;
}
}
TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscValueForMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT,mechanicMask);
// ..taken pct (melee/ranged)
if(attType == RANGED_ATTACK)

View file

@ -1235,31 +1235,42 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool AddAura(Aura *aur);
// removing specific aura stack
void RemoveAura(Aura* aura, 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 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 RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
void RemoveAurasByCasterSpell(uint32 spellId, 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 RemoveAurasDueToSpellByCancel(uint32 spellId);
void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
// removing unknown aura stacks by diff reasons and selections
void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
void RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId, bool non_positive = false);
void RemoveSpellsCausingAura(AuraType auraType);
void RemoveRankAurasDueToSpell(uint32 spellId);
bool RemoveNoStackAurasDueToAura(Aura *Aur);
void RemoveAurasWithInterruptFlags(uint32 flags);
void RemoveAurasWithDispelType( DispelType type );
void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveArenaAuras(bool onleave = false);
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);
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 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;
uint32 m_AuraFlags;

View file

@ -292,12 +292,13 @@ int Master::Run()
realCurrTime = realPrevTime = getMSTime();
///- Start up freeze catcher thread
ACE_Based::Thread* freeze_thread = NULL;
if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0))
{
FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
fdr->SetDelayTime(freeze_delay*1000);
ACE_Based::Thread freeze_thread(fdr);
freeze_thread.setPriority(ACE_Based::Highest);
freeze_thread = new ACE_Based::Thread(fdr);
freeze_thread->setPriority(ACE_Based::Highest);
}
///- Launch the world listener socket
@ -313,7 +314,14 @@ int Master::Run()
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);
///- Remove signal handling before leaving
@ -324,10 +332,10 @@ int Master::Run()
world_thread.wait();
rar_thread.wait ();
///- Clean database before leaving
///- Clean account database before leaving
clearOnlineAccounts();
///- Wait for delay threads to end
///- Wait for DB delay threads to end
CharacterDatabase.HaltDelayThread();
WorldDatabase.HaltDelayThread();
loginDatabase.HaltDelayThread();
@ -388,7 +396,7 @@ int Master::Run()
// fixes a memory leak related to detaching threads from the module
UnloadScriptingModule();
// Exit the process with specified return value
///- Exit the process with specified return value
return World::GetExitCode();
}

View file

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

View file

@ -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_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"
#endif // __REVISION_SQL_H__