Merge remote branch 'origin/master' into 330

This commit is contained in:
tomrus88 2009-12-30 01:16:15 +03:00
commit 33cd1a0aca
32 changed files with 659 additions and 293 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_9045_02_mangos_spell_chain` bit(1) default NULL `required_9074_01_mangos_command` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -743,7 +743,7 @@ INSERT INTO `command` VALUES
('server restart cancel',3,'Syntax: .server restart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('server restart cancel',3,'Syntax: .server restart cancel\r\n\r\nCancel the restart/shutdown timer if any.'),
('server set loglevel',4,'Syntax: .server set loglevel #level\r\n\r\nSet server log level (0 - errors only, 1 - basic, 2 - detail, 3 - debug).'), ('server set loglevel',4,'Syntax: .server set loglevel #level\r\n\r\nSet server log level (0 - errors only, 1 - basic, 2 - detail, 3 - debug).'),
('server set motd',3,'Syntax: .server set motd $MOTD\r\n\r\nSet server Message of the day.'), ('server set motd',3,'Syntax: .server set motd $MOTD\r\n\r\nSet server Message of the day.'),
('server shutdown',3,'Syntax: .server shutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds. Use #exist_code or 0 as program exist code.'), ('server shutdown',3,'Syntax: .server shutdown #delay [#exit_code]\r\n\r\nShut the server down after #delay seconds. Use #exit_code or 0 as program exit code.'),
('server shutdown cancel',3,'Syntax: .server shutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('server shutdown cancel',3,'Syntax: .server shutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'),
('setskill',3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'), ('setskill',3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'),
('showarea',3,'Syntax: .showarea #areaid\r\n\r\nReveal the area of #areaid to the selected character. If no character is selected, reveal this area to you.'), ('showarea',3,'Syntax: .showarea #areaid\r\n\r\nReveal the area of #areaid to the selected character. If no character is selected, reveal this area to you.'),
@ -15271,6 +15271,13 @@ INSERT INTO spell_chain VALUES
(10301,10300,7294,5,0), (10301,10300,7294,5,0),
(27150,10301,7294,6,0), (27150,10301,7294,6,0),
(54043,27150,7294,7,0), (54043,27150,7294,7,0),
/*Righteous Vengeance*/
(53380,0,53380,1,0),
(53381,53380,53380,2,0),
(53382,53381,53380,3,0),
/*The Art of War*/
(53486,0,53486,1,0),
(53488,53486,53486,2,0),
/*------------------ /*------------------
-- (185) Cooking -- (185) Cooking
------------------*/ ------------------*/
@ -18209,6 +18216,7 @@ INSERT INTO `spell_proc_event` VALUES
(45243, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (45243, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(45244, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (45244, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(45354, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45354, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(45355, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(45481, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45481, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(45482, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45482, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(45483, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45483, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
@ -18367,12 +18375,9 @@ INSERT INTO `spell_proc_event` VALUES
(53259, 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), (53260, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53290, 0x00000000, 9, 0x00000800, 0x00000001, 0x00000200, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53290, 0x00000000, 9, 0x00000800, 0x00000001, 0x00000200, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53380, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53380, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53381, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53382, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53397, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53397, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53486, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53486, 0x00000000, 0, 0x00000000, 0x00000000, 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), (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), (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), (53503, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
@ -18457,7 +18462,7 @@ INSERT INTO `spell_proc_event` VALUES
(58386, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0.000000, 0.000000, 0), (58386, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0.000000, 0.000000, 0),
(58442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 15), (58442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 15),
(58444, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5), (58444, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5),
(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,0), (58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,6),
(58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(58620, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58620, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(58626, 0x00000000, 15, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58626, 0x00000000, 15, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
@ -18535,7 +18540,10 @@ INSERT INTO `spell_proc_event` VALUES
(65661, 0x00000000, 15, 0x00400011, 0x00020004, 0x00000000, 0x00000010, 0x00000001, 0.000000, 100.000000,0), (65661, 0x00000000, 15, 0x00400011, 0x00020004, 0x00000000, 0x00000010, 0x00000001, 0.000000, 100.000000,0),
(64127, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (64127, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(67353, 0x00000000, 7, 0x00008000, 0x00100500, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (67353, 0x00000000, 7, 0x00008000, 0x00100500, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(67667, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45); (67667, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(67672, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 50),
(67702, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(67771, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45);
/*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;

View file

@ -0,0 +1,8 @@
ALTER TABLE db_version CHANGE COLUMN required_9045_02_mangos_spell_chain required_9064_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry IN (45355,67672,67702,67771);
INSERT INTO spell_proc_event VALUES
(45355, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(67672, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 50),
(67702, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(67771, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45);

View file

@ -0,0 +1,10 @@
ALTER TABLE db_version CHANGE COLUMN required_9064_01_mangos_spell_proc_event required_9068_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry IN (53380,53381,53382);
INSERT INTO spell_proc_event VALUES
(53380, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);
DELETE FROM spell_proc_event WHERE entry IN (53486,53488);
INSERT INTO spell_proc_event VALUES
(53486, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,14 @@
ALTER TABLE db_version CHANGE COLUMN required_9068_01_mangos_spell_proc_event required_9068_02_mangos_spell_chain bit;
/*Righteous Vengeance*/
DELETE FROM spell_chain WHERE first_spell = 53380;
INSERT INTO spell_chain VALUES
(53380, 0, 53380, 1, 0),
(53381, 53380, 53380, 2, 0),
(53382, 53381, 53380, 3, 0);
/*The Art of War*/
DELETE FROM spell_chain WHERE first_spell = 53486;
INSERT INTO spell_chain VALUES
(53486, 0, 53486, 1, 0),
(53488, 53486, 53486, 2, 0);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_9068_02_mangos_spell_chain required_9070_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` IN (58597);
INSERT INTO `spell_proc_event` VALUES
(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,6);

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_9070_01_mangos_spell_proc_event required_9074_01_mangos_command bit;
DELETE FROM command where name IN ('server shutdown');
INSERT INTO `command` VALUES
('server shutdown',3,'Syntax: .server shutdown #delay [#exit_code]\r\n\r\nShut the server down after #delay seconds. Use #exit_code or 0 as program exit code.');

