Merge commit 'origin/master' into 308

Conflicts:

	src/game/ObjectMgr.cpp
	src/shared/revision_nr.h
This commit is contained in:
VladimirMangos 2009-01-25 06:56:05 +03:00
commit 7a8a1a71bf
67 changed files with 1401 additions and 937 deletions

View file

@ -3,6 +3,7 @@
#include <stdio.h>
#include <deque>
#include <set>
#include <cstdlib>
#ifdef WIN32
#include "direct.h"

View file

@ -22,7 +22,7 @@
DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`required_7133_02_mangos_spell_loot_template` bit(1) default NULL
`required_7156_01_mangos_spell_proc_event` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -819,7 +819,7 @@ CREATE TABLE `creature_template` (
LOCK TABLES `creature_template` WRITE;
/*!40000 ALTER TABLE `creature_template` DISABLE KEYS */;
INSERT INTO `creature_template` VALUES
(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,8,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,0,1,0,0,0x82,'');
(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,0,1,0,0,0x82,'');
/*!40000 ALTER TABLE `creature_template` ENABLE KEYS */;
UNLOCK TABLES;
@ -1445,6 +1445,7 @@ CREATE TABLE `instance_template` (
`levelMin` tinyint(3) unsigned NOT NULL default '0',
`levelMax` tinyint(3) unsigned NOT NULL default '0',
`maxPlayers` tinyint(3) unsigned NOT NULL default '0',
`maxPlayersHeroic` tinyint(3) unsigned NOT NULL default '0',
`reset_delay` int(10) unsigned NOT NULL default '0',
`startLocX` float default NULL,
`startLocY` float default NULL,
@ -1461,32 +1462,35 @@ CREATE TABLE `instance_template` (
LOCK TABLES `instance_template` WRITE;
/*!40000 ALTER TABLE `instance_template` DISABLE KEYS */;
INSERT INTO `instance_template` VALUES
(33,0,22,30,10,7200,NULL,NULL,NULL,NULL,''),
(34,0,24,32,10,7200,NULL,NULL,NULL,NULL,''),
(36,0,15,20,10,7200,NULL,NULL,NULL,NULL,''),
(43,0,15,21,10,7200,NULL,NULL,NULL,NULL,''),
(47,0,29,38,10,7200,NULL,NULL,NULL,NULL,''),
(48,0,24,32,10,7200,NULL,NULL,NULL,NULL,''),
(70,0,35,47,10,7200,NULL,NULL,NULL,NULL,''),
(90,0,29,38,10,7200,NULL,NULL,NULL,NULL,''),
(109,0,45,55,10,7200,NULL,NULL,NULL,NULL,''),
(129,0,37,46,10,7200,NULL,NULL,NULL,NULL,''),
(189,0,34,45,10,7200,NULL,NULL,NULL,NULL,''),
(209,0,44,54,10,7200,NULL,NULL,NULL,NULL,''),
(229,0,58,0,10,120000,78.5083,-225.044,49.839,5.1,''),
(230,0,52,0,5,7200,NULL,NULL,NULL,NULL,''),
(249,0,60,0,40,432000,NULL,NULL,NULL,NULL,''),
(289,0,57,0,5,7200,NULL,NULL,NULL,NULL,''),
(309,0,60,0,20,259200,NULL,NULL,NULL,NULL,''),
(329,0,58,60,5,7200,NULL,NULL,NULL,NULL,''),
(349,0,46,55,10,7200,NULL,NULL,NULL,NULL,''),
(389,0,13,18,10,7200,NULL,NULL,NULL,NULL,''),
(409,0,60,0,40,604800,NULL,NULL,NULL,NULL,''),
(429,0,55,60,5,7200,NULL,NULL,NULL,NULL,''),
(469,0,60,0,40,604800,NULL,NULL,NULL,NULL,''),
(509,0,60,0,20,259200,NULL,NULL,NULL,NULL,''),
(531,0,60,0,40,604800,NULL,NULL,NULL,NULL,''),
(533,0,60,0,40,604800,NULL,NULL,NULL,NULL,'');
(33,0,22,30,10,10,7200,NULL,NULL,NULL,NULL,''),
(34,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''),
(36,0,15,20,10,10,7200,NULL,NULL,NULL,NULL,''),
(43,0,15,21,10,10,7200,NULL,NULL,NULL,NULL,''),
(47,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''),
(48,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''),
(70,0,35,47,10,10,7200,NULL,NULL,NULL,NULL,''),
(90,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''),
(109,0,45,55,10,10,7200,NULL,NULL,NULL,NULL,''),
(129,0,37,46,10,10,7200,NULL,NULL,NULL,NULL,''),
(189,0,34,45,10,10,7200,NULL,NULL,NULL,NULL,''),
(209,0,44,54,10,10,7200,NULL,NULL,NULL,NULL,''),
(229,0,58,0,10,10,120000,78.5083,-225.044,49.839,5.1,''),
(230,0,52,0,5,5,7200,NULL,NULL,NULL,NULL,''),
(249,0,60,0,40,40,432000,NULL,NULL,NULL,NULL,''),
(289,0,57,0,5,5,7200,NULL,NULL,NULL,NULL,''),
(309,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''),
(329,0,58,60,5,5,7200,NULL,NULL,NULL,NULL,''),
(349,0,46,55,10,10,7200,NULL,NULL,NULL,NULL,''),
(389,0,13,18,10,10,7200,NULL,NULL,NULL,NULL,''),
(409,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(429,0,55,60,5,5,7200,NULL,NULL,NULL,NULL,''),
(469,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(509,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''),
(531,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''),
(533,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(615,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(616,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(624,0,80,0,10,25,0,NULL,NULL,NULL,NULL,'');
/*!40000 ALTER TABLE `instance_template` ENABLE KEYS */;
UNLOCK TABLES;
@ -11765,6 +11769,7 @@ INSERT INTO `playercreateinfo_spell` VALUES
(7,9,22027,'Remove Insignia'),
(7,9,22810,'Opening - No Text'),
(7,9,45927,'Summon Friend'),
(7,9,58284,'Chaos Bolt Passive'),
(7,9,61437,'Opening'),
(8,1,78,'Heroic Strike'),
(8,1,81,'Dodge'),
@ -12379,6 +12384,7 @@ INSERT INTO `playercreateinfo_spell` VALUES
(10,9,28730,'Arcane Torrent'),
(10,9,28734,'Mana Tap'),
(10,9,28877,'Arcane Affinity'),
(10,9,58284,'Chaos Bolt Passive'),
(11,1,78,'Heroic Strike'),
(11,1,81,'Dodge'),
(11,1,107,'Block'),
@ -16856,6 +16862,7 @@ INSERT INTO `spell_proc_event` VALUES
(44394, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0),
(44395, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0),
(44396, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0),
(44401, 0x00000000, 3, 0x00200000, 0x00000000, 0x00000000, 0x00000000, 0x00000FFF, 0.000000, 0.000000, 0),
(44404, 0x00000000, 3, 0x20000021, 0x00009000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(44445, 0x00000000, 3, 0x00000013, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(44446, 0x00000000, 3, 0x00000013, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
@ -17042,8 +17049,8 @@ INSERT INTO `spell_proc_event` VALUES
(53221, 0x00000000, 9, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53222, 0x00000000, 9, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53224, 0x00000000, 9, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53228, 0x00000000, 9, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53232, 0x00000000, 9, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53228, 0x00000000, 9, 0x00000020, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53232, 0x00000000, 9, 0x00000020, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53256, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53259, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53260, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
@ -17059,6 +17066,9 @@ INSERT INTO `spell_proc_event` VALUES
(53384, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53486, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53488, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53501, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53502, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53503, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53551, 0x00000000, 10, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53552, 0x00000000, 10, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53553, 0x00000000, 10, 0x00001000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),

View file

@ -20,7 +20,7 @@ CREATE TABLE `spell_proc_event` (
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records
-- Records
-- ----------------------------
INSERT INTO `spell_proc_event` VALUES
(324, 0x00000000, 0, 0x0000000000000000, 0x00000000, 0x00000000, 0, 0, 3),
@ -703,4 +703,4 @@ INSERT INTO `spell_proc_event` VALUES
(60572, 0x00000000, 11, 0x0000000090100000, 0x00000000, 0x00000000, 0, 0, 0),
(60617, 0x00000000, 0, 0x0000000000000000, 0x00000000, 0x00000020, 0, 0, 0),
(60826, 0x00000000, 15, 0x0000000001400000, 0x00000000, 0x00000000, 0, 0, 0),
(61324, 0x00000000, 10, 0x0002000000000000, 0x00000000, 0x00000000, 0, 0, 0);
(61324, 0x00000000, 10, 0x0002000000000000, 0x00000000, 0x00000000, 0, 0, 0);

View file

@ -14,4 +14,4 @@ INSERT INTO `spell_proc_event` VALUES (48111, 0x00, 0, 0x00000000, 0x00000000, 0
-- (48113) Prayer of Mending (Rank 3)
DELETE FROM `spell_proc_event` WHERE `entry` IN (48113);
INSERT INTO `spell_proc_event` VALUES (48113, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x000A02A8, 0x00000000, 0.000000, 0.000000, 0);
INSERT INTO `spell_proc_event` VALUES (48113, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x000A02A8, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -10,4 +10,4 @@ DELETE FROM character_spell WHERE `spell` IN (
/*old Shadow Resistance, leaned as racial passive of race 5 */
DELETE FROM character_spell USING character_spell INNER JOIN characters ON character_spell.guid = characters.guid
WHERE character_spell.spell = 20579 AND characters.race <> 5;
WHERE character_spell.spell = 20579 AND characters.race <> 5;

View file

@ -20,4 +20,4 @@ INSERT INTO `spell_proc_event` VALUES (44395, 0x00, 0, 0x00000000, 0x00000000, 0
DELETE FROM `spell_proc_event` WHERE `entry` IN (44396);
INSERT INTO `spell_proc_event` VALUES (44396, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,12 @@
ALTER TABLE db_version CHANGE COLUMN required_7133_02_mangos_spell_loot_template required_7141_01_mangos_instance_template bit;
ALTER TABLE instance_template ADD maxPlayersHeroic tinyint(3) unsigned NOT NULL default '0' AFTER maxPlayers;
UPDATE instance_template SET maxPlayersHeroic = maxPlayers;
DELETE FROM instance_template WHERE map IN (533,615,616,624);
INSERT INTO instance_template VALUES
(533,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(615,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(616,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''),
(624,0,80,0,10,25,0,NULL,NULL,NULL,NULL,'');

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_7141_01_mangos_instance_template required_7147_01_mangos_creature_template bit;
UPDATE creature_template
SET family = 0 WHERE entry = 1;

View file

@ -0,0 +1,21 @@
ALTER TABLE db_version CHANGE COLUMN required_7147_01_mangos_creature_template required_7149_01_mangos_spell_proc_event bit;
-- (53501) Sheath of Light (Rank 1)
DELETE FROM `spell_proc_event` WHERE `entry` IN (53501);
INSERT INTO `spell_proc_event` VALUES (53501, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
-- (53502) Sheath of Light (Rank 2)
DELETE FROM `spell_proc_event` WHERE `entry` IN (53502);
INSERT INTO `spell_proc_event` VALUES (53502, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
-- (53503) Sheath of Light (Rank 3)
DELETE FROM `spell_proc_event` WHERE `entry` IN (53503);
INSERT INTO `spell_proc_event` VALUES (53503, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
-- (53228) Rapid Recuperation (Rank 1)
DELETE FROM `spell_proc_event` WHERE `entry` IN (53228);
INSERT INTO `spell_proc_event` VALUES (53228, 0x00, 9, 0x00000020, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
-- (53232) Rapid Recuperation (Rank 2)
DELETE FROM `spell_proc_event` WHERE `entry` IN (53232);
INSERT INTO `spell_proc_event` VALUES (53232, 0x00, 9, 0x00000020, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,10 @@
ALTER TABLE db_version CHANGE COLUMN required_7149_01_mangos_spell_proc_event required_7150_01_mangos_playercreateinfo_spell bit;
DELETE FROM `playercreateinfo_spell` WHERE Spell = 58284;
INSERT INTO `playercreateinfo_spell` VALUES
(1,9,58284,'Chaos Bolt Passive'),
(2,9,58284,'Chaos Bolt Passive'),
(5,9,58284,'Chaos Bolt Passive'),
(7,9,58284,'Chaos Bolt Passive'),
(10,9,58284,'Chaos Bolt Passive');

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_7150_01_mangos_playercreateinfo_spell required_7156_01_mangos_spell_proc_event bit;
-- (44401) Missile Barrage ()
DELETE FROM `spell_proc_event` WHERE `entry` IN (44401);
INSERT INTO `spell_proc_event` VALUES (44401, 0x00, 3, 0x00200000, 0x00000000, 0x00000000, 0x00000000, 0x00000FFF, 0.000000, 0.000000, 0);

View file

@ -145,6 +145,11 @@ pkgdata_DATA = \
7118_01_mangos_skill_discovery_template.sql \
7133_01_mangos_skill_discovery_template.sql \
7133_02_mangos_spell_loot_template.sql \
7141_01_mangos_instance_template.sql \
7147_01_mangos_creature_template.sql \
7149_01_mangos_spell_proc_event.sql \
7150_01_mangos_playercreateinfo_spell.sql \
7156_01_mangos_spell_proc_event.sql \
README
## Additional files to include when running 'make dist'
@ -270,4 +275,9 @@ EXTRA_DIST = \
7118_01_mangos_skill_discovery_template.sql \
7133_01_mangos_skill_discovery_template.sql \
7133_02_mangos_spell_loot_template.sql \
7141_01_mangos_instance_template.sql \
7147_01_mangos_creature_template.sql \
7149_01_mangos_spell_proc_event.sql \
7150_01_mangos_playercreateinfo_spell.sql \
7156_01_mangos_spell_proc_event.sql \
README

View file

@ -30,10 +30,10 @@ See an example below:
| Counter show number of sql update in updates list for provided revision
| and set proper order for sql updates for same revision
|
MaNGOS commit revison related to sql update.
MaNGOS commit revison related to sql update.
It included in commit description in form [6936] as you can see at http://github.com/mangos/mangos/commits/master
After appling this update DB compatiable with database that include this sql update.
SQL update include special protection against multiply and wrong order SQL updates apply.
So attempt apply sql update to more old DB without previous SQL update in list for targeted database
So attempt apply sql update to more old DB without previous SQL update in list for targeted database
or to DB with already applied this or later SQL update will generate error and not applied.

View file

@ -325,6 +325,10 @@ void AchievementMgr::CheckAllAchievementCriteria()
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time)
{
sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER)
return;
AchievementCriteriaEntryList const& achievementCriteriaList = achievementmgr.GetAchievementCriteriaByType(type);
for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
{
@ -907,14 +911,30 @@ AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteria
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
if(sAchievementCriteriaStore.GetNumRows()==0)
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outErrorDb(">> Loaded 0 achievement criteria.");
return;
}
barGoLink bar( sAchievementCriteriaStore.GetNumRows() );
for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
{
bar.step();
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
if(!criteria)
continue;
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
}
sLog.outString();
sLog.outErrorDb(">> Loaded %u achievement criteria.",m_AchievementCriteriasByType->size());
}
@ -923,15 +943,27 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
if(!result)
return;
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 realm completed achievements . DB table `character_achievement` is empty.");
return;
}
barGoLink bar(result->GetRowCount());
do
{
bar.step();
Field *fields = result->Fetch();
m_allCompletedAchievements.insert(fields[0].GetUInt32());
} while(result->NextRow());
delete result;
sLog.outString("");
sLog.outString(">> Loaded %u realm completed achievements.",m_allCompletedAchievements.size());
}
void AchievementGlobalMgr::LoadRewards()
@ -948,7 +980,7 @@ void AchievementGlobalMgr::LoadRewards()
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
sLog.outErrorDb(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
return;
}
@ -956,9 +988,9 @@ void AchievementGlobalMgr::LoadRewards()
do
{
Field *fields = result->Fetch();
bar.step();
Field *fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
if (!sAchievementStore.LookupEntry(entry))
{

View file

@ -409,9 +409,9 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node)
{
WorldSafeLocsEntry const *ClosestGrave = NULL;
Player *plr;
for (std::vector<uint64>::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr)
{
plr = objmgr.GetPlayer(*ghost_list.begin());
plr = objmgr.GetPlayer(*itr);
if( !plr )
continue;
if( !ClosestGrave )

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2005-2009 MaNGOS <http://www.mangosproject.org/>
*
* This program is free software; you can redistribute it and/or modify

View file

@ -80,7 +80,7 @@ bool LoginQueryHolder::Initialize()
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
// in other case still be dummy query
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid));

View file

@ -1073,7 +1073,7 @@ Creature* ChatHandler::getSelectedCreature()
if(!m_session)
return NULL;
return ObjectAccessor::GetCreatureOrPet(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection());
return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection());
}
char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1)

View file

@ -169,7 +169,7 @@ struct CreatureInfo
uint32 rangeattacktime;
uint32 unit_flags; // enum UnitFlags mask values
uint32 dynamicflags;
uint32 family; // enum CreatureFamily values for type==CREATURE_TYPE_BEAST, or 0 in another cases
uint32 family; // enum CreatureFamily values (optional)
uint32 trainer_type;
uint32 trainer_spell;
uint32 classNum;

View file

@ -111,49 +111,51 @@ void GameEvent::LoadFromDB()
if( !result )
{
mGameEvent.clear();
sLog.outString(">> Table game_event is empty:");
sLog.outString(">> Table game_event is empty!");
sLog.outString();
return;
}
uint32 count = 0;
barGoLink bar( result->GetRowCount() );
do
{
++count;
Field *fields = result->Fetch();
bar.step();
uint16 event_id = fields[0].GetUInt16();
if(event_id==0)
barGoLink bar( result->GetRowCount() );
do
{
sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
continue;
}
++count;
Field *fields = result->Fetch();
GameEventData& pGameEvent = mGameEvent[event_id];
uint64 starttime = fields[1].GetUInt64();
pGameEvent.start = time_t(starttime);
uint64 endtime = fields[2].GetUInt64();
pGameEvent.end = time_t(endtime);
pGameEvent.occurence = fields[3].GetUInt32();
pGameEvent.length = fields[4].GetUInt32();
bar.step();
if(pGameEvent.length==0) // length>0 is validity check
{
sLog.outErrorDb("`game_event` game event id (%i) have length 0 and can't be used.",event_id);
continue;
}
uint16 event_id = fields[0].GetUInt16();
if(event_id==0)
{
sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id);
continue;
}
pGameEvent.description = fields[5].GetCppString();
GameEventData& pGameEvent = mGameEvent[event_id];
uint64 starttime = fields[1].GetUInt64();
pGameEvent.start = time_t(starttime);
uint64 endtime = fields[2].GetUInt64();
pGameEvent.end = time_t(endtime);
pGameEvent.occurence = fields[3].GetUInt32();
pGameEvent.length = fields[4].GetUInt32();
} while( result->NextRow() );
if(pGameEvent.length==0) // length>0 is validity check
{
sLog.outErrorDb("`game_event` game event id (%i) have length 0 and can't be used.",event_id);
continue;
}
sLog.outString();
sLog.outString( ">> Loaded %u game events", count );
delete result;
pGameEvent.description = fields[5].GetCppString();
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u game events", count );
}
mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
// 1 2
@ -163,8 +165,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
barGoLink bar2(1);
bar2.step();
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString(">> Loaded %u creatures in game events", count );
@ -172,12 +174,12 @@ void GameEvent::LoadFromDB()
else
{
barGoLink bar2( result->GetRowCount() );
barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar2.step();
bar.step();
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
@ -195,9 +197,10 @@ void GameEvent::LoadFromDB()
crelist.push_back(guid);
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u creatures in game events", count );
delete result;
}
mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1);
@ -208,8 +211,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
barGoLink bar3(1);
bar3.step();
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString(">> Loaded %u gameobjects in game events", count );
@ -217,12 +220,12 @@ void GameEvent::LoadFromDB()
else
{
barGoLink bar3( result->GetRowCount() );
barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar3.step();
bar.step();
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
@ -240,10 +243,10 @@ void GameEvent::LoadFromDB()
golist.push_back(guid);
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u gameobjects in game events", count );
delete result;
}
mGameEventModelEquip.resize(mGameEvent.size());
@ -256,8 +259,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
barGoLink bar3(1);
bar3.step();
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString(">> Loaded %u model/equipment changes in game events", count );
@ -265,12 +268,12 @@ void GameEvent::LoadFromDB()
else
{
barGoLink bar3( result->GetRowCount() );
barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar3.step();
bar.step();
uint32 guid = fields[0].GetUInt32();
uint16 event_id = fields[1].GetUInt16();
@ -300,10 +303,10 @@ void GameEvent::LoadFromDB()
equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet));
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u model/equipment changes in game events", count );
delete result;
}
mGameEventQuests.resize(mGameEvent.size());
@ -313,8 +316,8 @@ void GameEvent::LoadFromDB()
count = 0;
if( !result )
{
barGoLink bar3(1);
bar3.step();
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString(">> Loaded %u quests additions in game events", count );
@ -322,12 +325,12 @@ void GameEvent::LoadFromDB()
else
{
barGoLink bar3( result->GetRowCount() );
barGoLink bar( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar3.step();
bar.step();
uint32 id = fields[0].GetUInt32();
uint32 quest = fields[1].GetUInt32();
uint16 event_id = fields[2].GetUInt16();
@ -343,10 +346,10 @@ void GameEvent::LoadFromDB()
questlist.push_back(QuestRelation(id, quest));
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u quests additions in game events", count );
delete result;
}
}

View file

@ -354,7 +354,7 @@ void GameObject::Update(uint32 /*p_time*/)
{
Unit *caster = owner ? owner : ok;
caster->CastSpell(ok, goInfo->trap.spellId, true);
caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
m_cooldownTime = time(NULL) + 4; // 4 seconds
if(NeedDespawn)
@ -404,7 +404,7 @@ void GameObject::Update(uint32 /*p_time*/)
for (; it != end; it++)
{
Unit* owner = Unit::GetUnit(*this, uint64(*it));
if (owner) owner->CastSpell(owner, spellId, false);
if (owner) owner->CastSpell(owner, spellId, false, 0, 0, GetGUID());
}
m_unique_users.clear();
@ -809,7 +809,7 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target)
// found correct GO
// FIXME: when GO casting will be implemented trap must cast spell to target
if(trapGO)
target->CastSpell(target,trapSpell,true);
target->CastSpell(target,trapSpell,true, 0, 0, GetGUID());
}
GameObject* GameObject::LookupFishingHoleAround(float range)

View file

@ -349,7 +349,7 @@ struct GameObjectInfo
uint32 state2Name; //3
} destructibleBuilding;
//34 GAMEOBJECT_TYPE_TRAPDOOR
struct
struct
{
uint32 whenToPause; // 0
uint32 startOpen; // 1

View file

@ -1586,7 +1586,7 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
@ -1616,7 +1616,7 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
{
data << uint8((*itr)->LogEntry);
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||

View file

@ -356,8 +356,8 @@ void InstanceSaveManager::PackInstances()
bar.step();
}
sLog.outString();
sLog.outString( ">> Instance numbers remapped, next instance id is %u", InstanceNumber );
sLog.outString();
}
void InstanceSaveManager::LoadResetTimes()
@ -449,7 +449,7 @@ void InstanceSaveManager::LoadResetTimes()
// add the global reset times to the priority queue
for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++)
{
InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i);
InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i);
if(!temp) continue;
// only raid/heroic maps have a global reset time
const MapEntry* entry = sMapStore.LookupEntry(temp->map);
@ -578,7 +578,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
{
// global reset for all instances of the given map
// note: this isn't fast but it's meant to be executed very rarely
Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid);
Map const *map = MapManager::Instance().GetBaseMap(mapid);
if(!map->Instanceable())
return;
uint64 now = (uint64)time(NULL);
@ -586,7 +586,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
if(!warn)
{
// this is called one minute before the reset time
InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid);
InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
if(!temp || !temp->reset_delay)
{
sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid);

View file

@ -3848,7 +3848,7 @@ bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
continue;
m_session->GetPlayer()->learnSpell(skillLine->spellId);
m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
}
}
}
@ -3919,7 +3919,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
continue;
if( !target->HasSpell(spellInfo->Id) )
m_session->GetPlayer()->learnSpell(skillLine->spellId);
m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
}
uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);

View file

@ -1638,7 +1638,7 @@ bool ChatHandler::HandleLearnAllCommand(const char* /*args*/)
continue;
}
m_session->GetPlayer()->learnSpell(spell);
m_session->GetPlayer()->learnSpell(spell,false);
}
SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS);
@ -1678,7 +1678,7 @@ bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/)
continue;
}
m_session->GetPlayer()->learnSpell(spell);
m_session->GetPlayer()->learnSpell(spell,false);
}
SendSysMessage(LANG_LEARNING_GM_SKILLS);
@ -1726,7 +1726,7 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
continue;
m_session->GetPlayer()->learnSpell(i);
m_session->GetPlayer()->learnSpell(i,false);
}
SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS);
@ -1738,7 +1738,7 @@ static void learnAllHighRanks(Player* player, uint32 spellid)
SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext();
for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spellid); itr != nextMap.upper_bound(spellid); ++itr)
{
player->learnSpell(itr->second);
player->learnSpell(itr->second,false);
learnAllHighRanks(player,itr->second);
}
}
@ -1781,7 +1781,7 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/)
continue;
// learn highest rank of talent
player->learnSpell(spellid);
player->learnSpell(spellid,false);
// and learn all non-talent spell ranks (recursive by tree)
learnAllHighRanks(player,spellid);
@ -1795,7 +1795,7 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/)
{
// skipping UNIVERSAL language (0)
for(int i = 1; i < LANGUAGES_COUNT; ++i)
m_session->GetPlayer()->learnSpell(lang_description[i].spell_id);
m_session->GetPlayer()->learnSpell(lang_description[i].spell_id,false);
SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG);
return true;
@ -1869,7 +1869,7 @@ bool ChatHandler::HandleLearnCommand(const char* args)
return false;
}
targetPlayer->learnSpell(spell);
targetPlayer->learnSpell(spell,false);
return true;
}

