mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
Merge commit 'origin/master' into 320
This commit is contained in:
commit
87930a6d07
35 changed files with 719 additions and 467 deletions
24
Makefile.am
24
Makefile.am
|
|
@ -20,19 +20,8 @@
|
||||||
SUBDIRS = dep doc sql src
|
SUBDIRS = dep doc sql src
|
||||||
|
|
||||||
## Additional files to include when running 'make dist'
|
## Additional files to include when running 'make dist'
|
||||||
# Win32 project workspace for Visual Studio .NET 2003
|
|
||||||
EXTRA_DIST = \
|
|
||||||
win/mangosdVC71.sln \
|
|
||||||
win/VC71/framework.vcproj \
|
|
||||||
win/VC71/game.vcproj \
|
|
||||||
win/VC71/mangosd.vcproj \
|
|
||||||
win/VC71/realmd.vcproj \
|
|
||||||
win/VC71/shared.vcproj \
|
|
||||||
win/VC71/zlib.vcproj \
|
|
||||||
win/VC71/g3dlite.vcproj
|
|
||||||
|
|
||||||
# Win32 project workspace for Visual Studio .NET 2005
|
# Win32 project workspace for Visual Studio .NET 2005
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST = \
|
||||||
win/mangosdVC80.sln \
|
win/mangosdVC80.sln \
|
||||||
win/VC80/framework.vcproj \
|
win/VC80/framework.vcproj \
|
||||||
win/VC80/game.vcproj \
|
win/VC80/game.vcproj \
|
||||||
|
|
@ -53,3 +42,14 @@ EXTRA_DIST += \
|
||||||
win/VC90/zlib.vcproj \
|
win/VC90/zlib.vcproj \
|
||||||
win/VC90/g3dlite.vcproj
|
win/VC90/g3dlite.vcproj
|
||||||
|
|
||||||
|
# Win32 project workspace for Visual Studio .NET 2010
|
||||||
|
EXTRA_DIST += \
|
||||||
|
win/mangosdVC100.sln \
|
||||||
|
win/VC100/framework.vcxproj \
|
||||||
|
win/VC100/game.vcxproj \
|
||||||
|
win/VC100/mangosd.vcxproj \
|
||||||
|
win/VC100/realmd.vcxproj \
|
||||||
|
win/VC100/shared.vcxproj \
|
||||||
|
win/VC100/zlib.vcxproj \
|
||||||
|
win/VC100/g3dlite.vcxproj
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
|
||||||
CREATE TABLE `db_version` (
|
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,
|
||||||
`required_8115_01_mangos_playercreateinfo_action` bit(1) default NULL
|
`required_8140_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';
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
@ -17123,9 +17123,9 @@ INSERT INTO `spell_proc_event` VALUES
|
||||||
(31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31871, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
(31871, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31872, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
(31872, 0x00000000, 10, 0x00000010, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(31904, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
(31904, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||||
(32385, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(32385, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
(32387, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
(32387, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
|
|
|
||||||
7
sql/updates/8140_01_mangos_spell_proc_event.sql
Normal file
7
sql/updates/8140_01_mangos_spell_proc_event.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
ALTER TABLE db_version CHANGE COLUMN required_8115_01_mangos_playercreateinfo_action required_8140_01_mangos_spell_proc_event bit;
|
||||||
|
|
||||||
|
DELETE FROM spell_proc_event WHERE entry IN (31876, 31877, 31878);
|
||||||
|
INSERT INTO spell_proc_event VALUES
|
||||||
|
(31876, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
|
(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||||
|
(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0);
|
||||||
|
|
@ -242,6 +242,7 @@ pkgdata_DATA = \
|
||||||
8104_01_characters.sql \
|
8104_01_characters.sql \
|
||||||
8112_01_mangos_spell_proc_event.sql \
|
8112_01_mangos_spell_proc_event.sql \
|
||||||
8115_01_mangos_playercreateinfo_action.sql \
|
8115_01_mangos_playercreateinfo_action.sql \
|
||||||
|
8140_01_mangos_spell_proc_event.sql \
|
||||||
README
|
README
|
||||||
|
|
||||||
## Additional files to include when running 'make dist'
|
## Additional files to include when running 'make dist'
|
||||||
|
|
@ -464,4 +465,5 @@ EXTRA_DIST = \
|
||||||
8104_01_characters.sql \
|
8104_01_characters.sql \
|
||||||
8112_01_mangos_spell_proc_event.sql \
|
8112_01_mangos_spell_proc_event.sql \
|
||||||
8115_01_mangos_playercreateinfo_action.sql \
|
8115_01_mangos_playercreateinfo_action.sql \
|
||||||
|
8140_01_mangos_spell_proc_event.sql \
|
||||||
README
|
README
|
||||||
|
|
|
||||||
|
|
@ -244,30 +244,31 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent character creating with invalid name
|
// prevent character creating with invalid name
|
||||||
if(!normalizePlayerName(name))
|
if (!normalizePlayerName(name))
|
||||||
{
|
{
|
||||||
data << (uint8)CHAR_NAME_INVALID_CHARACTER;
|
data << (uint8)CHAR_NAME_NO_NAME;
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId());
|
sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check name limitations
|
// check name limitations
|
||||||
if(!ObjectMgr::IsValidName(name,true))
|
uint8 res = ObjectMgr::CheckPlayerName(name,true);
|
||||||
|
if (res != CHAR_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
data << (uint8)CHAR_NAME_INVALID_CHARACTER;
|
data << uint8(res);
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name))
|
if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name))
|
||||||
{
|
{
|
||||||
data << (uint8)CHAR_NAME_RESERVED;
|
data << (uint8)CHAR_NAME_RESERVED;
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(objmgr.GetPlayerGUIDByName(name))
|
if (objmgr.GetPlayerGUIDByName(name))
|
||||||
{
|
{
|
||||||
data << (uint8)CHAR_CREATE_NAME_IN_USE;
|
data << (uint8)CHAR_CREATE_NAME_IN_USE;
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
|
|
@ -275,7 +276,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId());
|
||||||
if ( resultacct )
|
if (resultacct)
|
||||||
{
|
{
|
||||||
Field *fields=resultacct->Fetch();
|
Field *fields=resultacct->Fetch();
|
||||||
uint32 acctcharcount = fields[0].GetUInt32();
|
uint32 acctcharcount = fields[0].GetUInt32();
|
||||||
|
|
@ -967,7 +968,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
|
||||||
recv_data >> newname;
|
recv_data >> newname;
|
||||||
|
|
||||||
// prevent character rename to invalid name
|
// prevent character rename to invalid name
|
||||||
if(!normalizePlayerName(newname))
|
if (!normalizePlayerName(newname))
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||||
data << uint8(CHAR_NAME_NO_NAME);
|
data << uint8(CHAR_NAME_NO_NAME);
|
||||||
|
|
@ -975,16 +976,17 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ObjectMgr::IsValidName(newname, true))
|
uint8 res = ObjectMgr::CheckPlayerName(newname,true);
|
||||||
|
if (res != CHAR_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||||
data << uint8(CHAR_NAME_INVALID_CHARACTER);
|
data << uint8(res);
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check name limitations
|
// check name limitations
|
||||||
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||||
data << uint8(CHAR_NAME_RESERVED);
|
data << uint8(CHAR_NAME_RESERVED);
|
||||||
|
|
@ -1240,7 +1242,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent character rename to invalid name
|
// prevent character rename to invalid name
|
||||||
if(!normalizePlayerName(newname))
|
if (!normalizePlayerName(newname))
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||||
data << uint8(CHAR_NAME_NO_NAME);
|
data << uint8(CHAR_NAME_NO_NAME);
|
||||||
|
|
@ -1248,16 +1250,17 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ObjectMgr::IsValidName(newname,true))
|
uint8 res = ObjectMgr::CheckPlayerName(newname,true);
|
||||||
|
if (res != CHAR_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||||
data << uint8(CHAR_NAME_INVALID_CHARACTER);
|
data << uint8(res);
|
||||||
SendPacket( &data );
|
SendPacket( &data );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check name limitations
|
// check name limitations
|
||||||
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||||
data << uint8(CHAR_NAME_RESERVED);
|
data << uint8(CHAR_NAME_RESERVED);
|
||||||
|
|
@ -1266,9 +1269,9 @@ void WorldSession::HandleCharCustomize(WorldPacket& recv_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// character with this name already exist
|
// character with this name already exist
|
||||||
if(uint64 newguid = objmgr.GetPlayerGUIDByName(newname))
|
if (uint64 newguid = objmgr.GetPlayerGUIDByName(newname))
|
||||||
{
|
{
|
||||||
if(newguid != guid)
|
if (newguid != guid)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||||
data << uint8(CHAR_CREATE_NAME_IN_USE);
|
data << uint8(CHAR_CREATE_NAME_IN_USE);
|
||||||
|
|
|
||||||
|
|
@ -112,13 +112,6 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
||||||
if (pHolder.Event.event_inverse_phase_mask & (1 << Phase))
|
if (pHolder.Event.event_inverse_phase_mask & (1 << Phase))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Store random here so that all random actions match up
|
|
||||||
uint32 rnd = rand();
|
|
||||||
|
|
||||||
//Return if chance for event is not met
|
|
||||||
if (pHolder.Event.event_chance <= rnd % 100)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CreatureEventAI_Event const& event = pHolder.Event;
|
CreatureEventAI_Event const& event = pHolder.Event;
|
||||||
|
|
||||||
//Check event conditions based on the event type, also reset events
|
//Check event conditions based on the event type, also reset events
|
||||||
|
|
@ -330,6 +323,13 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
|
||||||
if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE))
|
if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE))
|
||||||
pHolder.Enabled = false;
|
pHolder.Enabled = false;
|
||||||
|
|
||||||
|
//Store random here so that all random actions match up
|
||||||
|
uint32 rnd = rand();
|
||||||
|
|
||||||
|
//Return if chance for event is not met
|
||||||
|
if (pHolder.Event.event_chance <= rnd % 100)
|
||||||
|
return false;
|
||||||
|
|
||||||
//Process actions
|
//Process actions
|
||||||
for (uint32 j = 0; j < MAX_ACTIONS; j++)
|
for (uint32 j = 0; j < MAX_ACTIONS; j++)
|
||||||
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker);
|
ProcessAction(pHolder.Event.action[j], rnd, pHolder.Event.event_id, pActionInvoker);
|
||||||
|
|
|
||||||
|
|
@ -473,9 +473,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
|
||||||
action.morph.modelId = 0;
|
action.morph.modelId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case ACTION_T_SOUND:
|
case ACTION_T_SOUND:
|
||||||
if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
|
if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
|
||||||
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ typedef GridRefManager<GameObject> GameObjectMapType;
|
||||||
typedef GridRefManager<Player> PlayerMapType;
|
typedef GridRefManager<Player> PlayerMapType;
|
||||||
|
|
||||||
typedef Grid<Player, AllWorldObjectTypes,AllGridObjectTypes> GridType;
|
typedef Grid<Player, AllWorldObjectTypes,AllGridObjectTypes> GridType;
|
||||||
typedef NGrid<8, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;
|
typedef NGrid<MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes> NGridType;
|
||||||
|
|
||||||
typedef TypeMapContainer<AllGridObjectTypes> GridTypeMapContainer;
|
typedef TypeMapContainer<AllGridObjectTypes> GridTypeMapContainer;
|
||||||
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;
|
typedef TypeMapContainer<AllWorldObjectTypes> WorldTypeMapContainer;
|
||||||
|
|
|
||||||
|
|
@ -673,7 +673,31 @@ void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data )
|
||||||
|
|
||||||
recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
|
recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
|
||||||
|
|
||||||
GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bagguid,bagslot);
|
uint8 bag = NULL_BAG; // init for case invalid bagGUID
|
||||||
|
|
||||||
|
// find bag slot by bag guid
|
||||||
|
if (bagguid == _player->GetGUID())
|
||||||
|
bag = INVENTORY_SLOT_BAG_0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;++i)
|
||||||
|
{
|
||||||
|
if (Bag *pBag = (Bag*)_player->GetItemByPos(INVENTORY_SLOT_BAG_0,i))
|
||||||
|
{
|
||||||
|
if (bagguid == pBag->GetGUID())
|
||||||
|
{
|
||||||
|
bag = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bag not found, cheating?
|
||||||
|
if (bag == NULL_BAG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bag,bagslot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
|
void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
|
||||||
|
|
|
||||||
|
|
@ -4504,9 +4504,6 @@ bool ChatHandler::HandleResetHonorCommand (const char * args)
|
||||||
|
|
||||||
static bool HandleResetStatsOrLevelHelper(Player* player)
|
static bool HandleResetStatsOrLevelHelper(Player* player)
|
||||||
{
|
{
|
||||||
PlayerInfo const *info = objmgr.GetPlayerInfo(player->getRace(), player->getClass());
|
|
||||||
if(!info) return false;
|
|
||||||
|
|
||||||
ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass());
|
ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass());
|
||||||
if(!cEntry)
|
if(!cEntry)
|
||||||
{
|
{
|
||||||
|
|
@ -4529,21 +4526,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player)
|
||||||
|
|
||||||
// reset only if player not in some form;
|
// reset only if player not in some form;
|
||||||
if(player->m_form==FORM_NONE)
|
if(player->m_form==FORM_NONE)
|
||||||
{
|
player->InitDisplayIds();
|
||||||
switch(player->getGender())
|
|
||||||
{
|
|
||||||
case GENDER_FEMALE:
|
|
||||||
player->SetDisplayId(info->displayId_f);
|
|
||||||
player->SetNativeDisplayId(info->displayId_f);
|
|
||||||
break;
|
|
||||||
case GENDER_MALE:
|
|
||||||
player->SetDisplayId(info->displayId_m);
|
|
||||||
player->SetNativeDisplayId(info->displayId_m);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
|
player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
|
||||||
player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form);
|
player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form);
|
||||||
|
|
@ -5623,18 +5606,18 @@ bool ChatHandler::HandlePDumpLoadCommand(const char *args)
|
||||||
char* name_str = strtok(NULL, " ");
|
char* name_str = strtok(NULL, " ");
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
if(name_str)
|
if (name_str)
|
||||||
{
|
{
|
||||||
name = name_str;
|
name = name_str;
|
||||||
// normalize the name if specified and check if it exists
|
// normalize the name if specified and check if it exists
|
||||||
if(!normalizePlayerName(name))
|
if (!normalizePlayerName(name))
|
||||||
{
|
{
|
||||||
PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
|
PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
|
||||||
SetSentErrorMessage(true);
|
SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ObjectMgr::IsValidName(name,true))
|
if (ObjectMgr::CheckPlayerName(name,true) != CHAR_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
|
PSendSysMessage(LANG_INVALID_CHARACTER_NAME);
|
||||||
SetSentErrorMessage(true);
|
SetSentErrorMessage(true);
|
||||||
|
|
@ -5646,17 +5629,17 @@ bool ChatHandler::HandlePDumpLoadCommand(const char *args)
|
||||||
|
|
||||||
uint32 guid = 0;
|
uint32 guid = 0;
|
||||||
|
|
||||||
if(guid_str)
|
if (guid_str)
|
||||||
{
|
{
|
||||||
guid = atoi(guid_str);
|
guid = atoi(guid_str);
|
||||||
if(!guid)
|
if (!guid)
|
||||||
{
|
{
|
||||||
PSendSysMessage(LANG_INVALID_CHARACTER_GUID);
|
PSendSysMessage(LANG_INVALID_CHARACTER_GUID);
|
||||||
SetSentErrorMessage(true);
|
SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(objmgr.GetPlayerAccountIdByGUID(guid))
|
if (objmgr.GetPlayerAccountIdByGUID(guid))
|
||||||
{
|
{
|
||||||
PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid);
|
PSendSysMessage(LANG_CHARACTER_GUID_IN_USE,guid);
|
||||||
SetSentErrorMessage(true);
|
SetSentErrorMessage(true);
|
||||||
|
|
@ -6562,8 +6545,7 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
||||||
player->SetByteValue(PLAYER_BYTES_3, 0, gender);
|
player->SetByteValue(PLAYER_BYTES_3, 0, gender);
|
||||||
|
|
||||||
// Change display ID
|
// Change display ID
|
||||||
player->SetDisplayId(gender ? info->displayId_f : info->displayId_m);
|
player->InitDisplayIds();
|
||||||
player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m);
|
|
||||||
|
|
||||||
char const* gender_full = gender ? "female" : "male";
|
char const* gender_full = gender ? "female" : "male";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,10 @@ void WorldSession::HandleLootOpcode( WorldPacket & recv_data )
|
||||||
uint64 guid;
|
uint64 guid;
|
||||||
recv_data >> guid;
|
recv_data >> guid;
|
||||||
|
|
||||||
|
// Check possible cheat
|
||||||
|
if(!_player->isAlive())
|
||||||
|
return;
|
||||||
|
|
||||||
GetPlayer()->SendLoot(guid, LOOT_CORPSE);
|
GetPlayer()->SendLoot(guid, LOOT_CORPSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -762,38 +762,40 @@ void WorldSession::HandleQueryNextMailTime(WorldPacket & /*recv_data*/ )
|
||||||
{
|
{
|
||||||
data << (uint32) 0; // float
|
data << (uint32) 0; // float
|
||||||
data << (uint32) 0; // count
|
data << (uint32) 0; // count
|
||||||
|
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
|
time_t now = time(NULL);
|
||||||
for(PlayerMails::iterator itr = _player->GetmailBegin(); itr != _player->GetmailEnd(); ++itr)
|
for(PlayerMails::iterator itr = _player->GetmailBegin(); itr != _player->GetmailEnd(); ++itr)
|
||||||
{
|
{
|
||||||
Mail *m = (*itr);
|
Mail *m = (*itr);
|
||||||
// not checked yet, already must be delivered
|
// must be not checked yet
|
||||||
if((m->checked & MAIL_CHECK_MASK_READ)==0 && (m->deliver_time <= time(NULL)))
|
if(m->checked & MAIL_CHECK_MASK_READ)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// and already delivered
|
||||||
|
if(now < m->deliver_time)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
data << (uint64) m->sender; // sender guid
|
||||||
|
|
||||||
|
switch(m->messageType)
|
||||||
{
|
{
|
||||||
++count;
|
case MAIL_AUCTION:
|
||||||
|
data << (uint32) 2;
|
||||||
if(count > 2)
|
data << (uint32) 2;
|
||||||
{
|
data << (uint32) m->stationery;
|
||||||
count = 2;
|
break;
|
||||||
|
default:
|
||||||
|
data << (uint32) 0;
|
||||||
|
data << (uint32) 0;
|
||||||
|
data << (uint32) m->stationery;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
data << (uint64) m->sender; // sender guid
|
|
||||||
|
|
||||||
switch(m->messageType)
|
|
||||||
{
|
|
||||||
case MAIL_AUCTION:
|
|
||||||
data << (uint32) 2;
|
|
||||||
data << (uint32) 2;
|
|
||||||
data << (uint32) m->stationery;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
data << (uint32) 0;
|
|
||||||
data << (uint32) 0;
|
|
||||||
data << (uint32) m->stationery;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
data << (uint32) 0xC6000000; // float unk, time or something
|
|
||||||
}
|
}
|
||||||
|
data << (uint32) 0xC6000000; // float unk, time or something
|
||||||
|
|
||||||
|
++count;
|
||||||
|
if(count == 2) // do not display more than 2 mails
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
data.put<uint32>(4, count);
|
data.put<uint32>(4, count);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6645,18 +6645,24 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectMgr::IsValidName( const std::string& name, bool create )
|
uint8 ObjectMgr::CheckPlayerName( const std::string& name, bool create )
|
||||||
{
|
{
|
||||||
std::wstring wname;
|
std::wstring wname;
|
||||||
if(!Utf8toWStr(name,wname))
|
if(!Utf8toWStr(name,wname))
|
||||||
return false;
|
return CHAR_NAME_INVALID_CHARACTER;
|
||||||
|
|
||||||
if(wname.size() < 1 || wname.size() > MAX_PLAYER_NAME)
|
if(wname.size() > MAX_PLAYER_NAME)
|
||||||
return false;
|
return CHAR_NAME_TOO_LONG;
|
||||||
|
|
||||||
|
uint32 minName = sWorld.getConfig(CONFIG_MIN_PLAYER_NAME);
|
||||||
|
if(wname.size() < minName)
|
||||||
|
return CHAR_NAME_TOO_SHORT;
|
||||||
|
|
||||||
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES);
|
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES);
|
||||||
|
if(!isValidString(wname,strictMask,false,create))
|
||||||
|
return CHAR_NAME_MIXED_LANGUAGES;
|
||||||
|
|
||||||
return isValidString(wname,strictMask,false,create);
|
return CHAR_NAME_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectMgr::IsValidCharterName( const std::string& name )
|
bool ObjectMgr::IsValidCharterName( const std::string& name )
|
||||||
|
|
@ -6665,7 +6671,11 @@ bool ObjectMgr::IsValidCharterName( const std::string& name )
|
||||||
if(!Utf8toWStr(name,wname))
|
if(!Utf8toWStr(name,wname))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(wname.size() < 1)
|
if(wname.size() > MAX_CHARTER_NAME)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32 minName = sWorld.getConfig(CONFIG_MIN_CHARTER_NAME);
|
||||||
|
if(wname.size() < minName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES);
|
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES);
|
||||||
|
|
@ -6673,18 +6683,24 @@ bool ObjectMgr::IsValidCharterName( const std::string& name )
|
||||||
return isValidString(wname,strictMask,true);
|
return isValidString(wname,strictMask,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectMgr::IsValidPetName( const std::string& name )
|
PetNameInvalidReason ObjectMgr::CheckPetName( const std::string& name )
|
||||||
{
|
{
|
||||||
std::wstring wname;
|
std::wstring wname;
|
||||||
if(!Utf8toWStr(name,wname))
|
if(!Utf8toWStr(name,wname))
|
||||||
return false;
|
return PET_NAME_INVALID;
|
||||||
|
|
||||||
if(wname.size() < 1)
|
if(wname.size() > MAX_PET_NAME)
|
||||||
return false;
|
return PET_NAME_TOO_LONG;
|
||||||
|
|
||||||
|
uint32 minName = sWorld.getConfig(CONFIG_MIN_PET_NAME);
|
||||||
|
if(wname.size() < minName)
|
||||||
|
return PET_NAME_TOO_SHORT;
|
||||||
|
|
||||||
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES);
|
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES);
|
||||||
|
if(!isValidString(wname,strictMask,false))
|
||||||
|
return PET_NAME_MIXED_LANGUAGES;
|
||||||
|
|
||||||
return isValidString(wname,strictMask,false);
|
return PET_NAME_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObjectMgr::GetIndexForLocale( LocaleConstant loc )
|
int ObjectMgr::GetIndexForLocale( LocaleConstant loc )
|
||||||
|
|
|
||||||
|
|
@ -279,8 +279,10 @@ enum SkillRangeType
|
||||||
|
|
||||||
SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial);
|
SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial);
|
||||||
|
|
||||||
#define MAX_PLAYER_NAME 12 // max allowed by client name length
|
#define MAX_PLAYER_NAME 12 // max allowed by client name length
|
||||||
#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length ( > MAX_PLAYER_NAME for support declined names )
|
#define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length ( > MAX_PLAYER_NAME for support declined names )
|
||||||
|
#define MAX_PET_NAME 12 // max allowed by client name length
|
||||||
|
#define MAX_CHARTER_NAME 24 // max allowed by client name length
|
||||||
|
|
||||||
bool normalizePlayerName(std::string& name);
|
bool normalizePlayerName(std::string& name);
|
||||||
|
|
||||||
|
|
@ -693,9 +695,9 @@ class ObjectMgr
|
||||||
bool IsReservedName(const std::string& name) const;
|
bool IsReservedName(const std::string& name) const;
|
||||||
|
|
||||||
// name with valid structure and symbols
|
// name with valid structure and symbols
|
||||||
static bool IsValidName( const std::string& name, bool create = false );
|
static uint8 CheckPlayerName( const std::string& name, bool create = false );
|
||||||
|
static PetNameInvalidReason CheckPetName( const std::string& name );
|
||||||
static bool IsValidCharterName( const std::string& name );
|
static bool IsValidCharterName( const std::string& name );
|
||||||
static bool IsValidPetName( const std::string& name );
|
|
||||||
|
|
||||||
static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names);
|
static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1459,13 +1459,16 @@ bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab)
|
||||||
{
|
{
|
||||||
if(removeSpell(spell_id,learn_prev,clear_ab))
|
if(removeSpell(spell_id,learn_prev,clear_ab))
|
||||||
{
|
{
|
||||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
if(!m_loading)
|
||||||
{
|
{
|
||||||
if(!m_loading)
|
if (Unit* owner = GetOwner())
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_PET_REMOVED_SPELL, 4);
|
if(owner->GetTypeId() == TYPEID_PLAYER)
|
||||||
data << uint32(spell_id);
|
{
|
||||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
WorldPacket data(SMSG_PET_REMOVED_SPELL, 4);
|
||||||
|
data << uint32(spell_id);
|
||||||
|
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ enum PetTalk
|
||||||
|
|
||||||
enum PetNameInvalidReason
|
enum PetNameInvalidReason
|
||||||
{
|
{
|
||||||
|
// custom, not send
|
||||||
|
PET_NAME_SUCCESS = 0,
|
||||||
|
|
||||||
PET_NAME_INVALID = 1,
|
PET_NAME_INVALID = 1,
|
||||||
PET_NAME_NO_NAME = 2,
|
PET_NAME_NO_NAME = 2,
|
||||||
PET_NAME_TOO_SHORT = 3,
|
PET_NAME_TOO_SHORT = 3,
|
||||||
|
|
|
||||||
|
|
@ -401,9 +401,10 @@ void WorldSession::HandlePetRename( WorldPacket & recv_data )
|
||||||
pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() )
|
pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!ObjectMgr::IsValidPetName(name))
|
PetNameInvalidReason res = ObjectMgr::CheckPetName(name);
|
||||||
|
if(res != PET_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
SendPetNameInvalid(PET_NAME_INVALID, name, NULL);
|
SendPetNameInvalid(res, name, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -556,27 +556,12 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
|
||||||
SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE);
|
SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE);
|
||||||
SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f);
|
SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f);
|
||||||
|
|
||||||
switch(gender)
|
|
||||||
{
|
|
||||||
case GENDER_FEMALE:
|
|
||||||
SetDisplayId(info->displayId_f );
|
|
||||||
SetNativeDisplayId(info->displayId_f );
|
|
||||||
break;
|
|
||||||
case GENDER_MALE:
|
|
||||||
SetDisplayId(info->displayId_m );
|
|
||||||
SetNativeDisplayId(info->displayId_m );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sLog.outError("Invalid gender %u for player",gender);
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFactionForRace(race);
|
setFactionForRace(race);
|
||||||
|
|
||||||
uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 );
|
uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 );
|
||||||
|
|
||||||
SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) );
|
SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) );
|
||||||
|
InitDisplayIds();
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
|
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
|
||||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE );
|
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE );
|
||||||
SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);
|
SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);
|
||||||
|
|
@ -1412,7 +1397,7 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )
|
||||||
PlayerInfo const *info = objmgr.GetPlayerInfo(pRace, pClass);
|
PlayerInfo const *info = objmgr.GetPlayerInfo(pRace, pClass);
|
||||||
if(!info)
|
if(!info)
|
||||||
{
|
{
|
||||||
sLog.outError("Player %u have incorrect race/class pair. Don't build enum.", guid);
|
sLog.outError("Player %u has incorrect race/class pair. Don't build enum.", guid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3354,6 +3339,22 @@ void Player::RemoveSpellCooldown( uint32 spell_id, bool update /* = false */ )
|
||||||
SendClearCooldown(spell_id, this);
|
SendClearCooldown(spell_id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::RemoveSpellCategoryCooldown(uint32 cat, bool update /* = false */)
|
||||||
|
{
|
||||||
|
SpellCategoryStore::const_iterator ct = sSpellCategoryStore.find(cat);
|
||||||
|
if (ct == sSpellCategoryStore.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SpellCategorySet& ct_set = ct->second;
|
||||||
|
for (SpellCooldowns::const_iterator i = m_spellCooldowns.begin(); i != m_spellCooldowns.end();)
|
||||||
|
{
|
||||||
|
if (ct_set.find(i->first) != ct_set.end())
|
||||||
|
RemoveSpellCooldown((i++)->first, update);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Player::RemoveArenaSpellCooldowns()
|
void Player::RemoveArenaSpellCooldowns()
|
||||||
{
|
{
|
||||||
// remove cooldowns on spells that has < 15 min CD
|
// remove cooldowns on spells that has < 15 min CD
|
||||||
|
|
@ -3406,7 +3407,7 @@ void Player::_LoadSpellCooldowns(QueryResult *result)
|
||||||
|
|
||||||
if(!sSpellStore.LookupEntry(spell_id))
|
if(!sSpellStore.LookupEntry(spell_id))
|
||||||
{
|
{
|
||||||
sLog.outError("Player %u have unknown spell %u in `character_spell_cooldown`, skipping.",GetGUIDLow(),spell_id);
|
sLog.outError("Player %u has unknown spell %u in `character_spell_cooldown`, skipping.",GetGUIDLow(),spell_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12524,7 +12525,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
|
|
||||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i )
|
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i )
|
||||||
{
|
{
|
||||||
if ( pQuest->ReqItemId[i] )
|
if (pQuest->ReqItemId[i])
|
||||||
DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
|
DestroyItemCount( pQuest->ReqItemId[i], pQuest->ReqItemCount[i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12532,12 +12533,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
// SetTimedQuest( 0 );
|
// SetTimedQuest( 0 );
|
||||||
m_timedquests.erase(pQuest->GetQuestId());
|
m_timedquests.erase(pQuest->GetQuestId());
|
||||||
|
|
||||||
if ( pQuest->GetRewChoiceItemsCount() > 0 )
|
if (pQuest->GetRewChoiceItemsCount() > 0)
|
||||||
{
|
{
|
||||||
if( pQuest->RewChoiceItemId[reward] )
|
if (pQuest->RewChoiceItemId[reward])
|
||||||
{
|
{
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK )
|
if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
Item* item = StoreNewItem( dest, pQuest->RewChoiceItemId[reward], true);
|
Item* item = StoreNewItem( dest, pQuest->RewChoiceItemId[reward], true);
|
||||||
SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false);
|
SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false);
|
||||||
|
|
@ -12545,14 +12546,14 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pQuest->GetRewItemsCount() > 0 )
|
if (pQuest->GetRewItemsCount() > 0)
|
||||||
{
|
{
|
||||||
for (uint32 i=0; i < pQuest->GetRewItemsCount(); ++i)
|
for (uint32 i=0; i < pQuest->GetRewItemsCount(); ++i)
|
||||||
{
|
{
|
||||||
if( pQuest->RewItemId[i] )
|
if (pQuest->RewItemId[i])
|
||||||
{
|
{
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
if( CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK )
|
if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
Item* item = StoreNewItem( dest, pQuest->RewItemId[i], true);
|
Item* item = StoreNewItem( dest, pQuest->RewItemId[i], true);
|
||||||
SendNewItem(item, pQuest->RewItemCount[i], true, false);
|
SendNewItem(item, pQuest->RewItemCount[i], true, false);
|
||||||
|
|
@ -12563,13 +12564,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
|
|
||||||
RewardReputation( pQuest );
|
RewardReputation( pQuest );
|
||||||
|
|
||||||
if( pQuest->GetRewSpellCast() > 0 )
|
|
||||||
CastSpell( this, pQuest->GetRewSpellCast(), true);
|
|
||||||
else if( pQuest->GetRewSpell() > 0)
|
|
||||||
CastSpell( this, pQuest->GetRewSpell(), true);
|
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot( quest_id );
|
uint16 log_slot = FindQuestSlot( quest_id );
|
||||||
if( log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
SetQuestSlot(log_slot,0);
|
SetQuestSlot(log_slot,0);
|
||||||
|
|
||||||
QuestStatusData& q_status = mQuestStatus[quest_id];
|
QuestStatusData& q_status = mQuestStatus[quest_id];
|
||||||
|
|
@ -12577,7 +12573,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
// Not give XP in case already completed once repeatable quest
|
// Not give XP in case already completed once repeatable quest
|
||||||
uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getRate(RATE_XP_QUEST));
|
uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getRate(RATE_XP_QUEST));
|
||||||
|
|
||||||
if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) )
|
if (getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||||
GiveXP( XP , NULL );
|
GiveXP( XP , NULL );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -12587,33 +12583,33 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
|
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
|
||||||
if(pQuest->GetRewOrReqMoney())
|
if (pQuest->GetRewOrReqMoney())
|
||||||
{
|
{
|
||||||
ModifyMoney( pQuest->GetRewOrReqMoney() );
|
ModifyMoney( pQuest->GetRewOrReqMoney() );
|
||||||
|
|
||||||
if(pQuest->GetRewOrReqMoney() > 0)
|
if (pQuest->GetRewOrReqMoney() > 0)
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney());
|
||||||
}
|
}
|
||||||
|
|
||||||
// honor reward
|
// honor reward
|
||||||
if(pQuest->GetRewHonorableKills())
|
if (pQuest->GetRewHonorableKills())
|
||||||
RewardHonor(NULL, 0, MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills()));
|
RewardHonor(NULL, 0, MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills()));
|
||||||
|
|
||||||
// title reward
|
// title reward
|
||||||
if(pQuest->GetCharTitleId())
|
if (pQuest->GetCharTitleId())
|
||||||
{
|
{
|
||||||
if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId()))
|
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId()))
|
||||||
SetTitle(titleEntry);
|
SetTitle(titleEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pQuest->GetBonusTalents())
|
if (pQuest->GetBonusTalents())
|
||||||
{
|
{
|
||||||
m_questRewardTalentCount+=pQuest->GetBonusTalents();
|
m_questRewardTalentCount+=pQuest->GetBonusTalents();
|
||||||
InitTalentForLevel();
|
InitTalentForLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send reward mail
|
// Send reward mail
|
||||||
if(pQuest->GetRewMailTemplateId())
|
if (pQuest->GetRewMailTemplateId())
|
||||||
{
|
{
|
||||||
MailMessageType mailType;
|
MailMessageType mailType;
|
||||||
uint32 senderGuidOrEntry;
|
uint32 senderGuidOrEntry;
|
||||||
|
|
@ -12651,9 +12647,9 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
uint32 max_slot = questMailLoot.GetMaxSlotInLootFor(this);
|
uint32 max_slot = questMailLoot.GetMaxSlotInLootFor(this);
|
||||||
for(uint32 i = 0; mi.size() < MAX_MAIL_ITEMS && i < max_slot; ++i)
|
for(uint32 i = 0; mi.size() < MAX_MAIL_ITEMS && i < max_slot; ++i)
|
||||||
{
|
{
|
||||||
if(LootItem* lootitem = questMailLoot.LootItemInSlot(i,this))
|
if (LootItem* lootitem = questMailLoot.LootItemInSlot(i,this))
|
||||||
{
|
{
|
||||||
if(Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this))
|
if (Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this))
|
||||||
{
|
{
|
||||||
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
|
item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
|
||||||
mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item);
|
mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item);
|
||||||
|
|
@ -12664,23 +12660,30 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
|
||||||
WorldSession::SendMailTo(this, mailType, MAIL_STATIONERY_NORMAL, senderGuidOrEntry, GetGUIDLow(), "", 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE,pQuest->GetRewMailDelaySecs(),pQuest->GetRewMailTemplateId());
|
WorldSession::SendMailTo(this, mailType, MAIL_STATIONERY_NORMAL, senderGuidOrEntry, GetGUIDLow(), "", 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE,pQuest->GetRewMailDelaySecs(),pQuest->GetRewMailTemplateId());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pQuest->IsDaily())
|
if (pQuest->IsDaily())
|
||||||
{
|
{
|
||||||
SetDailyQuestStatus(quest_id);
|
SetDailyQuestStatus(quest_id);
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !pQuest->IsRepeatable() )
|
if (!pQuest->IsRepeatable())
|
||||||
SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE);
|
SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE);
|
||||||
else
|
else
|
||||||
SetQuestStatus(quest_id, QUEST_STATUS_NONE);
|
SetQuestStatus(quest_id, QUEST_STATUS_NONE);
|
||||||
|
|
||||||
q_status.m_rewarded = true;
|
q_status.m_rewarded = true;
|
||||||
|
if (q_status.uState != QUEST_NEW)
|
||||||
|
q_status.uState = QUEST_CHANGED;
|
||||||
|
|
||||||
if(announce)
|
if (announce)
|
||||||
SendQuestReward( pQuest, XP, questGiver );
|
SendQuestReward( pQuest, XP, questGiver );
|
||||||
|
|
||||||
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
|
// cast spells after mark quest complete (some spells have quest completed state reqyurements in spell_area data)
|
||||||
|
if (pQuest->GetRewSpellCast() > 0)
|
||||||
|
CastSpell( this, pQuest->GetRewSpellCast(), true);
|
||||||
|
else if ( pQuest->GetRewSpell() > 0)
|
||||||
|
CastSpell( this, pQuest->GetRewSpell(), true);
|
||||||
|
|
||||||
if (pQuest->GetZoneOrSort() > 0)
|
if (pQuest->GetZoneOrSort() > 0)
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
||||||
|
|
@ -14028,7 +14031,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||||
m_name = fields[3].GetCppString();
|
m_name = fields[3].GetCppString();
|
||||||
|
|
||||||
// check name limitations
|
// check name limitations
|
||||||
if(!ObjectMgr::IsValidName(m_name) || (GetSession()->GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(m_name)))
|
if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS ||
|
||||||
|
GetSession()->GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(m_name))
|
||||||
{
|
{
|
||||||
delete result;
|
delete result;
|
||||||
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid ='%u'", uint32(AT_LOGIN_RENAME),guid);
|
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid ='%u'", uint32(AT_LOGIN_RENAME),guid);
|
||||||
|
|
@ -14060,6 +14064,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||||
SetUInt32Value(PLAYER_BYTES_3, (GetUInt32Value(PLAYER_BYTES_3) & ~1) | fields[6].GetUInt8());
|
SetUInt32Value(PLAYER_BYTES_3, (GetUInt32Value(PLAYER_BYTES_3) & ~1) | fields[6].GetUInt8());
|
||||||
SetUInt32Value(PLAYER_FLAGS, fields[12].GetUInt32());
|
SetUInt32Value(PLAYER_FLAGS, fields[12].GetUInt32());
|
||||||
|
|
||||||
|
InitDisplayIds();
|
||||||
|
|
||||||
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
|
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
|
||||||
for(uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
|
for(uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)
|
||||||
{
|
{
|
||||||
|
|
@ -14921,7 +14927,7 @@ void Player::_LoadMailedItems(Mail *mail)
|
||||||
|
|
||||||
if(!proto)
|
if(!proto)
|
||||||
{
|
{
|
||||||
sLog.outError( "Player %u have unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID);
|
sLog.outError( "Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID);
|
||||||
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low);
|
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low);
|
||||||
CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low);
|
CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -15514,7 +15520,6 @@ void Player::SaveToDB()
|
||||||
SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND);
|
SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND);
|
||||||
SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift
|
SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift
|
||||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||||
SetDisplayId(GetNativeDisplayId());
|
|
||||||
|
|
||||||
bool inworld = IsInWorld();
|
bool inworld = IsInWorld();
|
||||||
|
|
||||||
|
|
@ -15659,7 +15664,6 @@ void Player::SaveToDB()
|
||||||
CharacterDatabase.CommitTransaction();
|
CharacterDatabase.CommitTransaction();
|
||||||
|
|
||||||
// restore state (before aura apply, if aura remove flag then aura must set it ack by self)
|
// restore state (before aura apply, if aura remove flag then aura must set it ack by self)
|
||||||
SetDisplayId(tmp_displayid);
|
|
||||||
SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes);
|
SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes);
|
||||||
SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2);
|
SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2);
|
||||||
SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags);
|
SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags);
|
||||||
|
|
@ -16103,28 +16107,17 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid)
|
||||||
|
|
||||||
void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair)
|
void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair)
|
||||||
{
|
{
|
||||||
// 0 1 2 3 4
|
// 0
|
||||||
QueryResult* result = CharacterDatabase.PQuery("SELECT data, race, class, playerBytes, playerBytes2 FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
|
QueryResult* result = CharacterDatabase.PQuery("SELECT playerBytes2 FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
|
||||||
if(!result)
|
if(!result)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Field* fields = result->Fetch();
|
Field* fields = result->Fetch();
|
||||||
|
|
||||||
Tokens tokens = StrSplit(fields[0].GetString(), " ");
|
uint32 player_bytes2 = fields[0].GetUInt32();
|
||||||
|
|
||||||
PlayerInfo const* info = objmgr.GetPlayerInfo(fields[1].GetUInt8(), fields[2].GetUInt8());
|
|
||||||
if(!info)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// TODO: do not access data field here
|
|
||||||
SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m);
|
|
||||||
SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m);
|
|
||||||
|
|
||||||
uint32 player_bytes2 = fields[4].GetUInt32();
|
|
||||||
player_bytes2 &= ~0xFF;
|
player_bytes2 &= ~0xFF;
|
||||||
player_bytes2 |= facialHair;
|
player_bytes2 |= facialHair;
|
||||||
|
|
||||||
SaveValuesArrayInDB(tokens, guid);
|
|
||||||
CharacterDatabase.PExecute("UPDATE characters SET gender = '%u', playerBytes = '%u', playerBytes2 = '%u' WHERE guid = '%u'", gender, skin | (face << 8) | (hairStyle << 16) | (hairColor << 24), player_bytes2, GUID_LOPART(guid));
|
CharacterDatabase.PExecute("UPDATE characters SET gender = '%u', playerBytes = '%u', playerBytes2 = '%u' WHERE guid = '%u'", gender, skin | (face << 8) | (hairStyle << 16) | (hairColor << 24), player_bytes2, GUID_LOPART(guid));
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
|
|
@ -16379,9 +16372,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
|
||||||
|
|
||||||
if(pet->isControlled())
|
if(pet->isControlled())
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_PET_SPELLS, 8);
|
RemovePetActionBar();
|
||||||
data << uint64(0);
|
|
||||||
GetSession()->SendPacket(&data);
|
|
||||||
|
|
||||||
if(GetGroup())
|
if(GetGroup())
|
||||||
SetGroupUpdateFlag(GROUP_UPDATE_PET);
|
SetGroupUpdateFlag(GROUP_UPDATE_PET);
|
||||||
|
|
@ -16643,6 +16634,13 @@ void Player::CharmSpellInitialize()
|
||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::RemovePetActionBar()
|
||||||
|
{
|
||||||
|
WorldPacket data(SMSG_PET_SPELLS, 8);
|
||||||
|
data << uint64(0);
|
||||||
|
SendDirectMessage(&data);
|
||||||
|
}
|
||||||
|
|
||||||
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
|
bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell)
|
||||||
{
|
{
|
||||||
if (!mod || !spellInfo)
|
if (!mod || !spellInfo)
|
||||||
|
|
@ -17156,17 +17154,43 @@ void Player::InitDataForForm(bool reapplyMods)
|
||||||
UpdateAttackPowerAndDamage(true);
|
UpdateAttackPowerAndDamage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::InitDisplayIds()
|
||||||
|
{
|
||||||
|
PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass());
|
||||||
|
if(!info)
|
||||||
|
{
|
||||||
|
sLog.outError("Player %u has incorrect race/class pair. Can't init display ids.", GetGUIDLow());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 gender = getGender();
|
||||||
|
switch(gender)
|
||||||
|
{
|
||||||
|
case GENDER_FEMALE:
|
||||||
|
SetDisplayId(info->displayId_f );
|
||||||
|
SetNativeDisplayId(info->displayId_f );
|
||||||
|
break;
|
||||||
|
case GENDER_MALE:
|
||||||
|
SetDisplayId(info->displayId_m );
|
||||||
|
SetNativeDisplayId(info->displayId_m );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sLog.outError("Invalid gender %u for player",gender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return true is the bought item has a max count to force refresh of window by caller
|
// Return true is the bought item has a max count to force refresh of window by caller
|
||||||
bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot)
|
bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot)
|
||||||
{
|
{
|
||||||
// cheating attempt
|
// cheating attempt
|
||||||
if(count < 1) count = 1;
|
if (count < 1) count = 1;
|
||||||
|
|
||||||
if(!isAlive())
|
if (!isAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
|
ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
|
||||||
if( !pProto )
|
if (!pProto)
|
||||||
{
|
{
|
||||||
SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0);
|
SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -17188,7 +17212,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t vendor_slot = vItems->FindItemSlot(item);
|
size_t vendor_slot = vItems->FindItemSlot(item);
|
||||||
if(vendor_slot >= vItems->GetItemCount())
|
if (vendor_slot >= vItems->GetItemCount())
|
||||||
{
|
{
|
||||||
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
|
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -17197,39 +17221,39 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
VendorItem const* crItem = vItems->m_items[vendor_slot];
|
VendorItem const* crItem = vItems->m_items[vendor_slot];
|
||||||
|
|
||||||
// check current item amount if it limited
|
// check current item amount if it limited
|
||||||
if( crItem->maxcount != 0 )
|
if (crItem->maxcount != 0)
|
||||||
{
|
{
|
||||||
if(pCreature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count )
|
if (pCreature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count )
|
||||||
{
|
{
|
||||||
SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0);
|
SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
|
if (uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
|
||||||
{
|
{
|
||||||
SendBuyError( BUY_ERR_REPUTATION_REQUIRE, pCreature, item, 0);
|
SendBuyError( BUY_ERR_REPUTATION_REQUIRE, pCreature, item, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(crItem->ExtendedCost)
|
if (crItem->ExtendedCost)
|
||||||
{
|
{
|
||||||
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
||||||
if(!iece)
|
if (!iece)
|
||||||
{
|
{
|
||||||
sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
|
sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// honor points price
|
// honor points price
|
||||||
if(GetHonorPoints() < (iece->reqhonorpoints * count))
|
if (GetHonorPoints() < (iece->reqhonorpoints * count))
|
||||||
{
|
{
|
||||||
SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL);
|
SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// arena points price
|
// arena points price
|
||||||
if(GetArenaPoints() < (iece->reqarenapoints * count))
|
if (GetArenaPoints() < (iece->reqarenapoints * count))
|
||||||
{
|
{
|
||||||
SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL);
|
SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -17259,62 +17283,38 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
// reputation discount
|
// reputation discount
|
||||||
price = uint32(floor(price * GetReputationPriceDiscount(pCreature)));
|
price = uint32(floor(price * GetReputationPriceDiscount(pCreature)));
|
||||||
|
|
||||||
if( GetMoney() < price )
|
if (GetMoney() < price)
|
||||||
{
|
{
|
||||||
SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, item, 0);
|
SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, item, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 bag = 0; // init for case invalid bagGUID
|
if ((bag == NULL_BAG && slot == NULL_SLOT) || IsInventoryPos(bag, slot))
|
||||||
|
|
||||||
if (bagguid != NULL_BAG && slot != NULL_SLOT)
|
|
||||||
{
|
|
||||||
if( bagguid == GetGUID() )
|
|
||||||
{
|
|
||||||
bag = INVENTORY_SLOT_BAG_0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;++i)
|
|
||||||
{
|
|
||||||
if( Bag *pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0,i) )
|
|
||||||
{
|
|
||||||
if( bagguid == pBag->GetGUID() )
|
|
||||||
{
|
|
||||||
bag = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( IsInventoryPos( bag, slot ) || (bagguid == NULL_BAG && slot == NULL_SLOT) )
|
|
||||||
{
|
{
|
||||||
ItemPosCountVec dest;
|
ItemPosCountVec dest;
|
||||||
uint8 msg = CanStoreNewItem( bag, slot, dest, item, pProto->BuyCount * count );
|
uint8 msg = CanStoreNewItem( bag, slot, dest, item, pProto->BuyCount * count );
|
||||||
if( msg != EQUIP_ERR_OK )
|
if (msg != EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
SendEquipError( msg, NULL, NULL );
|
SendEquipError( msg, NULL, NULL );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifyMoney( -(int32)price );
|
ModifyMoney( -(int32)price );
|
||||||
if(crItem->ExtendedCost) // case for new honor system
|
if (crItem->ExtendedCost) // case for new honor system
|
||||||
{
|
{
|
||||||
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
||||||
if(iece->reqhonorpoints)
|
if (iece->reqhonorpoints)
|
||||||
ModifyHonorPoints( - int32(iece->reqhonorpoints * count));
|
ModifyHonorPoints( - int32(iece->reqhonorpoints * count));
|
||||||
if(iece->reqarenapoints)
|
if (iece->reqarenapoints)
|
||||||
ModifyArenaPoints( - int32(iece->reqarenapoints * count));
|
ModifyArenaPoints( - int32(iece->reqarenapoints * count));
|
||||||
for (uint8 i = 0; i < 5; ++i)
|
for (uint8 i = 0; i < 5; ++i)
|
||||||
{
|
{
|
||||||
if(iece->reqitem[i])
|
if (iece->reqitem[i])
|
||||||
DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
|
DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Item *it = StoreNewItem( dest, item, true ))
|
if (Item *it = StoreNewItem( dest, item, true ))
|
||||||
{
|
{
|
||||||
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
|
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
|
||||||
|
|
||||||
|
|
@ -17328,9 +17328,9 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
SendNewItem(it, pProto->BuyCount*count, true, false, false);
|
SendNewItem(it, pProto->BuyCount*count, true, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( IsEquipmentPos( bag, slot ) )
|
else if (IsEquipmentPos(bag, slot))
|
||||||
{
|
{
|
||||||
if(pProto->BuyCount * count != 1)
|
if (pProto->BuyCount * count != 1)
|
||||||
{
|
{
|
||||||
SendEquipError( EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL );
|
SendEquipError( EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL );
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -17338,19 +17338,19 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
|
|
||||||
uint16 dest;
|
uint16 dest;
|
||||||
uint8 msg = CanEquipNewItem( slot, dest, item, false );
|
uint8 msg = CanEquipNewItem( slot, dest, item, false );
|
||||||
if( msg != EQUIP_ERR_OK )
|
if (msg != EQUIP_ERR_OK)
|
||||||
{
|
{
|
||||||
SendEquipError( msg, NULL, NULL );
|
SendEquipError( msg, NULL, NULL );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifyMoney( -(int32)price );
|
ModifyMoney( -(int32)price );
|
||||||
if(crItem->ExtendedCost) // case for new honor system
|
if (crItem->ExtendedCost) // case for new honor system
|
||||||
{
|
{
|
||||||
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
|
||||||
if(iece->reqhonorpoints)
|
if (iece->reqhonorpoints)
|
||||||
ModifyHonorPoints( - int32(iece->reqhonorpoints));
|
ModifyHonorPoints( - int32(iece->reqhonorpoints));
|
||||||
if(iece->reqarenapoints)
|
if (iece->reqarenapoints)
|
||||||
ModifyArenaPoints( - int32(iece->reqarenapoints));
|
ModifyArenaPoints( - int32(iece->reqarenapoints));
|
||||||
for (uint8 i = 0; i < 5; ++i)
|
for (uint8 i = 0; i < 5; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -17359,7 +17359,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Item *it = EquipNewItem( dest, item, true ))
|
if (Item *it = EquipNewItem( dest, item, true ))
|
||||||
{
|
{
|
||||||
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
|
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
|
||||||
|
|
||||||
|
|
@ -17381,7 +17381,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return crItem->maxcount!=0;
|
return crItem->maxcount != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Player::GetMaxPersonalArenaRatingRequirement()
|
uint32 Player::GetMaxPersonalArenaRatingRequirement()
|
||||||
|
|
@ -19394,7 +19394,7 @@ void Player::EnterVehicle(Vehicle *vehicle)
|
||||||
|
|
||||||
vehicle->SetCharmerGUID(GetGUID());
|
vehicle->SetCharmerGUID(GetGUID());
|
||||||
vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||||
vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
|
vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
vehicle->setFaction(getFaction());
|
vehicle->setFaction(getFaction());
|
||||||
|
|
||||||
SetCharm(vehicle); // charm
|
SetCharm(vehicle); // charm
|
||||||
|
|
@ -19446,7 +19446,7 @@ void Player::ExitVehicle(Vehicle *vehicle)
|
||||||
{
|
{
|
||||||
vehicle->SetCharmerGUID(0);
|
vehicle->SetCharmerGUID(0);
|
||||||
vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
|
||||||
vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
|
vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
|
vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
|
||||||
|
|
||||||
SetCharm(NULL);
|
SetCharm(NULL);
|
||||||
|
|
@ -19468,9 +19468,7 @@ void Player::ExitVehicle(Vehicle *vehicle)
|
||||||
data << uint32(0); // fall time
|
data << uint32(0); // fall time
|
||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
|
|
||||||
data.Initialize(SMSG_PET_SPELLS, 8);
|
RemovePetActionBar();
|
||||||
data << uint64(0);
|
|
||||||
GetSession()->SendPacket(&data);
|
|
||||||
|
|
||||||
// maybe called at dummy aura remove?
|
// maybe called at dummy aura remove?
|
||||||
// CastSpell(this, 45472, true); // Parachute
|
// CastSpell(this, 45472, true); // Parachute
|
||||||
|
|
|
||||||
|
|
@ -1191,7 +1191,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
|
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
|
||||||
}
|
}
|
||||||
void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false );
|
void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false );
|
||||||
bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot);
|
bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
||||||
|
|
||||||
float GetReputationPriceDiscount( Creature const* pCreature ) const;
|
float GetReputationPriceDiscount( Creature const* pCreature ) const;
|
||||||
Player* GetTrader() const { return pTrader; }
|
Player* GetTrader() const { return pTrader; }
|
||||||
|
|
@ -1447,6 +1447,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void PetSpellInitialize();
|
void PetSpellInitialize();
|
||||||
void CharmSpellInitialize();
|
void CharmSpellInitialize();
|
||||||
void PossessSpellInitialize();
|
void PossessSpellInitialize();
|
||||||
|
void RemovePetActionBar();
|
||||||
|
|
||||||
bool HasSpell(uint32 spell) const;
|
bool HasSpell(uint32 spell) const;
|
||||||
bool HasActiveSpell(uint32 spell) const; // show in spellbook
|
bool HasActiveSpell(uint32 spell) const; // show in spellbook
|
||||||
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
|
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
|
||||||
|
|
@ -1497,6 +1499,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
|
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
|
||||||
PlayerSpellMap & GetSpellMap() { return m_spells; }
|
PlayerSpellMap & GetSpellMap() { return m_spells; }
|
||||||
|
|
||||||
|
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
|
||||||
|
|
||||||
void AddSpellMod(SpellModifier* mod, bool apply);
|
void AddSpellMod(SpellModifier* mod, bool apply);
|
||||||
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
|
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
|
||||||
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
|
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
|
||||||
|
|
@ -1520,6 +1524,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL);
|
void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL);
|
||||||
void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
|
void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
|
||||||
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
|
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
|
||||||
|
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
|
||||||
void SendClearCooldown( uint32 spell_id, Unit* target );
|
void SendClearCooldown( uint32 spell_id, Unit* target );
|
||||||
|
|
||||||
void RemoveArenaSpellCooldowns();
|
void RemoveArenaSpellCooldowns();
|
||||||
|
|
@ -1783,6 +1788,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
static uint32 getFactionForRace(uint8 race);
|
static uint32 getFactionForRace(uint8 race);
|
||||||
void setFactionForRace(uint8 race);
|
void setFactionForRace(uint8 race);
|
||||||
|
|
||||||
|
void InitDisplayIds();
|
||||||
|
|
||||||
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
|
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
|
||||||
bool RewardPlayerAndGroupAtKill(Unit* pVictim);
|
bool RewardPlayerAndGroupAtKill(Unit* pVictim);
|
||||||
void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource);
|
void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource);
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||||
{
|
{
|
||||||
QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account);
|
QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account);
|
||||||
uint8 charcount = 0;
|
uint8 charcount = 0;
|
||||||
if ( result )
|
if (result)
|
||||||
{
|
{
|
||||||
Field *fields=result->Fetch();
|
Field *fields=result->Fetch();
|
||||||
charcount = fields[0].GetUInt8();
|
charcount = fields[0].GetUInt8();
|
||||||
|
|
@ -405,7 +405,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *fin = fopen(file.c_str(), "r");
|
FILE *fin = fopen(file.c_str(), "r");
|
||||||
if(!fin)
|
if (!fin)
|
||||||
return DUMP_FILE_OPEN_ERROR;
|
return DUMP_FILE_OPEN_ERROR;
|
||||||
|
|
||||||
QueryResult * result = NULL;
|
QueryResult * result = NULL;
|
||||||
|
|
@ -413,7 +413,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||||
|
|
||||||
// make sure the same guid doesn't already exist and is safe to use
|
// make sure the same guid doesn't already exist and is safe to use
|
||||||
bool incHighest = true;
|
bool incHighest = true;
|
||||||
if(guid != 0 && guid < objmgr.m_hiCharGuid)
|
if (guid != 0 && guid < objmgr.m_hiCharGuid)
|
||||||
{
|
{
|
||||||
result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid);
|
result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid);
|
||||||
if (result)
|
if (result)
|
||||||
|
|
@ -427,10 +427,10 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||||
guid = objmgr.m_hiCharGuid;
|
guid = objmgr.m_hiCharGuid;
|
||||||
|
|
||||||
// normalize the name if specified and check if it exists
|
// normalize the name if specified and check if it exists
|
||||||
if(!normalizePlayerName(name))
|
if (!normalizePlayerName(name))
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
if(ObjectMgr::IsValidName(name,true))
|
if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS)
|
||||||
{
|
{
|
||||||
CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway
|
CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway
|
||||||
result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str());
|
result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str());
|
||||||
|
|
@ -440,7 +440,8 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else name = "";
|
else
|
||||||
|
name = "";
|
||||||
|
|
||||||
// name encoded or empty
|
// name encoded or empty
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
||||||
|
|
||||||
m_castPositionX = m_castPositionY = m_castPositionZ = 0;
|
m_castPositionX = m_castPositionY = m_castPositionZ = 0;
|
||||||
m_TriggerSpells.clear();
|
m_TriggerSpells.clear();
|
||||||
|
m_preCastSpells.clear();
|
||||||
m_IsTriggeredSpell = triggered;
|
m_IsTriggeredSpell = triggered;
|
||||||
//m_AreaAura = false;
|
//m_AreaAura = false;
|
||||||
m_CastItem = NULL;
|
m_CastItem = NULL;
|
||||||
|
|
@ -405,7 +406,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
||||||
focusObject = NULL;
|
focusObject = NULL;
|
||||||
m_cast_count = 0;
|
m_cast_count = 0;
|
||||||
m_glyphIndex = 0;
|
m_glyphIndex = 0;
|
||||||
m_preCastSpell = 0;
|
|
||||||
m_triggeredByAuraSpell = NULL;
|
m_triggeredByAuraSpell = NULL;
|
||||||
|
|
||||||
//Auto Shot & Shoot (wand)
|
//Auto Shot & Shoot (wand)
|
||||||
|
|
@ -1146,15 +1146,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||||
|
|
||||||
void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
||||||
{
|
{
|
||||||
if(!unit || !effectMask)
|
if (!unit || !effectMask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Unit* realCaster = m_originalCaster ? m_originalCaster : m_caster;
|
||||||
|
|
||||||
// Recheck immune (only for delayed spells)
|
// Recheck immune (only for delayed spells)
|
||||||
if( m_spellInfo->speed && (
|
if (m_spellInfo->speed && (
|
||||||
unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo)) ||
|
unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo)) ||
|
||||||
unit->IsImmunedToSpell(m_spellInfo)))
|
unit->IsImmunedToSpell(m_spellInfo)))
|
||||||
{
|
{
|
||||||
m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE);
|
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1164,67 +1166,65 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
||||||
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
|
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_caster->GetTypeId() == TYPEID_PLAYER)
|
if (realCaster->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
((Player*)realCaster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
|
||||||
((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_caster != unit )
|
if (realCaster != unit)
|
||||||
{
|
{
|
||||||
// Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells
|
// Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells
|
||||||
if (m_spellInfo->speed > 0.0f &&
|
if (m_spellInfo->speed > 0.0f &&
|
||||||
unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) &&
|
unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) &&
|
||||||
unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
|
unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
|
||||||
{
|
{
|
||||||
m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !m_caster->IsFriendlyTo(unit) )
|
if (!realCaster->IsFriendlyTo(unit))
|
||||||
{
|
{
|
||||||
// for delayed spells ignore not visible explicit target
|
// for delayed spells ignore not visible explicit target
|
||||||
if(m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() && !unit->isVisibleForOrDetect(m_caster,false))
|
if (m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() &&
|
||||||
|
!unit->isVisibleForOrDetect(m_caster,false))
|
||||||
{
|
{
|
||||||
m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
|
||||||
|
|
||||||
if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) )
|
if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO))
|
||||||
{
|
{
|
||||||
if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED))
|
if (!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED))
|
||||||
unit->SetStandState(UNIT_STAND_STATE_STAND);
|
unit->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
|
|
||||||
if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
|
if (!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
|
||||||
((Creature*)unit)->AI()->AttackedBy(m_caster);
|
((Creature*)unit)->AI()->AttackedBy(realCaster);
|
||||||
|
|
||||||
unit->AddThreat(m_caster, 0.0f);
|
unit->AddThreat(realCaster, 0.0f);
|
||||||
unit->SetInCombatWith(m_caster);
|
unit->SetInCombatWith(realCaster);
|
||||||
m_caster->SetInCombatWith(unit);
|
realCaster->SetInCombatWith(unit);
|
||||||
|
|
||||||
if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
|
if (Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||||
{
|
realCaster->SetContestedPvP(attackedPlayer);
|
||||||
m_caster->SetContestedPvP(attackedPlayer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// for delayed spells ignore negative spells (after duel end) for friendly targets
|
// for delayed spells ignore negative spells (after duel end) for friendly targets
|
||||||
if(m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id))
|
if (m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id))
|
||||||
{
|
{
|
||||||
m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assisting case, healing and resurrection
|
// assisting case, healing and resurrection
|
||||||
if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
|
if (unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
|
||||||
m_caster->SetContestedPvP();
|
realCaster->SetContestedPvP();
|
||||||
if( unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) )
|
|
||||||
|
if (unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO))
|
||||||
{
|
{
|
||||||
m_caster->SetInCombatState(unit->GetCombatTimer() > 0);
|
realCaster->SetInCombatState(unit->GetCombatTimer() > 0);
|
||||||
unit->getHostilRefManager().threatAssist(m_caster, 0.0f);
|
unit->getHostilRefManager().threatAssist(realCaster, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1233,12 +1233,17 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
||||||
m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo,m_triggeredByAuraSpell);
|
m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo,m_triggeredByAuraSpell);
|
||||||
m_diminishLevel = unit->GetDiminishing(m_diminishGroup);
|
m_diminishLevel = unit->GetDiminishing(m_diminishGroup);
|
||||||
// Increase Diminishing on unit, current informations for actually casts will use values above
|
// Increase Diminishing on unit, current informations for actually casts will use values above
|
||||||
if((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL)
|
if ((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) ||
|
||||||
|
GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL)
|
||||||
unit->IncrDiminishing(m_diminishGroup);
|
unit->IncrDiminishing(m_diminishGroup);
|
||||||
|
|
||||||
// Apply additional spell effects to target
|
// Apply additional spell effects to target
|
||||||
if (m_preCastSpell)
|
while (!m_preCastSpells.empty())
|
||||||
m_caster->CastSpell(unit, m_preCastSpell, true, m_CastItem);
|
{
|
||||||
|
uint32 spellId = *m_preCastSpells.begin();
|
||||||
|
m_caster->CastSpell(unit, spellId, true, m_CastItem);
|
||||||
|
m_preCastSpells.erase(m_preCastSpells.begin());
|
||||||
|
}
|
||||||
|
|
||||||
for(uint32 effectNumber = 0; effectNumber < 3; ++effectNumber)
|
for(uint32 effectNumber = 0; effectNumber < 3; ++effectNumber)
|
||||||
{
|
{
|
||||||
|
|
@ -1250,7 +1255,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
||||||
// Get multiplier
|
// Get multiplier
|
||||||
float multiplier = m_spellInfo->DmgMultiplier[effectNumber];
|
float multiplier = m_spellInfo->DmgMultiplier[effectNumber];
|
||||||
// Apply multiplier mods
|
// Apply multiplier mods
|
||||||
if(Player* modOwner = m_originalCaster->GetSpellModOwner())
|
if(Player* modOwner = realCaster->GetSpellModOwner())
|
||||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier, this);
|
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier, this);
|
||||||
m_damageMultipliers[effectNumber] *= multiplier;
|
m_damageMultipliers[effectNumber] *= multiplier;
|
||||||
}
|
}
|
||||||
|
|
@ -2287,17 +2292,17 @@ void Spell::cast(bool skipCheck)
|
||||||
case SPELLFAMILY_GENERIC:
|
case SPELLFAMILY_GENERIC:
|
||||||
{
|
{
|
||||||
if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
|
if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
|
||||||
m_preCastSpell = 11196; // Recently Bandaged
|
AddPrecastSpell(11196); // Recently Bandaged
|
||||||
else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20)
|
else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20)
|
||||||
// Blood Fury (Racial)
|
// Blood Fury (Racial)
|
||||||
m_preCastSpell = 23230; // Blood Fury - Healing Reduction
|
AddPrecastSpell(23230); // Blood Fury - Healing Reduction
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELLFAMILY_MAGE:
|
case SPELLFAMILY_MAGE:
|
||||||
{
|
{
|
||||||
// Ice Block
|
// Ice Block
|
||||||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
|
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000008000000000))
|
||||||
m_preCastSpell = 41425; // Hypothermia
|
AddPrecastSpell(41425); // Hypothermia
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELLFAMILY_PRIEST:
|
case SPELLFAMILY_PRIEST:
|
||||||
|
|
@ -2305,27 +2310,32 @@ void Spell::cast(bool skipCheck)
|
||||||
// Power Word: Shield
|
// Power Word: Shield
|
||||||
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
|
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
|
||||||
(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001)))
|
(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001)))
|
||||||
m_preCastSpell = 6788; // Weakened Soul
|
AddPrecastSpell(6788); // Weakened Soul
|
||||||
// Dispersion (transform)
|
// Dispersion (transform)
|
||||||
if (m_spellInfo->Id == 47585)
|
if (m_spellInfo->Id == 47585)
|
||||||
m_preCastSpell = 60069; // Dispersion (mana regen)
|
AddPrecastSpell(60069); // Dispersion (mana regen)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELLFAMILY_PALADIN:
|
case SPELLFAMILY_PALADIN:
|
||||||
{
|
{
|
||||||
// Divine Shield, Divine Protection or Hand of Protection
|
// Divine Shield, Divine Protection or Hand of Protection
|
||||||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080))
|
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000400080))
|
||||||
m_preCastSpell = 25771; // Forbearance
|
{
|
||||||
|
AddPrecastSpell(25771); // Forbearance
|
||||||
|
AddPrecastSpell(61987); // Avenging Wrath Marker
|
||||||
|
}
|
||||||
|
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x200000000000))
|
||||||
|
AddPrecastSpell(61987); // Avenging Wrath Marker
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELLFAMILY_SHAMAN:
|
case SPELLFAMILY_SHAMAN:
|
||||||
{
|
{
|
||||||
// Bloodlust
|
// Bloodlust
|
||||||
if (m_spellInfo->Id == 2825)
|
if (m_spellInfo->Id == 2825)
|
||||||
m_preCastSpell = 57724; // Sated
|
AddPrecastSpell(57724); // Sated
|
||||||
// Heroism
|
// Heroism
|
||||||
else if (m_spellInfo->Id == 32182)
|
else if (m_spellInfo->Id == 32182)
|
||||||
m_preCastSpell = 57723; // Exhaustion
|
AddPrecastSpell(57723); // Exhaustion
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -3659,8 +3669,17 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
// Caster aura req check if need
|
// Caster aura req check if need
|
||||||
if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell))
|
if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell))
|
||||||
return SPELL_FAILED_CASTER_AURASTATE;
|
return SPELL_FAILED_CASTER_AURASTATE;
|
||||||
if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell))
|
if(m_spellInfo->excludeCasterAuraSpell)
|
||||||
return SPELL_FAILED_CASTER_AURASTATE;
|
{
|
||||||
|
// Special cases of non existing auras handling
|
||||||
|
if(m_spellInfo->excludeCasterAuraSpell == 61988)
|
||||||
|
{
|
||||||
|
if(m_caster->HasAura(61987))
|
||||||
|
return SPELL_FAILED_CASTER_AURASTATE;
|
||||||
|
}
|
||||||
|
else if(m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell))
|
||||||
|
return SPELL_FAILED_CASTER_AURASTATE;
|
||||||
|
}
|
||||||
|
|
||||||
// cancel autorepeat spells if cast start when moving
|
// cancel autorepeat spells if cast start when moving
|
||||||
// (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
|
// (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
|
||||||
|
|
@ -4093,6 +4112,14 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPELL_EFFECT_APPLY_GLYPH:
|
||||||
|
{
|
||||||
|
uint32 glyphId = m_spellInfo->EffectMiscValue[i];
|
||||||
|
if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyphId))
|
||||||
|
if(m_caster->HasAura(gp->SpellId))
|
||||||
|
return SPELL_FAILED_UNIQUE_GLYPH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPELL_EFFECT_FEED_PET:
|
case SPELL_EFFECT_FEED_PET:
|
||||||
{
|
{
|
||||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
|
@ -4356,8 +4383,13 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPELL_AURA_MOD_POSSESS:
|
case SPELL_AURA_MOD_POSSESS:
|
||||||
case SPELL_AURA_MOD_CHARM:
|
|
||||||
{
|
{
|
||||||
|
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return SPELL_FAILED_UNKNOWN;
|
||||||
|
|
||||||
|
if(m_targets.getUnitTarget() == m_caster)
|
||||||
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
|
|
||||||
if(m_caster->GetPetGUID())
|
if(m_caster->GetPetGUID())
|
||||||
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
||||||
|
|
||||||
|
|
@ -4378,6 +4410,51 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPELL_AURA_MOD_CHARM:
|
||||||
|
{
|
||||||
|
if(m_targets.getUnitTarget() == m_caster)
|
||||||
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
|
|
||||||
|
if(m_caster->GetPetGUID())
|
||||||
|
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
|
||||||
|
|
||||||
|
if(m_caster->GetCharmGUID())
|
||||||
|
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||||
|
|
||||||
|
if(m_caster->GetCharmerGUID())
|
||||||
|
return SPELL_FAILED_CHARMED;
|
||||||
|
|
||||||
|
if(!m_targets.getUnitTarget())
|
||||||
|
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||||
|
|
||||||
|
if(m_targets.getUnitTarget()->GetCharmerGUID())
|
||||||
|
return SPELL_FAILED_CHARMED;
|
||||||
|
|
||||||
|
if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget()))
|
||||||
|
return SPELL_FAILED_HIGHLEVEL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPELL_AURA_MOD_POSSESS_PET:
|
||||||
|
{
|
||||||
|
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return SPELL_FAILED_UNKNOWN;
|
||||||
|
|
||||||
|
if(m_caster->GetCharmGUID())
|
||||||
|
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||||
|
|
||||||
|
if(m_caster->GetCharmerGUID())
|
||||||
|
return SPELL_FAILED_CHARMED;
|
||||||
|
|
||||||
|
Pet* pet = m_caster->GetPet();
|
||||||
|
if(!pet)
|
||||||
|
return SPELL_FAILED_NO_PET;
|
||||||
|
|
||||||
|
if(pet->GetCharmerGUID())
|
||||||
|
return SPELL_FAILED_CHARMED;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPELL_AURA_MOUNTED:
|
case SPELL_AURA_MOUNTED:
|
||||||
{
|
{
|
||||||
if (m_caster->IsInWater())
|
if (m_caster->IsInWater())
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,6 @@ class Spell
|
||||||
Item* m_CastItem;
|
Item* m_CastItem;
|
||||||
uint8 m_cast_count;
|
uint8 m_cast_count;
|
||||||
uint32 m_glyphIndex;
|
uint32 m_glyphIndex;
|
||||||
uint32 m_preCastSpell;
|
|
||||||
SpellCastTargets m_targets;
|
SpellCastTargets m_targets;
|
||||||
|
|
||||||
int32 GetCastTime() const { return m_casttime; }
|
int32 GetCastTime() const { return m_casttime; }
|
||||||
|
|
@ -440,6 +439,7 @@ class Spell
|
||||||
bool CheckTargetCreatureType(Unit* target) const;
|
bool CheckTargetCreatureType(Unit* target) const;
|
||||||
|
|
||||||
void AddTriggeredSpell(SpellEntry const* spell) { m_TriggerSpells.push_back(spell); }
|
void AddTriggeredSpell(SpellEntry const* spell) { m_TriggerSpells.push_back(spell); }
|
||||||
|
void AddPrecastSpell(uint32 spellId) { m_preCastSpells.push_back(spellId); }
|
||||||
|
|
||||||
void CleanupTargetList();
|
void CleanupTargetList();
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -559,7 +559,9 @@ class Spell
|
||||||
|
|
||||||
//List For Triggered Spells
|
//List For Triggered Spells
|
||||||
typedef std::list<SpellEntry const*> TriggerSpells;
|
typedef std::list<SpellEntry const*> TriggerSpells;
|
||||||
|
typedef std::list<uint32> SpellPrecasts;
|
||||||
TriggerSpells m_TriggerSpells;
|
TriggerSpells m_TriggerSpells;
|
||||||
|
SpellPrecasts m_preCastSpells;
|
||||||
|
|
||||||
uint32 m_spellState;
|
uint32 m_spellState;
|
||||||
uint32 m_timer;
|
uint32 m_timer;
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ enum AuraType
|
||||||
SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells
|
SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells
|
||||||
SPELL_AURA_284,
|
SPELL_AURA_284,
|
||||||
SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285,
|
SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285,
|
||||||
SPELL_AURA_286,
|
SPELL_AURA_ABILITY_PERIODIC_CRIT = 286,
|
||||||
SPELL_AURA_DEFLECT_SPELLS,
|
SPELL_AURA_DEFLECT_SPELLS,
|
||||||
SPELL_AURA_288,
|
SPELL_AURA_288,
|
||||||
SPELL_AURA_289,
|
SPELL_AURA_289,
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
||||||
&Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
|
&Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
|
||||||
&Aura::HandleUnused, //284 not used by any spells (3.08a)
|
&Aura::HandleUnused, //284 not used by any spells (3.08a)
|
||||||
&Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage
|
&Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage
|
||||||
&Aura::HandleUnused, //286 not used by any spells (3.08a)
|
&Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from Aura::PeriodicTick
|
||||||
&Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
|
&Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
|
||||||
&Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell.
|
&Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell.
|
||||||
&Aura::HandleUnused, //289 unused
|
&Aura::HandleUnused, //289 unused
|
||||||
|
|
@ -1178,23 +1178,32 @@ void Aura::SendAuraUpdate(bool remove)
|
||||||
|
|
||||||
void Aura::SetStackAmount(uint8 stackAmount)
|
void Aura::SetStackAmount(uint8 stackAmount)
|
||||||
{
|
{
|
||||||
if (stackAmount != m_stackAmount)
|
if (stackAmount == m_stackAmount)
|
||||||
|
// Nothing changed
|
||||||
|
return;
|
||||||
|
|
||||||
|
Unit *target = GetTarget();
|
||||||
|
Unit *caster = GetCaster();
|
||||||
|
if (!target || !caster)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool refresh = stackAmount > m_stackAmount;
|
||||||
|
m_stackAmount = stackAmount;
|
||||||
|
int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
|
||||||
|
// Reapply if amount change
|
||||||
|
if (amount!=m_modifier.m_amount)
|
||||||
{
|
{
|
||||||
Unit *target = GetTarget();
|
ApplyModifier(false, true);
|
||||||
Unit *caster = GetCaster();
|
m_modifier.m_amount = amount;
|
||||||
if (!target || !caster)
|
ApplyModifier(true, true);
|
||||||
return;
|
|
||||||
m_stackAmount = stackAmount;
|
|
||||||
int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target);
|
|
||||||
// Reapply if amount change
|
|
||||||
if (amount!=m_modifier.m_amount)
|
|
||||||
{
|
|
||||||
ApplyModifier(false, true);
|
|
||||||
m_modifier.m_amount = amount;
|
|
||||||
ApplyModifier(true, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RefreshAura();
|
|
||||||
|
if (refresh)
|
||||||
|
// Stack increased refresh duration
|
||||||
|
RefreshAura();
|
||||||
|
else
|
||||||
|
// Stack decreased only send update
|
||||||
|
SendAuraUpdate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Aura::modStackAmount(int32 num)
|
bool Aura::modStackAmount(int32 num)
|
||||||
|
|
@ -3065,33 +3074,33 @@ void Aura::HandleModPossess(bool apply, bool Real)
|
||||||
if(!Real)
|
if(!Real)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(m_target->getLevel() > m_modifier.m_amount)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// not possess yourself
|
// not possess yourself
|
||||||
if(GetCasterGUID() == m_target->GetGUID())
|
if(GetCasterGUID() == m_target->GetGUID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Unit* caster = GetCaster();
|
Unit* caster = GetCaster();
|
||||||
if(!caster)
|
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Player* p_caster = (Player*)caster;
|
||||||
|
|
||||||
|
|
||||||
if( apply )
|
if( apply )
|
||||||
{
|
{
|
||||||
m_target->SetCharmerGUID(GetCasterGUID());
|
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
m_target->setFaction(caster->getFaction());
|
|
||||||
|
|
||||||
caster->SetCharm(m_target);
|
m_target->SetCharmerGUID(p_caster->GetGUID());
|
||||||
|
m_target->setFaction(p_caster->getFaction());
|
||||||
|
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
p_caster->SetCharm(m_target);
|
||||||
{
|
|
||||||
((Player*)caster)->SetFarSightGUID(m_target->GetGUID());
|
p_caster->SetFarSightGUID(m_target->GetGUID());
|
||||||
((Player*)caster)->SetClientControl(m_target, 1);
|
p_caster->SetClientControl(m_target, 1);
|
||||||
((Player*)caster)->SetMover(m_target);
|
p_caster->SetMover(m_target);
|
||||||
}
|
|
||||||
|
|
||||||
m_target->CombatStop();
|
m_target->CombatStop();
|
||||||
m_target->DeleteThreatList();
|
m_target->DeleteThreatList();
|
||||||
|
|
||||||
if(m_target->GetTypeId() == TYPEID_UNIT)
|
if(m_target->GetTypeId() == TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
m_target->StopMoving();
|
m_target->StopMoving();
|
||||||
|
|
@ -3106,13 +3115,14 @@ void Aura::HandleModPossess(bool apply, bool Real)
|
||||||
if(CharmInfo *charmInfo = m_target->InitCharmInfo(m_target))
|
if(CharmInfo *charmInfo = m_target->InitCharmInfo(m_target))
|
||||||
charmInfo->InitPossessCreateSpells();
|
charmInfo->InitPossessCreateSpells();
|
||||||
|
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
p_caster->PossessSpellInitialize();
|
||||||
((Player*)caster)->PossessSpellInitialize();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
|
|
||||||
m_target->SetCharmerGUID(0);
|
m_target->SetCharmerGUID(0);
|
||||||
caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now
|
p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now
|
||||||
|
|
||||||
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
|
|
@ -3125,18 +3135,13 @@ void Aura::HandleModPossess(bool apply, bool Real)
|
||||||
m_target->setFaction(cinfo->faction_A);
|
m_target->setFaction(cinfo->faction_A);
|
||||||
}
|
}
|
||||||
|
|
||||||
caster->SetCharm(NULL);
|
p_caster->SetCharm(NULL);
|
||||||
|
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
p_caster->SetFarSightGUID(0);
|
||||||
{
|
p_caster->SetClientControl(m_target, 0);
|
||||||
((Player*)caster)->SetFarSightGUID(0);
|
p_caster->SetMover(NULL);
|
||||||
((Player*)caster)->SetClientControl(m_target, 0);
|
|
||||||
((Player*)caster)->SetMover(NULL);
|
|
||||||
|
|
||||||
WorldPacket data(SMSG_PET_SPELLS, 8);
|
p_caster->RemovePetActionBar();
|
||||||
data << uint64(0);
|
|
||||||
((Player*)caster)->GetSession()->SendPacket(&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_target->GetTypeId() == TYPEID_UNIT)
|
if(m_target->GetTypeId() == TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
|
|
@ -3161,14 +3166,16 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
|
||||||
if(!pet || pet != m_target)
|
if(!pet || pet != m_target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(apply)
|
Player* p_caster = (Player*)caster;
|
||||||
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
|
|
||||||
else
|
|
||||||
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24);
|
|
||||||
|
|
||||||
((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0);
|
if(apply)
|
||||||
((Player*)caster)->SetCharm(apply ? pet : NULL);
|
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
((Player*)caster)->SetClientControl(pet, apply ? 1 : 0);
|
else
|
||||||
|
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
|
||||||
|
|
||||||
|
p_caster->SetFarSightGUID(apply ? pet->GetGUID() : 0);
|
||||||
|
p_caster->SetCharm(apply ? pet : NULL);
|
||||||
|
p_caster->SetClientControl(pet, apply ? 1 : 0);
|
||||||
((Player*)caster)->SetMover(apply ? pet : NULL);
|
((Player*)caster)->SetMover(apply ? pet : NULL);
|
||||||
|
|
||||||
if(apply)
|
if(apply)
|
||||||
|
|
@ -3208,100 +3215,92 @@ void Aura::HandleModCharm(bool apply, bool Real)
|
||||||
if(!caster)
|
if(!caster)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(int32(m_target->getLevel()) <= m_modifier.m_amount)
|
if( apply )
|
||||||
{
|
{
|
||||||
if( apply )
|
m_target->SetCharmerGUID(GetCasterGUID());
|
||||||
|
m_target->setFaction(caster->getFaction());
|
||||||
|
m_target->CastStop(m_target == caster ? GetId() : 0);
|
||||||
|
caster->SetCharm(m_target);
|
||||||
|
|
||||||
|
m_target->CombatStop();
|
||||||
|
m_target->DeleteThreatList();
|
||||||
|
|
||||||
|
if(m_target->GetTypeId() == TYPEID_UNIT)
|
||||||
{
|
{
|
||||||
m_target->SetCharmerGUID(GetCasterGUID());
|
((Creature*)m_target)->AIM_Initialize();
|
||||||
m_target->setFaction(caster->getFaction());
|
CharmInfo *charmInfo = m_target->InitCharmInfo(m_target);
|
||||||
m_target->CastStop(m_target == caster ? GetId() : 0);
|
charmInfo->InitCharmCreateSpells();
|
||||||
caster->SetCharm(m_target);
|
charmInfo->SetReactState( REACT_DEFENSIVE );
|
||||||
|
|
||||||
m_target->CombatStop();
|
if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
|
||||||
m_target->DeleteThreatList();
|
|
||||||
|
|
||||||
if(m_target->GetTypeId() == TYPEID_UNIT)
|
|
||||||
{
|
|
||||||
((Creature*)m_target)->AIM_Initialize();
|
|
||||||
CharmInfo *charmInfo = m_target->InitCharmInfo(m_target);
|
|
||||||
charmInfo->InitCharmCreateSpells();
|
|
||||||
charmInfo->SetReactState( REACT_DEFENSIVE );
|
|
||||||
|
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
|
|
||||||
{
|
|
||||||
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
|
|
||||||
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
|
||||||
{
|
|
||||||
//does not appear to have relevance. Why code added initially? See note below at !apply
|
|
||||||
//to prevent client crash
|
|
||||||
//m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
|
|
||||||
//just to enable stat window
|
|
||||||
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
|
|
||||||
//if charmed two demons the same session, the 2nd gets the 1st one's name
|
|
||||||
m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
{
|
|
||||||
((Player*)caster)->CharmSpellInitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_target->SetCharmerGUID(0);
|
|
||||||
|
|
||||||
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
((Player*)m_target)->setFactionForRace(m_target->getRace());
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
|
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
|
||||||
|
if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||||
// restore faction
|
|
||||||
if(((Creature*)m_target)->isPet())
|
|
||||||
{
|
{
|
||||||
if(Unit* owner = m_target->GetOwner())
|
//does not appear to have relevance. Why code added initially? See note below at !apply
|
||||||
m_target->setFaction(owner->getFaction());
|
//to prevent client crash
|
||||||
else if(cinfo)
|
//m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
|
||||||
m_target->setFaction(cinfo->faction_A);
|
//just to enable stat window
|
||||||
|
charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
|
||||||
|
//if charmed two demons the same session, the 2nd gets the 1st one's name
|
||||||
|
m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
|
||||||
}
|
}
|
||||||
else if(cinfo) // normal creature
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
((Player*)caster)->CharmSpellInitialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_target->SetCharmerGUID(0);
|
||||||
|
|
||||||
|
if(m_target->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
((Player*)m_target)->setFactionForRace(m_target->getRace());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
|
||||||
|
|
||||||
|
// restore faction
|
||||||
|
if(((Creature*)m_target)->isPet())
|
||||||
|
{
|
||||||
|
if(Unit* owner = m_target->GetOwner())
|
||||||
|
m_target->setFaction(owner->getFaction());
|
||||||
|
else if(cinfo)
|
||||||
m_target->setFaction(cinfo->faction_A);
|
m_target->setFaction(cinfo->faction_A);
|
||||||
|
|
||||||
// restore UNIT_FIELD_BYTES_0
|
|
||||||
if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
|
|
||||||
{
|
|
||||||
//does not appear to have relevance. Why code added initially? Class, gender, powertype should be same.
|
|
||||||
//db field removed and replaced with better way to set class, restore using this if problems
|
|
||||||
/*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
|
|
||||||
if(cainfo && cainfo->bytes0 != 0)
|
|
||||||
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
|
|
||||||
else
|
|
||||||
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/
|
|
||||||
|
|
||||||
if(m_target->GetCharmInfo())
|
|
||||||
m_target->GetCharmInfo()->SetPetNumber(0, true);
|
|
||||||
else
|
|
||||||
sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if(cinfo) // normal creature
|
||||||
|
m_target->setFaction(cinfo->faction_A);
|
||||||
|
|
||||||
caster->SetCharm(NULL);
|
// restore UNIT_FIELD_BYTES_0
|
||||||
|
if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
|
||||||
if(caster->GetTypeId() == TYPEID_PLAYER)
|
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_PET_SPELLS, 8);
|
//does not appear to have relevance. Why code added initially? Class, gender, powertype should be same.
|
||||||
data << uint64(0);
|
//db field removed and replaced with better way to set class, restore using this if problems
|
||||||
((Player*)caster)->GetSession()->SendPacket(&data);
|
/*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
|
||||||
}
|
if(cainfo && cainfo->bytes0 != 0)
|
||||||
if(m_target->GetTypeId() == TYPEID_UNIT)
|
m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
|
||||||
{
|
else
|
||||||
((Creature*)m_target)->AIM_Initialize();
|
m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/
|
||||||
if (((Creature*)m_target)->AI())
|
|
||||||
((Creature*)m_target)->AI()->AttackedBy(caster);
|
if(m_target->GetCharmInfo())
|
||||||
|
m_target->GetCharmInfo()->SetPetNumber(0, true);
|
||||||
|
else
|
||||||
|
sLog.outError("Aura::HandleModCharm: target (GUID: %u TypeId: %u) has a charm aura but no charm info!", m_target->GetGUIDLow(), m_target->GetTypeId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caster->SetCharm(NULL);
|
||||||
|
|
||||||
|
if(caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
((Player*)caster)->RemovePetActionBar();
|
||||||
|
|
||||||
|
if(m_target->GetTypeId() == TYPEID_UNIT)
|
||||||
|
{
|
||||||
|
((Creature*)m_target)->AIM_Initialize();
|
||||||
|
if (((Creature*)m_target)->AI())
|
||||||
|
((Creature*)m_target)->AI()->AttackedBy(caster);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5887,6 +5886,9 @@ void Aura::PeriodicTick()
|
||||||
else
|
else
|
||||||
pdamage = uint32(m_target->GetMaxHealth()*amount/100);
|
pdamage = uint32(m_target->GetMaxHealth()*amount/100);
|
||||||
|
|
||||||
|
// This method can modify pdamage
|
||||||
|
bool isCrit = IsCritFromAbilityAura(pCaster, pdamage);
|
||||||
|
|
||||||
// As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
|
// As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
|
||||||
// Reduce dot damage from resilience for players
|
// Reduce dot damage from resilience for players
|
||||||
if (m_target->GetTypeId() == TYPEID_PLAYER)
|
if (m_target->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
|
@ -5899,7 +5901,7 @@ void Aura::PeriodicTick()
|
||||||
|
|
||||||
pCaster->DealDamageMods(m_target, pdamage, &absorb);
|
pCaster->DealDamageMods(m_target, pdamage, &absorb);
|
||||||
|
|
||||||
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f);
|
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f, isCrit);
|
||||||
m_target->SendPeriodicAuraLog(&pInfo);
|
m_target->SendPeriodicAuraLog(&pInfo);
|
||||||
|
|
||||||
Unit* target = m_target; // aura can be deleted in DealDamage
|
Unit* target = m_target; // aura can be deleted in DealDamage
|
||||||
|
|
@ -6021,10 +6023,13 @@ void Aura::PeriodicTick()
|
||||||
|
|
||||||
pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
|
pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount());
|
||||||
|
|
||||||
|
// This method can modify pdamage
|
||||||
|
bool isCrit = IsCritFromAbilityAura(pCaster, pdamage);
|
||||||
|
|
||||||
sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
|
sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
|
||||||
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
|
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
|
||||||
|
|
||||||
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f);
|
SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f, isCrit);
|
||||||
m_target->SendPeriodicAuraLog(&pInfo);
|
m_target->SendPeriodicAuraLog(&pInfo);
|
||||||
|
|
||||||
int32 gain = m_target->ModifyHealth(pdamage);
|
int32 gain = m_target->ModifyHealth(pdamage);
|
||||||
|
|
@ -6912,3 +6917,19 @@ void Aura::HandleAuraSafeFall( bool Apply, bool Real )
|
||||||
if(Apply && Real && GetId() == 32474 && m_target->GetTypeId() == TYPEID_PLAYER)
|
if(Apply && Real && GetId() == 32474 && m_target->GetTypeId() == TYPEID_PLAYER)
|
||||||
((Player*)m_target)->ActivateTaxiPathTo(506, GetId());
|
((Player*)m_target)->ActivateTaxiPathTo(506, GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Aura::IsCritFromAbilityAura(Unit* caster, uint32& damage)
|
||||||
|
{
|
||||||
|
Unit::AuraList const& auras = caster->GetAurasByType(SPELL_AURA_ABILITY_PERIODIC_CRIT);
|
||||||
|
for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (!(*itr)->isAffectedOnSpell(m_spellProto))
|
||||||
|
continue;
|
||||||
|
if (!caster->isSpellCrit(m_target, m_spellProto, GetSpellSchoolMask(m_spellProto)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, m_target);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,8 @@ class MANGOS_DLL_SPEC Aura
|
||||||
protected:
|
protected:
|
||||||
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
||||||
|
|
||||||
|
bool IsCritFromAbilityAura(Unit* caster, uint32& damage);
|
||||||
|
|
||||||
Modifier m_modifier;
|
Modifier m_modifier;
|
||||||
SpellModifier *m_spellmod;
|
SpellModifier *m_spellmod;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1187,21 +1187,19 @@ void Spell::EffectDummy(uint32 i)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// immediately finishes the cooldown on Frost spells
|
// immediately finishes the cooldown on Frost spells
|
||||||
const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
|
const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
|
||||||
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
|
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
|
||||||
{
|
{
|
||||||
if (itr->second->state == PLAYERSPELL_REMOVED)
|
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
|
||||||
continue;
|
|
||||||
|
|
||||||
uint32 classspell = itr->first;
|
|
||||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
|
|
||||||
|
|
||||||
if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
|
if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
|
||||||
(GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
|
(GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
|
||||||
spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
|
spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
|
||||||
{
|
{
|
||||||
((Player*)m_caster)->RemoveSpellCooldown(classspell, true);
|
((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1436,14 +1434,15 @@ void Spell::EffectDummy(uint32 i)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//immediately finishes the cooldown on certain Rogue abilities
|
//immediately finishes the cooldown on certain Rogue abilities
|
||||||
const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
|
const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
|
||||||
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
|
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
|
||||||
{
|
{
|
||||||
uint32 classspell = itr->first;
|
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
|
||||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
|
|
||||||
|
|
||||||
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
|
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & UI64LIT(0x0000024000000860)))
|
||||||
((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
|
((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1487,14 +1486,15 @@ void Spell::EffectDummy(uint32 i)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//immediately finishes the cooldown for hunter abilities
|
//immediately finishes the cooldown for hunter abilities
|
||||||
const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
|
const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
|
||||||
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
|
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
|
||||||
{
|
{
|
||||||
uint32 classspell = itr->first;
|
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
|
||||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
|
|
||||||
|
|
||||||
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
|
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
|
||||||
((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
|
((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2317,7 +2317,7 @@ void Spell::EffectUnlearnSpecialization( uint32 i )
|
||||||
|
|
||||||
_player->removeSpell(spellToUnlearn);
|
_player->removeSpell(spellToUnlearn);
|
||||||
|
|
||||||
sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
|
sLog.outDebug( "Spell: Player %u has unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::EffectPowerDrain(uint32 i)
|
void Spell::EffectPowerDrain(uint32 i)
|
||||||
|
|
@ -3320,7 +3320,7 @@ void Spell::EffectLearnSpell(uint32 i)
|
||||||
uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
|
uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
|
||||||
player->learnSpell(spellToLearn,false);
|
player->learnSpell(spellToLearn,false);
|
||||||
|
|
||||||
sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
|
sLog.outDebug( "Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::EffectDispel(uint32 i)
|
void Spell::EffectDispel(uint32 i)
|
||||||
|
|
@ -4327,24 +4327,30 @@ void Spell::EffectWeaponDmg(uint32 i)
|
||||||
spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
|
spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
|
||||||
}
|
}
|
||||||
// Devastate bonus and sunder armor refresh
|
// Devastate bonus and sunder armor refresh
|
||||||
else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
|
else if(m_spellInfo->SpellVisual[0] == 12295 && m_spellInfo->SpellIconID == 1508)
|
||||||
{
|
{
|
||||||
uint32 stack = 0;
|
uint32 stack = 0;
|
||||||
// Need refresh all Sunder Armor auras from this caster
|
// Need refresh all Sunder Armor auras from this caster
|
||||||
Unit::AuraMap& suAuras = unitTarget->GetAuras();
|
Unit::AuraMap& suAuras = unitTarget->GetAuras();
|
||||||
|
SpellEntry const *spellInfo;
|
||||||
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
|
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
|
||||||
{
|
{
|
||||||
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
|
spellInfo = (*itr).second->GetSpellProto();
|
||||||
if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
|
if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
|
||||||
(spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
|
(spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
|
||||||
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
|
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
|
||||||
{
|
{
|
||||||
(*itr).second->RefreshAura();
|
(*itr).second->RefreshAura();
|
||||||
stack = (*itr).second->GetStackAmount();
|
stack = (*itr).second->GetStackAmount();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stack)
|
if (stack)
|
||||||
spell_bonus += stack * CalculateDamage(2, unitTarget);
|
spell_bonus += stack * CalculateDamage(2, unitTarget);
|
||||||
|
if (!stack || stack < spellInfo->StackAmount)
|
||||||
|
// Devastate causing Sunder Armor Effect
|
||||||
|
// and no need to cast over max stack amount
|
||||||
|
m_caster->CastSpell(unitTarget, 58567, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Spell.h"
|
#include "Spell.h"
|
||||||
#include "ScriptCalls.h"
|
#include "ScriptCalls.h"
|
||||||
#include "Totem.h"
|
#include "Totem.h"
|
||||||
|
#include "SpellAuras.h"
|
||||||
|
|
||||||
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
|
|
@ -377,10 +378,6 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
CHECK_PACKET_SIZE(recvPacket,4);
|
CHECK_PACKET_SIZE(recvPacket,4);
|
||||||
|
|
||||||
// ignore for remote control state
|
|
||||||
if(_player->m_mover != _player)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32 spellId;
|
uint32 spellId;
|
||||||
recvPacket >> spellId;
|
recvPacket >> spellId;
|
||||||
|
|
||||||
|
|
@ -388,10 +385,34 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
|
||||||
if (!spellInfo)
|
if (!spellInfo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL
|
if (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)
|
||||||
if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(!IsPositiveSpell(spellId))
|
||||||
|
{
|
||||||
|
// ignore for remote control state
|
||||||
|
if (_player->m_mover != _player)
|
||||||
|
{
|
||||||
|
// except own aura spells
|
||||||
|
bool allow = false;
|
||||||
|
for(int k = 0; k < 3; ++k)
|
||||||
|
{
|
||||||
|
if (spellInfo->EffectApplyAuraName[k] == SPELL_AURA_MOD_POSSESS ||
|
||||||
|
spellInfo->EffectApplyAuraName[k] == SPELL_AURA_MOD_POSSESS_PET)
|
||||||
|
{
|
||||||
|
allow = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this also include case when aura not found
|
||||||
|
if(!allow)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// channeled spell case (it currently casted then)
|
// channeled spell case (it currently casted then)
|
||||||
if (IsChanneledSpell(spellInfo))
|
if (IsChanneledSpell(spellInfo))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1126,7 +1126,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
||||||
if(!spellInfo_1 || !spellInfo_2)
|
if(!spellInfo_1 || !spellInfo_2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(spellInfo_1->Id == spellId_2)
|
if(spellId_1 == spellId_2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//I think we don't check this correctly because i need a exception for spell:
|
//I think we don't check this correctly because i need a exception for spell:
|
||||||
|
|
@ -1193,6 +1193,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPELLFAMILY_MAGE:
|
||||||
|
// Arcane Intellect and Insight
|
||||||
|
if( spellInfo_2->SpellIconID == 125 && spellInfo_1->Id == 18820 )
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
case SPELLFAMILY_WARRIOR:
|
case SPELLFAMILY_WARRIOR:
|
||||||
{
|
{
|
||||||
// Scroll of Protection and Defensive Stance (multi-family check)
|
// Scroll of Protection and Defensive Stance (multi-family check)
|
||||||
|
|
@ -1274,6 +1279,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
||||||
if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 )
|
if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Arcane Intellect and Insight
|
||||||
|
if( spellInfo_1->SpellIconID == 125 && spellInfo_2->Id == 18820 )
|
||||||
|
return false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SPELLFAMILY_WARLOCK:
|
case SPELLFAMILY_WARLOCK:
|
||||||
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK )
|
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK )
|
||||||
|
|
|
||||||
|
|
@ -4278,13 +4278,13 @@ void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo)
|
||||||
data << uint32(GetSpellSchoolMask(aura->GetSpellProto()));
|
data << uint32(GetSpellSchoolMask(aura->GetSpellProto()));
|
||||||
data << uint32(pInfo->absorb); // absorb
|
data << uint32(pInfo->absorb); // absorb
|
||||||
data << uint32(pInfo->resist); // resist
|
data << uint32(pInfo->resist); // resist
|
||||||
data << uint8(0); // new 3.1.2
|
data << uint8(pInfo->critical ? 1 : 0); // new 3.1.2 critical flag
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_PERIODIC_HEAL:
|
case SPELL_AURA_PERIODIC_HEAL:
|
||||||
case SPELL_AURA_OBS_MOD_HEALTH:
|
case SPELL_AURA_OBS_MOD_HEALTH:
|
||||||
data << uint32(pInfo->damage); // damage
|
data << uint32(pInfo->damage); // damage
|
||||||
data << uint32(pInfo->overDamage); // overheal?
|
data << uint32(pInfo->overDamage); // overheal?
|
||||||
data << uint8(0); // new 3.1.2
|
data << uint8(pInfo->critical ? 1 : 0); // new 3.1.2 critical flag
|
||||||
break;
|
break;
|
||||||
case SPELL_AURA_OBS_MOD_MANA:
|
case SPELL_AURA_OBS_MOD_MANA:
|
||||||
case SPELL_AURA_PERIODIC_ENERGIZE:
|
case SPELL_AURA_PERIODIC_ENERGIZE:
|
||||||
|
|
@ -5521,6 +5521,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Judgements of the Wise
|
||||||
|
case 31876:
|
||||||
|
case 31877:
|
||||||
|
case 31878:
|
||||||
|
target = this;
|
||||||
|
basepoints0 = GetCreatePowers(POWER_MANA) * 25 / 100;
|
||||||
|
triggered_spell_id = 31930;
|
||||||
|
|
||||||
|
// Replenishment
|
||||||
|
CastSpell(this, 57669, true, NULL, triggeredByAura);
|
||||||
|
break;
|
||||||
// Holy Power (Redemption Armor set)
|
// Holy Power (Redemption Armor set)
|
||||||
case 28789:
|
case 28789:
|
||||||
{
|
{
|
||||||
|
|
@ -6767,6 +6778,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Sword and Board
|
||||||
|
case 50227:
|
||||||
|
{
|
||||||
|
// Remove cooldown on Shield Slam
|
||||||
|
if (GetTypeId() == TYPEID_PLAYER)
|
||||||
|
((Player*)this)->RemoveSpellCategoryCooldown(1209, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
// Brain Freeze
|
// Brain Freeze
|
||||||
case 57761:
|
case 57761:
|
||||||
{
|
{
|
||||||
|
|
@ -9788,7 +9807,8 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde
|
||||||
|
|
||||||
if(spellProto->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION && spellProto->spellLevel &&
|
if(spellProto->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION && spellProto->spellLevel &&
|
||||||
spellProto->Effect[effect_index] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE &&
|
spellProto->Effect[effect_index] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE &&
|
||||||
spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK)
|
spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK &&
|
||||||
|
(spellProto->Effect[effect_index] != SPELL_EFFECT_APPLY_AURA || spellProto->EffectApplyAuraName[effect_index] != SPELL_AURA_MOD_DECREASE_SPEED))
|
||||||
value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f));
|
value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f));
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ enum UnitFlags
|
||||||
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
|
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
|
||||||
UNIT_FLAG_CONFUSED = 0x00400000,
|
UNIT_FLAG_CONFUSED = 0x00400000,
|
||||||
UNIT_FLAG_FLEEING = 0x00800000,
|
UNIT_FLAG_FLEEING = 0x00800000,
|
||||||
UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet...
|
UNIT_FLAG_PLAYER_CONTROLLED= 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature
|
||||||
UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
|
UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
|
||||||
UNIT_FLAG_SKINNABLE = 0x04000000,
|
UNIT_FLAG_SKINNABLE = 0x04000000,
|
||||||
UNIT_FLAG_MOUNT = 0x08000000,
|
UNIT_FLAG_MOUNT = 0x08000000,
|
||||||
|
|
@ -686,8 +686,8 @@ struct SpellNonMeleeDamage{
|
||||||
|
|
||||||
struct SpellPeriodicAuraLogInfo
|
struct SpellPeriodicAuraLogInfo
|
||||||
{
|
{
|
||||||
SpellPeriodicAuraLogInfo(Aura *_aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier)
|
SpellPeriodicAuraLogInfo(Aura *_aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical = false)
|
||||||
: aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier) {}
|
: aura(_aura), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier), critical(_critical) {}
|
||||||
|
|
||||||
Aura *aura;
|
Aura *aura;
|
||||||
uint32 damage;
|
uint32 damage;
|
||||||
|
|
@ -695,6 +695,7 @@ struct SpellPeriodicAuraLogInfo
|
||||||
uint32 resist;
|
uint32 resist;
|
||||||
uint32 overDamage; // overkill/overheal
|
uint32 overDamage; // overkill/overheal
|
||||||
float multiplier;
|
float multiplier;
|
||||||
|
bool critical;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition);
|
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition);
|
||||||
|
|
|
||||||
|
|
@ -624,6 +624,27 @@ void World::LoadConfigSettings(bool reload)
|
||||||
m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0);
|
m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0);
|
||||||
m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0);
|
m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0);
|
||||||
|
|
||||||
|
m_configs[CONFIG_MIN_PLAYER_NAME] = sConfig.GetIntDefault ("MinPlayerName", 2);
|
||||||
|
if(m_configs[CONFIG_MIN_PLAYER_NAME] < 1 || m_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME)
|
||||||
|
{
|
||||||
|
sLog.outError("MinPlayerName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_PLAYER_NAME],MAX_PLAYER_NAME);
|
||||||
|
m_configs[CONFIG_MIN_PLAYER_NAME] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_configs[CONFIG_MIN_CHARTER_NAME] = sConfig.GetIntDefault ("MinCharterName", 2);
|
||||||
|
if(m_configs[CONFIG_MIN_CHARTER_NAME] < 1 || m_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME)
|
||||||
|
{
|
||||||
|
sLog.outError("MinCharterName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_CHARTER_NAME],MAX_CHARTER_NAME);
|
||||||
|
m_configs[CONFIG_MIN_CHARTER_NAME] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_configs[CONFIG_MIN_PET_NAME] = sConfig.GetIntDefault ("MinPetName", 2);
|
||||||
|
if(m_configs[CONFIG_MIN_PET_NAME] < 1 || m_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME)
|
||||||
|
{
|
||||||
|
sLog.outError("MinPetName (%i) must be in range 1..%u. Set to 2.",m_configs[CONFIG_MIN_PET_NAME],MAX_PET_NAME);
|
||||||
|
m_configs[CONFIG_MIN_PET_NAME] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0);
|
m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0);
|
||||||
|
|
||||||
m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10);
|
m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10);
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,9 @@ enum WorldConfigs
|
||||||
CONFIG_STRICT_PLAYER_NAMES,
|
CONFIG_STRICT_PLAYER_NAMES,
|
||||||
CONFIG_STRICT_CHARTER_NAMES,
|
CONFIG_STRICT_CHARTER_NAMES,
|
||||||
CONFIG_STRICT_PET_NAMES,
|
CONFIG_STRICT_PET_NAMES,
|
||||||
|
CONFIG_MIN_PLAYER_NAME,
|
||||||
|
CONFIG_MIN_CHARTER_NAME,
|
||||||
|
CONFIG_MIN_PET_NAME,
|
||||||
CONFIG_CHARACTERS_CREATING_DISABLED,
|
CONFIG_CHARACTERS_CREATING_DISABLED,
|
||||||
CONFIG_CHARACTERS_PER_ACCOUNT,
|
CONFIG_CHARACTERS_PER_ACCOUNT,
|
||||||
CONFIG_CHARACTERS_PER_REALM,
|
CONFIG_CHARACTERS_PER_REALM,
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,18 @@ LogColors = ""
|
||||||
# (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts).
|
# (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts).
|
||||||
# 3 basic latin characters + server timezone specific
|
# 3 basic latin characters + server timezone specific
|
||||||
#
|
#
|
||||||
|
# MinPlayerName
|
||||||
|
# Minimal name length (1..12)
|
||||||
|
# Default: 2
|
||||||
|
#
|
||||||
|
# MinCharterName
|
||||||
|
# Minimal name length (1..24)
|
||||||
|
# Default: 2
|
||||||
|
#
|
||||||
|
# MinPetName
|
||||||
|
# Minimal name length (1..12)
|
||||||
|
# Default: 2
|
||||||
|
#
|
||||||
# CharactersCreatingDisabled
|
# CharactersCreatingDisabled
|
||||||
# Disable characters creating for specific team or any (non-player accounts not affected)
|
# Disable characters creating for specific team or any (non-player accounts not affected)
|
||||||
# Default: 0 - enabled
|
# Default: 0 - enabled
|
||||||
|
|
@ -579,6 +591,9 @@ DeclinedNames = 0
|
||||||
StrictPlayerNames = 0
|
StrictPlayerNames = 0
|
||||||
StrictCharterNames = 0
|
StrictCharterNames = 0
|
||||||
StrictPetNames = 0
|
StrictPetNames = 0
|
||||||
|
MinPlayerName = 2
|
||||||
|
MinCharterName = 2
|
||||||
|
MinPetName = 2
|
||||||
CharactersCreatingDisabled = 0
|
CharactersCreatingDisabled = 0
|
||||||
CharactersPerAccount = 50
|
CharactersPerAccount = 50
|
||||||
CharactersPerRealm = 10
|
CharactersPerRealm = 10
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8118"
|
#define REVISION_NR "8147"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue