aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game/Spell.cpp177
-rw-r--r--src/game/Spell.h1
-rw-r--r--src/game/SpellEffects.cpp95
-rw-r--r--src/shared/Database/DBCStructure.h10
4 files changed, 105 insertions, 178 deletions
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 7ecf1ff4b8d..bfc58631079 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -4076,115 +4076,31 @@ uint8 Spell::CanCast(bool strict)
return SPELL_FAILED_TRY_AGAIN;
// get the lock entry
- LockEntry const *lockInfo = NULL;
+ uint32 lockId = 0;
if (GameObject* go=m_targets.getGOTarget())
- lockInfo = sLockStore.LookupEntry(go->GetLockId());
+ lockId = go->GetLockId();
else if(Item* itm=m_targets.getItemTarget())
- lockInfo = sLockStore.LookupEntry(itm->GetProto()->LockID);
+ lockId = itm->GetProto()->LockID;
- // check lock compatibility
- if (lockInfo)
- {
- // check for lock - key pair (checked by client also, just prevent cheating
- bool ok_key = false;
- bool req_key = false;
- for(int it = 0; it < 8; ++it)
- {
- switch(lockInfo->Type[it])
- {
- case LOCK_KEY_NONE:
- break;
- case LOCK_KEY_ITEM:
- {
- req_key = true;
- if(lockInfo->Index[it])
- {
- if(m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
- ok_key =true;
- break;
- }
- }
- case LOCK_KEY_SKILL:
- {
- req_key = true;
- if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->Index[it])
- break;
-
- SkillType skill = SkillByLockType(LockType(lockInfo->Index[it]));
- if(skill==SKILL_NONE)
- ok_key =true;
- else if(((Player*)m_caster)->HasSkill(skill))
- ok_key =true;
- }
- }
- if(ok_key)
- break;
- }
+ SkillType skillId =SKILL_NONE;
+ int32 reqSkillValue = 0;
+ int32 skillValue = 0;
- if(!ok_key && req_key)
- return SPELL_FAILED_BAD_TARGETS;
- }
+ // check lock compatibility
+ SpellCastResult res = CanOpenLock(i,lockId,skillId,reqSkillValue,skillValue);
+ if(res != SPELL_CAST_OK)
+ return res;
// chance for fail at orange mining/herb/LockPicking gathering attempt
- if (!m_selfContainer || ((*m_selfContainer) != this))
- break;
-
- // get the skill value of the player
- int32 SkillValue = 0;
- bool canFailAtMax = true;
- if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_HERBALISM)
- {
- SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_HERBALISM);
- canFailAtMax = false;
- }
- else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_MINING)
- {
- SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_MINING);
- canFailAtMax = false;
- }
- else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
- SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_LOCKPICKING);
-
- // castitem check: rogue using skeleton keys. the skill values should not be added in this case.
- if(m_CastItem)
- SkillValue = 0;
-
- // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value)
- // TODO: is this a hack?
- SkillValue += m_currentBasePoints[i]+1;
-
- // get the required lock value
- int32 ReqValue=0;
- if (lockInfo)
+ // second check prevent fail at rechecks
+ if(skillId != SKILL_NONE && (!m_selfContainer || ((*m_selfContainer) != this)))
{
- // check for lock - key pair
- bool ok = false;
- for(int it = 0; it < 8; ++it)
- {
- if(lockInfo->Type[it]==LOCK_KEY_ITEM && lockInfo->Index[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
- {
- // if so, we're good to go
- ok = true;
- break;
- }
- }
- if(ok)
- break;
+ bool canFailAtMax = skillId != SKILL_HERBALISM && skillId != SKILL_MINING;
- if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
- ReqValue = lockInfo->Skill[1];
- else
- ReqValue = lockInfo->Skill[0];
+ // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill)
+ if((canFailAtMax || skillValue < sWorld.GetConfigMaxSkillValue()) && reqSkillValue > irand(skillValue-25, skillValue+37))
+ return SPELL_FAILED_TRY_AGAIN;
}
-
- // skill doesn't meet the required value
- if (ReqValue > SkillValue)
- return SPELL_FAILED_LOW_CASTLEVEL;
-
- // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill)
- if((canFailAtMax || SkillValue < sWorld.GetConfigMaxSkillValue()) && ReqValue > irand(SkillValue-25, SkillValue+37))
- return SPELL_FAILED_TRY_AGAIN;
-
break;
}
case SPELL_EFFECT_SUMMON_DEAD_PET:
@@ -5729,3 +5645,64 @@ int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *mul
return damageDone;
}
+SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue)
+{
+ if(!lockId) // possible case for GO and maybe for items.
+ return SPELL_CAST_OK;
+
+ // Get LockInfo
+ LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
+
+ if (!lockInfo)
+ return SPELL_FAILED_BAD_TARGETS;
+
+ bool reqKey = false; // some locks not have reqs
+
+ for(int j = 0; j < 8; ++j)
+ {
+ switch(lockInfo->Type[j])
+ {
+ // check key item (many fit cases can be)
+ case LOCK_KEY_ITEM:
+ if(lockInfo->Index[j] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[j])
+ return SPELL_CAST_OK;
+ reqKey = true;
+ break;
+ // check key skill (only single first fit case can be)
+ case LOCK_KEY_SKILL:
+ {
+ reqKey = true;
+
+ // wrong locktype, skip
+ if(uint32(m_spellInfo->EffectMiscValue[effIndex]) != lockInfo->Index[j])
+ continue;
+
+ skillId = SkillByLockType(LockType(lockInfo->Index[j]));
+
+ if ( skillId != SKILL_NONE )
+ {
+ // skill bonus provided by casting spell (mostly item spells)
+ // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value)
+ uint32 spellSkillBonus = uint32(m_currentBasePoints[effIndex]+1);
+ reqSkillValue = lockInfo->Skill[j];
+
+ // castitem check: rogue using skeleton keys. the skill values should not be added in this case.
+ skillValue = m_CastItem || m_caster->GetTypeId()!= TYPEID_PLAYER ?
+ 0 : ((Player*)m_caster)->GetSkillValue(skillId);
+
+ skillValue += spellSkillBonus;
+
+ if (skillValue < reqSkillValue)
+ return SPELL_FAILED_LOW_CASTLEVEL;
+ }
+
+ return SPELL_CAST_OK;
+ }
+ }
+ }
+
+ if(reqKey)
+ return SPELL_FAILED_BAD_TARGETS;
+
+ return SPELL_CAST_OK;
+}
diff --git a/src/game/Spell.h b/src/game/Spell.h
index f28d55b23a1..1fb074a396c 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -595,6 +595,7 @@ class Spell
void SpellDamageSchoolDmg(uint32 i);
void SpellDamageWeaponDmg(uint32 i);
void SpellDamageHeal(uint32 i);
+ SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
// -------------------------------------------
//List For Triggered Spells
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 4f5e630c56b..e494274b751 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -3143,92 +3143,39 @@ void Spell::EffectOpenLock(uint32 effIndex)
return;
}
- if(!lockId) // possible case for GO and maybe for items.
- {
- SendLoot(guid, LOOT_CORPSE);
- return;
- }
+ SkillType skillId = SKILL_NONE;
+ int32 reqSkillValue = 0;
+ int32 skillValue;
- // Get LockInfo
- LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
-
- if (!lockInfo)
+ SpellCastResult res = CanOpenLock(effIndex,lockId,skillId,reqSkillValue,skillValue);
+ if(res != SPELL_CAST_OK)
{
- sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
- (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
- SendCastResult(SPELL_FAILED_BAD_TARGETS);
+ SendCastResult(res);
return;
}
- bool reqKey = false; // some locks not have reqs
+ SendLoot(guid, LOOT_SKINNING);
- for(int j = 0; j < 8; ++j)
+ // not allow use skill grou at item base open
+ if(!m_CastItem && skillId != SKILL_NONE)
{
- switch(lockInfo->Type[j])
+ // update skill if really known
+ if(uint32 pureSkillValue = player->GetPureSkillValue(skillId))
{
- // check key item (many fit cases can be)
- case LOCK_KEY_ITEM:
- if(lockInfo->Index[j] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[j])
- {
- SendLoot(guid, LOOT_CORPSE);
- return;
- }
- reqKey = true;
- break;
- // check key skill (only single first fit case can be)
- case LOCK_KEY_SKILL:
+ if(gameObjTarget)
{
- reqKey = true;
-
- // wrong locktype, skip
- if(uint32(m_spellInfo->EffectMiscValue[effIndex]) != lockInfo->Index[j])
- continue;
-
- SkillType skillId = SkillByLockType(LockType(lockInfo->Index[j]));
-
- if ( skillId != SKILL_NONE )
- {
- // skill bonus provided by casting spell (mostly item spells)
- uint32 spellSkillBonus = uint32(damage);
- uint32 reqSkillValue = lockInfo->Skill[j];
-
- if ( player->GetSkillValue(skillId) + spellSkillBonus < reqSkillValue )
- {
- SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
- return;
- }
-
- // update skill if really known
- if(uint32 SkillValue = player->GetPureSkillValue(skillId))
- {
- if(gameObjTarget)
- {
- // Allow one skill-up until respawned
- if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
- player->UpdateGatherSkill(skillId, SkillValue, reqSkillValue) )
- gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
- }
- else if(itemTarget)
- {
- // Do one skill-up
- player->UpdateGatherSkill(skillId, SkillValue, reqSkillValue);
- }
- }
- }
-
- SendLoot(guid, LOOT_SKINNING);
- return;
+ // Allow one skill-up until respawned
+ if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
+ player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) )
+ gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
+ }
+ else if(itemTarget)
+ {
+ // Do one skill-up
+ player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue);
}
}
}
-
- if(reqKey)
- {
- SendCastResult(SPELL_FAILED_BAD_TARGETS);
- return;
- }
-
- SendLoot(guid, LOOT_SKINNING);
}
void Spell::EffectSummonChangeItem(uint32 i)
diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h
index 8f2fa87e17f..12fa9f7d323 100644
--- a/src/shared/Database/DBCStructure.h
+++ b/src/shared/Database/DBCStructure.h
@@ -981,13 +981,15 @@ struct ItemSetEntry
uint32 required_skill_value; // 52 m_requiredSkillRank
};
+#define MAX_LOCK_CASE 8
+
struct LockEntry
{
uint32 ID; // 0 m_ID
- uint32 Type[8]; // 1-8 m_Type
- uint32 Index[8]; // 9-16 m_Index
- uint32 Skill[8]; // 17-24 m_Skill
- //uint32 Action[8]; // 25-32 m_Action
+ uint32 Type[MAX_LOCK_CASE]; // 1-8 m_Type
+ uint32 Index[MAX_LOCK_CASE]; // 9-16 m_Index
+ uint32 Skill[MAX_LOCK_CASE]; // 17-24 m_Skill
+ //uint32 Action[MAX_LOCK_CASE]; // 25-32 m_Action
};
struct MailTemplateEntry