View file

@ -128,7 +128,7 @@ class LootStore
{
public:
explicit LootStore(char const* name, char const* entryName, bool ratesAllowed)
: m_name(name), m_entryName(entryName), m_ratesAllowed(m_ratesAllowed) {}
: m_name(name), m_entryName(entryName), m_ratesAllowed(ratesAllowed) {}
virtual ~LootStore() { Clear(); }
void Verify() const;

View file

@ -1528,10 +1528,10 @@ bool InstanceMap::CanEnter(Player *player)
}
// cannot enter if the instance is full (player cap), GMs don't count
InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers)
uint32 maxPlayers = GetMaxPlayers();
if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers)
{
sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName());
sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;
}
@ -1824,6 +1824,14 @@ void InstanceMap::SetResetSchedule(bool on)
}
}
uint32 InstanceMap::GetMaxPlayers() const
{
InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId());
if(!iTemplate)
return 0;
return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers;
}
/* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId)

View file

@ -98,7 +98,8 @@ struct InstanceTemplate
uint32 levelMin;
uint32 levelMax;
uint32 maxPlayers;
uint32 reset_delay;
uint32 maxPlayersHeroic;
uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
float startLocX;
float startLocY;
float startLocZ;
@ -364,6 +365,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
bool CanEnter(Player* player);
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
uint32 GetMaxPlayers() const;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;

View file

@ -254,7 +254,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
data << uint64(_player->GetGUID()) << uint32(0x016A);
SendPacket(&data);
_player->learnSpell(spellId);
_player->learnSpell(spellId,false);
}
WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);

View file

@ -58,8 +58,9 @@ uint32 GuidHigh2TypeId(uint32 guid_hi)
case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT;
case HIGHGUID_CORPSE: return TYPEID_CORPSE;
case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
case HIGHGUID_VEHICLE: return TYPEID_UNIT;
}
return 10; // unknown
return MAX_TYPEID; // unknown
}
Object::Object( )
@ -258,7 +259,7 @@ void Object::DestroyForPlayer(Player *target) const
void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) const
{
uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0);
if(GetTypeId() == TYPEID_UNIT)
if(((Creature*)this)->isVehicle())
unk_flags |= 0x20; // always allow pitch

View file

@ -64,6 +64,7 @@ enum TypeID
TYPEID_AIGROUP = 8,
TYPEID_AREATRIGGER = 9
};
#define MAX_TYPEID 10
uint32 GuidHigh2TypeId(uint32 guid_hi);

View file

@ -128,7 +128,7 @@ ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint3
}
Creature*
ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid)
ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid)
{
if(Creature *unit = GetPet(guid))
return unit;
@ -164,18 +164,23 @@ ObjectAccessor::GetUnit(WorldObject const &u, uint64 guid)
if(IS_PLAYER_GUID(guid))
return FindPlayer(guid);
return GetCreatureOrPet(u, guid);
return GetCreatureOrPetOrVehicle(u, guid);
}
Corpse*
ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid)
{
Corpse * ret = GetObjectInWorld(guid, (Corpse*)NULL);
if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
if(!ret)
return NULL;
if(ret->GetMapId() != u.GetMapId())
ret = NULL;
if(ret->GetInstanceId() != u.GetInstanceId())
return NULL;
return ret;
}
Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 typemask)
Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, uint32 typemask)
{
Object *obj = NULL;
@ -187,7 +192,7 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32
if(typemask & TYPEMASK_UNIT)
{
obj = GetCreatureOrPet(p,guid);
obj = GetCreatureOrPetOrVehicle(p,guid);
if(obj) return obj;
}
@ -203,9 +208,9 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32
if(obj) return obj;
}
if(typemask & TYPEMASK_ITEM)
if(typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
{
obj = p.GetItemByGuid( guid );
obj = ((Player const &)p).GetItemByGuid( guid );
if(obj) return obj;
}
@ -216,15 +221,25 @@ GameObject*
ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid)
{
GameObject * ret = GetObjectInWorld(guid, (GameObject*)NULL);
if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
if(!ret)
return NULL;
if(ret->GetMapId() != u.GetMapId())
ret = NULL;
if(ret->GetInstanceId() != u.GetInstanceId())
return NULL;
return ret;
}
DynamicObject*
ObjectAccessor::GetDynamicObject(Unit const &u, uint64 guid)
ObjectAccessor::GetDynamicObject(WorldObject const &u, uint64 guid)
{
DynamicObject * ret = GetObjectInWorld(guid, (DynamicObject*)NULL);
if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL;
if(!ret)
return NULL;
if(ret->GetMapId() != u.GetMapId())
ret = NULL;
if(ret->GetInstanceId() != u.GetInstanceId())
return NULL;
return ret;
}

View file

@ -136,15 +136,15 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
else return NULL;
}
static Object* GetObjectByTypeMask(Player const &, uint64, uint32 typemask);
static Object* GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask);
static Creature* GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask);
static Creature* GetCreature(WorldObject const &, uint64);
static Creature* GetCreatureOrPet(WorldObject const &, uint64);
static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, uint64);
static Unit* GetUnit(WorldObject const &, uint64);
static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); }
static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); }
static GameObject* GetGameObject(WorldObject const &, uint64);
static DynamicObject* GetDynamicObject(Unit const &, uint64);
static DynamicObject* GetDynamicObject(WorldObject const &, uint64);
static Corpse* GetCorpse(WorldObject const &u, uint64 guid);
static Pet* GetPet(uint64 guid);
static Vehicle* GetVehicle(uint64 guid);

View file

@ -766,6 +766,19 @@ void ObjectMgr::LoadCreatureTemplates()
if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type);
if(cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type))
{
sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type);
const_cast<CreatureInfo*>(cInfo)->type = CREATURE_TYPE_HUMANOID;
}
// must exist or used hidden but used in data horse case
if(cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM )
{
sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family);
const_cast<CreatureInfo*>(cInfo)->family = 0;
}
if(cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE)
{
sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType);
@ -1447,18 +1460,36 @@ void ObjectMgr::LoadAuctions()
{
QueryResult *result = CharacterDatabase.Query("SELECT COUNT(*) FROM auctionhouse");
if( !result )
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
}
Field *fields = result->Fetch();
uint32 AuctionCount=fields[0].GetUInt32();
delete result;
if(!AuctionCount)
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
}
result = CharacterDatabase.Query( "SELECT id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location FROM auctionhouse" );
if( !result )
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty.");
return;
}
barGoLink bar( AuctionCount );
@ -1499,7 +1530,6 @@ void ObjectMgr::LoadAuctions()
sLog.outString();
sLog.outString( ">> Loaded %u auctions", AuctionCount );
sLog.outString();
}
void ObjectMgr::LoadItemLocales()
@ -1933,7 +1963,13 @@ void ObjectMgr::LoadAuctionItems()
QueryResult *result = CharacterDatabase.Query( "SELECT data,itemguid,item_template FROM auctionhouse JOIN item_instance ON itemguid = guid" );
if( !result )
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Loaded 0 auction items");
return;
}
barGoLink bar( result->GetRowCount() );
@ -1968,7 +2004,6 @@ void ObjectMgr::LoadAuctionItems()
++count;
}
while( result->NextRow() );
delete result;
sLog.outString();
@ -4336,14 +4371,20 @@ void ObjectMgr::LoadInstanceTemplate()
else if(!entry->HasResetTime())
continue;
//FIXME: now exist heroic instance, normal/heroic raid instances
// entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
// entry->resetTimeRaid store reset time for normal raid only
// for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode.
// but at some point wee need implement reset time dependen from raid insatance mode
if(temp->reset_delay == 0)
{
// use defaults from the DBC
if(entry->SupportsHeroicMode())
if(entry->resetTimeHeroic) // for both raid and non raids, read above
{
temp->reset_delay = entry->resetTimeHeroic / DAY;
}
else if (entry->resetTimeRaid && entry->map_type == MAP_RAID)
// for normal raid only
{
temp->reset_delay = entry->resetTimeRaid / DAY;
}
@ -4521,14 +4562,27 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
// 0 1 2 3 4 5 6 7 8 9
QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" I64FMTD "'", (uint64)basetime);
if ( !result )
{
barGoLink bar(1);
bar.step();
sLog.outString("");
sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty.");
return; // any mails need to be returned or deleted
Field *fields;
}
//std::ostringstream delitems, delmails; //will be here for optimization
//bool deletemail = false, deleteitem = false;
//delitems << "DELETE FROM item_instance WHERE guid IN ( ";
//delmails << "DELETE FROM mail WHERE id IN ( "
barGoLink bar( result->GetRowCount() );
uint32 count = 0;
Field *fields;
do
{
bar.step();
fields = result->Fetch();
Mail *m = new Mail;
m->messageID = fields[0].GetUInt32();
@ -4594,8 +4648,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
//delmails << m->messageID << ", ";
CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID);
delete m;
++count;
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u mails", count );
}
void ObjectMgr::LoadQuestAreaTriggers()
@ -4761,24 +4819,31 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, u
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
if(node && node->map_id == mapid && node->MountCreatureID[team == ALLIANCE ? 1 : 0])
if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0])
continue;
uint8 field = (uint8)((i - 1) / 32);
uint32 submask = 1<<((i-1)%32);
// skip not taxi network nodes
if((sTaxiNodesMask[field] & submask)==0)
continue;
float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
if(found)
{
float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
if(found)
if(dist2 < dist)
{
if(dist2 < dist)
{
dist = dist2;
id = i;
}
}
else
{
found = true;
dist = dist2;
id = i;
}
}
else
{
found = true;
dist = dist2;
id = i;
}
}
return id;
@ -6250,11 +6315,18 @@ void ObjectMgr::LoadReservedPlayersNames()
bar.step();
fields = result->Fetch();
std::string name= fields[0].GetCppString();
if(normalizePlayerName(name))
std::wstring wstr;
if(!Utf8toWStr (name,wstr))
{
m_ReservedNames.insert(name);
++count;
sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str() );
continue;
}
wstrToLower(wstr);
m_ReservedNames.insert(wstr);
++count;
} while ( result->NextRow() );
delete result;
@ -6263,6 +6335,17 @@ void ObjectMgr::LoadReservedPlayersNames()
sLog.outString( ">> Loaded %u reserved player names", count );
}
bool ObjectMgr::IsReservedName( const std::string& name ) const
{
std::wstring wstr;
if(!Utf8toWStr (name,wstr))
return false;
wstrToLower(wstr);
return m_ReservedNames.find(wstr) != m_ReservedNames.end();
}
enum LanguageType
{
LT_BASIC_LATIN = 0x0000,
@ -6455,11 +6538,22 @@ void ObjectMgr::LoadGameObjectForQuests()
{
mGameObjectForQuestSet.clear(); // need for reload case
if( !sGOStorage.MaxEntry )
{
barGoLink bar( 1 );
bar.step();
sLog.outString();
sLog.outString( ">> Loaded 0 GameObjects for quests" );
return;
}
barGoLink bar( sGOStorage.MaxEntry - 1 );
uint32 count = 0;
// collect GO entries for GO that must activated
for(uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry)
{
bar.step();
GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(go_entry);
if(!goInfo)
continue;
@ -6494,7 +6588,7 @@ void ObjectMgr::LoadGameObjectForQuests()
}
sLog.outString();
sLog.outString( ">> Loaded %u GameObject for quests", count );
sLog.outString( ">> Loaded %u GameObjects for quests", count );
}
bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value)
@ -6986,11 +7080,10 @@ void ObjectMgr::LoadGameTele()
++count;
}
while (result->NextRow());
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u game tele's", count );
sLog.outString( ">> Loaded %u GameTeleports", count );
}
GameTele const* ObjectMgr::GetGameTele(const std::string& name) const
@ -7160,7 +7253,7 @@ void ObjectMgr::LoadTrainerSpell()
delete result;
sLog.outString();
sLog.outString( ">> Loaded Trainers %d", count );
sLog.outString( ">> Loaded %d Trainers", count );
}
void ObjectMgr::LoadVendors()
@ -7438,16 +7531,30 @@ void ObjectMgr::LoadScriptNames()
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
if(result)
if( !result )
{
do
{
m_scriptNames.push_back((*result)[0].GetString());
} while (result->NextRow());
delete result;
barGoLink bar( 1 );
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded empty set of Script Names!");
return;
}
barGoLink bar( result->GetRowCount() );
uint32 count = 0;
do
{
bar.step();
m_scriptNames.push_back((*result)[0].GetString());
++count;
} while (result->NextRow());
delete result;
std::sort(m_scriptNames.begin(), m_scriptNames.end());
sLog.outString();
sLog.outString( ">> Loaded %d Script Names", count );
}
uint32 ObjectMgr::GetScriptId(const char *name)

View file

@ -702,10 +702,7 @@ class ObjectMgr
// reserved names
void LoadReservedPlayersNames();
bool IsReservedName(const std::string& name) const
{
return m_ReservedNames.find(name) != m_ReservedNames.end();
}
bool IsReservedName(const std::string& name) const;
// name with valid structure and symbols
static bool IsValidName( const std::string& name, bool create = false );
@ -834,7 +831,7 @@ class ObjectMgr
PetCreateSpellMap mPetCreateSpell;
//character reserved names
typedef std::set<std::string> ReservedNamesMap;
typedef std::set<std::wstring> ReservedNamesMap;
ReservedNamesMap m_ReservedNames;
GraveYardMap mGraveYardMap;

View file

@ -39,25 +39,14 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
"'s Companion" // MINI_PET
};
Pet::Pet(PetType type) : Creature()
Pet::Pet(PetType type) :
Creature(), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duration(0), m_bonusdamage(0),
m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false),
m_declinedname(NULL)
{
m_isPet = true;
m_name = "Pet";
m_petType = type;
m_removed = false;
m_regenTimer = 4000;
m_happinessTimer = 7500;
m_duration = 0;
m_bonusdamage = 0;
m_resetTalentsCost = 0;
m_resetTalentsTime = 0;
m_usedTalentCount = 0;
m_auraUpdateMask = 0;
m_loading = false;
// pets always have a charminfo, even if they are not actually charmed
CharmInfo* charmInfo = InitCharmInfo(this);
@ -66,13 +55,6 @@ Pet::Pet(PetType type) : Creature()
charmInfo->SetReactState(REACT_PASSIVE);
else if(type == GUARDIAN_PET) // always aggressive
charmInfo->SetReactState(REACT_AGGRESSIVE);
m_spells.clear();
m_Auras.clear();
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
m_autospells.clear();
m_declinedname = NULL;
}
Pet::~Pet()
@ -768,11 +750,10 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/4);
SetUInt32Value(UNIT_NPC_FLAGS, 0);
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family);
if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] )
SetName(familyname);
if(CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]);
else
SetName(creature->GetName());
SetName(creature->GetNameForLocaleIdx(objmgr.GetDBCLocaleIndex()));
if(cinfo->type == CREATURE_TYPE_BEAST)
{
@ -1088,7 +1069,7 @@ void Pet::_LoadSpells()
{
Field *fields = result->Fetch();
addSpell(fields[0].GetUInt16(), fields[1].GetUInt16(), PETSPELL_UNCHANGED);
addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED);
}
while( result->NextRow() );
@ -1241,7 +1222,7 @@ void Pet::_SaveAuras()
}
}
bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpellType type)
bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpellType type)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo)
@ -1354,7 +1335,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, PetSpell
return true;
}
bool Pet::learnSpell(uint16 spell_id)
bool Pet::learnSpell(uint32 spell_id)
{
// prevent duplicated entires in spell book
if (!addSpell(spell_id))
@ -1391,7 +1372,7 @@ void Pet::learnLevelupSpells()
}
}
bool Pet::unlearnSpell(uint16 spell_id)
bool Pet::unlearnSpell(uint32 spell_id)
{
if(removeSpell(spell_id))
{
@ -1409,7 +1390,7 @@ bool Pet::unlearnSpell(uint16 spell_id)
return false;
}
bool Pet::removeSpell(uint16 spell_id)
bool Pet::removeSpell(uint32 spell_id)
{
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end())
@ -1443,7 +1424,7 @@ bool Pet::removeSpell(uint16 spell_id)
return true;
}
bool Pet::_removeSpell(uint16 spell_id)
bool Pet::_removeSpell(uint32 spell_id)
{
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
@ -1460,7 +1441,7 @@ void Pet::InitPetCreateSpells()
m_charmInfo->InitPetActionBar();
m_spells.clear();
int32 petspellid;
uint32 petspellid;
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
if(CreateSpells)
{
@ -1480,7 +1461,7 @@ void Pet::InitPetCreateSpells()
if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id))
{
if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right
((Player*)owner)->learnSpell(learn_spellproto->Id);
((Player*)owner)->learnSpell(learn_spellproto->Id,false);
else
AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id);
}
@ -1514,7 +1495,7 @@ void Pet::CheckLearning(uint32 spellid)
if(urand(0, 100) < 10)
{
((Player*)owner)->learnSpell(itr->second);
((Player*)owner)->learnSpell(itr->second,false);
m_teachspells.erase(itr);
}
}
@ -1655,7 +1636,7 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
if(IsPassiveSpell(spellid))
return;
PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid);
PetSpellMap::const_iterator itr = m_spells.find(spellid);
int i;
@ -1709,7 +1690,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
bool Pet::HasSpell(uint32 spell) const
{
PetSpellMap::const_iterator itr = m_spells.find((uint16)spell);
PetSpellMap::const_iterator itr = m_spells.find(spell);
return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED );
}

View file

@ -103,7 +103,7 @@ enum PetNameInvalidReason
PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 16
};
typedef UNORDERED_MAP<uint16, PetSpell*> PetSpellMap;
typedef UNORDERED_MAP<uint32, PetSpell*> PetSpellMap;
typedef std::map<uint32,uint32> TeachSpellMap;
typedef std::vector<uint32> AutoSpellList;
@ -188,12 +188,12 @@ class Pet : public Creature
void _LoadSpells();
void _SaveSpells();
bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL);
bool learnSpell(uint16 spell_id);
bool addSpell(uint32 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL);
bool learnSpell(uint32 spell_id);
void learnLevelupSpells();
bool unlearnSpell(uint16 spell_id);
bool removeSpell(uint16 spell_id);
bool _removeSpell(uint16 spell_id);
bool unlearnSpell(uint32 spell_id);
bool removeSpell(uint32 spell_id);
bool _removeSpell(uint32 spell_id);
PetSpellMap m_spells;
TeachSpellMap m_teachspells;

View file

@ -285,7 +285,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data )
void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber)
{
Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid);
Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber)
return;
@ -327,7 +327,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
if(ObjectAccessor::FindPlayer(petguid))
return;
Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid);
Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid);
if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
{
@ -464,7 +464,7 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data )
sLog.outDetail( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid) );
// pet/charmed
Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, guid);
Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid);
if(pet)
{
if(pet->isPet())
@ -529,7 +529,7 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket )
if(ObjectAccessor::FindPlayer(guid))
return;
Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid);
Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm()))
{
@ -581,7 +581,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
if (GUID_HIPART(guid) == HIGHGUID_PLAYER)
return;
Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player,guid);
Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if(!pet || (pet != _player->GetPet() && pet!= _player->GetCharm()))
{

View file

@ -190,7 +190,7 @@ void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all )
}
}
bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values )
bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values, uint32 team )
{
ClearTaxiDestinations();
@ -218,6 +218,10 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values )
return false;
}
// can't load taxi path without mount set (quest taxi path?)
if(!objmgr.GetTaxiMount(GetTaxiSource(),team))
return false;
return true;
}
@ -293,6 +297,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
m_comboPoints = 0;
m_usedTalentCount = 0;
m_questRewardTalentCount = 0;
m_regenTimer = 0;
m_weaponChangeTimer = 0;
@ -422,7 +427,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this)
for (int i = 0; i < MAX_COMBAT_RATING; i++)
m_baseRatingValue[i] = 0;
m_baseSpellDamage = 0;
m_baseSpellHealing = 0;
m_baseFeralAP = 0;
@ -2239,7 +2244,8 @@ void Player::InitTalentForLevel()
}
else
{
uint32 talentPointsForLevel = uint32((level-9)*sWorld.getRate(RATE_TALENT));
uint32 talentPointsForLevel = CalculateTalentsPoints();
// if used more that have then reset
if(m_usedTalentCount > talentPointsForLevel)
{
@ -2535,7 +2541,7 @@ void Player::AddNewMailDeliverTime(time_t deliver_time)
}
}
bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled)
bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo)
@ -2568,29 +2574,78 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED;
bool dependent_set = false;
bool disabled_case = false;
bool superceded_old = false;
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
{
uint32 next_active_spell_id = 0;
// fix activate state for non-stackable low rank (and find next spell for !active case)
if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext();
for(SpellChainMapNext::const_iterator next_itr = nextMap.lower_bound(spell_id); next_itr != nextMap.upper_bound(spell_id); ++next_itr)
{
if(HasSpell(next_itr->second))
{
// high rank already known so this must !active
active = false;
next_active_spell_id = next_itr->second;
break;
}
}
}
// not do anything if already known in expected state
if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active &&
itr->second->dependent == dependent && itr->second->disabled == disabled)
return false;
// dependent spell known as not dependent, overwrite state
if (itr->second->state != PLAYERSPELL_REMOVED && !itr->second->dependent && dependent)
{
itr->second->dependent = dependent;
if (itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
dependent_set = true;
}
// update active state for known spell
if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled)
{
itr->second->active = active;
// !IsInWorld() && !learning == explicitly load from DB and then exist in it already and set correctly
if(!IsInWorld() && !learning)
if(!IsInWorld() && !learning && !dependent_set)
itr->second->state = PLAYERSPELL_UNCHANGED;
else if(itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
if(!active)
if(active)
{
WorldPacket data(SMSG_REMOVED_SPELL, 4);
data << uint16(spell_id);
GetSession()->SendPacket(&data);
if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo))
CastSpell (this,spell_id,true);
}
else if(IsInWorld())
{
if(next_active_spell_id)
{
// update spell ranks in spellbook and action bar
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
data << uint16(spell_id);
data << uint16(next_active_spell_id);
GetSession()->SendPacket( &data );
}
else
{
WorldPacket data(SMSG_REMOVED_SPELL, 4);
data << uint16(spell_id);
GetSession()->SendPacket(&data);
}
}
return active; // learn (show in spell book if active now)
}
@ -2619,7 +2674,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
default: // known not saved yet spell (new or modified)
{
// can be in case spell loading but learned at some previous spell loading
if(!IsInWorld() && !learning)
if(!IsInWorld() && !learning && !dependent_set)
itr->second->state = PLAYERSPELL_UNCHANGED;
return false;
@ -2652,16 +2707,17 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
// non talent spell: learn low ranks (recursive call)
else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id))
{
if(!IsInWorld()) // at spells loading, no output, but allow save
addSpell(prev_spell,active,true,disabled);
if(!IsInWorld() || disabled) // at spells loading, no output, but allow save
addSpell(prev_spell,active,true,true,disabled);
else // at normal learning
learnSpell(prev_spell);
learnSpell(prev_spell,true);
}
PlayerSpell *newspell = new PlayerSpell;
newspell->active = active;
newspell->state = state;
newspell->disabled = disabled;
newspell->state = state;
newspell->active = active;
newspell->dependent = dependent;
newspell->disabled = disabled;
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
@ -2688,7 +2744,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
// mark old spell as disable (SMSG_SUPERCEDED_SPELL replace it in client by new)
itr->second->active = false;
itr->second->state = PLAYERSPELL_CHANGED;
if(itr->second->state != PLAYERSPELL_NEW)
itr->second->state = PLAYERSPELL_CHANGED;
superceded_old = true; // new spell replace old in action bars and spell book.
}
else if(spellmgr.IsHighRankOfSpell(itr->first,spell_id))
@ -2730,26 +2787,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
// also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks
else if (IsPassiveSpell(spell_id))
{
bool need_cast = false;
switch(spell_id)
{
// some spells not have stance data expacted cast at form change or present
case 5420: need_cast = (m_form == FORM_TREE); break;
case 5419: need_cast = (m_form == FORM_TRAVEL); break;
case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break;
case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break;
case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break;
case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break;
case 33948: need_cast = (m_form == FORM_FLIGHT); break;
case 34764: need_cast = (m_form == FORM_FLIGHT); break;
case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
// another spells have proper stance data
default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break;
}
//Check CasterAuraStates
if (need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))))
if(IsNeedCastPassiveSpellAtLearn(spellInfo))
CastSpell(this, spell_id, true);
}
else if( IsSpellHaveEffect(spellInfo,SPELL_EFFECT_SKILL_STEP) )
@ -2834,9 +2872,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
if(!itr->second.autoLearned)
{
if(!IsInWorld() || !itr->second.active) // at spells loading, no output, but allow save
addSpell(itr->second.spell,itr->second.active,true,false);
addSpell(itr->second.spell,itr->second.active,true,true,false);
else // at normal learning
learnSpell(itr->second.spell);
learnSpell(itr->second.spell,true);
}
}
@ -2850,14 +2888,39 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled
return active && !disabled && !superceded_old;
}
void Player::learnSpell(uint32 spell_id)
bool Player::IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const
{
bool need_cast = false;
switch(spellInfo->Id)
{
// some spells not have stance data expacted cast at form change or present
case 5420: need_cast = (m_form == FORM_TREE); break;
case 5419: need_cast = (m_form == FORM_TRAVEL); break;
case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break;
case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break;
case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break;
case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break;
case 33948: need_cast = (m_form == FORM_FLIGHT); break;
case 34764: need_cast = (m_form == FORM_FLIGHT); break;
case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
// another spells have proper stance data
default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break;
}
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState)));
}
void Player::learnSpell(uint32 spell_id, bool dependent)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
bool disabled = (itr != m_spells.end()) ? itr->second->disabled : false;
bool active = disabled ? itr->second->active : true;
bool learning = addSpell(spell_id,active,true,false);
bool learning = addSpell(spell_id,active,true,dependent,false);
// learn all disabled higher ranks (recursive)
if(disabled)
@ -2867,7 +2930,7 @@ void Player::learnSpell(uint32 spell_id)
{
PlayerSpellMap::iterator iter = m_spells.find(i->second);
if (iter != m_spells.end() && iter->second->disabled)
learnSpell(i->second);
learnSpell(i->second,false);
}
}
@ -2895,10 +2958,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled)
if(HasSpell(itr2->second) && !GetTalentSpellPos(itr2->second))
removeSpell(itr2->second,disabled);
// removing
WorldPacket data(SMSG_REMOVED_SPELL, 4);
data << uint16(spell_id);
GetSession()->SendPacket(&data);
bool cur_active = itr->second->active;
bool cur_dependent = itr->second->dependent;
if (disabled)
{
@ -3011,7 +3072,54 @@ void Player::removeSpell(uint32 spell_id, bool disabled)
for(SpellLearnSpellMap::const_iterator itr2 = spell_begin; itr2 != spell_end; ++itr2)
removeSpell(itr2->second.spell, disabled);
// TODO: recast if need lesser ranks spell for passive with IsPassiveSpellStackableWithRanks
// activate lesser rank in spellbook/action bar, and cast it if need
bool prev_activate = false;
if(uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id))
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
// if talent then lesser rank also talen and need learn
if(talentCosts)
learnSpell (prev_id,false);
// if ranked non-stackable spell: need activate lesser rank and update dendence state
else if(cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
// need manually update dependence state (learn spell ignore like attempts)
PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id);
if (prev_itr != m_spells.end())
{
if(prev_itr->second->dependent != cur_dependent)
{
prev_itr->second->dependent = cur_dependent;
if(prev_itr->second->state != PLAYERSPELL_NEW)
prev_itr->second->state = PLAYERSPELL_CHANGED;
}
// now re-learn if need re-activate
if(cur_active && !prev_itr->second->active)
{
if(addSpell(prev_id,true,false,prev_itr->second->dependent,prev_itr->second->disabled))
{
// downgrade spell ranks in spellbook and action bar
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
data << uint16(spell_id);
data << uint16(prev_id);
GetSession()->SendPacket( &data );
prev_activate = true;
}
}
}
}
}
// remove from spell book if not replaced by lesser rank
if(!prev_activate)
{
WorldPacket data(SMSG_REMOVED_SPELL, 4);
data << uint16(spell_id);
GetSession()->SendPacket(&data);
}
}
void Player::RemoveArenaSpellCooldowns()
@ -3154,8 +3262,7 @@ bool Player::resetTalents(bool no_cost)
CharacterDatabase.PExecute("UPDATE characters set at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_TALENTS), GetGUIDLow());
}
uint32 level = getLevel();
uint32 talentPointsForLevel = level < 10 ? 0 : uint32((level-9)*sWorld.getRate(RATE_TALENT));
uint32 talentPointsForLevel = CalculateTalentsPoints();
if (m_usedTalentCount == 0)
{
@ -3452,8 +3559,16 @@ void Player::DestroyForPlayer( Player *target ) const
bool Player::HasSpell(uint32 spell) const
{
PlayerSpellMap::const_iterator itr = m_spells.find((uint16)spell);
return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled);
PlayerSpellMap::const_iterator itr = m_spells.find(spell);
return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED &&
!itr->second->disabled);
}
bool Player::HasActiveSpell(uint32 spell) const
{
PlayerSpellMap::const_iterator itr = m_spells.find(spell);
return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED &&
itr->second->active && !itr->second->disabled);
}
TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell) const
@ -4530,7 +4645,7 @@ float Player::OCTRegenMPPerSpirit()
void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
{
m_baseRatingValue[cr]+=(apply ? value : -value);
int32 amount = uint32(m_baseRatingValue[cr]);
// Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT
// stat used stored in miscValueB for this aura
@ -4703,7 +4818,7 @@ bool Player::UpdateCraftSkill(uint32 spellid)
if(spellEntry && spellEntry->Mechanic==MECHANIC_DISCOVERY)
{
if(uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this))
learnSpell(discoveredSpell);
learnSpell(discoveredSpell,false);
}
uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING);
@ -4759,6 +4874,11 @@ bool Player::UpdateFishingSkill()
return UpdateSkillPro(SKILL_FISHING,chance*10,gathering_skill_gain);
}
// levels sync. with spell requirement for skill levels to learn
// bonus abilities in sSkillLineAbilityStore
// Used only to avoid scan DBC at each skill grow
static uint32 bonusSkillLevels[] = {75,150,225,300,375,450};
bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
{
sLog.outDebug("UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance/10.0);
@ -4793,6 +4913,14 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
new_value = MaxValue;
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue));
for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl)
{
if((SkillValue < *bsl && new_value >= *bsl))
{
learnSkillRewardedSpells( SkillId, new_value);
break;
}
}
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0);
return true;
@ -4969,6 +5097,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
if(currVal)
{
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal));
learnSkillRewardedSpells(id, currVal);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL);
}
else //remove
@ -4979,26 +5108,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
// remove spells that depend on this skill when removing the skill
for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next)
{
++next;
if(itr->second->state == PLAYERSPELL_REMOVED)
continue;
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{
if (_spell_idx->second->skillId == id)
{
// this may remove more than one spell (dependents)
removeSpell(itr->first);
next = m_spells.begin();
break;
}
}
}
learnSkillRewardedSpells(id, 0);
}
}
else if(currVal) //add
@ -5036,7 +5146,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
(*i)->ApplyModifier(true);
// Learn all spells for skill
learnSkillRewardedSpells(id);
learnSkillRewardedSpells(id, currVal);
return;
}
}
@ -9931,7 +10041,7 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
if(!CanDualWield())
return EQUIP_ERR_CANT_DUAL_WIELD;
}
else if (type == INVTYPE_2HWEAPON)
else if (type == INVTYPE_2HWEAPON)
{
if(!CanDualWield() || !CanTitanGrip())
return EQUIP_ERR_CANT_DUAL_WIELD;
@ -12675,6 +12785,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SetTitle(titleEntry);
}
if(pQuest->GetBonusTalents())
{
m_questRewardTalentCount+=pQuest->GetBonusTalents();
InitTalentForLevel();
}
// Send reward mail
if(pQuest->GetRewMailTemplateId())
{
@ -14325,16 +14441,15 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
_LoadSpells(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLS));
// after spell load
InitTalentForLevel();
learnSkillRewardedSpells();
learnDefaultSpells();
// after spell load, learn rewarded spell if need also
_LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS));
_LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS));
// after spell and quest load
InitTalentForLevel();
learnSkillRewardedSpells();
learnDefaultSpells();
_LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS));
// must be before inventory (some items required reputation check)
@ -14364,7 +14479,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
}
// Not finish taxi flight path
if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes))
if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes,GetTeam()))
{
// problems with taxi path loading
TaxiNodesEntry const* nodeEntry = NULL;
@ -14585,7 +14700,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
damage = aura->GetModifier()->m_amount;
aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges);
AddAura(aura);
sLog.outString("Added aura spellid %u, effect %u", spellproto->Id, effindex);
sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex);
}
}
while( result->NextRow() );
@ -15008,6 +15123,9 @@ void Player::_LoadQuestStatus(QueryResult *result)
if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId()))
SetTitle(titleEntry);
}
if(pQuest->GetBonusTalents())
m_questRewardTalentCount+=pQuest->GetBonusTalents();
}
sLog.outDebug("Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow());
@ -15135,7 +15253,7 @@ void Player::_LoadSpells(QueryResult *result)
{
Field *fields = result->Fetch();
addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, fields[2].GetBool());
addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, false, fields[2].GetBool());
}
while( result->NextRow() );
@ -15284,29 +15402,29 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, b
void Player::SendRaidInfo()
{
uint32 counter = 0;
WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4);
uint32 counter = 0, i;
for(i = 0; i < TOTAL_DIFFICULTIES; i++)
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
if(itr->second.perm) counter++;
size_t p_counter = data.wpos();
data << uint32(counter); // placeholder
data << counter;
for(i = 0; i < TOTAL_DIFFICULTIES; i++)
for(int i = 0; i < TOTAL_DIFFICULTIES; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
if(itr->second.perm)
{
InstanceSave *save = itr->second.save;
data << (save->GetMapId());
data << (uint32)(save->GetResetTime() - time(NULL));
data << save->GetInstanceId();
data << uint32(counter);
counter--;
data << uint32(save->GetMapId());
data << uint32(save->GetResetTime() - time(NULL));
data << uint32(save->GetInstanceId());
data << uint32(save->GetDifficulty());
++counter;
}
}
}
data.put<uint32>(p_counter,counter);
GetSession()->SendPacket(&data);
}
@ -15897,7 +16015,9 @@ void Player::_SaveSpells()
++next;
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED)
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first);
if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)
// add only changed/new not dependent spells
if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED))
CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0);
if (itr->second->state == PLAYERSPELL_REMOVED)
@ -18116,9 +18236,9 @@ void Player::learnDefaultSpells()
uint32 tspell = *itr;
sLog.outDebug("PLAYER (Class: %u Race: %u): Adding initial spell, id = %u",uint32(getClass()),uint32(getRace()), tspell);
if(!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add
addSpell(tspell,true,true,false);
addSpell(tspell,true,true,true,false);
else // but send in normal spell in game learn case
learnSpell(tspell);
learnSpell(tspell,true);
}
}
@ -18210,7 +18330,7 @@ void Player::learnQuestRewardedSpells()
}
}
void Player::learnSkillRewardedSpells(uint32 skill_id )
void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value )
{
uint32 raceMask = getRaceMask();
uint32 classMask = getClassMask();
@ -18228,8 +18348,14 @@ void Player::learnSkillRewardedSpells(uint32 skill_id )
if (sSpellStore.LookupEntry(pAbility->spellId))
{
// Ok need learn spell
learnSpell(pAbility->spellId);
// need unlearn spell
if (skill_value < pAbility->req_skill_value)
removeSpell(pAbility->spellId);
// need learn
else if (!IsInWorld())
addSpell(pAbility->spellId,true,true,true,false);
else
learnSpell(pAbility->spellId,true);
}
}
}
@ -18241,9 +18367,10 @@ void Player::learnSkillRewardedSpells()
if(!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
continue;
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
uint32 pskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_INDEX(i)));
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
learnSkillRewardedSpells(pskill);
learnSkillRewardedSpells(pskill, vskill);
}
}
@ -18692,7 +18819,7 @@ bool Player::isHonorOrXPTarget(Unit* pVictim)
if(pVictim->GetTypeId() == TYPEID_UNIT)
{
if (((Creature*)pVictim)->isTotem() ||
if (((Creature*)pVictim)->isTotem() ||
((Creature*)pVictim)->isPet() ||
((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
return false;
@ -18859,8 +18986,7 @@ void Player::SetClientControl(Unit* target, uint8 allowMove)
void Player::UpdateZoneDependentAuras( uint32 newZone )
{
// remove new continent flight forms
uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), newZone);
if( !isGameMaster() && v_map != 530 && v_map != 571)
if( !IsAllowUseFlyMountsHere() )
{
RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
RemoveSpellsCausingAura(SPELL_AURA_FLY);
@ -19268,7 +19394,7 @@ void Player::SetTitle(CharTitlesEntry const* title)
void Player::ConvertRune(uint8 index, uint8 newType)
{
SetCurrentRune(index, newType);
WorldPacket data(SMSG_CONVERT_RUNE, 2);
data << uint8(index);
data << uint8(newType);
@ -19333,3 +19459,29 @@ void Player::AutoStoreLootItem(uint8 bag, uint8 slot, uint32 loot_id, LootStore
StoreNewItem (dest,lootItem->itemid,true,lootItem->randomPropertyId);
}
uint32 Player::CalculateTalentsPoints() const
{
uint32 base_talent = getLevel() < 10 ? 0 : uint32((getLevel()-9)*sWorld.getRate(RATE_TALENT));
if(getClass() != CLASS_DEATH_KNIGHT)
return base_talent;
uint32 talentPointsForLevel =
(getLevel() < 56 ? 0 : uint32((getLevel()-55)*sWorld.getRate(RATE_TALENT)))
+ m_questRewardTalentCount;
if(talentPointsForLevel > base_talent)
talentPointsForLevel = base_talent;
return talentPointsForLevel;
}
bool Player::IsAllowUseFlyMountsHere() const
{
if (isGameMaster())
return true;
uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), GetZoneId());
return v_map == 530 || v_map == 571 && HasSpell(54197);
}

View file

@ -85,8 +85,9 @@ enum PlayerSpellState
struct PlayerSpell
{
PlayerSpellState state : 8;
bool active : 1;
bool disabled : 1;
bool active : 1; // show in spellbook
bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc
bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks
};
// Spell modifier (used for modify other spells)
@ -103,7 +104,7 @@ struct SpellModifier
Spell const* lastAffected;
};
typedef UNORDERED_MAP<uint16, PlayerSpell*> PlayerSpellMap;
typedef UNORDERED_MAP<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
struct SpellCooldown
@ -440,7 +441,7 @@ enum PlayerFlags
PLAYER_FLAGS_UNK18 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
PLAYER_FLAGS_UNK20 = 0x00080000,
PLAYER_FLAGS_UNK21 = 0x00100000,
PLAYER_FLAGS_UNK21 = 0x00100000,
PLAYER_FLAGS_UNK22 = 0x00200000,
PLAYER_FLAGS_UNK23 = 0x00400000,
PLAYER_FLAGS_UNK24 = 0x00800000, // disabled all abilitys on tab except autoattack
@ -938,7 +939,7 @@ class MANGOS_DLL_SPEC PlayerTaxi
void AppendTaximaskTo(ByteBuffer& data,bool all);
// Destinations
bool LoadTaxiDestinationsFromString(const std::string& values);
bool LoadTaxiDestinationsFromString(const std::string& values, uint32 team);
std::string SaveTaxiDestinationsToString();
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
@ -1475,13 +1476,15 @@ class MANGOS_DLL_SPEC Player : public Unit
void CharmSpellInitialize();
void PossessSpellInitialize();
bool HasSpell(uint32 spell) const;
bool HasActiveSpell(uint32 spell) const; // show in spellbook
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
bool IsSpellFitByClassAndRace( uint32 spell_id ) const;
bool IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const;
void SendProficiency(uint8 pr1, uint32 pr2);
void SendInitialSpells();
bool addSpell(uint32 spell_id, bool active, bool learning, bool disabled);
void learnSpell(uint32 spell_id);
bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled);
void learnSpell(uint32 spell_id, bool dependent);
void removeSpell(uint32 spell_id, bool disabled = false);
void resetSpells();
void learnDefaultSpells();
@ -1494,6 +1497,8 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 resetTalentsCost() const;
void InitTalentForLevel();
uint32 CalculateTalentsPoints() const;
void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
@ -1766,7 +1771,7 @@ class MANGOS_DLL_SPEC Player : public Unit
int16 GetSkillPermBonusValue(uint32 skill) const;
int16 GetSkillTempBonusValue(uint32 skill) const;
bool HasSkill(uint32 skill) const;
void learnSkillRewardedSpells( uint32 id );
void learnSkillRewardedSpells(uint32 id, uint32 value);
void learnSkillRewardedSpells();
void SetDontMove(bool dontMove);
@ -2049,6 +2054,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool CanFly() const { return HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); }
bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); }
bool IsAllowUseFlyMountsHere() const;
void HandleDrowning();
@ -2393,6 +2399,7 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;

View file

@ -84,7 +84,8 @@ bool LoadScriptingModule(char const* libName)
return false;
}
printf("Scripts Library %s was successfully loaded.\n",name.c_str());
sLog.outString();
sLog.outString( ">>> Scripts Library %s was successfully loaded.\n", name.c_str() );
//heh we are still there :P we have a valid library
//we reload script

View file

@ -383,7 +383,7 @@ enum ItemQualities
#define SPELL_ATTR_EX5_UNK6 0x00000040 // 6
#define SPELL_ATTR_EX5_UNK7 0x00000080 // 7
#define SPELL_ATTR_EX5_UNK8 0x00000100 // 8
#define SPELL_ATTR_EX5_UNK9 0x00000200 // 9
#define SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY 0x00000200 // 9 begin periodic tick at aura apply
#define SPELL_ATTR_EX5_UNK10 0x00000400 // 10
#define SPELL_ATTR_EX5_UNK11 0x00000800 // 11
#define SPELL_ATTR_EX5_UNK12 0x00001000 // 12
@ -807,7 +807,7 @@ enum Targets
TARGET_EFFECT_SELECT = 18, // highly depends on the spell effect
TARGET_ALL_PARTY_AROUND_CASTER = 20,
TARGET_SINGLE_FRIEND = 21,
TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB
TARGET_CASTER_COORDINATES = 22, // used only in TargetA, target selection dependent from TargetB
TARGET_GAMEOBJECT = 23,
TARGET_IN_FRONT_OF_CASTER = 24,
TARGET_DUELVSPLAYER = 25,
@ -838,6 +838,7 @@ enum Targets
TARGET_AREAEFFECT_PARTY_AND_CLASS = 61,
TARGET_DUELVSPLAYER_COORDINATES = 63,
TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells
TARGET_DYNAMIC_OBJECT_COORDINATES = 76,
TARGET_SINGLE_ENEMY = 77,
TARGET_SELF2 = 87,
TARGET_NONCOMBAT_PET = 90,
@ -1505,6 +1506,7 @@ enum TrainerType // this is important
#define MAX_TRAINER_TYPE 4
// CreatureType.dbc
enum CreatureType
{
CREATURE_TYPE_BEAST = 1,
@ -1524,6 +1526,7 @@ enum CreatureType
uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1));
// CreatureFamily.dbc
enum CreatureFamily
{
CREATURE_FAMILY_WOLF = 1,
@ -1535,6 +1538,7 @@ enum CreatureFamily
CREATURE_FAMILY_CARRION_BIRD = 7,
CREATURE_FAMILY_CRAB = 8,
CREATURE_FAMILY_GORILLA = 9,
CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB
CREATURE_FAMILY_RAPTOR = 11,
CREATURE_FAMILY_TALLSTRIDER = 12,
CREATURE_FAMILY_FELHUNTER = 15,

View file

@ -127,7 +127,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
return;
// learn! (other talent ranks will unlearned at learning)
GetPlayer( )->learnSpell(spellid);
GetPlayer( )->learnSpell(spellid,false);
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
// update free talent points

View file

@ -101,6 +101,14 @@ void SpellCastTargets::setDestination(float x, float y, float z)
m_targetMask |= TARGET_FLAG_DEST_LOCATION;
}
void SpellCastTargets::setSource(float x, float y, float z)
{
m_srcX = x;
m_srcY = y;
m_srcZ = z;
m_targetMask |= TARGET_FLAG_SOURCE_LOCATION;
}
void SpellCastTargets::setGOTarget(GameObject *target)
{
m_GOTarget = target;
@ -349,6 +357,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
focusObject = NULL;
m_cast_count = 0;
m_glyphIndex = 0;
m_preCastSpell = 0;
m_triggeredByAuraSpell = NULL;
//Auto Shot & Shoot (wand)
@ -418,17 +427,11 @@ void Spell::FillTargetMap()
// but need it support in some know cases
switch(m_spellInfo->EffectImplicitTargetA[i])
{
case TARGET_ALL_AROUND_CASTER:
if( m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_PARTY ||
m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER ||
m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_RAID_AROUND_CASTER )
{
SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
}
case TARGET_CASTER_COORDINATES:
// Note: this hack with search required until GO casting not implemented
// environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
// currently each enemy selected explicitly and self cast damage
else if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
{
if(m_targets.getUnitTarget())
tmpUnitMap.push_back(m_targets.getUnitTarget());
@ -640,8 +643,6 @@ void Spell::FillTargetMap()
break;
}
}
if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty())
m_needAliveTargetMask |= (1<<i);
if(m_caster->GetTypeId() == TYPEID_PLAYER)
{
@ -709,11 +710,12 @@ void Spell::prepareDataForTriggerSystem()
case SPELLFAMILY_ROGUE: // For poisons need do it
if (m_spellInfo->SpellFamilyFlags & 0x000000101001E000LL) m_canTrigger = true;
break;
case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect
if (m_spellInfo->SpellFamilyFlags & 0x0100200000000014LL) m_canTrigger = true;
case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect/Explosive Shot
if (m_spellInfo->SpellFamilyFlags & 0x0100200000000214LL ||
m_spellInfo->SpellFamilyFlags2 & 0x200) m_canTrigger = true;
break;
case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true;
case SPELLFAMILY_PALADIN: // For Judgements (all) / Holy Shock triggers need do it
if (m_spellInfo->SpellFamilyFlags & 0x0001000900B80400LL) m_canTrigger = true;
break;
}
}
@ -928,7 +930,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
return;
// Get original caster (if exist) and calculate damage/healing from him data
Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
Unit *caster = m_originalCaster ? m_originalCaster : m_caster;
// Skip if m_originalCaster not avaiable
if (!caster)
@ -1010,25 +1012,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
int32 damagePoint = damageInfo.damage * 33 / 100;
m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
}
// Bloodthirst
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
{
uint32 BTAura = 0;
switch(m_spellInfo->Id)
{
case 23881: BTAura = 23885; break;
case 23892: BTAura = 23886; break;
case 23893: BTAura = 23887; break;
case 23894: BTAura = 23888; break;
case 25251: BTAura = 25252; break;
case 30335: BTAura = 30339; break;
default:
sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
break;
}
if (BTAura)
m_caster->CastSpell(m_caster,BTAura,true);
}
}
// Passive spell hits/misses or active spells only misses (only triggers)
else
@ -1146,6 +1129,10 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
if((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL)
unit->IncrDiminishing(m_diminishGroup);
// Apply additional spell effects to target
if (m_preCastSpell)
m_caster->CastSpell(unit,m_preCastSpell, true, m_CastItem);
for(uint32 effectNumber=0;effectNumber<3;effectNumber++)
{
if (effectMask & (1<<effectNumber))
@ -1480,6 +1467,19 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}break;
case TARGET_ALL_ENEMY_IN_AREA:
{
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap());
}break;
case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
{
@ -1564,25 +1564,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET)
TagUnitMap.push_back(target);
}break;
case TARGET_ALL_AROUND_CASTER:
case TARGET_CASTER_COORDINATES:
{
CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_AOE_DAMAGE);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap());
m_targets.setDestination(m_targets.m_srcX, m_targets.m_srcY, m_targets.m_srcZ);
}break;
case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
{
CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
@ -1725,7 +1713,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
// targets the ground, not the units in the area
if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
{
CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
@ -1998,6 +1986,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
m_targets.setDestination(_target_x, _target_y, _target_z);
}
}break;
case TARGET_DYNAMIC_OBJECT_COORDINATES:
{
// if parent spell create dynamic object extract area from it
if(DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell ? m_triggeredByAuraSpell->Id : m_spellInfo->Id))
m_targets.setDestination(dynObj->GetPositionX(), dynObj->GetPositionY(), dynObj->GetPositionZ());
}break;
default:
break;
}
@ -2044,6 +2038,18 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)
m_spellState = SPELL_STATE_PREPARING;
if (!(m_targets.m_targetMask & TARGET_FLAG_SOURCE_LOCATION))
{
// Check original caster is GO - set its coordinates as src cast
WorldObject *caster = NULL;
if (m_originalCasterGUID)
caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID);
if (!caster)
caster = m_caster;
// Set cast source for targets
m_targets.setSource(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
}
m_castPositionX = m_caster->GetPositionX();
m_castPositionY = m_caster->GetPositionY();
m_castPositionZ = m_caster->GetPositionZ();
@ -2192,6 +2198,47 @@ void Spell::cast(bool skipCheck)
}
}
switch(m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
m_preCastSpell = 11196; // Recently Bandaged
else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) // Blood Fury (Racial)
m_preCastSpell = 23230; // Blood Fury - Healing Reduction
break;
}
case SPELLFAMILY_MAGE:
{
if (m_spellInfo->SpellFamilyFlags&0x0000008000000000LL) // Ice Block
m_preCastSpell = 41425; // Hypothermia
break;
}
case SPELLFAMILY_PRIEST:
{
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
m_spellInfo->SpellIconID == 566) // Power Word: Shield
m_preCastSpell = 6788; // Weakened Soul
break;
}
case SPELLFAMILY_PALADIN:
{
if (m_spellInfo->SpellFamilyFlags&0x0000000000400080LL) // Divine Shield, Divine Protection or Hand of Protection
m_preCastSpell = 25771; // Forbearance
break;
}
case SPELLFAMILY_SHAMAN:
{
if (m_spellInfo->Id == 2825) // Bloodlust
m_preCastSpell = 57724; // Sated
else if (m_spellInfo->Id == 32182) // Heroism
m_preCastSpell = 57723; // Exhaustion
break;
}
default:
break;
}
// Conflagrate - consumes immolate
if ((m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) && m_targets.getUnitTarget())
{
@ -2266,6 +2313,9 @@ void Spell::handle_immediate()
int32 duration = GetSpellDuration(m_spellInfo);
if (duration)
{
// Apply duration mod
if(Player* modOwner = m_caster->GetSpellModOwner())
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
m_spellState = SPELL_STATE_CASTING;
SendChannelStart(duration);
}
@ -2684,68 +2734,6 @@ void Spell::finish(bool ok)
((Player*)m_caster)->ClearComboPoints();
}
// Post effects apply on spell targets in some spells
if(!m_UniqueTargetInfo.empty())
{
uint32 spellId = 0;
switch(m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
spellId = 11196; // Recently Bandaged
else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) // Blood Fury (Racial)
spellId = 23230; // Blood Fury - Healing Reduction
break;
}
case SPELLFAMILY_MAGE:
{
if (m_spellInfo->SpellFamilyFlags&0x0000008000000000LL) // Ice Block
spellId = 41425; // Hypothermia
break;
}
case SPELLFAMILY_PRIEST:
{
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
m_spellInfo->SpellIconID == 566) // Power Word: Shield
spellId = 6788; // Weakened Soul
break;
}
case SPELLFAMILY_PALADIN:
{
if (m_spellInfo->SpellFamilyFlags&0x0000000000400080LL) // Divine Shield, Divine Protection or Hand of Protection
spellId = 25771; // Forbearance
break;
}
case SPELLFAMILY_SHAMAN:
{
if (m_spellInfo->Id == 2825) // Bloodlust
spellId = 57724; // Sated
else if (m_spellInfo->Id == 32182) // Heroism
spellId = 57723; // Exhaustion
break;
}
default:
break;
}
if (spellId)
{
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
{
Unit* unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
if (unit)
{
// TODO: fix me use cast spell (now post spell can immune by this spell)
// m_caster->CastSpell(unit, spellId, true, m_CastItem);
SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
if (!AdditionalSpellInfo)
continue;
Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unit, m_caster, m_CastItem);
unit->AddAura(AdditionalAura);
}
}
}
}
// call triggered spell only at successful cast (after clear combo points -> for add some if need)
if(!m_TriggerSpells.empty())
TriggerSpell();
@ -2892,6 +2880,7 @@ void Spell::SendSpellGo()
}
WorldPacket data(SMSG_SPELL_GO, 50); // guess size
if(m_CastItem)
data.append(m_CastItem->GetPackGUID());
else
@ -2989,6 +2978,8 @@ void Spell::WriteAmmoToPacket( WorldPacket * data )
void Spell::WriteSpellGoTargets( WorldPacket * data )
{
// This function also fill data for channeled spells:
// m_needAliveTargetMask req for stop channelig if one target die
uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO
uint32 miss = 0;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
@ -3008,7 +2999,10 @@ void Spell::WriteSpellGoTargets( WorldPacket * data )
*data << (uint8)hit;
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits
{
*data << uint64(ihit->targetGUID);
m_needAliveTargetMask |=ihit->effectMask;
}
for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit)
*data << uint64(ighit->targetGUID); // Always hits
@ -3024,6 +3018,9 @@ void Spell::WriteSpellGoTargets( WorldPacket * data )
*data << uint8(ihit->reflectResult);
}
}
// Reset m_needAliveTargetMask for non channeled spell
if(!IsChanneledSpell(m_spellInfo))
m_needAliveTargetMask = 0;
}
void Spell::SendLogExecute()
@ -4247,7 +4244,7 @@ uint8 Spell::CanCast(bool strict)
break;
}
// This is generic summon effect
// This is generic summon effect
case SPELL_EFFECT_SUMMON:
{
switch(m_spellInfo->EffectMiscValueB[i])
@ -4421,8 +4418,7 @@ uint8 Spell::CanCast(bool strict)
// not allow cast fly spells at old maps by players (all spells is self target)
if(m_caster->GetTypeId()==TYPEID_PLAYER)
{
uint32 v_map = GetVirtualMapForMapAndZone(m_caster->GetMapId(), m_caster->GetZoneId());
if( !((Player*)m_caster)->isGameMaster() && v_map != 530 && !(v_map == 571 && ((Player*)m_caster)->HasSpell(54197)))
if( !((Player*)m_caster)->IsAllowUseFlyMountsHere() )
return SPELL_FAILED_NOT_HERE;
}
@ -5407,7 +5403,13 @@ bool Spell::CheckTarget( Unit* target, uint32 eff )
// all ok by some way or another, skip normal check
break;
default: // normal case
if(target!=m_caster && !target->IsWithinLOSInMap(m_caster))
// Get GO cast coordinates if original caster -> GO
WorldObject *caster = NULL;
if (m_originalCasterGUID)
caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID);
if (!caster)
caster = m_caster;
if(target!=m_caster && !target->IsWithinLOSInMap(caster))
return false;
break;
}

View file

@ -150,6 +150,7 @@ class SpellCastTargets
Unit *getUnitTarget() const { return m_unitTarget; }
void setUnitTarget(Unit *target);
void setDestination(float x, float y, float z);
void setSource(float x, float y, float z);
uint64 getGOTargetGUID() const { return m_GOTargetGUID; }
GameObject *getGOTarget() const { return m_GOTarget; }
@ -290,6 +291,7 @@ class Spell
void EffectCharge(uint32 i);
void EffectProspecting(uint32 i);
void EffectMilling(uint32 i);
void EffectRenamePet(uint32 i);
void EffectSendTaxi(uint32 i);
void EffectSummonCritter(uint32 i);
void EffectKnockBack(uint32 i);
@ -387,6 +389,7 @@ class Spell
Item* m_CastItem;
uint8 m_cast_count;
uint32 m_glyphIndex;
uint32 m_preCastSpell;
SpellCastTargets m_targets;
int32 GetCastTime() const { return m_casttime; }

View file

@ -237,7 +237,7 @@ enum AuraType
SPELL_AURA_HASTE_MELEE = 192,
SPELL_AURA_MELEE_SLOW = 193,
SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194,
SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT
SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL = 195,
SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath
SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197,
SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198,
@ -269,7 +269,7 @@ enum AuraType
SPELL_AURA_224 = 224,
SPELL_AURA_PRAYER_OF_MENDING = 225,
SPELL_AURA_PERIODIC_DUMMY = 226,
SPELL_AURA_227 = 227,
SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227,
SPELL_AURA_DETECT_STEALTH = 228,
SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229,
SPELL_AURA_230 = 230,
@ -309,10 +309,10 @@ enum AuraType
SPELL_AURA_264 = 264,
SPELL_AURA_265 = 265,
SPELL_AURA_266 = 266,
SPELL_AURA_267 = 267,
SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267,
SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268,
SPELL_AURA_269 = 269,
SPELL_AURA_270 = 270,
SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive
SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271,
SPELL_AURA_272 = 272,
SPELL_AURA_273 = 273,

View file

@ -112,7 +112,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
&Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
&Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
&Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete?
&Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
&Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED
@ -245,7 +245,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
&Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
&Aura::HandleUnused, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL
&Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
&Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage
&Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
&Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
&Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
@ -277,7 +277,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleUnused, //224 unused
&Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
&Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
&Aura::HandleNULL, //227 periodic trigger spell
&Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
&Aura::HandleNoImmediateEffect, //228 stealth detection
&Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
&Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
@ -305,7 +305,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNULL, //252 haste all?
&Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE
&Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield
&Aura::HandleNULL, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT
&Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus
&Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
&Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
&Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
@ -317,10 +317,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNULL, //264 unused
&Aura::HandleNULL, //265 unused
&Aura::HandleNULL, //266 unused
&Aura::HandleNULL, //267 some immunity?
&Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
&Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
&Aura::HandleNULL, //269 ignore DR effects?
&Aura::HandleNULL, //270
&Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST
&Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&Aura::HandleNULL, //272 reduce spell cast time?
&Aura::HandleNULL, //273
@ -340,7 +340,7 @@ Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, U
m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target),
m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),
m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_isPersistent(false),
m_positive(false), m_permanent(false), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false),
m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
{
assert(target);
@ -405,14 +405,19 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
m_duration = m_maxduration;
if(modOwner)
modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
m_effIndex = eff;
SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
// Apply periodic time mod
if(modOwner && m_modifier.periodictime)
modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_modifier.periodictime);
// Start periodic on next tick or at aura apply
if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
m_periodicTimer += m_modifier.periodictime;
m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
m_procCharges = m_spellProto->procCharges;
@ -606,25 +611,11 @@ void Aura::Update(uint32 diff)
if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
{
m_periodicTimer -= diff;
if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
{
if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
// Cannibalize, eating items and other spells
m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
// Eating items and other spells
m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
{
ApplyModifier(true);
return;
}
// update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
m_periodicTimer += m_modifier.periodictime;
if(m_isTrigger)
TriggerSpell();
else
PeriodicTick();
PeriodicTick();
}
}
}
@ -927,19 +918,6 @@ void Aura::_AddAura()
}
}
}
// not call total regen auras at adding
switch (m_modifier.m_auraname)
{
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_OBS_MOD_MANA:
m_periodicTimer = m_modifier.periodictime;
break;
case SPELL_AURA_MOD_REGEN:
case SPELL_AURA_MOD_POWER_REGEN:
case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
m_periodicTimer = 5000;
break;
}
Unit* caster = GetCaster();
@ -963,6 +941,10 @@ void Aura::_AddAura()
//*****************************************************
if (!secondaura)
{
// Sitdown on apply aura req seated
if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState())
m_target->SetStandState(PLAYER_STATE_SIT);
// register aura diminishing on apply
if (getDiminishGroup() != DIMINISHING_NONE )
m_target->ApplyDiminishingAura(getDiminishGroup(),true);
@ -974,7 +956,7 @@ void Aura::_AddAura()
// Conflagrate aura state on Immolate
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags & 4)
m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
// Faerie Fire (druid versions)
if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true);
@ -1097,7 +1079,7 @@ void Aura::_RemoveAura()
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags )
{
found = true;
@ -1317,6 +1299,7 @@ void Aura::HandleAddTargetTrigger(bool apply, bool Real)
m_spellmod = NULL;
}
}
void Aura::TriggerSpell()
{
Unit* caster = GetCaster();
@ -1328,8 +1311,6 @@ void Aura::TriggerSpell()
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
uint64 originalCasterGUID = GetCasterGUID();
SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
SpellEntry const *auraSpellInfo = GetSpellProto();
uint32 auraId = auraSpellInfo->Id;
@ -1983,28 +1964,33 @@ void Aura::TriggerSpell()
return;
caster = target;
originalCasterGUID = 0;
break;
}
// Mana Tide
case 16191:
{
caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this);
return;
}
}
}
// All ok cast by default case
Spell *spell = new Spell(caster, triggeredSpellInfo, true, originalCasterGUID );
caster->CastSpell(target, triggeredSpellInfo, true, 0, this);
}
SpellCastTargets targets;
targets.setUnitTarget( target );
void Aura::TriggerSpellWithValue()
{
Unit* caster = GetCaster();
Unit* target = GetTriggerTarget();
// if spell create dynamic object extract area from it
if(DynamicObject* dynObj = caster->GetDynObject(GetId()))
targets.setDestination(dynObj->GetPositionX(),dynObj->GetPositionY(),dynObj->GetPositionZ());
if(!caster || !target)
return;
spell->prepare(&targets, this);
// generic casting code with custom spells and target/caster customs
uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
int32 basepoints0 = this->GetModifier()->m_amount;
caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this);
}
/*********************************************************/
@ -2146,14 +2132,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
if (caster && m_removeMode == AURA_REMOVE_BY_DEATH)
{
// Stop caster Arcane Missle chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE &&
m_spellProto->SpellFamilyFlags&0x0000000000000800LL)
{
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}
// Stop caster Penance chanelling on death
if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST &&
m_spellProto->SpellFamilyFlags2 & 0x00000080)
{
caster->InterruptSpell(CURRENT_CHANNELED_SPELL);
@ -2365,54 +2351,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
}
void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
Unit* caster = GetCaster();
SpellEntry const*spell = GetSpellProto();
switch( spell->SpellFamilyName)
{
case SPELLFAMILY_ROGUE:
{
// Master of Subtlety
if (spell->Id==31666 && !apply && Real)
{
m_target->RemoveAurasDueToSpell(31665);
break;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Aspect of the Viper
if (spell->SpellFamilyFlags&0x0004000000000000LL)
{
// Update regen on remove
if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
((Player*)m_target)->UpdateManaRegen();
break;
}
// Explosive Shot
if (spell->SpellFamilyFlags & 0x8000000000000000LL)
{
if (apply && caster)
{
int32 damage = m_modifier.m_amount + caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
}
break;
}
break;
}
}
m_isPeriodic = apply;
}
void Aura::HandleAuraMounted(bool apply, bool Real)
{
// only at real add/remove aura
@ -4066,26 +4004,71 @@ void Aura::HandleAuraModStalked(bool apply, bool Real)
void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
m_isTrigger = apply;
}
void Aura::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandlePeriodicEnergize(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
if (!Real)
return;
m_isPeriodic = apply;
// Replenishment (0.25% from max)
// Infinite Replenishment
if (GetId() == 57669 ||
GetId() == 61782)
m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000;
}
void Aura::HandleAuraPowerBurn(bool apply, bool Real)
{
m_isPeriodic = apply;
}
void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
{
// spells required only Real aura add/remove
if(!Real)
return;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
Unit* caster = GetCaster();
SpellEntry const*spell = GetSpellProto();
switch( spell->SpellFamilyName)
{
case SPELLFAMILY_ROGUE:
{
// Master of Subtlety
if (spell->Id==31666 && !apply)
{
m_target->RemoveAurasDueToSpell(31665);
break;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Explosive Shot
if (apply && !loading && caster)
m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
break;
}
}
m_isPeriodic = apply;
}
void Aura::HandlePeriodicHeal(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
// For prevent double apply bonuses
@ -4129,18 +4112,17 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
if(!Real)
return;
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
// For prevent double apply bonuses
bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
Unit *caster = GetCaster();
// Custom damage calculation after
if (!apply || loading || !caster)
if (!apply || loading)
return;
Unit *caster = GetCaster();
if (!caster)
return;
switch (m_spellProto->SpellFamilyName)
@ -4315,25 +4297,21 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandlePeriodicLeech(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandlePeriodicHealthFunnel(bool apply, bool Real)
{
m_isPeriodic = apply;
}
@ -4578,117 +4556,47 @@ void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real)
/********************************/
void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
{
/*
Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
so this aura not fully working.
*/
if(apply)
{
if(!m_target->isAlive())
return;
if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
m_target->SetStandState(PLAYER_STATE_SIT);
if(m_periodicTimer <= 0)
{
m_periodicTimer += m_modifier.periodictime;
if(m_target->GetHealth() < m_target->GetMaxHealth())
{
// PeriodicTick can cast triggered spells with stats changes
PeriodicTick();
}
}
}
m_isPeriodic = apply;
}
void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
{
if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
m_target->SetStandState(PLAYER_STATE_SIT);
if(apply)
{
if(m_modifier.periodictime == 0)
m_modifier.periodictime = 1000;
if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
{
m_periodicTimer += m_modifier.periodictime;
if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
{
// PeriodicTick can cast triggered spells with stats changes
PeriodicTick();
}
}
}
if(m_modifier.periodictime == 0)
m_modifier.periodictime = 1000;
m_periodicTimer = m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandleModRegen(bool apply, bool Real) // eating
{
if(apply)
{
if(!m_target->isAlive())
return;
if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
m_target->SetStandState(PLAYER_STATE_SIT);
if(m_periodicTimer <= 0)
{
m_periodicTimer += 5000;
int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
Unit *caster = GetCaster();
if (caster)
{
SpellEntry const *spellProto = GetSpellProto();
if (spellProto)
m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
}
}
}
if(m_modifier.periodictime == 0)
m_modifier.periodictime = 5000;
m_periodicTimer = 5000;
m_isPeriodic = apply;
}
void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
{
if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
m_target->SetStandState(PLAYER_STATE_SIT);
if (!Real)
return;
if(apply && m_periodicTimer <= 0)
Powers pt = m_target->getPowerType();
if(m_modifier.periodictime == 0)
{
m_periodicTimer += 2000;
Powers pt = m_target->getPowerType();
if(int32(pt) != m_modifier.m_miscvalue)
return;
if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
{
// eating anim
m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
}
else if( GetId() == 20577 )
{
// cannibalize anim
m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
}
// Warrior talent, gain 1 rage every 3 seconds while in combat
if(pt == POWER_RAGE && m_target->isInCombat())
{
m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
m_periodicTimer += 1000;
}
if (pt == POWER_RAGE)
m_modifier.periodictime = 1000;
else
m_modifier.periodictime = 2000;
}
m_isPeriodic = apply;
if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
m_periodicTimer = 5000;
if (m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
((Player*)m_target)->UpdateManaRegen();
m_isPeriodic = apply;
}
void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real)
@ -5263,6 +5171,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
break;
case FORM_TREE:
spellId = 5420;
spellId2 = 34123;
break;
case FORM_TRAVEL:
spellId = 5419;
@ -5603,14 +5512,6 @@ void Aura::CleanupTriggeredSpells()
m_target->RemoveAurasDueToSpell(tSpellId);
}
void Aura::HandleAuraPowerBurn(bool apply, bool Real)
{
if (m_periodicTimer <= 0)
m_periodicTimer += m_modifier.periodictime;
m_isPeriodic = apply;
}
void Aura::HandleSchoolAbsorb(bool apply, bool Real)
{
if(!Real)
@ -5792,6 +5693,7 @@ void Aura::PeriodicTick()
break;
}
case SPELL_AURA_PERIODIC_LEECH:
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
{
Unit *pCaster = GetCaster();
if(!pCaster)
@ -5804,7 +5706,7 @@ void Aura::PeriodicTick()
pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
return;
// Check for immune (not use charges)
// Check for immune
if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
return;
@ -6188,12 +6090,51 @@ void Aura::PeriodicTick()
pCaster->DealSpellDamage(&damageInfo, true);
break;
}
case SPELL_AURA_MOD_REGEN:
{
int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
if (Unit *caster = GetCaster())
m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_MOD_POWER_REGEN:
{
Powers pt = m_target->getPowerType();
if(int32(pt) != m_modifier.m_miscvalue)
return;
if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
{
// eating anim
m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
}
else if( GetId() == 20577 )
{
// cannibalize anim
m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE);
}
// Warrior talent, gain 1 rage every 3 seconds while in combat
if(pt == POWER_RAGE && m_target->isInCombat())
m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
break;
}
// Here tick dummy auras
case SPELL_AURA_PERIODIC_DUMMY:
{
PeriodicDummyTick();
break;
}
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
{
TriggerSpell();
break;
}
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
{
TriggerSpellWithValue();
break;
}
default:
break;
}
@ -6232,47 +6173,11 @@ void Aura::PeriodicDummyTick()
{
if ((*i)->GetId() == GetId())
{
// Get tick number
int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
// Default case (not on arenas)
if (tick == 0)
{
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
// Disable continue
m_isPeriodic = false;
}
return;
//**********************************************
// Code commended since arena patch not added
// This feature uses only in arenas
//**********************************************
// Here need increase mana regen per tick (6 second rule)
// on 0 tick - 0 (handled in 2 second)
// on 1 tick - 166% (handled in 4 second)
// on 2 tick - 133% (handled in 6 second)
// Not need update after 3 tick
/*
if (tick > 3)
return;
// Apply bonus for 0 - 3 tick
switch (tick)
{
case 0: // 0%
(*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
break;
case 1: // 166%
(*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
break;
case 2: // 133%
(*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
break;
default: // 100% - normal regen
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
break;
}
(*i)->GetModifier()->m_amount = m_modifier.m_amount;
((Player*)m_target)->UpdateManaRegen();
return;*/
// Disable continue
m_isPeriodic = false;
return;
}
}
return;
@ -6304,29 +6209,6 @@ void Aura::PeriodicDummyTick()
// case 33208: break;
// // Gossip NPC Periodic - Despawn
// case 33209: break;
// TODO: now its not periodic dummy - need move out from here
// Aspect of the Viper
case 34074:
{
if (m_target->GetTypeId() != TYPEID_PLAYER)
return;
// Should be manauser
if (m_target->getPowerType()!=POWER_MANA)
return;
if (!caster)
return;
// Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
int mana = m_target->GetPower(POWER_MANA);
int max_mana = m_target->GetMaxPower(POWER_MANA);
int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
float regen_pct = 1.20f - 1.1f * mana / max_mana;
if (regen_pct > 1.0f) regen_pct = 1.0f;
else if (regen_pct < 0.2f) regen_pct = 0.2f;
m_modifier.m_amount = int32 (base_regen * regen_pct);
((Player*)m_target)->UpdateManaRegen();
return;
}
// // Steal Weapon
// case 36207: break;
// // Simon Game START timer, (DND)
@ -6552,11 +6434,13 @@ void Aura::PeriodicDummyTick()
{
if (!caster)
return;
// Skip 0 tick
int32 damage = m_modifier.m_amount;
// Full damage to target at 0 tick
if (m_duration > m_modifier.periodictime)
{
caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this);
return;
int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target);
damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100;
}
damage/=4;
caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this);
return;