View file

@ -219,6 +219,11 @@ pkgdata_DATA = \
9034_01_mangos_spell_proc_event.sql \ 9034_01_mangos_spell_proc_event.sql \
9045_01_mangos_spell_proc_event.sql \ 9045_01_mangos_spell_proc_event.sql \
9045_02_mangos_spell_chain.sql \ 9045_02_mangos_spell_chain.sql \
9064_01_mangos_spell_proc_event.sql \
9068_01_mangos_spell_proc_event.sql \
9068_02_mangos_spell_chain.sql \
9070_01_mangos_spell_proc_event.sql \
9074_01_mangos_command.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -418,4 +423,9 @@ EXTRA_DIST = \
9034_01_mangos_spell_proc_event.sql \ 9034_01_mangos_spell_proc_event.sql \
9045_01_mangos_spell_proc_event.sql \ 9045_01_mangos_spell_proc_event.sql \
9045_02_mangos_spell_chain.sql \ 9045_02_mangos_spell_chain.sql \
9064_01_mangos_spell_proc_event.sql \
9068_01_mangos_spell_proc_event.sql \
9068_02_mangos_spell_chain.sql \
9070_01_mangos_spell_proc_event.sql \
9074_01_mangos_command.sql \
README README

View file

@ -18,6 +18,7 @@
#include "CreatureAI.h" #include "CreatureAI.h"
#include "Creature.h" #include "Creature.h"
#include "DBCStores.h"
CreatureAI::~CreatureAI() CreatureAI::~CreatureAI()
{ {
@ -28,3 +29,90 @@ void CreatureAI::AttackedBy( Unit* attacker )
if(!m_creature->getVictim()) if(!m_creature->getVictim())
AttackStart(attacker); AttackStart(attacker);
} }
CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered)
{
// If not triggered, we check
if (!isTriggered)
{
// State does not allow
if (m_creature->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DIED))
return CAST_FAIL_STATE;
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return CAST_FAIL_STATE;
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
return CAST_FAIL_STATE;
// Check for power (also done by Spell::CheckCast())
if (m_creature->GetPower((Powers)pSpell->powerType) < pSpell->manaCost)
return CAST_FAIL_POWER;
}
if (const SpellRangeEntry *pSpellRange = sSpellRangeStore.LookupEntry(pSpell->rangeIndex))
{
if (pTarget != m_creature)
{
// pTarget is out of range of this spell (also done by Spell::CheckCast())
float fDistance = m_creature->GetCombatDistance(pTarget);
if (fDistance > (m_creature->IsHostileTo(pTarget) ? pSpellRange->maxRange : pSpellRange->maxRangeFriendly))
return CAST_FAIL_TOO_FAR;
float fMinRange = m_creature->IsHostileTo(pTarget) ? pSpellRange->minRange : pSpellRange->minRangeFriendly;
if (fMinRange && fDistance < fMinRange)
return CAST_FAIL_TOO_CLOSE;
}
return CAST_OK;
}
else
return CAST_FAIL_OTHER;
}
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint64 uiOriginalCasterGUID)
{
Unit* pCaster = m_creature;
if (uiCastFlags & CAST_FORCE_TARGET_SELF)
pCaster = pTarget;
// Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS)))
{
if (const SpellEntry* pSpell = sSpellStore.LookupEntry(uiSpell))
{
// If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
if (uiCastFlags & CAST_AURA_NOT_PRESENT)
{
if (pTarget->HasAura(uiSpell))
return CAST_FAIL_TARGET_AURA;
}
// Check if cannot cast spell
if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
{
CanCastResult castResult = CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED);
if (castResult != CAST_OK)
return castResult;
}
// Interrupt any previous spell
if (uiCastFlags & CAST_INTURRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
pCaster->InterruptNonMeleeSpells(false);
pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID);
return CAST_OK;
}
else
{
sLog.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature->GetEntry(), uiSpell);
return CAST_FAIL_OTHER;
}
}
else
return CAST_FAIL_IS_CASTING;
}

