Merge commit 'origin/master' into 320

This commit is contained in:
tomrus88 2009-08-15 10:16:27 +04:00
commit 48a470dfc1
23 changed files with 471 additions and 193 deletions

View file

@ -23,7 +23,8 @@ DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`required_8342_01_mangos_spell_proc_event` bit(1) default NULL
`cache_id` int(10) default '0',
`required_8364_01_mangos_db_version` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -13591,6 +13592,7 @@ CREATE TABLE `spell_bonus_data` (
LOCK TABLES `spell_bonus_data` WRITE;
/*!40000 ALTER TABLE `spell_bonus_data` DISABLE KEYS */;
INSERT INTO `spell_bonus_data` VALUES
/* Death Knight */
('48721', '0', '0', '0.04', 'Death Knight - Blood Boil'),
('55078', '0', '0', '0.055', 'Death Knight - Blood Plague Dummy Proc'),
('50444', '0', '0', '0.105', 'Death Knight - Corpse Explosion Triggered'),
@ -13605,6 +13607,7 @@ INSERT INTO `spell_bonus_data` VALUES
('50536', '0', '0', '0.013', 'Death Knight - Unholy Blight Triggered'),
('50401', '0', '0', '0', 'Death Knight - Razor Frost'),
('56903', '0', '0', '0', 'Death Knight - Lichflame'),
/* Druid */
('5185', '1.6104', '0', '0', 'Druid - Healing Touch'),
('33763', '0', '0.09518', '0', 'Druid - Lifebloom'),
('774', '0', '0.37604', '0', 'Druid - Rejuvenation'),
@ -13621,6 +13624,7 @@ INSERT INTO `spell_bonus_data` VALUES
('8921', '0.1515', '0.13', '0', 'Druid - Moonfire'),
('2912', '1', '0', '0', 'Druid - Starfire'),
('5176', '0.5714', '0', '0', 'Druid - Wrath'),
/* Mage */
('30451', '0.7143', '0', '0', 'Mage - Arcane Blast'),
('1449', '0.2128', '0', '0', 'Mage - Arcane Explosion'),
('7268', '0.2857', '0', '0', 'Mage - Arcane Missiles Triggered Spell'),
@ -13642,6 +13646,7 @@ INSERT INTO `spell_bonus_data` VALUES
('11426', '0.8053', '0', '0', 'Mage - Ice Barrier'),
('30455', '0.1429', '0', '0', 'Mage - Ice Lance'),
('34913','0', '0', '0', 'Mage - Molten Armor Triggered'),
/* Paladin */
('19750','0.4286', '0', '0', 'Paladin - Flash of Light'),
('635', '0.7143', '0', '0', 'Paladin - Holy Light'),
('25912', '0.4286', '0', '0', 'Paladin - Holy Shock Triggered Hurt'),
@ -13662,7 +13667,7 @@ INSERT INTO `spell_bonus_data` VALUES
('25742', '0.07', '0', '0.039', 'Paladin - Seal of Righteousness Dummy Proc'),
('53595', '0', '0', '0','Paladin - Hammer of the Righteous'),
('31803', '0', '0.013', '0.15', 'Paladin - Holy Vengeance'),
('52042', '0.045', '0', '0', 'Shaman - Healing Stream Totem Triggered Heal'),
/* Priest */
('32546', '0.8068', '0', '0', 'Priest - Binding Heal'),
('34861', '0.402', '0', '0', 'Priest - Circle of Healing'),
('19236', '0.8068', '0', '0', 'Priest - Desperate Prayer'),
@ -13685,9 +13690,11 @@ INSERT INTO `spell_bonus_data` VALUES
('589', '0', '0.1829', '0', 'Priest - Shadow Word: Pain'),
('585', '0.714', '0', '0', 'Priest - Smite'),
('34914', '0', '0.4', '0', 'Priest - Vampiric Touch'),
/* Shaman */
('974', '0.4762', '0', '0', 'Shaman - Earth Shield'),
('1064', '1.34', '0', '0', 'Shaman - Chain Heal'),
('331', '1.6106', '0', '0', 'Shaman - Healing Wave'),
('52042', '0.045', '0', '0', 'Shaman - Healing Stream Totem Triggered Heal'),
('8004', '0.8082', '0', '0', 'Shaman - Lesser Healing Wave'),
('61295', '0.4', '0.18', '0', 'Shaman - Riptide'),
('421', '0.57', '0', '0', 'Shaman - Chain Lightning'),
@ -13702,6 +13709,7 @@ INSERT INTO `spell_bonus_data` VALUES
('26364', '0.33', '0', '0', 'Shaman - Lightning Shield Proc'),
('8188', '0.1', '0', '0', 'Shaman - Magma Totam Passive'),
('3606', '0.1667', '0', '0', 'Shaman - Searing Totem Attack'),
/* Warlock */
('980', '0', '0.1', '0', 'Warlock - Curse of Agony'),
('603', '0', '2', '0', 'Warlock - Curse of Doom'),
('172', '0', '0.3', '0', 'Warlock - Corruption'),
@ -13728,7 +13736,9 @@ INSERT INTO `spell_bonus_data` VALUES
('42223', '0.952', '0', '0', 'Warlock - Rain of Fire Triggered'),
('18220', '0.96', '0', '0', 'Warlock - Dark Pact'),
('6229', '0.3', '0', '0', 'Warlock - Shadow Ward'),
('63106', '0', '0', '0', 'Warlock - Siphon Life Triggered');
('63106', '0', '0', '0', 'Warlock - Siphon Life Triggered'),
/* Item */
(40293, 0, 0, 0, 'Item - Siphon Essence');
/*!40000 ALTER TABLE `spell_bonus_data` ENABLE KEYS */;
UNLOCK TABLES;

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8342_01_mangos_spell_proc_event required_8361_01_mangos_spell_bonus_data bit;
DELETE FROM `spell_bonus_data` where entry in (40293);
INSERT INTO `spell_bonus_data` VALUES
(40293, 0, 0, 0, 'Item - Siphon Essence');

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_8361_01_mangos_spell_bonus_data required_8364_01_mangos_db_version bit;
ALTER TABLE db_version
ADD COLUMN cache_id int(10) default '0' AFTER creature_ai_version;

View file

@ -80,6 +80,8 @@ pkgdata_DATA = \
8339_01_characters_characters.sql \
8339_02_characters_character_battleground_data.sql \
8342_01_mangos_spell_proc_event.sql \
8361_01_mangos_spell_bonus_data.sql \
8364_01_mangos_db_version.sql \
README
## Additional files to include when running 'make dist'
@ -140,4 +142,6 @@ EXTRA_DIST = \
8339_01_characters_characters.sql \
8339_02_characters_character_battleground_data.sql \
8342_01_mangos_spell_proc_event.sql \
8361_01_mangos_spell_bonus_data.sql \
8364_01_mangos_db_version.sql \
README

View file

@ -855,7 +855,7 @@ void BattleGround::RewardItem(Player *plr, uint32 item_id, uint32 count)
if( count != 0 && !dest.empty()) // can add some
if (Item* item = plr->StoreNewItem( dest, item_id, true, 0))
plr->SendNewItem(item,count,false,true);
plr->SendNewItem(item,count,true,false);
if (no_space_count > 0)
SendRewardMarkByMail(plr,item_id,no_space_count);

View file

@ -19,6 +19,11 @@
#ifndef DBCENUMS_H
#define DBCENUMS_H
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
// use as default max player level, must be fit max level for used client
// also see MAX_LEVEL and STRONG_MAX_LEVEL define
#define DEFAULT_MAX_LEVEL 80
// client supported max level for player/pets/etc. Avoid overflow or client stability affected.
// also see GT_MAX_LEVEL define
#define MAX_LEVEL 100

View file

@ -1094,8 +1094,8 @@ void Player::Update( uint32 p_time )
if( q_status.m_timer <= p_time )
{
uint32 quest_id = *iter;
++iter; // current iter will be removed in FailTimedQuest
FailTimedQuest( quest_id );
++iter; // current iter will be removed in FailQuest
FailQuest(quest_id);
}
else
{
@ -6510,13 +6510,20 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply)
void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply, bool only_level_scale /*= false*/)
{
if(slot >= INVENTORY_SLOT_BAG_END || !proto)
if (slot >= INVENTORY_SLOT_BAG_END || !proto)
return;
ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : NULL;
ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : NULL;
if (only_level_scale && !ssd)
return;
if(only_level_scale && !(ssd && ssv))
// req. check at equip, but allow use for extended range if range limit max level, set proper level
uint32 ssd_level = getLevel();
if (ssd && ssd_level > ssd->MaxLevel)
ssd_level = ssd->MaxLevel;
ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
if (only_level_scale && !ssv)
return;
for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
@ -9786,7 +9793,8 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo
}
ScalingStatDistributionEntry const *ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0;
if (ssd && ssd->MaxLevel < getLevel())
// check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items)
if (ssd && ssd->MaxLevel < DEFAULT_MAX_LEVEL && ssd->MaxLevel < getLevel())
return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED;
uint8 eslot = FindEquipSlot( pProto, slot, swap );
@ -12784,41 +12792,30 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
SetCanDelayTeleport(false);
}
void Player::FailQuest( uint32 quest_id )
void Player::FailQuest(uint32 questId)
{
if( quest_id )
if (Quest const* pQuest = objmgr.GetQuestTemplate(questId))
{
IncompleteQuest( quest_id );
SetQuestStatus(questId, QUEST_STATUS_FAILED);
uint16 log_slot = FindQuestSlot( quest_id );
if( log_slot < MAX_QUEST_LOG_SIZE)
uint16 log_slot = FindQuestSlot(questId);
if (log_slot < MAX_QUEST_LOG_SIZE)
{
SetQuestSlotTimer(log_slot, 1 );
SetQuestSlotState(log_slot,QUEST_STATE_FAIL);
SetQuestSlotTimer(log_slot, 1);
SetQuestSlotState(log_slot, QUEST_STATE_FAIL);
}
SendQuestFailed( quest_id );
}
}
void Player::FailTimedQuest( uint32 quest_id )
{
if( quest_id )
{
QuestStatusData& q_status = mQuestStatus[quest_id];
q_status.m_timer = 0;
if (q_status.uState != QUEST_NEW)
q_status.uState = QUEST_CHANGED;
IncompleteQuest( quest_id );
uint16 log_slot = FindQuestSlot( quest_id );
if( log_slot < MAX_QUEST_LOG_SIZE)
if (pQuest->HasFlag(QUEST_MANGOS_FLAGS_TIMED))
{
SetQuestSlotTimer(log_slot, 1 );
SetQuestSlotState(log_slot,QUEST_STATE_FAIL);
QuestStatusData& q_status = mQuestStatus[questId];
q_status.m_timer = 0;
SendQuestTimerFailed(questId);
}
SendQuestTimerFailed( quest_id );
else
SendQuestFailed(questId);
}
}
@ -13267,21 +13264,22 @@ bool Player::CanShareQuest(uint32 quest_id) const
return false;
}
void Player::SetQuestStatus( uint32 quest_id, QuestStatus status )
void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
{
Quest const* qInfo = objmgr.GetQuestTemplate(quest_id);
if( qInfo )
if (Quest const* qInfo = objmgr.GetQuestTemplate(quest_id))
{
if( status == QUEST_STATUS_NONE || status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_COMPLETE )
if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_FAILED)
{
if( qInfo->HasFlag( QUEST_MANGOS_FLAGS_TIMED ) )
if (qInfo->HasFlag(QUEST_MANGOS_FLAGS_TIMED))
m_timedquests.erase(qInfo->GetQuestId());
}
QuestStatusData& q_status = mQuestStatus[quest_id];
q_status.m_status = status;
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
if (q_status.uState != QUEST_NEW)
q_status.uState = QUEST_CHANGED;
}
UpdateForQuestWorldObjects();
@ -15124,16 +15122,20 @@ void Player::_LoadQuestStatus(QueryResult *result)
questStatusData.uState = QUEST_UNCHANGED;
// add to quest log
if( slot < MAX_QUEST_LOG_SIZE &&
( questStatusData.m_status == QUEST_STATUS_INCOMPLETE ||
questStatusData.m_status == QUEST_STATUS_COMPLETE &&
(!questStatusData.m_rewarded || pQuest->IsDaily()) ) )
if (slot < MAX_QUEST_LOG_SIZE &&
((questStatusData.m_status == QUEST_STATUS_INCOMPLETE ||
questStatusData.m_status == QUEST_STATUS_COMPLETE ||
questStatusData.m_status == QUEST_STATUS_FAILED) &&
(!questStatusData.m_rewarded || pQuest->IsDaily())))
{
SetQuestSlot(slot, quest_id, quest_time);
if(questStatusData.m_status == QUEST_STATUS_COMPLETE)
if (questStatusData.m_status == QUEST_STATUS_COMPLETE)
SetQuestSlotState(slot, QUEST_STATE_COMPLETE);
if (questStatusData.m_status == QUEST_STATUS_FAILED)
SetQuestSlotState(slot, QUEST_STATE_FAIL);
for(uint8 idx = 0; idx < QUEST_OBJECTIVES_COUNT; ++idx)
if(questStatusData.m_creatureOrGOcount[idx])
SetQuestSlotCounter(slot, idx, questStatusData.m_creatureOrGOcount[idx]);

View file

@ -1296,7 +1296,6 @@ class MANGOS_DLL_SPEC Player : public Unit
void IncompleteQuest( uint32 quest_id );
void RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce = true );
void FailQuest( uint32 quest_id );
void FailTimedQuest( uint32 quest_id );
bool SatisfyQuestSkillOrClass( Quest const* qInfo, bool msg );
bool SatisfyQuestLevel( Quest const* qInfo, bool msg );
bool SatisfyQuestLog( bool msg );