View file

@ -110,6 +110,7 @@ class MANGOS_DLL_SPEC Aura
void HandleAuraModRegenInterrupt(bool Apply, bool Real);
void HandleHaste(bool Apply, bool Real);
void HandlePeriodicTriggerSpell(bool Apply, bool Real);
void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real);
void HandlePeriodicEnergize(bool Apply, bool Real);
void HandleAuraModResistanceExclusive(bool Apply, bool Real);
void HandleAuraModPetTalentsPoints(bool Apply, bool Real);
@ -147,6 +148,7 @@ class MANGOS_DLL_SPEC Aura
void HandleModSpellHitChance(bool Apply, bool Real);
void HandleAuraModScale(bool Apply, bool Real);
void HandlePeriodicManaLeech(bool Apply, bool Real);
void HandlePeriodicHealthFunnel(bool apply, bool Real);
void HandleModCastingSpeed(bool Apply, bool Real);
void HandleAuraMounted(bool Apply, bool Real);
void HandleWaterBreathing(bool Apply, bool Real);
@ -257,7 +259,7 @@ class MANGOS_DLL_SPEC Aura
uint8 GetAuraLevel() const { return m_auraLevel; }
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
uint8 GetAuraCharges() const { return m_procCharges; }
void SetAuraCharges(uint8 charges)
void SetAuraCharges(uint8 charges)
{
if (m_procCharges == charges)
return;
@ -265,7 +267,7 @@ class MANGOS_DLL_SPEC Aura
SendAuraUpdate(false);
}
bool DropAuraCharge() // return true if last charge dropped
{
{
if (m_procCharges == 0)
return false;
m_procCharges--;
@ -288,7 +290,6 @@ class MANGOS_DLL_SPEC Aura
bool IsPermanent() const { return m_permanent; }
bool IsAreaAura() const { return m_isAreaAura; }
bool IsPeriodic() const { return m_isPeriodic; }
bool IsTrigger() const { return m_isTrigger; }
bool IsPassive() const { return m_isPassive; }
bool IsPersistent() const { return m_isPersistent; }
bool IsDeathPersistent() const { return m_isDeathPersist; }
@ -315,6 +316,7 @@ class MANGOS_DLL_SPEC Aura
DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; }
void TriggerSpell();
void TriggerSpellWithValue();
void PeriodicTick();
void PeriodicDummyTick();
@ -351,7 +353,6 @@ class MANGOS_DLL_SPEC Aura
bool m_positive:1;
bool m_permanent:1;
bool m_isPeriodic:1;
bool m_isTrigger:1;
bool m_isAreaAura:1;
bool m_isPassive:1;
bool m_isPersistent:1;

View file

@ -146,7 +146,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
&Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
&Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
&Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
&Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
&Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
&Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
&Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
@ -215,9 +215,9 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //154 unused
&Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
&Spell::EffectNULL, //156 Add Socket
&Spell::EffectCreateItem, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
&Spell::EffectMilling, //158 milling
&Spell::EffectNULL //159 allow rename pet once again
&Spell::EffectCreateItem, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession
&Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
&Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
};
void Spell::EffectNULL(uint32 /*i*/)
@ -493,7 +493,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
// Lookup for Deadly poison (only attacker applied)
Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE &&
(*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000 &&
(*itr)->GetCasterGUID()==m_caster->GetGUID() )
{
@ -928,7 +928,7 @@ void Spell::EffectDummy(uint32 i)
{
Aura * dummy = m_caster->GetDummyAura(28734);
if (dummy)
{
{
int32 bp = damage * dummy->GetStackAmount();
m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
m_caster->RemoveAurasDueToSpell(28734);
@ -1265,7 +1265,7 @@ void Spell::EffectDummy(uint32 i)
if (Aura *aura = m_caster->GetDummyAura(58367))
rage+=aura->GetModifier()->m_amount;
int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
m_caster->SetPower(POWER_RAGE,0);
@ -1288,6 +1288,12 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
return;
}
// Bloodthirst
case 23881:
{
m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL);
return;
}
}
break;
case SPELLFAMILY_WARLOCK:
@ -1398,16 +1404,6 @@ void Spell::EffectDummy(uint32 i)
}
break;
case SPELLFAMILY_DRUID:
switch(m_spellInfo->Id )
{
case 5420: // Tree of Life passive
{
// Tree of Life area effect
int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
return;
}
}
break;
case SPELLFAMILY_ROGUE:
switch(m_spellInfo->Id )
@ -1754,7 +1750,7 @@ void Spell::EffectDummy(uint32 i)
Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
{
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN &&
(*itr)->GetSpellProto()->SpellFamilyFlags & 0x0000000000200000LL &&
(*itr)->GetCastItemGUID() == item->GetGUID())
{
@ -2218,7 +2214,7 @@ void Spell::EffectApplyAura(uint32 i)
(unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
return;
Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
Unit* caster = m_originalCaster ? m_originalCaster : m_caster;
if(!caster)
return;
@ -3345,7 +3341,7 @@ void Spell::EffectLearnSpell(uint32 i)
Player *player = (Player*)unitTarget;
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);
player->learnSpell(spellToLearn,false);
sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
}
@ -4285,8 +4281,8 @@ void Spell::EffectWeaponDmg(uint32 i)
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
spellInfo->SpellFamilyFlags & 0x0000000000004000LL &&
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
{
(*itr).second->RefreshAura();
@ -4866,7 +4862,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
// learn random explicit discovery recipe (if any)
if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player))
player->learnSpell(discoveredSpell);
player->learnSpell(discoveredSpell,false);
return;
}
}
@ -5926,6 +5922,12 @@ void Spell::EffectSendTaxi(uint32 i)
case 34905: //Stealth Flight
mountid = 6851;
break;
case 45883: //Amber Ledge to Beryl Point
mountid = 23524;
break;
case 46064: //Amber Ledge to Coldarra
mountid = 6371;
break;
case 53335: //Stormwind Harbor Flight - Peaceful
mountid = 6852;
break;
@ -6426,7 +6428,7 @@ void Spell::EffectQuestFail(uint32 i)
((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
}
void Spell::EffectActivateRune(uint32 i)
void Spell::EffectActivateRune(uint32 eff_idx)
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
@ -6438,15 +6440,24 @@ void Spell::EffectActivateRune(uint32 i)
for(uint32 j = 0; j < MAX_RUNES; ++j)
{
if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[i])
if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
{
plr->SetRuneCooldown(j, 0);
}
}
}
void Spell::EffectTitanGrip(uint32 i)
void Spell::EffectTitanGrip(uint32 /*eff_idx*/)
{
if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
((Player*)unitTarget)->SetCanTitanGrip(true);
}
void Spell::EffectRenamePet(uint32 /*eff_idx*/)
{
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT ||
!((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET)
return;
unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
}

View file

@ -261,8 +261,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
// not have spell or spell passive and not casted by client
if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) )
// not have spell in spellbook or spell passive and not casted by client
if ( !_player->HasActiveSpell (spellId) || IsPassiveSpell(spellId) )
{
//cheater? kick? ban?
return;
@ -357,7 +357,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
return;
}
Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid);
Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid);
if(!pet)
{

View file

@ -172,7 +172,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
// only hunter aspects have this (but not all aspects in hunter family)
if( spellInfo->SpellFamilyFlags & 0x0044000000380000LL || spellInfo->SpellFamilyFlags2 & 0x00003010)
return SPELL_ASPECT;
if( spellInfo->SpellFamilyFlags2 & 0x00000002 )
return SPELL_TRACKER;
@ -273,7 +273,7 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB)
case TARGET_CURRENT_ENEMY_COORDINATES:
case TARGET_SINGLE_ENEMY:
return false;
case TARGET_ALL_AROUND_CASTER:
case TARGET_CASTER_COORDINATES:
return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER);
default:
break;
@ -736,7 +736,7 @@ void SpellMgr::LoadSpellAffects()
case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
default:
default:
continue;
}
if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2])
@ -776,7 +776,7 @@ void SpellMgr::LoadSpellAffects()
case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
default:
default:
continue;
}
if(ptr[0] || ptr[1] || ptr[2])
@ -1016,28 +1016,38 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI
bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{
if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell
return false;
if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
return false;
if(IsProfessionOrRidingSpell(spellInfo->Id))
return false;
if(spellmgr.IsSkillBonusSpell(spellInfo->Id))
return false;
// All stance spells. if any better way, change it.
for (int i = 0; i < 3; i++)
{
// Paladin aura Spell
if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
&& spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID)
return false;
// Druid form Spell
if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
&& spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
&& spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
return false;
// Rogue Stealth
if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
&& spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
&& spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
return false;
switch(spellInfo->SpellFamilyName)
{
case SPELLFAMILY_PALADIN:
// Paladin aura Spell
if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID)
return false;
break;
case SPELLFAMILY_DRUID:
// Druid form Spell
if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA &&
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
return false;
break;
case SPELLFAMILY_ROGUE:
// Rogue Stealth
if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA &&
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
return false;
}
}
return true;
}
@ -1450,6 +1460,24 @@ bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
}
bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const
{
SkillLineAbilityMap::const_iterator lower = GetBeginSkillLineAbilityMap(spellId);
SkillLineAbilityMap::const_iterator upper = GetEndSkillLineAbilityMap(spellId);
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{
SkillLineAbilityEntry const *pAbility = _spell_idx->second;
if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL)
continue;
if(pAbility->req_skill_value > 0)
return true;
}
return false;
}
SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
{
// ignore passive spells
@ -1667,8 +1695,10 @@ void SpellMgr::LoadSpellLearnSkills()
// search auto-learned skills and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0;
barGoLink bar( sSpellStore.GetNumRows() );
for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
{
bar.step();
SpellEntry const* entry = sSpellStore.LookupEntry(spell);
if(!entry)
@ -2358,10 +2388,12 @@ void SpellMgr::LoadSkillLineAbilityMap()
{
mSkillLineAbilityMap.clear();
barGoLink bar( sSkillLineAbilityStore.GetNumRows() );
uint32 count = 0;
for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
{
bar.step();
SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
if(!SkillInfo)
continue;
@ -2371,7 +2403,7 @@ void SpellMgr::LoadSkillLineAbilityMap()
}
sLog.outString();
sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count);
sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count);
}
DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered)

