*Item enchancment/proc patch - original code by Thenecromancer
--HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE `spell_enchant_proc_data` (
|
||||
`entry` INT(10) UNSIGNED NOT NULL,
|
||||
`customChance` INT(10) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`PPMChance` FLOAT UNSIGNED NOT NULL DEFAULT '0',
|
||||
`procEx` FLOAT UNSIGNED NOT NULL DEFAULT '0'
|
||||
) ENGINE=MYISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Spell enchant proc data';
|
||||
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2, 0, 8.8,0);
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (12, 0, 8.8,0);
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (524, 0, 8.8,0);
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1667, 0, 8.8,0);
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1668, 0, 8.8,0);
|
||||
INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2635, 0, 8.8,0);
|
||||
+69
-35
@@ -6991,7 +6991,7 @@ void Player::UpdateEquipSpellsAtFormChange()
|
||||
}
|
||||
}
|
||||
|
||||
void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType)
|
||||
void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo)
|
||||
{
|
||||
if(!item || item->IsBroken())
|
||||
return;
|
||||
@@ -7000,46 +7000,53 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy
|
||||
if(!proto)
|
||||
return;
|
||||
|
||||
Unit * Target = damageInfo->target;
|
||||
WeaponAttackType attType = damageInfo->attackType;
|
||||
|
||||
if (!Target || Target == this )
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
// Can do effect if any damage done to target
|
||||
if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
|
||||
{
|
||||
_Spell const& spellData = proto->Spells[i];
|
||||
|
||||
// no spell
|
||||
if(!spellData.SpellId )
|
||||
continue;
|
||||
|
||||
// wrong triggering type
|
||||
if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT)
|
||||
continue;
|
||||
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId);
|
||||
if(!spellInfo)
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId);
|
||||
continue;
|
||||
_Spell const& spellData = proto->Spells[i];
|
||||
|
||||
// no spell
|
||||
if(!spellData.SpellId )
|
||||
continue;
|
||||
|
||||
// wrong triggering type
|
||||
if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT)
|
||||
continue;
|
||||
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId);
|
||||
if(!spellInfo)
|
||||
{
|
||||
sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// not allow proc extra attack spell at extra attack
|
||||
if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) )
|
||||
return;
|
||||
|
||||
float chance = spellInfo->procChance;
|
||||
|
||||
if(spellData.SpellPPMRate)
|
||||
{
|
||||
uint32 WeaponSpeed = GetAttackTime(attType);
|
||||
chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate);
|
||||
}
|
||||
else if(chance > 100.0f)
|
||||
{
|
||||
chance = GetWeaponProcChance();
|
||||
}
|
||||
|
||||
if (roll_chance_f(chance))
|
||||
CastSpell(Target, spellInfo->Id, true, item);
|
||||
}
|
||||
|
||||
// not allow proc extra attack spell at extra attack
|
||||
if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) )
|
||||
return;
|
||||
|
||||
float chance = spellInfo->procChance;
|
||||
|
||||
if(spellData.SpellPPMRate)
|
||||
{
|
||||
uint32 WeaponSpeed = GetAttackTime(attType);
|
||||
chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate);
|
||||
}
|
||||
else if(chance > 100.0f)
|
||||
{
|
||||
chance = GetWeaponProcChance();
|
||||
}
|
||||
|
||||
if (roll_chance_f(chance))
|
||||
CastSpell(Target, spellInfo->Id, true, item);
|
||||
}
|
||||
|
||||
// item combat enchantments
|
||||
@@ -7053,6 +7060,21 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy
|
||||
if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
|
||||
continue;
|
||||
|
||||
SpellEnchantProcEntry const* entry = spellmgr.GetSpellEnchantProcEvent(enchant_id);
|
||||
|
||||
if (entry && entry->procEx)
|
||||
{
|
||||
// Check hit/crit/dodge/parry requirement
|
||||
if((entry->procEx & damageInfo->procEx) == 0)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can do effect if any damage done to target
|
||||
if (!(damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE))
|
||||
continue;
|
||||
}
|
||||
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]);
|
||||
if (!spellInfo)
|
||||
{
|
||||
@@ -7061,6 +7083,18 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy
|
||||
}
|
||||
|
||||
float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance();
|
||||
|
||||
if (entry && entry->PPMChance)
|
||||
{
|
||||
uint32 WeaponSpeed = GetAttackTime(attType);
|
||||
chance = GetPPMProcChance(WeaponSpeed, entry->PPMChance);
|
||||
}
|
||||
else if (entry && entry->customChance)
|
||||
chance = entry->customChance;
|
||||
|
||||
// Apply spell mods
|
||||
ApplySpellMod(pEnchant->spellid[s],SPELLMOD_CHANCE_OF_SUCCESS,chance);
|
||||
|
||||
if (roll_chance_f(chance))
|
||||
{
|
||||
if(IsPositiveSpell(pEnchant->spellid[s]))
|
||||
|
||||
+1
-1
@@ -1797,7 +1797,7 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
void ApplyItemEquipSpell(Item *item, bool apply, bool form_change = false);
|
||||
void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false);
|
||||
void UpdateEquipSpellsAtFormChange();
|
||||
void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType);
|
||||
void CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo);
|
||||
|
||||
void SendInitWorldStates(bool force = false, uint32 forceZoneId = 0);
|
||||
void SendUpdateWorldState(uint32 Field, uint32 Value);
|
||||
|
||||
@@ -1330,6 +1330,58 @@ void SpellMgr::LoadSpellThreats()
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
void SpellMgr::LoadSpellEnchantProcData()
|
||||
{
|
||||
mSpellEnchantProcEventMap.clear(); // need for reload case
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
// 0 1 2 3
|
||||
QueryResult *result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx");
|
||||
if( !result )
|
||||
{
|
||||
|
||||
barGoLink bar( 1 );
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %u spell enchant proc event conditions", count );
|
||||
return;
|
||||
}
|
||||
|
||||
barGoLink bar( result->GetRowCount() );
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
bar.step();
|
||||
|
||||
uint32 enchantId = fields[0].GetUInt32();
|
||||
|
||||
SpellItemEnchantmentEntry const *ench = sSpellItemEnchantmentStore.LookupEntry(enchantId);
|
||||
if (!ench)
|
||||
{
|
||||
sLog.outErrorDb("Enchancment %u listed in `spell_enchant_proc_data` does not exist", enchantId);
|
||||
continue;
|
||||
}
|
||||
|
||||
SpellEnchantProcEntry spe;
|
||||
|
||||
spe.customChance = fields[1].GetUInt32();
|
||||
spe.PPMChance = fields[2].GetFloat();
|
||||
spe.procEx = fields[3].GetUInt32();
|
||||
|
||||
mSpellEnchantProcEventMap[enchantId] = spe;
|
||||
|
||||
++count;
|
||||
} while( result->NextRow() );
|
||||
|
||||
delete result;
|
||||
|
||||
sLog.outString( ">> Loaded %u enchant proc data definitions", count);
|
||||
}
|
||||
|
||||
bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const
|
||||
{
|
||||
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
|
||||
|
||||
@@ -564,6 +564,15 @@ struct SpellProcEventEntry
|
||||
|
||||
typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap;
|
||||
|
||||
struct SpellEnchantProcEntry
|
||||
{
|
||||
uint32 customChance;
|
||||
float PPMChance;
|
||||
uint32 procEx;
|
||||
};
|
||||
|
||||
typedef UNORDERED_MAP<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap;
|
||||
|
||||
#define ELIXIR_BATTLE_MASK 0x1
|
||||
#define ELIXIR_GUARDIAN_MASK 0x2
|
||||
#define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK)
|
||||
@@ -785,6 +794,14 @@ class SpellMgr
|
||||
|
||||
static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active);
|
||||
|
||||
SpellEnchantProcEntry const* GetSpellEnchantProcEvent(uint32 enchId) const
|
||||
{
|
||||
SpellEnchantProcEventMap::const_iterator itr = mSpellEnchantProcEventMap.find(enchId);
|
||||
if( itr != mSpellEnchantProcEventMap.end( ) )
|
||||
return &itr->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Spell target coordinates
|
||||
SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const
|
||||
{
|
||||
@@ -986,6 +1003,7 @@ class SpellMgr
|
||||
void LoadSpellPetAuras();
|
||||
void LoadSpellCustomAttr();
|
||||
void LoadSpellLinked();
|
||||
void LoadSpellEnchantProcData();
|
||||
|
||||
private:
|
||||
SpellScriptTarget mSpellScriptTarget;
|
||||
@@ -1002,6 +1020,7 @@ class SpellMgr
|
||||
SpellPetAuraMap mSpellPetAuraMap;
|
||||
SpellCustomAttribute mSpellCustomAttr;
|
||||
SpellLinkedMap mSpellLinkedMap;
|
||||
SpellEnchantProcEventMap mSpellEnchantProcEventMap;
|
||||
};
|
||||
|
||||
#define spellmgr SpellMgr::Instance()
|
||||
|
||||
+39
-5
@@ -1611,15 +1611,49 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
|
||||
}
|
||||
}
|
||||
|
||||
// If not miss
|
||||
if (!(damageInfo->HitInfo & HITINFO_MISS))
|
||||
if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive())
|
||||
{
|
||||
if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive())
|
||||
for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
|
||||
{
|
||||
for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++)
|
||||
((Player*)this)->CastItemCombatSpell(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), pVictim, damageInfo->attackType);
|
||||
EquipmentSlots slot = (EquipmentSlots)i;
|
||||
// For weapon slots check if valid attack type and if weapon useable
|
||||
if (i == EQUIPMENT_SLOT_MAINHAND
|
||||
|| i == EQUIPMENT_SLOT_OFFHAND
|
||||
|| i == EQUIPMENT_SLOT_RANGED)
|
||||
{
|
||||
switch (damageInfo->attackType)
|
||||
{
|
||||
case BASE_ATTACK: slot = EQUIPMENT_SLOT_MAINHAND; break;
|
||||
case OFF_ATTACK: slot = EQUIPMENT_SLOT_OFFHAND; break;
|
||||
case RANGED_ATTACK: slot = EQUIPMENT_SLOT_RANGED; break;
|
||||
}
|
||||
// offhand item cannot proc from main hand hit etc
|
||||
if (slot != i)
|
||||
slot=EQUIPMENT_SLOT_END;
|
||||
else
|
||||
{
|
||||
// Check if item is useable (forms or disarm)
|
||||
if (damageInfo->attackType == BASE_ATTACK)
|
||||
{
|
||||
if (!((Player*)this)->IsUseEquipedWeapon(true))
|
||||
slot=EQUIPMENT_SLOT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((Player*)this)->IsInFeralForm())
|
||||
slot=EQUIPMENT_SLOT_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If usable, try to cast item spell
|
||||
if(slot!=EQUIPMENT_SLOT_END)
|
||||
(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), &damageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Do effect if any damage done to target
|
||||
if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
|
||||
{
|
||||
// victim's damage shield
|
||||
std::set<Aura*> alreadyDone;
|
||||
uint32 removedAuras = pVictim->m_removedAuras;
|
||||
|
||||
@@ -1150,6 +1150,9 @@ void World::SetInitialWorldSettings()
|
||||
sLog.outString( "Loading NPC Texts..." );
|
||||
objmgr.LoadGossipText();
|
||||
|
||||
sLog.outString( "Loading Enchant Spells Proc datas...");
|
||||
spellmgr.LoadSpellEnchantProcData();
|
||||
|
||||
sLog.outString( "Loading Item Random Enchantments Table..." );
|
||||
LoadRandomEnchantmentsTable();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user