View file

@ -97,6 +97,7 @@ enum QuestStatus
QUEST_STATUS_UNAVAILABLE = 2,
QUEST_STATUS_INCOMPLETE = 3,
QUEST_STATUS_AVAILABLE = 4,
QUEST_STATUS_FAILED = 5,
MAX_QUEST_STATUS
};

View file

@ -1045,6 +1045,14 @@ enum Targets
TARGET_BEHIND_VICTIM = 65, // uses in teleport behind spells, caster/target dependent from spell effect
TARGET_DYNAMIC_OBJECT_COORDINATES = 76,
TARGET_SINGLE_ENEMY = 77,
TARGET_POINT_AT_NORTH = 78, // 78-85 possible _COORDINATES at radius with pi/4 step around target in unknown order, N?
TARGET_POINT_AT_SOUTH = 79, // S?
TARGET_POINT_AT_EAST = 80, // 80/81 must be symmetric from line caster->target, E (base at 82/83, 84/85 order) ?
TARGET_POINT_AT_WEST = 81, // 80/81 must be symmetric from line caster->target, W (base at 82/83, 84/85 order) ?
TARGET_POINT_AT_NE = 82, // from spell desc: "(NE)"
TARGET_POINT_AT_NW = 83, // from spell desc: "(NW)"
TARGET_POINT_AT_SE = 84, // from spell desc: "(SE)"
TARGET_POINT_AT_SW = 85, // from spell desc: "(SW)"
TARGET_SELF2 = 87,
TARGET_DIRECTLY_FORWARD = 89,
TARGET_NONCOMBAT_PET = 90,
@ -1833,11 +1841,26 @@ enum CreatureFamily
enum CreatureTypeFlags
{
CREATURE_TYPEFLAGS_TAMEABLE = 0x00001,
CREATURE_TYPEFLAGS_HERBLOOT = 0x00100,
CREATURE_TYPEFLAGS_MININGLOOT = 0x00200,
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x08000,
CREATURE_TYPEFLAGS_EXOTIC = 0x10000
CREATURE_TYPEFLAGS_TAMEABLE = 0x00001, //tameable by any hunter
CREATURE_TYPEFLAGS_UNK2 = 0x00002, //? Related to spirits/ghosts in any form? Allow gossip interaction if player is also ghost? Visibility?
CREATURE_TYPEFLAGS_UNK3 = 0x00004,
CREATURE_TYPEFLAGS_UNK4 = 0x00008,
CREATURE_TYPEFLAGS_UNK5 = 0x00010,
CREATURE_TYPEFLAGS_UNK6 = 0x00020,
CREATURE_TYPEFLAGS_UNK7 = 0x00040,
CREATURE_TYPEFLAGS_UNK8 = 0x00080,
CREATURE_TYPEFLAGS_HERBLOOT = 0x00100, //can be looted by herbalist
CREATURE_TYPEFLAGS_MININGLOOT = 0x00200, //can be looted by miner
CREATURE_TYPEFLAGS_UNK11 = 0x00400,
CREATURE_TYPEFLAGS_UNK12 = 0x00800, //? Related to mounts in some way. If mounted, fight mounted, mount appear as independant when rider dies?
CREATURE_TYPEFLAGS_UNK13 = 0x01000, //? Can aid any player in combat if in range?
CREATURE_TYPEFLAGS_UNK14 = 0x02000,
CREATURE_TYPEFLAGS_UNK15 = 0x04000, //? Possibly not in use
CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x08000, //can be looted by engineer
CREATURE_TYPEFLAGS_EXOTIC = 0x10000, //can be tamed by hunter as exotic pet
CREATURE_TYPEFLAGS_UNK18 = 0x20000, //? Related to veichles/pvp?
CREATURE_TYPEFLAGS_UNK19 = 0x40000, //? Related to veichle/siege weapons?
CREATURE_TYPEFLAGS_UNK20 = 0x80000
};
enum CreatureEliteType