View file

@ -367,7 +367,6 @@ inline bool IsAreaEffectTarget( Targets target )
case TARGET_ALL_ENEMY_IN_AREA:
case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
case TARGET_ALL_PARTY_AROUND_CASTER:
case TARGET_ALL_AROUND_CASTER:
case TARGET_IN_FRONT_OF_CASTER:
case TARGET_ALL_ENEMY_IN_AREA_CHANNELED:
case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
@ -898,6 +897,9 @@ class SpellMgr
static bool IsPrimaryProfessionSpell(uint32 spellId);
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const;
bool IsSkillBonusSpell(uint32 spellId) const;
// Spell script targets
SpellScriptTarget::const_iterator GetBeginSpellScriptTarget(uint32 spell_id) const
{

View file

@ -1090,8 +1090,21 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
// Calculate absorb resist
if(damage > 0)
{
CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
damage-= damageInfo->absorb + damageInfo->resist;
// lookup absorb/resist ignore auras on caster for spell
bool ignore = false;
Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL);
for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i)
if ((*i)->isAffectedOnSpell(spellInfo))
{
ignore = true;
break;
}
if (!ignore)
{
CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
damage-= damageInfo->absorb + damageInfo->resist;
}
}
else
damage = 0;
@ -1820,7 +1833,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
// Remove all expired absorb auras
if (existExpired)
{
for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end();)
for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();)
{
if ((*i)->GetModifier()->m_amount<=0)
{
@ -2386,7 +2399,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
// Can`t dodge from behind in PvP (but its possible in PvE)
if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
canDodge = false;
// Can`t parry
// Can`t parry
canParry = false;
}
// Check creatures flags_extra for disable parry
@ -4731,7 +4744,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetSpellProto();
if( spell->Mechanic == MECHANIC_STUN ||
if( spell->Mechanic == MECHANIC_STUN ||
spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
{
pVictim->RemoveAurasDueToSpell(spell->Id);
@ -5294,7 +5307,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
// Rapid Recuperation
if ( dummySpell->SpellIconID == 3560 )
{
// mane regen from Rapid Killing
// This effect only from Rapid Killing (mana regen)
if (!(procSpell->SpellFamilyFlags & 0x0100000000000000LL))
return false;
triggered_spell_id = 56654;
target = this;
break;
@ -5320,6 +5335,22 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
// Righteous Vengeance
if (dummySpell->SpellIconID == 3025)
{
// 4 damage tick
basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/400;
triggered_spell_id = 61840;
break;
}
// Sheath of Light
if (dummySpell->SpellIconID == 3030)
{
// 4 healing tick
basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/400;
triggered_spell_id = 54203;
break;
}
switch(dummySpell->Id)
{
// Judgement of Light
@ -5824,7 +5855,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
// Mark of Blood
if (dummySpell->Id == 49005)
{
// TODO: need more info (cooldowns/PPM)
// TODO: need more info (cooldowns/PPM)
triggered_spell_id = 50424;
break;
}
@ -6481,6 +6512,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false;
break;
}
// Rapid Recuperation
case 53228:
case 53232:
{
// This effect only from Rapid Fire (ability cast)
if (!(procSpell->SpellFamilyFlags & 0x0000000000000020LL))
return false;
break;
}
}
// Costum basepoints/target for exist spell
@ -6510,11 +6550,16 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Need add combopoint AFTER finish movie (or they dropped in finish phase)
break;
}
// Bloodthirst (($m/100)% of max health)
case 23880:
{
basepoints0 = int32(GetMaxHealth() * triggerAmount / 10000);
break;
}
// Shamanistic Rage triggered spell
case 30824:
{
basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
trigger_spell_id = 30824;
break;
}
// Enlightenment (trigger only from mana cost spells)
@ -7474,6 +7519,16 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto))
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
// Mod damage from spell mechanic
uint32 mechanicMask = GetAllSpellMechanicMask(spellProto);
if (mechanicMask)
{
AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue)))
TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
// Distribute Damage over multiple effects, reduce by AoE
CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
@ -7819,7 +7874,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
}
// Glyph of Shadowburn
if (spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK &&
spellProto->SpellFamilyFlags & 0x0000000000000080LL &&
spellProto->SpellFamilyFlags & 0x0000000000000080LL &&
pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
{
AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
@ -8204,6 +8259,13 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con
for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
if(itr->type == aura)
return true;
// Check for immune to application of harmful magical effects
AuraList const& immuneAuraApply = GetAurasByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
for(AuraList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff
((*iter)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellInfo)) && // Check school
!IsPositiveEffect(spellInfo->Id, index)) // Harmful
return true;
}
return false;
@ -9292,6 +9354,8 @@ bool Unit::SelectHostilTarget()
assert(GetTypeId()== TYPEID_UNIT);
if (!this->isAlive())
return false;
//This function only useful once AI has been initialized
if (!((Creature*)this)->AI())
return false;