View file

@ -34,6 +34,18 @@ struct SpellEntry;
#define TIME_INTERVAL_LOOK 5000 #define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000 #define VISIBILITY_RANGE 10000
enum CanCastResult
{
CAST_OK = 0,
CAST_FAIL_IS_CASTING = 1,
CAST_FAIL_OTHER = 2,
CAST_FAIL_TOO_FAR = 3,
CAST_FAIL_TOO_CLOSE = 4,
CAST_FAIL_POWER = 5,
CAST_FAIL_STATE = 6,
CAST_FAIL_TARGET_AURA = 7
};
enum CastFlags enum CastFlags
{ {
CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
@ -68,6 +80,10 @@ class MANGOS_DLL_SPEC CreatureAI
// Called at any heal cast/item used (call non implemented) // Called at any heal cast/item used (call non implemented)
virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {} virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {}
// Helper functions for cast spell
CanCastResult DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, uint64 uiOriginalCasterGUID = 0);
virtual CanCastResult CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered);
// Called at any Damage to any victim (before damage apply) // Called at any Damage to any victim (before damage apply)
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {} virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}

View file

@ -1752,6 +1752,13 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const
case 856: // The Noxious Glade (Eastern Plaguelands) case 856: // The Noxious Glade (Eastern Plaguelands)
case 2456: // Death's Breach (Eastern Plaguelands) case 2456: // Death's Breach (Eastern Plaguelands)
if(z > 350.0f) areaflag = 1950; break; if(z > 350.0f) areaflag = 1950; break;
// Winterfin Caverns
case 1652: // Coldarra
case 1653: // The Westrift
case 1661: // Winterfin Village
if (x > 3823.0f && x < 4141.5f && y > 6247.0f && y < 64890.0f && z < 42.5f)
areaflag = 1723;
break;
// Dalaran // Dalaran
case 2492: // Forlorn Woods (Crystalsong Forest) case 2492: // Forlorn Woods (Crystalsong Forest)
case 2371: // Valley of Echoes (Icecrown Glacier) case 2371: // Valley of Echoes (Icecrown Glacier)

View file

@ -463,3 +463,12 @@ bool MotionMaster::GetDestination(float &x, float &y, float &z)
return top()->GetDestination(x,y,z); return top()->GetDestination(x,y,z);
} }
void MotionMaster::UpdateFinalDistanceToTarget(float fDistance)
{
if (!empty())
{
if (top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
top()->UpdateFinalDistance(fDistance);
}
}

View file

@ -121,6 +121,9 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *>
void propagateSpeedChange(); void propagateSpeedChange();
// will only work in MMgens where we have a target (TARGETED_MOTION_TYPE)
void UpdateFinalDistanceToTarget(float fDistance);
bool GetDestination(float &x, float &y, float &z); bool GetDestination(float &x, float &y, float &z);
private: private:
void Mutate(MovementGenerator *m); // use Move* functions instead void Mutate(MovementGenerator *m); // use Move* functions instead

View file

@ -44,6 +44,8 @@ class MANGOS_DLL_SPEC MovementGenerator
virtual void unitSpeedChanged() { } virtual void unitSpeedChanged() { }
virtual void UpdateFinalDistance(float fDistance) { }
virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; }
}; };

View file

@ -40,7 +40,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
Pet::Pet(PetType type) : Pet::Pet(PetType type) :
Creature(), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0), Creature(), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0),
m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false), m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false),
m_declinedname(NULL) m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT)
{ {
m_isPet = true; m_isPet = true;
m_name = "Pet"; m_name = "Pet";
@ -1948,3 +1948,20 @@ void Pet::SynchronizeLevelWithOwner()
break; break;
} }
} }
void Pet::ApplyModeFlags(PetModeFlags mode, bool apply)
{
if (apply)
m_petModeFlags = PetModeFlags(m_petModeFlags | mode);
else
m_petModeFlags = PetModeFlags(m_petModeFlags & ~mode);
Unit* owner = GetOwner();
if(!owner || owner->GetTypeId()!=TYPEID_PLAYER)
return;
WorldPacket data(SMSG_PET_MODE, 12);
data << uint64(GetGUID());
data << uint32(m_petModeFlags);
((Player*)owner)->GetSession()->SendPacket(&data);
}