View file

@ -1205,7 +1205,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
// can cause back attack (if detected)
if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) &&
if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) && !IsPositiveSpell(m_spellInfo->Id) &&
m_caster->isVisibleForOrDetect(unit,false)) // stealth removed at Spell::cast if spell break it
{
// use speedup check to avoid re-remove after above lines
@ -2110,6 +2110,39 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap)
if(DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell ? m_triggeredByAuraSpell->Id : m_spellInfo->Id))
m_targets.setDestination(dynObj->GetPositionX(), dynObj->GetPositionY(), dynObj->GetPositionZ());
break;
case TARGET_POINT_AT_NORTH:
case TARGET_POINT_AT_SOUTH:
case TARGET_POINT_AT_EAST:
case TARGET_POINT_AT_WEST:
case TARGET_POINT_AT_NE:
case TARGET_POINT_AT_NW:
case TARGET_POINT_AT_SE:
case TARGET_POINT_AT_SW:
{
if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
{
Unit* currentTarget = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
float angle = currentTarget != m_caster ? currentTarget->GetAngle(m_caster) : m_caster->GetOrientation();
switch(cur)
{
case TARGET_POINT_AT_NORTH: break;
case TARGET_POINT_AT_SOUTH: angle += M_PI; break;
case TARGET_POINT_AT_EAST: angle -= M_PI/2; break;
case TARGET_POINT_AT_WEST: angle += M_PI/2; break;
case TARGET_POINT_AT_NE: angle -= M_PI/4; break;
case TARGET_POINT_AT_NW: angle += M_PI/4; break;
case TARGET_POINT_AT_SE: angle -= 3*M_PI/4; break;
case TARGET_POINT_AT_SW: angle += 3*M_PI/4; break;
}
float x,y;
currentTarget->GetNearPoint2D(x,y,radius,angle);
m_targets.setDestination(x,y,currentTarget->GetPositionZ());
}
break;
}
case TARGET_DIRECTLY_FORWARD:
{
if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
@ -2345,6 +2378,9 @@ void Spell::cast(bool skipCheck)
if (m_spellInfo->Mechanic == MECHANIC_SHIELD &&
(m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000001)))
AddPrecastSpell(6788); // Weakened Soul
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000))
AddTriggeredSpell(41637);
switch(m_spellInfo->Id)
{
@ -2362,6 +2398,14 @@ void Spell::cast(bool skipCheck)
}
break;
}
case SPELLFAMILY_ROGUE:
// Fan of Knives (main hand)
if (m_spellInfo->Id == 51723 && m_caster->GetTypeId() == TYPEID_PLAYER &&
((Player*)m_caster)->haveOffhandWeapon())
{
AddTriggeredSpell(52874); // Fan of Knives (offhand)
}
break;
case SPELLFAMILY_PALADIN:
{
// Divine Shield, Divine Protection or Hand of Protection
@ -2783,12 +2827,16 @@ void Spell::finish(bool ok)
// Not drop combopoints if negative spell and if any miss on enemy exist
bool needDrop = true;
if (!IsPositiveSpell(m_spellInfo->Id))
for(std::list<TargetInfo>::const_iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
if (ihit->missCondition != SPELL_MISS_NONE && ihit->targetGUID!=m_caster->GetGUID())
{
for(std::list<TargetInfo>::const_iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
{
needDrop = false;
break;
if (ihit->missCondition != SPELL_MISS_NONE && ihit->targetGUID!=m_caster->GetGUID())
{
needDrop = false;
break;
}
}
}
if (needDrop)
((Player*)m_caster)->ClearComboPoints();
}
@ -3796,11 +3844,21 @@ SpellCastResult Spell::CheckCast(bool strict)
// auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
// this case can be triggered if rank not found (too low-level target for first rank)
if(m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
if (m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
{
for(int i=0;i<3;++i)
if(IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
if(target->getLevel() + 10 < m_spellInfo->spellLevel)
return SPELL_FAILED_LOWLEVEL;
{
// check only spell that apply positive auras
if (IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
// at not self target
!IsCasterSourceTarget(m_spellInfo->EffectImplicitTargetA[i]) &&
// and target low level
target->getLevel() + 10 < m_spellInfo->spellLevel)
{
return SPELL_FAILED_LOWLEVEL;
}
}
}
}
else if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster
{

View file

@ -2198,6 +2198,21 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
return;
}
case 36730: // Flame Strike
{
m_target->CastSpell(m_target, 36731, true, NULL, this);
return;
}
case 44191: // Flame Strike
{
if (m_target->GetMap()->IsDungeon())
{
uint32 spellId = m_target->GetMap()->IsHeroic() ? 46163 : 44190;
m_target->CastSpell(m_target, spellId, true, NULL, this);
}
return;
}
case 45934: // Dark Fiend
{
// Kill target if dispelled
@ -2389,6 +2404,19 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
return;
}
case 52610: // Savage Roar
{
if(apply)
{
if(m_target->m_form != FORM_CAT)
return;
m_target->CastSpell(m_target, 62071, true);
}
else
m_target-> RemoveAurasDueToSpell(62071);
return;
}
case 61336: // Survival Instincts
{
if(apply)
@ -2450,6 +2478,32 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
((Player*)m_target)->UpdateAttackPowerAndDamage();
return;
}
// Improved Moonkin Form
if(GetSpellProto()->SpellIconID == 2855)
{
uint32 spell_id;
switch(GetId())
{
case 48384: spell_id = 50170; //Rank 1
case 48395: spell_id = 50171; //Rank 2
case 48396: spell_id = 50172; //Rank 3
default:
sLog.outError("HandleAuraDummy: Not handled rank of IMF (Spell: %u)",GetId());
return;
}
if(apply)
{
if(m_target->m_form != FORM_MOONKIN)
return;
m_target->CastSpell(m_target, spell_id, true);
}
else
m_target-> RemoveAurasDueToSpell(spell_id);
return;
}
break;
}
case SPELLFAMILY_HUNTER:
@ -2721,10 +2775,12 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real)
{
SpellEntry const* aurSpellInfo = (*iter)->GetSpellProto();
uint32 aurMechMask = GetAllSpellMechanicMask(aurSpellInfo);
// If spell that caused this aura has Croud Control or Daze effect
if((GetAllSpellMechanicMask(aurSpellInfo) & MECHANIC_NOT_REMOVED_BY_SHAPESHIFT) ||
// some Daze spells have these parameters instead of MECHANIC_DAZE
(aurSpellInfo->SpellIconID == 15 && aurSpellInfo->Dispel == 0))
if((aurMechMask & MECHANIC_NOT_REMOVED_BY_SHAPESHIFT) ||
// some Daze spells have these parameters instead of MECHANIC_DAZE (skip snare spells)
aurSpellInfo->SpellIconID == 15 && aurSpellInfo->Dispel == 0 && (aurMechMask & (1 << MECHANIC_SNARE))==0)
{
++iter;
continue;
@ -5366,7 +5422,9 @@ void Aura::HandleShapeshiftBoosts(bool apply)
uint32 HotWSpellId = 0;
uint32 MasterShaperSpellId = 0;
switch(GetModifier()->m_miscvalue)
uint32 form = GetModifier()->m_miscvalue;
switch(form)
{
case FORM_CAT:
spellId = 3025;
@ -5438,8 +5496,6 @@ void Aura::HandleShapeshiftBoosts(bool apply)
break;
}
uint32 form = GetModifier()->m_miscvalue-1;
if(apply)
{
if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
@ -5455,7 +5511,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7))))
continue;
if (spellInfo->Stances & (1<<form))
if (spellInfo->Stances & (1<<(form-1)))
m_target->CastSpell(m_target, itr->first, true, NULL, this);
}
@ -5478,10 +5534,41 @@ void Aura::HandleShapeshiftBoosts(bool apply)
if (((Player*)m_target)->HasSpell(17007))
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
if (spellInfo && spellInfo->Stances & (1<<form))
if (spellInfo && spellInfo->Stances & (1<<(form-1)))
m_target->CastSpell(m_target, 24932, true, NULL, this);
}
// Savage Roar
if (form == FORM_CAT && ((Player*)m_target)->HasAura(52610))
m_target->CastSpell(m_target, 62071, true);
// Improved Moonkin Form
if (form == FORM_MOONKIN)
{
Unit::AuraList const& dummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = dummyAuras.begin(); i != dummyAuras.end(); i++)
{
if ((*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID &&
(*i)->GetSpellProto()->SpellIconID == 2855)
{
uint32 spell_id = 0;
switch((*i)->GetId())
{
case 48384:spell_id=50170;break;//Rank 1
case 48395:spell_id=50171;break;//Rank 2
case 48396:spell_id=50172;break;//Rank 3
default:
sLog.outError("Aura::HandleShapeshiftBoosts: Not handled rank of IMF (Spell: %u)",(*i)->GetId());
break;
}
if(spell_id)
m_target->CastSpell(m_target, spell_id, true, NULL, this);
break;
}
}
}
// Heart of the Wild
if (HotWSpellId)
{
@ -5519,9 +5606,6 @@ void Aura::HandleShapeshiftBoosts(bool apply)
++itr;
}
}
/*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
}
void Aura::HandleSpellSpecificBoosts(bool apply)
@ -5610,15 +5694,18 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
return;
}
// prevent aura deletion, specially in multi-boost case
SetInUse(true);
if (apply)
{
if (spellId1)
m_target->CastSpell(m_target, spellId1, true, NULL, this);
if (spellId2)
if (spellId2 && !IsDeleted())
m_target->CastSpell(m_target, spellId2, true, NULL, this);
if (spellId3)
if (spellId3 && !IsDeleted())
m_target->CastSpell(m_target, spellId3, true, NULL, this);
if (spellId4)
if (spellId4 && !IsDeleted())
m_target->CastSpell(m_target, spellId4, true, NULL, this);
}
else
@ -5632,6 +5719,8 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
if (spellId4)
m_target->RemoveAurasByCasterSpell(spellId4, GetCasterGUID());
}
SetInUse(false);
}
void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/)

View file

@ -1957,9 +1957,17 @@ void Spell::EffectForceCast(uint32 i)
unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID);
}
void Spell::EffectTriggerSpell(uint32 i)
void Spell::EffectTriggerSpell(uint32 effIndex)
{
uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
// only unit case known
if (!unitTarget)
{
if(gameObjTarget || itemTarget)
sLog.outError("Spell::EffectTriggerSpell (Spell: %u): Unsupported non-unit case!",m_spellInfo->Id);
return;
}
uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effIndex];
// special cases
switch(triggered_spell_id)
@ -1967,21 +1975,21 @@ void Spell::EffectTriggerSpell(uint32 i)
// Vanish (not exist)
case 18461:
{
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
// if this spell is given to NPC it must handle rest by it's own AI
if ( m_caster->GetTypeId() != TYPEID_PLAYER )
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
// get highest rank of the Stealth spell
uint32 spellId = 0;
const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
const PlayerSpellMap& sp_list = ((Player*)unitTarget)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
// only highest rank is shown in spell book, so simply check if shown in spell book
if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
if (!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
@ -2000,10 +2008,10 @@ void Spell::EffectTriggerSpell(uint32 i)
return;
// reset cooldown on it if needed
if(((Player*)m_caster)->HasSpellCooldown(spellId))
((Player*)m_caster)->RemoveSpellCooldown(spellId);
if (((Player*)unitTarget)->HasSpellCooldown(spellId))
((Player*)unitTarget)->RemoveSpellCooldown(spellId);
m_caster->CastSpell(m_caster, spellId, true);
m_caster->CastSpell(unitTarget, spellId, true);
return;
}
// just skip
@ -2043,7 +2051,7 @@ void Spell::EffectTriggerSpell(uint32 i)
// Cloak of Shadows
case 35729:
{
Unit::AuraMap& Auras = m_caster->GetAuras();
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
{
// remove all harmful spells on you...
@ -2061,7 +2069,7 @@ void Spell::EffectTriggerSpell(uint32 i)
// Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
case 41967:
{
if (Unit *pet = m_caster->GetPet())
if (Unit *pet = unitTarget->GetPet())
pet->CastSpell(pet, 28305, true);
return;
}
@ -2069,63 +2077,54 @@ void Spell::EffectTriggerSpell(uint32 i)
// normal case
SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
if(!spellInfo)
if (!spellInfo)
{
sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
return;
}
// select formal caster for triggered spell
Unit* caster = m_caster;
// some triggered spells require specific equipment
if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
if (spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
{
// main hand weapon required
if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
{
Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
// skip spell if no weapon in slot or broken
if(!item || item->IsBroken() )
if (!item || item->IsBroken() )
return;
// skip spell if weapon not fit to triggered spell
if(!item->IsFitToSpellRequirements(spellInfo))
if (!item->IsFitToSpellRequirements(spellInfo))
return;
}
// offhand hand weapon required
if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
{
Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
// skip spell if no weapon in slot or broken
if(!item || item->IsBroken() )
if (!item || item->IsBroken() )
return;
// skip spell if weapon not fit to triggered spell
if(!item->IsFitToSpellRequirements(spellInfo))
if (!item->IsFitToSpellRequirements(spellInfo))
return;
}
}
// some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
bool instant = false;
for(uint32 j = i+1; j < 3; ++j)
{
if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
{
instant = true;
break;
}
}
if(instant)
{
if (unitTarget)
m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
}
else
AddTriggeredSpell(spellInfo);
{
// Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true
// so this just for speedup places in else
caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster;
}
caster->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
}
void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
@ -2403,15 +2402,7 @@ void Spell::EffectApplyAura(uint32 i)
Aur->SetAuraDuration(duration);
}
bool added = unitTarget->AddAura(Aur);
// Aura not added and deleted in AddAura call;
if (!added)
return;
// Prayer of Mending (jump animation), we need formal caster instead original for correct animation
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000)))
m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID);
unitTarget->AddAura(Aur);
}
void Spell::EffectUnlearnSpecialization( uint32 i )
@ -2686,6 +2677,26 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype)
return;
}
// bg reward have some special in code work
uint32 bgType = 0;
switch(m_spellInfo->Id)
{
case SPELL_AV_MARK_WINNER:
case SPELL_AV_MARK_LOSER:
bgType = BATTLEGROUND_AV;
break;
case SPELL_WS_MARK_WINNER:
case SPELL_WS_MARK_LOSER:
bgType = BATTLEGROUND_WS;
break;
case SPELL_AB_MARK_WINNER:
case SPELL_AB_MARK_LOSER:
bgType = BATTLEGROUND_AB;
break;
default:
break;
}
uint32 num_to_add;
// TODO: maybe all this can be replaced by using correct calculated `damage` value
@ -2766,35 +2777,17 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype)
// send info to the client
if(pItem)
player->SendNewItem(pItem, num_to_add, true, true);
player->SendNewItem(pItem, num_to_add, true, bgType == 0);
// we succeeded in creating at least one item, so a levelup is possible
player->UpdateCraftSkill(m_spellInfo->Id);
if(bgType == 0)
player->UpdateCraftSkill(m_spellInfo->Id);
}
// for battleground marks send by mail if not add all expected
if(no_space > 0 )
if(no_space > 0 && bgType)
{
BattleGroundTypeId bgType;
switch(m_spellInfo->Id)
{
case SPELL_AV_MARK_WINNER:
case SPELL_AV_MARK_LOSER:
bgType = BATTLEGROUND_AV;
break;
case SPELL_WS_MARK_WINNER:
case SPELL_WS_MARK_LOSER:
bgType = BATTLEGROUND_WS;
break;
case SPELL_AB_MARK_WINNER:
case SPELL_AB_MARK_LOSER:
bgType = BATTLEGROUND_AB;
break;
default:
return;
}
if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundTypeId(bgType)))
bg->SendRewardMarkByMail(player, newitemid, no_space);
}
}
@ -4485,6 +4478,13 @@ void Spell::EffectWeaponDmg(uint32 i)
if(found)
totalDamagePercentMod *= 1.2f; // 120% if poisoned
}
// Fan of Knives
else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
{
Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true);
if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
totalDamagePercentMod *= 1.5f; // 150% to daggers
}
break;
}
case SPELLFAMILY_PALADIN:
@ -5054,6 +5054,11 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
return;
}
case 55693: // Remove Collapsing Cave Aura
if(unitTarget)
return;
unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex));
break;
case 58418: // Portal to Orgrimmar
case 58420: // Portal to Stormwind
{
@ -6061,8 +6066,11 @@ void Spell::EffectCharge(uint32 /*i*/)
if (!unitTarget)
return;
//TODO: research more ContactPoint/attack distance.
//3.666666 instead of ATTACK_DISTANCE(5.0f) in below seem to give more accurate result.
float x, y, z;
unitTarget->GetContactPoint(m_caster, x, y, z);
unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
((Creature *)unitTarget)->StopMoving();
@ -6090,7 +6098,7 @@ void Spell::EffectCharge2(uint32 /*i*/)
((Creature *)unitTarget)->StopMoving();
}
else if (unitTarget && unitTarget != m_caster)
unitTarget->GetContactPoint(m_caster, x, y, z);
unitTarget->GetContactPoint(m_caster, x, y, z, 3.666666f);
else
return;