View file

@ -650,7 +650,7 @@ struct UnitActionBarEntry
union
{
struct
struct
{
uint16 SpellOrAction;
uint16 Type;

View file

@ -57,97 +57,105 @@ void WaypointManager::Load()
uint32 total_behaviors = 0;
QueryResult *result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id");
if(result)
if(!result)
{
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outString( ">> Loaded 0 paths. DB table `creature_movement` is empty." );
return;
} else {
total_paths = result->GetRowCount();
barGoLink bar( total_paths );
do
{
bar.step();
Field *fields = result->Fetch();
uint32 id = fields[0].GetUInt32();
uint32 count = fields[1].GetUInt32();
m_pathMap[id].resize(count);
total_nodes += count;
bar.step();
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Paths loaded" );
}
result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id, point FROM creature_movement");
if(result)
barGoLink bar( result->GetRowCount() );
do
{
barGoLink bar( result->GetRowCount() );
do
bar.step();
Field *fields = result->Fetch();
uint32 point = fields[15].GetUInt32();
uint32 id = fields[14].GetUInt32();
WaypointPath &path = m_pathMap[id];
// the cleanup queries make sure the following is true
assert(point >= 1 && point <= path.size());
WaypointNode &node = path[point-1];
node.x = fields[0].GetFloat();
node.y = fields[1].GetFloat();
node.z = fields[2].GetFloat();
node.orientation = fields[3].GetFloat();
node.delay = fields[6].GetUInt16();
// prevent using invalid coordinates
if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation))
{
Field *fields = result->Fetch();
uint32 point = fields[15].GetUInt32();
uint32 id = fields[14].GetUInt32();
WaypointPath &path = m_pathMap[id];
// the cleanup queries make sure the following is true
assert(point >= 1 && point <= path.size());
WaypointNode &node = path[point-1];
node.x = fields[0].GetFloat();
node.y = fields[1].GetFloat();
node.z = fields[2].GetFloat();
node.orientation = fields[3].GetFloat();
node.delay = fields[6].GetUInt16();
// prevent using invalid coordinates
if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation))
{
QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id);
if(result1)
sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y);
else
sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
id, point, node.x, node.y);
MaNGOS::NormalizeMapCoord(node.x);
MaNGOS::NormalizeMapCoord(node.y);
if(result1)
{
node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z);
delete result1;
}
WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point);
}
WaypointBehavior be;
be.model1 = fields[4].GetUInt32();
be.model2 = fields[5].GetUInt32();
be.emote = fields[7].GetUInt32();
be.spell = fields[8].GetUInt32();
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
{
be.textid[i] = fields[9+i].GetUInt32();
if(be.textid[i])
{
if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID)
{
sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[i]);
continue;
}
}
}
// save memory by not storing empty behaviors
if(!be.isEmpty())
{
node.behavior = new WaypointBehavior(be);
++total_behaviors;
}
QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id);
if(result1)
sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y);
else
node.behavior = NULL;
bar.step();
} while( result->NextRow() );
delete result;
}
sLog.outString( ">> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors);
sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
id, point, node.x, node.y);
MaNGOS::NormalizeMapCoord(node.x);
MaNGOS::NormalizeMapCoord(node.y);
if(result1)
{
node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z);
delete result1;
}
WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point);
}
WaypointBehavior be;
be.model1 = fields[4].GetUInt32();
be.model2 = fields[5].GetUInt32();
be.emote = fields[7].GetUInt32();
be.spell = fields[8].GetUInt32();
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
{
be.textid[i] = fields[9+i].GetUInt32();
if(be.textid[i])
{
if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID)
{
sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[i]);
continue;
}
}
}
// save memory by not storing empty behaviors
if(!be.isEmpty())
{
node.behavior = new WaypointBehavior(be);
++total_behaviors;
}
else
node.behavior = NULL;
} while( result->NextRow() );
delete result;
sLog.outString();
sLog.outString( ">> Waypoints and behaviors loaded" );
sLog.outString();
sLog.outString( ">>> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors);
}
void WaypointManager::Cleanup()