View file

@ -46,6 +46,17 @@ enum PetSaveMode
PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100 PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
}; };
// There might be a lot more
enum PetModeFlags
{
PET_MODE_UNKNOWN_0 = 0x0000001,
PET_MODE_UNKNOWN_2 = 0x0000100,
PET_MODE_DISABLE_ACTIONS = 0x8000000,
// autoset in client at summon
PET_MODE_DEFAULT = PET_MODE_UNKNOWN_0 | PET_MODE_UNKNOWN_2,
};
enum HappinessState enum HappinessState
{ {
UNHAPPY = 1, UNHAPPY = 1,
@ -182,6 +193,9 @@ class Pet : public Creature
bool CanTakeMoreActiveSpells(uint32 SpellIconID); bool CanTakeMoreActiveSpells(uint32 SpellIconID);
void ToggleAutocast(uint32 spellid, bool apply); void ToggleAutocast(uint32 spellid, bool apply);
void ApplyModeFlags(PetModeFlags mode, bool apply);
PetModeFlags GetModeFlags() const { return m_petModeFlags; }
bool HasSpell(uint32 spell) const; bool HasSpell(uint32 spell) const;
void LearnPetPassives(); void LearnPetPassives();
@ -242,6 +256,8 @@ class Pet : public Creature
DeclinedName *m_declinedname; DeclinedName *m_declinedname;
private: private:
PetModeFlags m_petModeFlags;
void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
{ {
assert(false); assert(false);

View file

@ -44,9 +44,16 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK), inComb
void PetAI::MoveInLineOfSight(Unit *u) void PetAI::MoveInLineOfSight(Unit *u)
{ {
if( !m_creature->getVictim() && m_creature->GetCharmInfo() && if (m_creature->getVictim())
m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) && return;
u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
if (m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
return;
if (u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
u->isInAccessablePlaceFor(m_creature)) u->isInAccessablePlaceFor(m_creature))
{ {
float attackRadius = m_creature->GetAttackDistance(u); float attackRadius = m_creature->GetAttackDistance(u);
@ -139,7 +146,7 @@ void PetAI::UpdateAI(const uint32 diff)
else else
m_updateAlliesTimer -= diff; m_updateAlliesTimer -= diff;
if (inCombat && !m_creature->getVictim()) if (inCombat && (!m_creature->getVictim() || m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))
_stopAttack(); _stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.

View file

@ -44,23 +44,33 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
// used also for charmed creature // used also for charmed creature
Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); Unit* pet= ObjectAccessor::GetUnit(*_player, guid1);
sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2)) ); sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2)) );
if(!pet) if (!pet)
{ {
sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) ); sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) );
return; return;
} }
if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) if (pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm())
{ {
sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() );
return; return;
} }
if(!pet->isAlive()) if (!pet->isAlive())
return; return;
if(pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) if (pet->GetTypeId() == TYPEID_PLAYER)
return; {
// controller player can only do melee attack
if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK))
return;
}
else if (((Creature*)pet)->isPet())
{
// pet can have action bar disabled
if(((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
}
CharmInfo *charmInfo = pet->GetCharmInfo(); CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo) if(!charmInfo)
@ -316,6 +326,10 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
return; return;
} }
// pet can have action bar disabled
if(pet->isPet() && ((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)
return;
CharmInfo *charmInfo = pet->GetCharmInfo(); CharmInfo *charmInfo = pet->GetCharmInfo();
if(!charmInfo) if(!charmInfo)
{ {

View file

@ -17095,6 +17095,18 @@ void Player::PetSpellInitialize()
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
} }
void Player::SendPetGUIDs()
{
if(!GetPetGUID())
return;
// Later this function might get modified for multiple guids
WorldPacket data(SMSG_PET_GUIDS, 12);
data << uint32(1); // count
data << uint64(GetPetGUID());
GetSession()->SendPacket(&data);
}
void Player::PossessSpellInitialize() void Player::PossessSpellInitialize()
{ {
Unit* charm = GetCharm(); Unit* charm = GetCharm();

View file

@ -1565,6 +1565,7 @@ class MANGOS_DLL_SPEC Player : public Unit
} }
void PetSpellInitialize(); void PetSpellInitialize();
void SendPetGUIDs();
void CharmSpellInitialize(); void CharmSpellInitialize();
void PossessSpellInitialize(); void PossessSpellInitialize();
void RemovePetActionBar(); void RemovePetActionBar();

View file

@ -358,7 +358,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = {
#define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX4_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX4_NOT_STEALABLE 0x00000040 // 6 although such auras might be dispellable, they cannot be stolen #define SPELL_ATTR_EX4_NOT_STEALABLE 0x00000040 // 6 although such auras might be dispellable, they cannot be stolen
#define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 #define SPELL_ATTR_EX4_UNK7 0x00000080 // 7
#define SPELL_ATTR_EX4_UNK8 0x00000100 // 8 #define SPELL_ATTR_EX4_STACK_DOT_MODIFIER 0x00000100 // 8 no effect on non DoTs?
#define SPELL_ATTR_EX4_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX4_UNK9 0x00000200 // 9
#define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag #define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag
#define SPELL_ATTR_EX4_UNK11 0x00000800 // 11 #define SPELL_ATTR_EX4_UNK11 0x00000800 // 11
@ -445,7 +445,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = {
#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 #define SPELL_ATTR_EX6_NO_DMG_PERCENT_MODS 0x20000000 // 29 do not apply damage percent mods (usually in cases where it has already been applied)
#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3
#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3

File diff suppressed because it is too large Load diff

View file

@ -372,12 +372,12 @@ class Spell
typedef std::list<Unit*> UnitList; typedef std::list<Unit*> UnitList;
void FillTargetMap(); void FillTargetMap();
void SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap); void SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList &targetUnitMap);
void FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ); void FillAreaTargets(UnitList &targetUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets);
void FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster ); void FillRaidOrPartyTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster);
void FillRaidOrPartyManaPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); void FillRaidOrPartyManaPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster);
void FillRaidOrPartyHealthPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); void FillRaidOrPartyHealthPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster);
template<typename T> WorldObject* FindCorpseUsing(); template<typename T> WorldObject* FindCorpseUsing();