View file

@ -301,15 +301,17 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
if (!spellproto) return false;
switch(spellId)
{
case 28441: // not positive dummy spell
case 37675: // Chaos Blast
return false;
}
switch(spellproto->Effect[effIndex])
{
case SPELL_EFFECT_DUMMY:
// some explicitly required dummy effect sets
switch(spellId)
{
case 28441: return false; // AB Effect 000
default:
break;
}
break;
// always positive effects (check before target checks that provided non-positive result in some case for positive effects)
case SPELL_EFFECT_HEAL:
case SPELL_EFFECT_LEARN_SPELL:
@ -349,15 +351,21 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
break;
}
} break;
case SPELL_AURA_MOD_STAT:
case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative)
case SPELL_AURA_MOD_STAT:
case SPELL_AURA_MOD_SKILL:
case SPELL_AURA_MOD_HEALING_PCT:
case SPELL_AURA_MOD_HEALING_DONE:
if(spellproto->CalculateSimpleValue(effIndex) < 0)
return false;
break;
case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative)
if(spellproto->CalculateSimpleValue(effIndex) > 0)
return false;
break;
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
if(spellproto->CalculateSimpleValue(effIndex) > 0)
return true; // some expected possitive spells have SPELL_ATTR_EX_NEGATIVE
return true; // some expected positive spells have SPELL_ATTR_EX_NEGATIVE
break;
case SPELL_AURA_ADD_TARGET_TRIGGER:
return true;
@ -391,11 +399,14 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
if(spellproto->Id == 17624)
return false;
break;
case SPELL_AURA_MOD_PACIFY_SILENCE:
if(spellproto->Id == 24740) // Wisp Costume
return true;
return false;
case SPELL_AURA_MOD_ROOT:
case SPELL_AURA_MOD_SILENCE:
case SPELL_AURA_GHOST:
case SPELL_AURA_PERIODIC_LEECH:
case SPELL_AURA_MOD_PACIFY_SILENCE:
case SPELL_AURA_MOD_STALKED:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
return false;
@ -460,14 +471,6 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
break;
}
} break;
case SPELL_AURA_MOD_HEALING_PCT:
if(spellproto->CalculateSimpleValue(effIndex) < 0)
return false;
break;
case SPELL_AURA_MOD_SKILL:
if(spellproto->CalculateSimpleValue(effIndex) < 0)
return false;
break;
case SPELL_AURA_FORCE_REACTION:
if(spellproto->Id==42792) // Recently Dropped Flag (prevent cancel)
return false;
@ -1411,6 +1414,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Survival Instincts and Survival Instincts
if( spellInfo_1->Id == 61336 && spellInfo_2->Id == 50322 || spellInfo_2->Id == 61336 && spellInfo_1->Id == 50322 )
return false;
// Savage Roar and Savage Roar (triggered)
if (spellInfo_1->SpellIconID == 2865 && spellInfo_2->SpellIconID == 2865)
return false;
}
// Leader of the Pack and Scroll of Stamina (multi-family check)
@ -2490,17 +2497,17 @@ void SpellMgr::LoadSpellAreas()
SpellAreaMapBounds sa_bounds = GetSpellAreaMapBounds(spellArea.spellId);
for(SpellAreaMap::const_iterator itr = sa_bounds.first; itr != sa_bounds.second; ++itr)
{
if(spellArea.spellId && itr->second.spellId && spellArea.spellId != itr->second.spellId)
if (spellArea.spellId != itr->second.spellId)
continue;
if(spellArea.areaId && itr->second.areaId && spellArea.areaId!= itr->second.areaId)
if (spellArea.areaId != itr->second.areaId)
continue;
if(spellArea.questStart && itr->second.questStart && spellArea.questStart!= itr->second.questStart)
if (spellArea.questStart != itr->second.questStart)
continue;
if(spellArea.auraSpell && itr->second.auraSpell && spellArea.auraSpell!= itr->second.auraSpell)
if (spellArea.auraSpell != itr->second.auraSpell)
continue;
if(spellArea.raceMask && itr->second.raceMask && (spellArea.raceMask & itr->second.raceMask)==0)
if ((spellArea.raceMask & itr->second.raceMask) == 0)
continue;
if(spellArea.gender != GENDER_NONE && itr->second.gender != GENDER_NONE && spellArea.gender!= itr->second.gender)
if (spellArea.gender != itr->second.gender)
continue;
// duplicate by requirements

View file

@ -240,9 +240,18 @@ inline bool IsCasterSourceTarget(uint32 target)
inline bool IsSpellWithCasterSourceTargetsOnly(SpellEntry const* spellInfo)
{
for(int i = 0; i < 3; ++i)
if(uint32 target = spellInfo->EffectImplicitTargetA[i])
if(!IsCasterSourceTarget(target))
return false;
{
uint32 targetA = spellInfo->EffectImplicitTargetA[i];
if(targetA && !IsCasterSourceTarget(targetA))
return false;
uint32 targetB = spellInfo->EffectImplicitTargetB[i];
if(targetB && !IsCasterSourceTarget(targetB))
return false;
if(!targetA && !targetB)
return false;
}
return true;
}
@ -257,6 +266,14 @@ inline bool IsPointEffectTarget( Targets target )
case TARGET_CURRENT_ENEMY_COORDINATES:
case TARGET_DUELVSPLAYER_COORDINATES:
case TARGET_DYNAMIC_OBJECT_COORDINATES:
case TARGET_POINT_AT_NORTH:
case TARGET_POINT_AT_SOUTH:
case TARGET_POINT_AT_EAST:
case TARGET_POINT_AT_WEST:
case TARGET_POINT_AT_NE:
case TARGET_POINT_AT_NW:
case TARGET_POINT_AT_SE:
case TARGET_POINT_AT_SW:
return true;
default:
break;

View file

@ -452,9 +452,10 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(cInfo && cInfo->lootid)
pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
// some critters required for quests
// some critters required for quests (need normal entry instead possible heroic in any cases)
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->KilledMonster(cInfo ,pVictim->GetGUID());
if(CreatureInfo const* normalInfo = objmgr.GetCreatureTemplate(pVictim->GetEntry()))
((Player*)this)->KilledMonster(normalInfo,pVictim->GetGUID());
return damage;
}
@ -3602,9 +3603,14 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
if(i_spellId == spellId) continue;
bool is_triggered_by_spell = false;
// prevent triggered aura of removing aura that triggered it
// prevent triggering aura of removing aura that triggered it
for(int j = 0; j < 3; ++j)
if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id)
if (i_spellProto->EffectTriggerSpell[j] == spellId)
is_triggered_by_spell = true;
// prevent triggered aura of removing aura that triggering it (triggered effect early some aura of parent spell
for(int j = 0; j < 3; ++j)
if (spellProto->EffectTriggerSpell[j] == i_spellId)
is_triggered_by_spell = true;
if (is_triggered_by_spell)
@ -5567,6 +5573,10 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 31876:
case 31877:
case 31878:
// triggered only at casted Judgement spells, not at additional Judgement effects
if(!procSpell || procSpell->Category != 1210)
return false;
target = this;
triggered_spell_id = 31930;
@ -11036,7 +11046,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
(isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
HandleMeandingAuraProc(triggeredByAura);
HandleMendingAuraProc(triggeredByAura);
break;
}
case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
@ -11816,7 +11826,7 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry con
return roll_chance_f(chance);
}
bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
bool Unit::HandleMendingAuraProc( Aura* triggeredByAura )
{
// aura can be deleted at casts
SpellEntry const* spellProto = triggeredByAura->GetSpellProto();
@ -11854,9 +11864,14 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
mod->mask = spellProto->SpellFamilyFlags;
mod->mask2 = spellProto->SpellFamilyFlags2;
// remove before apply next (locked against deleted)
triggeredByAura->SetInUse(true);
RemoveAurasByCasterSpell(spellProto->Id,caster->GetGUID());
caster->AddSpellMod(mod, true);
CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
caster->AddSpellMod(mod, false);
triggeredByAura->SetInUse(false);
}
}
}