View file

@ -799,6 +799,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
}
m_configs[CONFIG_GM_LOWER_SECURITY] = sConfig.GetBoolDefault("GM.LowerSecurity", false);
m_configs[CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS] = sConfig.GetBoolDefault("GM.AllowAchievementGain", true);
m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0);
@ -1069,7 +1070,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Script Names...");
objmgr.LoadScriptNames();
sLog.outString( "Loading InstanceTemplate" );
sLog.outString( "Loading InstanceTemplate..." );
objmgr.LoadInstanceTemplate();
sLog.outString( "Loading SkillLineAbilityMultiMap Data..." );
@ -1082,6 +1083,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Packing instances..." );
sInstanceSaveManager.PackInstances();
sLog.outString();
sLog.outString( "Loading Localization strings..." );
objmgr.LoadCreatureLocales();
objmgr.LoadGameObjectLocales();
@ -1091,6 +1093,8 @@ void World::SetInitialWorldSettings()
objmgr.LoadPageTextLocales();
objmgr.LoadNpcOptionLocales();
objmgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
sLog.outString( ">>> Localization strings loaded" );
sLog.outString();
sLog.outString( "Loading Page Texts..." );
objmgr.LoadPageTexts();
@ -1150,7 +1154,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadCreatures();
sLog.outString( "Loading Creature Addon Data..." );
sLog.outString();
objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
sLog.outString( ">>> Creature Addon Data loaded" );
sLog.outString();
sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances()
objmgr.LoadCreatureRespawnTimes();
@ -1162,7 +1169,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadGameobjectRespawnTimes();
sLog.outString( "Loading Game Event Data...");
sLog.outString();
gameeventmgr.LoadFromDB();
sLog.outString( ">>> Game Event Data loaded" );
sLog.outString();
sLog.outString( "Loading Weather Data..." );
objmgr.LoadWeatherZoneChances();
@ -1171,7 +1181,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
sLog.outString( "Loading Quests Relations..." );
sLog.outString();
objmgr.LoadQuestRelations(); // must be after quest load
sLog.outString( ">>> Quests Relations loaded" );
sLog.outString();
sLog.outString( "Loading AreaTrigger definitions..." );
objmgr.LoadAreaTriggerTeleports(); // must be after item template load
@ -1200,8 +1213,11 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading pet levelup spells..." );
spellmgr.LoadPetLevelupSpellMap();
sLog.outString( "Loading player Create Info & Level Stats..." );
sLog.outString( "Loading Player Create Info & Level Stats..." );
sLog.outString();
objmgr.LoadPlayerInfo();
sLog.outString( ">>> Player Create Info & Level Stats loaded" );
sLog.outString();
sLog.outString( "Loading Exploration BaseXP Data..." );
objmgr.LoadExplorationBaseXP();
@ -1219,7 +1235,10 @@ void World::SetInitialWorldSettings()
objmgr.LoadCorpses();
sLog.outString( "Loading Loot Tables..." );
sLog.outString();
LoadLootTables();
sLog.outString( ">>> Loot Tables loaded" );
sLog.outString();
sLog.outString( "Loading Skill Discovery Table..." );
LoadSkillDiscoveryTable();
@ -1230,22 +1249,22 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Skill Fishing base level requirements..." );
objmgr.LoadFishingBaseSkillLevel();
sLog.outString( "Loading AchievementCriteriaList..." );
sLog.outString( "Loading Achievements..." );
sLog.outString();
achievementmgr.LoadAchievementCriteriaList();
sLog.outString( "Loading achievement rewards..." );
achievementmgr.LoadRewards();
sLog.outString( "Loading achievement reward locale strings..." );
achievementmgr.LoadRewardLocales();
sLog.outString( "Loading completed achievements..." );
achievementmgr.LoadCompletedAchievements();
sLog.outString( ">>> Achievements loaded" );
sLog.outString();
///- Load dynamic data tables from the database
sLog.outString( "Loading Auctions..." );
sLog.outString();
objmgr.LoadAuctionItems();
objmgr.LoadAuctions();
sLog.outString( ">>> Auctions loaded" );
sLog.outString();
sLog.outString( "Loading Guilds..." );
objmgr.LoadGuilds();
@ -1259,7 +1278,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading ReservedNames..." );
objmgr.LoadReservedPlayersNames();
sLog.outString( "Loading GameObject for quests..." );
sLog.outString( "Loading GameObjects for quests..." );
objmgr.LoadGameObjectForQuests();
sLog.outString( "Loading BattleMasters..." );
@ -1274,13 +1293,14 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Npc Options..." );
objmgr.LoadNpcOptions();
sLog.outString( "Loading vendors..." );
sLog.outString( "Loading Vendors..." );
objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
sLog.outString( "Loading trainers..." );
sLog.outString( "Loading Trainers..." );
objmgr.LoadTrainerSpell(); // must be after load CreatureTemplate
sLog.outString( "Loading Waypoints..." );
sLog.outString();
WaypointMgr.Load();
sLog.outString( "Loading GM tickets...");
@ -1292,11 +1312,14 @@ void World::SetInitialWorldSettings()
///- Load and initialize scripts
sLog.outString( "Loading Scripts..." );
sLog.outString();
objmgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
objmgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
sLog.outString( ">>> Scripts loaded" );
sLog.outString();
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings();
@ -1409,6 +1432,7 @@ void World::DetectDBCLang()
m_defaultDbcLocale = LocaleConstant(default_locale);
sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
sLog.outString();
}
/// Update the World !