View file

@ -205,7 +205,7 @@ enum AuraType
SPELL_AURA_MOD_AOE_AVOIDANCE = 160, SPELL_AURA_MOD_AOE_AVOIDANCE = 160,
SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161,
SPELL_AURA_POWER_BURN_MANA = 162, SPELL_AURA_POWER_BURN_MANA = 162,
SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE = 163, SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163,
SPELL_AURA_164 = 164, SPELL_AURA_164 = 164,
SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165,
SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, SPELL_AURA_MOD_ATTACK_POWER_PCT = 166,

View file

@ -213,7 +213,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
&Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT implemented in Player::RegenerateAll and Player::RegenerateHealth &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT implemented in Player::RegenerateAll and Player::RegenerateHealth
&Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
&Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE implememnted in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS implemented in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus
&Aura::HandleUnused, //164 unused (3.0.8a-3.2.2a), only one test spell 10654 &Aura::HandleUnused, //164 unused (3.0.8a-3.2.2a), only one test spell 10654
&Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
&Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
@ -2241,6 +2241,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
if (Unit* caster = GetCaster()) if (Unit* caster = GetCaster())
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
return; return;
case 7057: // Haunting Spirits
// expected to tick with 30 sec period (tick part see in Aura::PeriodicTick)
m_isPeriodic = true;
m_modifier.periodictime = 30*IN_MILISECONDS;
m_periodicTimer = m_modifier.periodictime;
return;
case 13139: // net-o-matic case 13139: // net-o-matic
// root to self part of (root_target->charge->root_self sequence // root to self part of (root_target->charge->root_self sequence
if (Unit* caster = GetCaster()) if (Unit* caster = GetCaster())
@ -2389,6 +2395,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
switch(GetId()) switch(GetId())
{ {
case 28169: // Mutating Injection
{
// Mutagen Explosion
m_target->CastSpell(m_target, 28206, true, NULL, this);
// Poison Cloud
m_target->CastSpell(m_target, 28240, true, NULL, this);
return;
}
case 36730: // Flame Strike case 36730: // Flame Strike
{ {
m_target->CastSpell(m_target, 36731, true, NULL, this); m_target->CastSpell(m_target, 36731, true, NULL, this);
@ -2813,7 +2827,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real)
if (minfo) if (minfo)
display_id = minfo->modelid; display_id = minfo->modelid;
m_target->Mount(display_id); m_target->Mount(display_id, m_spellProto->Id);
} }
else else
{ {
@ -7014,6 +7028,7 @@ void Aura::PeriodicTick()
break; break;
} }
// Here tick dummy auras // Here tick dummy auras
case SPELL_AURA_DUMMY: // some spells have dummy aura
case SPELL_AURA_PERIODIC_DUMMY: case SPELL_AURA_PERIODIC_DUMMY:
{ {
PeriodicDummyTick(); PeriodicDummyTick();
@ -7099,6 +7114,10 @@ void Aura::PeriodicDummyTick()
// 7053 Forsaken Skill: Shadow // 7053 Forsaken Skill: Shadow
return; return;
} }
case 7057: // Haunting Spirits
if (roll_chance_i(33))
m_target->CastSpell(m_target,m_modifier.m_amount,true,NULL,this);
return;
// // Panda // // Panda
// case 19230: break; // case 19230: break;
// // Gossip NPC Periodic - Talk // // Gossip NPC Periodic - Talk
@ -7253,6 +7272,21 @@ void Aura::PeriodicDummyTick()
// case 50493: break; // case 50493: break;
// // Love Rocket Barrage // // Love Rocket Barrage
// case 50530: break; // case 50530: break;
case 50789: // Summon iron dwarf (left or right)
case 59860:
m_target->CastSpell(m_target, roll_chance_i(50) ? 50790 : 50791, true, NULL, this);
return;
case 50792: // Summon iron trogg (left or right)
case 59859:
m_target->CastSpell(m_target, roll_chance_i(50) ? 50793 : 50794, true, NULL, this);
return;
case 50801: // Summon malformed ooze (left or right)
case 59858:
m_target->CastSpell(m_target, roll_chance_i(50) ? 50802 : 50803, true, NULL, this);
return;
case 50824: // Summon earthen dwarf
m_target->CastSpell(m_target, roll_chance_i(50) ? 50825 : 50826, true, NULL, this);
return;
// Exist more after, need add later // Exist more after, need add later
default: default:
break; break;

View file

@ -749,44 +749,6 @@ void Spell::EffectDummy(uint32 i)
((Creature*)unitTarget)->setDeathState(JUST_ALIVED); ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
return; return;
} }
case 12162: // Deep wounds
case 12850: // (now good common check for this spells)
case 12868:
{
if (!unitTarget)
return;
float damage;
// DW should benefit of attack power, damage percent mods etc.
// TODO: check if using offhand damage is correct and if it should be divided by 2
if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
else
damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
switch (m_spellInfo->Id)
{
case 12162: damage *= 0.16f; break; // Rank 1
case 12850: damage *= 0.32f; break; // Rank 2
case 12868: damage *= 0.48f; break; // Rank 3
default:
sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
return;
};
// get remaining damage of old Deep Wound aura
Aura* deepWound = unitTarget->GetAura(12721, 0);
if (deepWound)
{
int32 remainingTicks = deepWound->GetAuraDuration() / deepWound->GetModifier()->periodictime;
damage += remainingTicks * deepWound->GetModifier()->m_amount;
}
// 1 tick/sec * 6 sec = 6 ticks
int32 deepWoundsDotBasePoints0 = int32(damage / 6);
m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
return;
}
case 13120: // net-o-matic case 13120: // net-o-matic
{ {
if (!unitTarget) if (!unitTarget)
@ -6477,7 +6439,11 @@ void Spell::EffectPlayerPull(uint32 i)
if(!unitTarget) if(!unitTarget)
return; return;
unitTarget->KnockBackFrom(m_caster,float(damage ? damage : unitTarget->GetDistance2d(m_caster)),float(m_spellInfo->EffectMiscValue[i])/10); float dist = unitTarget->GetDistance2d(m_caster);
if (damage && dist > damage)
dist = damage;
unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[i])/10);
} }
void Spell::EffectDispelMechanic(uint32 i) void Spell::EffectDispelMechanic(uint32 i)