View file

@ -1551,7 +1551,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown);
bool HandleMeandingAuraProc(Aura* triggeredByAura);
bool HandleMendingAuraProc(Aura* triggeredByAura);
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;

View file

@ -160,10 +160,10 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
else
creature.Say(behavior->textid[0], 0, 0);
}
i_hasDone[idx] = true;
MovementInform(creature);
} // wpBehaviour found
i_hasDone[idx] = true;
MovementInform(creature);
} // HasDone == false
} // i_creature.IsStopped()

View file

@ -237,6 +237,11 @@ World::AddSession_ (WorldSession* s)
s->SendPacket (&packet);
s->SendAddonsInfo();
WorldPacket pkt(SMSG_CLIENTCACHE_VERSION, 4);
pkt << uint32(sWorld.getConfig(CONFIG_CLIENTCACHE_VERSION));
s->SendPacket(&pkt);
s->SendTutorialsData();
UpdateMaxSessionCounters ();
@ -673,12 +678,12 @@ void World::LoadConfigSettings(bool reload)
if(reload)
{
uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", 80);
uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if(val!=m_configs[CONFIG_MAX_PLAYER_LEVEL])
sLog.outError("MaxPlayerLevel option can't be changed at mangosd.conf reload, using current value (%u).",m_configs[CONFIG_MAX_PLAYER_LEVEL]);
}
else
m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 80);
m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL)
{
@ -867,7 +872,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfig.GetIntDefault("MaxOverspeedPings",2);
if(m_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
{
sLog.outError("MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check. Set to 2.",m_configs[CONFIG_MAX_OVERSPEED_PINGS]);
sLog.outError("MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check). Set to 2.",m_configs[CONFIG_MAX_OVERSPEED_PINGS]);
m_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2;
}
@ -954,6 +959,18 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET] = sConfig.GetBoolDefault("OffhandCheckAtTalentsReset", false);
if(int clientCacheId = sConfig.GetIntDefault("ClientCacheVersion", 0))
{
// overwrite DB/old value
if(clientCacheId > 0)
{
m_configs[CONFIG_CLIENTCACHE_VERSION] = clientCacheId;
sLog.outString("Client cache version set to: %u", clientCacheId);
}
else
sLog.outError("ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
}
m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR);
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
@ -2115,13 +2132,16 @@ void World::UpdateMaxSessionCounters()
void World::LoadDBVersion()
{
QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version FROM db_version LIMIT 1");
QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version, cache_id FROM db_version LIMIT 1");
if(result)
{
Field* fields = result->Fetch();
m_DBVersion = fields[0].GetCppString();
m_CreatureEventAIVersion = fields[1].GetCppString();
// will be overwrite by config values if different and non-0
m_configs[CONFIG_CLIENTCACHE_VERSION] = fields[2].GetUInt32();
delete result;
}

View file

@ -212,6 +212,7 @@ enum WorldConfigs
CONFIG_ARENA_SEASON_ID,
CONFIG_ARENA_SEASON_IN_PROGRESS,
CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET,
CONFIG_CLIENTCACHE_VERSION,
CONFIG_VALUE_COUNT
};

View file

@ -569,6 +569,10 @@ LogColors = ""
# Default: 0 - recheck offhand slot weapon only at zone update
# 1 - recheck offhand slot weapon at talent reset also
#
# ClientCacheVersion
# Client cache version for client cache data reset. Use any different from DB value and not recently used for triggering reset.
# Default: 0 (use DB value from world DB db_version.cache_id field)
#
# Event.Announce
# Default: 0 (false)
# 1 (true)
@ -627,6 +631,7 @@ MailDeliveryDelay = 3600
SkillChance.Prospecting = 0
SkillChance.Milling = 0
OffhandCheckAtTalentsReset = 0
ClientCacheVersion = 0
Event.Announce = 0
BeepAtStart = 1
Motd = "Welcome to the Massive Network Game Object Server."

View file

@ -70,4 +70,8 @@ enum LoginResult
#define EXPECTED_MANGOS_CLIENT_BUILD {10257, 0}
// At update excepted builds please update if need define DEFAULT_MAX_LEVEL
// in DBCEnum.h to default max player level expected by build
// and also in mangosd.conf.in
#endif

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8342"
#define REVISION_NR "8372"
#endif // __REVISION_NR_H__