View file

@ -130,6 +130,7 @@ enum WorldConfigs
CONFIG_GM_LOG_TRADE,
CONFIG_START_GM_LEVEL,
CONFIG_GM_LOWER_SECURITY,
CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS,
CONFIG_GROUP_VISIBILITY,
CONFIG_MAIL_DELIVERY_DELAY,
CONFIG_UPTIME_UPDATE,

View file

@ -531,7 +531,7 @@ void WorldSession::LoadAccountData()
if(!result)
return;
do
do
{
Field *fields = result->Fetch();

View file

@ -875,17 +875,23 @@ Channel.SilentlyGMJoin = 0
# Default: 0 (disable)
# 1 (enable)
#
# GM.AllowAchievementGain
# If enabled it allows gaining achievements for GM characters
# Default: 0 (disable)
# 1 (enable) (default)
#
###################################################################################################################
GM.LoginState = 2
GM.AcceptTickets = 2
GM.Chat = 2
GM.WhisperingTo = 2
GM.InGMList = 0
GM.InWhoList = 0
GM.LogTrade = 1
GM.StartLevel = 1
GM.LowerSecurity = 0
GM.LoginState = 2
GM.AcceptTickets = 2
GM.Chat = 2
GM.WhisperingTo = 2
GM.InGMList = 0
GM.InWhoList = 0
GM.LogTrade = 1
GM.StartLevel = 1
GM.LowerSecurity = 0
GM.AllowAchievementGain = 1
###################################################################################################################
# VISIBILITY AND RADIUSES

View file

@ -138,7 +138,7 @@ int DOTCONFDocument::cleanupLine(char * line)
quoted = !quoted;
++line; continue;
}
if(isspace(*line) && !quoted){
if(isspace((unsigned char)*line) && !quoted){
*bg++ = 0;
if(strlen(start)){
@ -154,7 +154,7 @@ int DOTCONFDocument::cleanupLine(char * line)
words.push_back(word);
}
start = bg;
while(isspace(*++line)) {}
while(isspace((unsigned char)*++line)) {}
continue;
}

View file

@ -48,6 +48,7 @@ DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
@ -190,7 +191,7 @@ void LoadDBCStores(const std::string& dataPath)
{
std::string dbcPath = dataPath+"dbc/";
const uint32 DBCFilesCount = 69;
const uint32 DBCFilesCount = 70;
barGoLink bar( DBCFilesCount );
@ -221,7 +222,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
@ -229,6 +230,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc");
@ -405,18 +407,6 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc");
// Initialize global taxinodes mask
memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
if(sTaxiNodesStore.LookupEntry(i))
{
uint8 field = (uint8)((i - 1) / 32);
uint32 submask = 1<<((i-1)%32);
sTaxiNodesMask[field] |= submask;
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc");
for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
@ -444,6 +434,47 @@ void LoadDBCStores(const std::string& dataPath)
sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay);
sTaxiPathNodeStore.Clear();
// Initialize global taxinodes mask
// include existed nodes that have at least single not spell base (scripted) path
{
std::set<uint32> spellPaths;
for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i)
if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
for(int j=0; j < 3; ++j)
if(sInfo->Effect[j]==123 /*SPELL_EFFECT_SEND_TAXI*/)
spellPaths.insert(sInfo->EffectMiscValue[j]);
memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
if(!sTaxiNodesStore.LookupEntry(i))
continue;
TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i);
if(src_i!=sTaxiPathSetBySource.end() && !src_i->second.empty())
{
bool ok = false;
for(TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin();dest_i != src_i->second.end(); ++dest_i)
{
// not spell path
if(spellPaths.find(dest_i->second.ID)==spellPaths.end())
{
ok = true;
break;
}
}
if(!ok)
continue;
}
// valid taxi netowrk node
uint8 field = (uint8)((i - 1) / 32);
uint32 submask = 1<<((i-1)%32);
sTaxiNodesMask[field] |= submask;
}
}
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc");
@ -474,11 +505,11 @@ void LoadDBCStores(const std::string& dataPath)
// check at up-to-date DBC files (2425 is last item extended cost added in 3.0.1)
// check at up-to-date DBC files (76 is last char title added in 3.0.1)
// check at up-to-date DBC files (2311 is last area added in 3.0.1)
if( !sSpellStore.LookupEntry(54909) ||
!sSkillLineAbilityStore.LookupEntry(19162) ||
if( !sSpellStore.LookupEntry(54909) ||
!sSkillLineAbilityStore.LookupEntry(19162) ||
!sMapStore.LookupEntry(619) ||
!sGemPropertiesStore.LookupEntry(1361) ||
!sItemExtendedCostStore.LookupEntry(2425) ||
!sGemPropertiesStore.LookupEntry(1361) ||
!sItemExtendedCostStore.LookupEntry(2425) ||
!sCharTitlesStore.LookupEntry(76) ||
!sAreaStore.LookupEntry(2311) )
{
@ -487,8 +518,7 @@ void LoadDBCStores(const std::string& dataPath)
}
sLog.outString();
sLog.outString( ">> Loaded %d data stores", DBCFilesCount );
sLog.outString();
sLog.outString( ">> Initialized %d data stores", DBCFilesCount );
}
SimpleFactionsList const* GetFactionTeamList(uint32 faction)