View file

@ -1568,6 +1568,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
(spellId_2 == 33891 && spellId_1 == 34123)) (spellId_2 == 33891 && spellId_1 == 34123))
return false; return false;
// Lifebloom and Wild Growth
if (spellInfo_1->SpellIconID == 2101 && spellInfo_2->SpellIconID == 2864 ||
spellInfo_2->SpellIconID == 2101 && spellInfo_1->SpellIconID == 2864 )
return false;
// Innervate and Glyph of Innervate and some other spells // Innervate and Glyph of Innervate and some other spells
if (spellInfo_1->SpellIconID == 62 && spellInfo_2->SpellIconID == 62) if (spellInfo_1->SpellIconID == 62 && spellInfo_2->SpellIconID == 62)
return false; return false;

View file

@ -102,6 +102,19 @@ void TargetedMovementGenerator<Creature>::Initialize(Creature &owner)
_setTargetLocation(owner); _setTargetLocation(owner);
} }
template<>
void TargetedMovementGenerator<Player>::UpdateFinalDistance(float fDistance)
{
// nothing to do for Player
}
template<>
void TargetedMovementGenerator<Creature>::UpdateFinalDistance(float fDistance)
{
i_offset = fDistance;
i_recalculateTravel = true;
}
template<> template<>
void TargetedMovementGenerator<Player>::Initialize(Player &owner) void TargetedMovementGenerator<Player>::Initialize(Player &owner)
{ {

View file

@ -61,6 +61,8 @@ class MANGOS_DLL_SPEC TargetedMovementGenerator
} }
void unitSpeedChanged() { i_recalculateTravel=true; } void unitSpeedChanged() { i_recalculateTravel=true; }
void UpdateFinalDistance(float fDistance);
private: private:
void _setTargetLocation(T &); void _setTargetLocation(T &);

