From 1c244cced512d069f748922055bb6b51ae7a85ee Mon Sep 17 00:00:00 2001 From: leak Date: Wed, 29 Dec 2010 17:18:29 +0100 Subject: [PATCH] Core/Entities: Fixed disarming and related exploits - Disarm shouldn't deduct stats other than weapon damage - Ferals shouldn't be affected by disarm - Fixed meta gem stacking exploit --- src/server/game/Entities/Player/Player.cpp | 94 +++++++++++-------- src/server/game/Entities/Player/Player.h | 1 + .../game/Spells/Auras/SpellAuraEffects.cpp | 39 +++++--- 3 files changed, 85 insertions(+), 49 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ca41e0ca7c..de2f5d16a3 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5730,9 +5730,9 @@ void Player::SetRegularAttackTime() ItemPrototype const *proto = tmpitem->GetProto(); if (proto->Delay) SetAttackTime(WeaponAttackType(i), proto->Delay); - else - SetAttackTime(WeaponAttackType(i), BASE_ATTACK_TIME); } + else + SetAttackTime(WeaponAttackType(i), BASE_ATTACK_TIME); // If there is no weapon reset attack time to base (might have been changed from forms) } } @@ -7368,10 +7368,6 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) uint8 attacktype = Player::GetAttackBySlot(slot); - // check disarm only on mod apply to allow remove item mods - if (!CanUseAttackType(attacktype)) - return; - if (proto->Socket[0].Color) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items CorrectMetaGemEnchants(slot, apply); @@ -7650,34 +7646,12 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl attType = OFF_ATTACK; } - float minDamage = proto->Damage[0].DamageMin; - float maxDamage = proto->Damage[0].DamageMax; - int32 extraDPS = 0; - // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage - if (ssv) - { - extraDPS = ssv->getDPSMod(proto->ScalingStatValue); - if (extraDPS) - { - float average = extraDPS * proto->Delay / 1000.0f; - minDamage = 0.7f * average; - maxDamage = 1.3f * average; - } - } - if (minDamage > 0) - { - damage = apply ? minDamage : BASE_MINDAMAGE; - SetBaseWeaponDamage(attType, MINDAMAGE, damage); - //sLog->outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE)); - } + if(CanUseAttackType(attType)) + _ApplyWeaponDamage(slot, proto, ssv, apply); - if (maxDamage > 0) - { - damage = apply ? maxDamage : BASE_MAXDAMAGE; - SetBaseWeaponDamage(attType, MAXDAMAGE, damage); - } + int32 extraDPS = ssv->getDPSMod(proto->ScalingStatValue); - // Apply feral bonus from ScalingStatValue if set + // Apply feral bonus from ScalingStatValue if set if (ssv) { if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue)) @@ -7691,10 +7665,53 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl ApplyFeralAPBonus(feral_bonus, apply); } - if (IsInFeralForm() || !CanUseAttackType(attType)) - return; + } - if (proto->Delay) +void Player::_ApplyWeaponDamage(uint8 slot, ItemPrototype const *proto, ScalingStatValuesEntry const *ssv, bool apply) +{ + WeaponAttackType attType = BASE_ATTACK; + float damage = 0.0f; + + if (slot == EQUIPMENT_SLOT_RANGED && ( + proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN || + proto->InventoryType == INVTYPE_RANGEDRIGHT)) + { + attType = RANGED_ATTACK; + } + else if (slot == EQUIPMENT_SLOT_OFFHAND) + { + attType = OFF_ATTACK; + } + + float minDamage = proto->Damage[0].DamageMin; + float maxDamage = proto->Damage[0].DamageMax; + int32 extraDPS = 0; + + // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage + if (ssv) + { + extraDPS = ssv->getDPSMod(proto->ScalingStatValue); + if (extraDPS) + { + float average = extraDPS * proto->Delay / 1000.0f; + minDamage = 0.7f * average; + maxDamage = 1.3f * average; + } + } + + if (minDamage > 0) + { + damage = apply ? minDamage : BASE_MINDAMAGE; + SetBaseWeaponDamage(attType, MINDAMAGE, damage); + } + + if (maxDamage > 0) + { + damage = apply ? maxDamage : BASE_MAXDAMAGE; + SetBaseWeaponDamage(attType, MAXDAMAGE, damage); + } + + if (proto->Delay && !IsInFeralForm()) { if (slot == EQUIPMENT_SLOT_RANGED) SetAttackTime(RANGED_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); @@ -7704,6 +7721,10 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); } + // No need to modify any physical damage for ferals as it is calculated from stats only + if (IsInFeralForm()) + return; + if (CanModifyStats() && (damage || proto->Delay)) UpdateDamagePhysical(attType); } @@ -13168,9 +13189,6 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool if (!item || !item->IsEquipped()) return; - if (!CanUseAttackType(Player::GetAttackBySlot(item->GetSlot()))) - return; - if (slot >= MAX_ENCHANTMENT_SLOT) return; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index de4b62eed8..d1f217d7a3 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2012,6 +2012,7 @@ class Player : public Unit, public GridObject void _ApplyAllItemMods(); void _ApplyAllLevelScaleItemMods(bool apply); void _ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply, bool only_level_scale = false); + void _ApplyWeaponDamage(uint8 slot, ItemPrototype const *proto, ScalingStatValuesEntry const *ssv, bool apply); void _ApplyAmmoBonuses(); bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot); void ToggleMetaGemsActive(uint8 exceptslot, bool apply); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 87a951b793..3afd452044 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3200,8 +3200,20 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const * aurApp, uint8 m { // Dash if (AuraEffect * aurEff =target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8)) - aurEff->RecalculateAmount(); + aurEff->RecalculateAmount(); + + // Disarm handling + // If druid shifts while being disarmed we need to deal with that since forms aren't affected by disarm + // and also HandleAuraModDisarm is not triggered + if(!target->CanUseAttackType(BASE_ATTACK)) + { + if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + { + target->ToPlayer()->_ApplyWeaponDamage(EQUIPMENT_SLOT_MAINHAND, pItem->GetProto(), NULL, apply); + } + } } + if (target->GetTypeId() == TYPEID_PLAYER) { SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form); @@ -3563,21 +3575,26 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const * aurApp, uint8 mode, return; } - if (!(apply)) + if (!apply) target->RemoveFlag(field, flag); - if (target->GetTypeId() == TYPEID_PLAYER) - { - // This is between the two because there is a check in _ApplyItemMods - // we must make sure that flag is always removed when call that function - // refer to DurabilityPointsLoss - if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) - target->ToPlayer()->_ApplyItemMods(pItem, slot, !apply); - } - if (apply) target->SetFlag(field, flag); + // Handle damage modifcation, shapeshifted druids are not affected + if (target->GetTypeId() == TYPEID_PLAYER && !target->IsInFeralForm()) + { + if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + { + uint8 attacktype = Player::GetAttackBySlot(slot); + + if (attacktype < MAX_ATTACK) + target->ToPlayer()->_ApplyWeaponDamage(slot, pItem->GetProto(), NULL, !apply); + } + } + + + if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->GetCurrentEquipmentId()) target->UpdateDamagePhysical(attType); }