View file

@ -146,6 +146,7 @@ extern DBCStorage <ChrRacesEntry> sChrRacesStore;
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore;
extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
extern DBCStorage <EmotesTextEntry> sEmotesTextStore;

View file

@ -664,6 +664,14 @@ struct CreatureSpellDataEntry
//uint32 availability[4]; // 4-7 m_availability[4]
};
struct CreatureTypeEntry
{
uint32 ID; // 0 m_ID
//char* Name[16]; // 1-16 name
// 17 string flags
//uint32 no_expirience; // 18 no exp? critters, non-combat pets, gas cloud.
};
struct DurabilityCostsEntry
{
uint32 Itemlvl; // 0
@ -941,14 +949,16 @@ struct MapEntry
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
bool IsBattleArena() const { return map_type == MAP_ARENA; }
bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
bool SupportsHeroicMode() const { return resetTimeHeroic && !resetTimeRaid; }
bool SupportsHeroicMode() const { return resetTimeHeroic != 0; }
bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; }
bool IsMountAllowed() const
{
return !IsDungeon() ||
MapID==568 || MapID==309 || MapID==209 || MapID==534 ||
MapID==560 || MapID==509 || MapID==269;
MapID==209 || MapID==269 || MapID==309 || // TanarisInstance, CavernsOfTime, Zul'gurub
MapID==509 || MapID==534 || MapID==560 || // AhnQiraj, HyjalPast, HillsbradPast
MapID==568 || MapID==580 || MapID==615 || // ZulAman, Sunwell Plateau, Obsidian Sanctrum
MapID==616; // Eye Of Eternity
}
bool IsContinent() const
@ -1409,7 +1419,7 @@ struct VehicleEntry
uint32 m_uiSeatIndicatorType; // 42
};
struct VehicleSeatEntry
struct VehicleSeatEntry
{
uint32 m_ID; // 0
uint32 m_flags; // 1

View file

@ -33,6 +33,7 @@ const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxx
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx";
const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx";
const char CreatureSpellDatafmt[]="nxxxxxxxx";
const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx";
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
const char DurabilityQualityfmt[]="nf";
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx";

View file

@ -37,8 +37,8 @@ const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii";
const char PageTextfmt[]="isi";
const char SpellThreatfmt[]="ii";
const char InstanceTemplatesrcfmt[]="iiiiiiffffs";
const char InstanceTemplatedstfmt[]="iiiiiiffffi";
const char InstanceTemplatesrcfmt[]="iiiiiiiffffs";
const char InstanceTemplatedstfmt[]="iiiiiiiffffi";
SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template");
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7135"
#define REVISION_NR "7167"
#endif // __REVISION_NR_H__