View file

@ -216,17 +216,17 @@ void Unit::Update( uint32 p_time )
// Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away // Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away
// targets without stopping half way there and running off. // targets without stopping half way there and running off.
// These flags are reset after target dies or another command is given. // These flags are reset after target dies or another command is given.
if( m_HostileRefManager.isEmpty() ) if (m_HostileRefManager.isEmpty())
{ {
// m_CombatTimer set at aura start and it will be freeze until aura removing // m_CombatTimer set at aura start and it will be freeze until aura removing
if ( m_CombatTimer <= p_time ) if (m_CombatTimer <= p_time)
ClearInCombat(); CombatStop();
else else
m_CombatTimer -= p_time; m_CombatTimer -= p_time;
} }
} }
if(uint32 base_att = getAttackTimer(BASE_ATTACK)) if (uint32 base_att = getAttackTimer(BASE_ATTACK))
{ {
setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) ); setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) );
} }
@ -1292,10 +1292,9 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da
if(damageInfo->attackType == RANGED_ATTACK) if(damageInfo->attackType == RANGED_ATTACK)
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
else else
{
mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
} mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, SPELL_SCHOOL_MASK_NORMAL);
uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask(); uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
@ -3608,16 +3607,26 @@ bool Unit::AddAura(Aura *Aur)
{ {
for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2)
{ {
if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) Aura* aur2 = i2->second;
if(aur2->GetCasterGUID()==Aur->GetCasterGUID())
{ {
// Aura can stack on self -> Stack it; // Aura can stack on self -> Stack it;
if(aurSpellInfo->StackAmount) if(aurSpellInfo->StackAmount)
{ {
// can be created with >1 stack by some spell mods // can be created with >1 stack by some spell mods
i2->second->modStackAmount(Aur->GetStackAmount()); aur2->modStackAmount(Aur->GetStackAmount());
delete Aur; delete Aur;
return false; return false;
} }
// Carry over removed Aura's remaining damage if Aura still has ticks remaining
else if (aur2->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_STACK_DOT_MODIFIER && aurName == SPELL_AURA_PERIODIC_DAMAGE && aur2->GetAuraDuration() > 0)
{
int32 remainingTicks = 1 + (aur2->GetAuraDuration() / aur2->GetModifier()->periodictime);
int32 remainingDamage = aur2->GetModifier()->m_amount * remainingTicks;
int32 maxTicks = Aur->GetAuraMaxDuration() / Aur->GetModifier()->periodictime;
Aur->GetModifier()->m_amount += int32(remainingDamage / maxTicks);
}
// can be only single (this check done at _each_ aura add // can be only single (this check done at _each_ aura add
RemoveAura(i2,AURA_REMOVE_BY_STACK); RemoveAura(i2,AURA_REMOVE_BY_STACK);
break; break;
@ -5833,6 +5842,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
// Wrath crit // Wrath crit
if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000001)) if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000001))
{ {
if (HasAura(48517))
return false;
if (!roll_chance_i(60)) if (!roll_chance_i(60))
return false; return false;
triggered_spell_id = 48518; triggered_spell_id = 48518;
@ -5842,6 +5853,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
// Starfire crit // Starfire crit
if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000004)) if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000004))
{ {
if (HasAura(48518))
return false;
triggered_spell_id = 48517; triggered_spell_id = 48517;
target = this; target = this;
break; break;
@ -7007,6 +7020,34 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
} }
break; break;
case SPELLFAMILY_WARRIOR: case SPELLFAMILY_WARRIOR:
// Deep Wounds (replace triggered spells to directly apply DoT), dot spell have finilyflags
if (auraSpellInfo->SpellFamilyFlags == UI64LIT(0x0) && auraSpellInfo->SpellIconID == 243)
{
float weaponDamage;
// DW should benefit of attack power, damage percent mods etc.
// TODO: check if using offhand damage is correct and if it should be divided by 2
if (haveOffhandWeapon() && getAttackTimer(BASE_ATTACK) > getAttackTimer(OFF_ATTACK))
weaponDamage = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
else
weaponDamage = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
switch (auraSpellInfo->Id)
{
case 12834: basepoints[0] = int32(weaponDamage * 16 / 100); break;
case 12849: basepoints[0] = int32(weaponDamage * 32 / 100); break;
case 12867: basepoints[0] = int32(weaponDamage * 48 / 100); break;
// Impossible case
default:
sLog.outError("Unit::HandleProcTriggerSpell: DW unknown spell rank %u",auraSpellInfo->Id);
return false;
}
// 1 tick/sec * 6 sec = 6 ticks
basepoints[0] /= 6;
trigger_spell_id = 12721;
break;
}
if (auraSpellInfo->Id == 50421) // Scent of Blood if (auraSpellInfo->Id == 50421) // Scent of Blood
trigger_spell_id = 50422; trigger_spell_id = 50422;
break; break;
@ -8346,6 +8387,9 @@ void Unit::SetPet(Pet* pet)
{ {
SetPetGUID(pet ? pet->GetGUID() : 0); SetPetGUID(pet ? pet->GetGUID() : 0);
if(pet && GetTypeId() == TYPEID_PLAYER)
((Player*)this)->SendPetGUIDs();
// FIXME: hack, speed must be set only at follow // FIXME: hack, speed must be set only at follow
if(pet && GetTypeId()==TYPEID_PLAYER) if(pet && GetTypeId()==TYPEID_PLAYER)
for(int i = 0; i < MAX_MOVE_TYPE; ++i) for(int i = 0; i < MAX_MOVE_TYPE; ++i)
@ -8520,16 +8564,19 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() ) if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); if (!(spellProto->AttributesEx6 & SPELL_ATTR_EX6_NO_DMG_PERCENT_MODS))
for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
{ {
if (((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
(*i)->GetSpellProto()->EquippedItemClass == -1 && for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
// -1 == any item class (not wand then)
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0)
// 0 == any inventory type (not wand then)
{ {
DoneTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f; if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) &&
(*i)->GetSpellProto()->EquippedItemClass == -1 &&
// -1 == any item class (not wand then)
(*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
// 0 == any inventory type (not wand then)
{
DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
}
} }
} }
@ -9034,17 +9081,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
break; break;
} }
case SPELL_DAMAGE_CLASS_MELEE: case SPELL_DAMAGE_CLASS_MELEE:
{
// Judgement of Command proc always crits on stunned target
if(spellProto->SpellFamilyName == SPELLFAMILY_PALADIN)
{
if(spellProto->SpellFamilyFlags & 0x0000000000800000LL && spellProto->SpellIconID == 561)
{
if(pVictim->hasUnitState(UNIT_STAT_STUNNED))
return true;
}
}
}
case SPELL_DAMAGE_CLASS_RANGED: case SPELL_DAMAGE_CLASS_RANGED:
{ {
if (pVictim) if (pVictim)
@ -9095,14 +9131,13 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damag
if(GetWeaponAttackType(spellProto) == RANGED_ATTACK) if(GetWeaponAttackType(spellProto) == RANGED_ATTACK)
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
else else
{
critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
}
} }
else else
critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE,GetSpellSchoolMask(spellProto)); critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE,GetSpellSchoolMask(spellProto));
critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, GetSpellSchoolMask(spellProto));
uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
critPctDamageMod += GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask); critPctDamageMod += GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask);
@ -9839,9 +9874,9 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60)) return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
} }
void Unit::Mount(uint32 mount) void Unit::Mount(uint32 mount, uint32 spellId)
{ {
if(!mount) if (!mount)
return; return;
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING); RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING);
@ -9850,9 +9885,27 @@ void Unit::Mount(uint32 mount)
SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT );
// unsummon pet if (GetTypeId() == TYPEID_PLAYER)
if(GetTypeId() == TYPEID_PLAYER) {
((Player*)this)->UnsummonPetTemporaryIfAny(); // Called by Taxi system / GM command
if (!spellId)
((Player*)this)->UnsummonPetTemporaryIfAny();
// Called by mount aura
else if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId))
{
// Flying case (Unsummon any pet)
if (IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))
((Player*)this)->UnsummonPetTemporaryIfAny();
// Normal case (Unsummon only permanent pet)
else if (Pet* pet = GetPet())
{
if (pet->IsPermanentPetFor((Player*)this))
((Player*)this)->UnsummonPetTemporaryIfAny();
else
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,true);
}
}
}
} }
void Unit::Unmount() void Unit::Unmount()
@ -9869,7 +9922,12 @@ void Unit::Unmount()
// this prevents adding a pet to a not created map which would otherwise cause a crash // this prevents adding a pet to a not created map which would otherwise cause a crash
// (it could probably happen when logging in after a previous crash) // (it could probably happen when logging in after a previous crash)
if(GetTypeId() == TYPEID_PLAYER) if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); {
if(Pet* pet = GetPet())
pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,false);
else
((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
}
} }
void Unit::SetInCombatWith(Unit* enemy) void Unit::SetInCombatWith(Unit* enemy)

View file

@ -1026,7 +1026,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
void Mount(uint32 mount); void Mount(uint32 mount, uint32 spellId = 0);
void Unmount(); void Unmount();
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9055" #define REVISION_NR "9086"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills" #define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills"
#define REVISION_DB_MANGOS "required_9045_02_mangos_spell_chain" #define REVISION_DB_MANGOS "required_9074_01_mangos_command"
#define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #define REVISION_DB_REALMD "required_9010_01_realmd_realmlist"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__