diff options
author | megamage <none@none> | 2009-02-03 15:05:04 -0600 |
---|---|---|
committer | megamage <none@none> | 2009-02-03 15:05:04 -0600 |
commit | 3b8bce566ec9d3e56e35ebc3c3a0e9136faabdc6 (patch) | |
tree | d6c99472398f57257198200f1599952d000619bf | |
parent | 7fdb40ec5cfe99ad97d8c0768538d7a7b60016d8 (diff) | |
parent | 516cb0c6da103f2e5297beab80a19dfc88ffb4af (diff) |
*Merge.
--HG--
branch : trunk
-rw-r--r-- | src/game/Player.cpp | 31 | ||||
-rw-r--r-- | src/game/Player.h | 13 | ||||
-rw-r--r-- | src/game/Spell.cpp | 66 | ||||
-rw-r--r-- | src/game/Spell.h | 1 | ||||
-rw-r--r-- | src/game/SpellAuraDefines.h | 14 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 83 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 29 | ||||
-rw-r--r-- | src/game/SpellHandler.cpp | 4 | ||||
-rw-r--r-- | src/game/StatSystem.cpp | 11 | ||||
-rw-r--r-- | src/game/Unit.cpp | 88 | ||||
-rw-r--r-- | src/game/Unit.h | 14 |
11 files changed, 233 insertions, 121 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9366907c9b1..985865cb812 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6742,7 +6742,12 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) sLog.outDetail("applying mods for item %u ",item->GetGUIDLow()); - uint32 attacktype = Player::GetAttackBySlot(slot); + uint8 attacktype = Player::GetAttackBySlot(slot); + + //check disarm only on mod apply to allow remove item mods + if (apply && !CanUseAttackType(attacktype) ) + return; + if(attacktype < MAX_ATTACK) _ApplyWeaponDependentAuraMods(item,WeaponAttackType(attacktype),apply); @@ -6993,7 +6998,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl SetBaseWeaponDamage(attType, MAXDAMAGE, damage); } - if(!IsUseEquipedWeapon(slot==EQUIPMENT_SLOT_MAINHAND)) + if(IsInFeralForm()) return; if (proto->Delay) @@ -8883,14 +8888,14 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons default: return NULL; } - Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, slot); if (!item || item->GetProto()->Class != ITEM_CLASS_WEAPON) return NULL; if(!useable) return item; - if( item->IsBroken() || !IsUseEquipedWeapon(attackType==BASE_ATTACK) ) + if( item->IsBroken() || IsInFeralForm()) return NULL; return item; @@ -8898,7 +8903,7 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons Item* Player::GetShield(bool useable) const { - Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if (!item || item->GetProto()->Class != ITEM_CLASS_ARMOR) return NULL; @@ -8911,7 +8916,7 @@ Item* Player::GetShield(bool useable) const return item; } -uint32 Player::GetAttackBySlot( uint8 slot ) +uint8 Player::GetAttackBySlot( uint8 slot ) { switch(slot) { @@ -9177,13 +9182,13 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const Item *pItem; for(uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) { - pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + pItem = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } for(uint8 i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; ++i) { - pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + pItem = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } @@ -9193,7 +9198,7 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const { for(uint32 j = 0; j < pBag->GetBagSize(); ++j) { - pItem = GetItemByPos( i, j ); + pItem = GetUseableItemByPos( i, j ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } @@ -19154,7 +19159,7 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons case ITEM_CLASS_WEAPON: { for(int i= EQUIPMENT_SLOT_MAINHAND; i < EQUIPMENT_SLOT_TABARD; ++i) - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i )) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; break; @@ -19163,17 +19168,17 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons { // tabard not have dependent spells for(int i= EQUIPMENT_SLOT_START; i< EQUIPMENT_SLOT_MAINHAND; ++i) - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i )) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; // shields can be equipped to offhand slot - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; // ranged slot can have some armor subclasses - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; diff --git a/src/game/Player.h b/src/game/Player.h index d27137c7cc9..f7858f3419b 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1061,9 +1061,15 @@ class TRINITY_DLL_SPEC Player : public Unit Item* GetItemByGuid( uint64 guid ) const; Item* GetItemByPos( uint16 pos ) const; Item* GetItemByPos( uint8 bag, uint8 slot ) const; + inline Item* Player::GetUseableItemByPos( uint8 bag, uint8 slot ) const //Does additional check for disarmed weapons + { + if (!CanUseAttackType(GetAttackBySlot(slot))) + return NULL; + return GetItemByPos(bag, slot); + } Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const; Item* GetShield(bool useable = false) const; - static uint32 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot + static uint8 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot std::vector<Item *> &GetItemUpdateQueue() { return m_itemUpdateQueue; } static bool IsInventoryPos( uint16 pos ) { return IsInventoryPos(pos >> 8,pos & 255); } static bool IsInventoryPos( uint8 bag, uint8 slot ); @@ -1153,11 +1159,6 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetWeaponProficiency() const { return m_WeaponProficiency; } uint32 GetArmorProficiency() const { return m_ArmorProficiency; } bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; } - bool IsUseEquipedWeapon( bool mainhand ) const - { - // disarm applied only to mainhand weapon - return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); - } bool IsTwoHandUsed() const { Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index ddac7d5c970..36766c67011 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1442,6 +1442,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; + Unit::AuraList const& Auras = m_caster->GetAurasByType(SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS); + for(Unit::AuraList::const_iterator j = Auras.begin();j != Auras.end(); ++j) + { + if((*j)->isAffectedOnSpell(m_spellInfo)) + unMaxTargets+=(*j)->GetModifier()->m_amount; + } + if(m_originalCaster) { if(Player* modOwner = m_originalCaster->GetSpellModOwner()) @@ -3294,6 +3301,35 @@ void Spell::TakePower() m_caster->SetLastManaUse(getMSTime()); } +void Spell::TakeAmmo() +{ + if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) + { + Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); + + // wands don't have ammo + if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) + return; + + if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) + { + if(pItem->GetMaxStackCount()==1) + { + // decrease durability for non-stackable throw weapon + ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); + } + else + { + // decrease items amount for stackable throw weapon + uint32 count = 1; + ((Player*)m_caster)->DestroyItemCount( pItem, count, true); + } + } + else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) + ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); + } +} + uint8 Spell::CheckRuneCost(uint32 runeCostID) { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -5618,6 +5654,14 @@ void Spell::CalculateDamageDoneForAllTargets() } } + bool usesAmmo=true; + Unit::AuraList const& Auras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO); + for(Unit::AuraList::const_iterator j = Auras.begin();j != Auras.end(); ++j) + { + if((*j)->isAffectedOnSpell(m_spellInfo)) + usesAmmo=false; + } + for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { TargetInfo &target = *ihit; @@ -5630,6 +5674,28 @@ void Spell::CalculateDamageDoneForAllTargets() if (!unit) continue; + if (usesAmmo) + { + bool ammoTaken=false; + for (uint8 i=0;i<3;i++) + { + if (!(mask & 1<<i)) + continue; + switch (m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + ammoTaken=true; + TakeAmmo(); + } + if (ammoTaken) + break; + } + } + if (target.missCondition==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target target.damage += CalculateDamageDone(unit, mask, multiplier); else if (target.missCondition == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit) diff --git a/src/game/Spell.h b/src/game/Spell.h index ac7f8c8c7ea..38345525b65 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -360,6 +360,7 @@ class Spell void cast(bool skipCheck = false); void finish(bool ok = true); void TakePower(); + void TakeAmmo(); uint8 CheckRuneCost(uint32 runeCostID); void TakeRunePower(); void TakeReagents(); diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index abe3438aa43..77270d20c7f 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -238,8 +238,8 @@ enum AuraType SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, SPELL_AURA_HASTE_MELEE = 192, SPELL_AURA_MELEE_SLOW = 193, - SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194, - SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL = 195, + SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL = 194, + SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL = 195, SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198, @@ -298,7 +298,7 @@ enum AuraType SPELL_AURA_MOD_ENEMY_DODGE = 251, SPELL_AURA_252 = 252, SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, - SPELL_AURA_MOD_DISARM_SHIELD = 254, + SPELL_AURA_MOD_DISARM_OFFHAND = 254, SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, SPELL_AURA_NO_REAGENT_USE = 256, SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, @@ -313,15 +313,15 @@ enum AuraType SPELL_AURA_266 = 266, SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, - SPELL_AURA_269 = 269, - SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive + SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269, + SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, SPELL_AURA_272 = 272, SPELL_AURA_273 = 273, - SPELL_AURA_274 = 274, + SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274, SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done - SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277, + SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS = 277, SPELL_AURA_MOD_DISARM_RANGED = 278, SPELL_AURA_279 = 279, SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE = 280, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index f831dc2d045..58d1b6253d4 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -248,8 +248,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleUnused, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL - &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage + &Aura::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist + &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS @@ -308,7 +308,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE &Aura::HandleNULL, //252 haste all? &Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE - &Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield + &Aura::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select @@ -323,16 +323,16 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //266 unused &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT - &Aura::HandleNULL, //269 ignore DR effects? - &Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST + &Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &Aura::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus &Aura::HandleNULL, //272 reduce spell cast time? - &Aura::HandleNULL, //273 - &Aura::HandleNULL, //274 proc free shot? + &Aura::HandleUnused, //273 clientside + &Aura::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select &Aura::HandleNULL, //276 mod damage % mechanic? - &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select - &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon + &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap + &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon &Aura::HandleNULL, //279 &Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor @@ -3223,37 +3223,52 @@ void Aura::HandleFeignDeath(bool apply, bool Real) void Aura::HandleAuraModDisarm(bool apply, bool Real) { - if(!Real) - return; - - if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM)) + if (!Real) return; - - // not sure for it's correctness + AuraType type = GetModifier()->m_auraname; + + //Prevent handling aura twice + if(apply && m_target->GetAurasByType(type).size()>1) + return; + if(!apply && m_target->HasAuraType(type)) + return; + uint32 field, flag, slot; + WeaponAttackType attType; + switch (type) + { + case SPELL_AURA_MOD_DISARM: + field=UNIT_FIELD_FLAGS; + flag=UNIT_FLAG_DISARMED; + slot=EQUIPMENT_SLOT_MAINHAND; + attType=BASE_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_OFFHAND: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_OFFHAND; + slot=EQUIPMENT_SLOT_OFFHAND; + attType=OFF_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_RANGED: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_RANGED; + slot=EQUIPMENT_SLOT_RANGED; + attType=RANGED_ATTACK; + break; + } if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + m_target->SetFlag(field, flag); else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + m_target->RemoveFlag(field, flag); if (m_target->GetTypeId() == TYPEID_PLAYER) { - // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. - if (((Player *)m_target)->IsInFeralForm()) - return; - - if (apply) - m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); - else - ((Player *)m_target)->SetRegularAttackTime(); - } - else - { - // creature does not have equipment - if(apply && !((Creature*)m_target)->GetCurrentEquipmentId()) + Item *pItem = ((Player*)m_target)->GetItemByPos( INVENTORY_SLOT_BAG_0, slot ); + if(!pItem ) return; + ((Player*)m_target)->_ApplyItemMods(pItem, slot, !apply); } - - m_target->UpdateDamagePhysical(BASE_ATTACK); + else if (((Creature*)m_target)->GetCurrentEquipmentId()) + m_target->UpdateDamagePhysical(attType); } void Aura::HandleAuraModStun(bool apply, bool Real) @@ -5478,7 +5493,7 @@ void Aura::PeriodicTick() if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); @@ -5549,7 +5564,7 @@ void Aura::PeriodicTick() if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); if(m_target->GetHealth() < pdamage) pdamage = uint32(m_target->GetHealth()); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2ef4a3827c4..0fec6925203 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -300,7 +300,7 @@ void Spell::EffectEnvirinmentalDMG(uint32 i) // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; - m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo); m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); if(m_caster->GetTypeId() == TYPEID_PLAYER) @@ -4575,33 +4575,6 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // Add melee damage bonuses (also check for negative) m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo); m_damage+= eff_damage; - - // take ammo - if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) - { - Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); - - // wands don't have ammo - if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) - return; - - if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) - { - if(pItem->GetMaxStackCount()==1) - { - // decrease durability for non-stackable throw weapon - ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); - } - else - { - // decrease items amount for stackable throw weapon - uint32 count = 1; - ((Player*)m_caster)->DestroyItemCount( pItem, count, true); - } - } - else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) - ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); - } } void Spell::EffectThreat(uint32 /*i*/) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 4186336fe18..7323bed1915 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -50,7 +50,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; - Item *pItem = pUser->GetItemByPos(bagIndex, slot); + Item *pItem = pUser->GetUseableItemByPos(bagIndex, slot); if(!pItem) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); @@ -349,7 +349,7 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) } } - + // channeled spell case (it currently casted then) if(IsChanneledSpell(spellInfo)) { diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 5473206e8bd..8f520125986 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -427,8 +427,15 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, fl weapon_mindamage = lvl*0.85*att_speed; weapon_maxdamage = lvl*1.25*att_speed; } - else if(!IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) + else if(!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case) { + //cannot use ranged/off attack, set values to 0 + if (attType != BASE_ATTACK) + { + min_damage=0; + max_damage=0; + return; + } weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; } @@ -820,7 +827,7 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); - if(attType == BASE_ATTACK && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED)) + if(!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0c79a7d2bd3..a576abc0360 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1267,21 +1267,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama // Calculate absorb resist if(damage > 0) { - // lookup absorb/resist ignore auras on caster for spell - bool ignore = false; - Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL); - for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i) - if ((*i)->isAffectedOnSpell(spellInfo)) - { - ignore = true; - break; - } - - if (!ignore) - { - CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist); - damage-= damageInfo->absorb + damageInfo->resist; - } + CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo); + damage-= damageInfo->absorb + damageInfo->resist; } else damage = 0; @@ -1293,15 +1280,15 @@ int32 Unit::GetIgnoredArmorMultiplier(SpellEntry const *spellInfo, WeaponAttackT if (GetTypeId() != TYPEID_PLAYER) return 0; //check if spell uses weapon - if (spellInfo && spellInfo->EquippedItemClass!=ITEM_CLASS_WEAPON) + if (!spellInfo || spellInfo->EquippedItemClass!=ITEM_CLASS_WEAPON) return 0; Item *item = NULL; if(attackType == BASE_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); else if (attackType == OFF_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); else if (attackType == RANGED_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); if (!item) return 0; @@ -1657,7 +1644,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) { 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); + ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0,i), pVictim, damageInfo->attackType); } // victim's damage shield @@ -1722,6 +1709,21 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt if(Player *modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor); + AuraList const& ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAurasAb.begin();j != ResIgnoreAurasAb.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL + && (*j)->isAffectedOnSpell(spellInfo)) + armor= float(armor) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } + + AuraList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAuras.begin();j != ResIgnoreAuras.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + armor= float(armor) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } + // Apply Player CR_ARMOR_PENETRATION rating if (GetTypeId()==TYPEID_PLAYER) armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f; @@ -1744,7 +1746,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt return (newdamage > 1) ? newdamage : 1; } -void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist) +void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo) { if(!pVictim || !pVictim->isAlive() || !damage) return; @@ -1780,6 +1782,21 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe *resist += uint32(damage * m / 4); if(*resist > damage) *resist = damage; + + AuraList const& ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAurasAb.begin();j != ResIgnoreAurasAb.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & schoolMask + && (*j)->isAffectedOnSpell(spellInfo)) + *resist= float(*resist) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } + + AuraList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAuras.begin();j != ResIgnoreAuras.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & schoolMask) + *resist= float(*resist) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } } else *resist = 0; @@ -1990,6 +2007,21 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe if (RemainingDamage < currentAbsorb) currentAbsorb = RemainingDamage; + AuraList const& AbsIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL); + for(AuraList::const_iterator j = AbsIgnoreAurasAb.begin();j != AbsIgnoreAurasAb.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & (*i)->GetModifier()->m_miscvalue + && (*j)->isAffectedOnSpell(spellInfo)) + currentAbsorb= float(currentAbsorb) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } + + AuraList const& AbsIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL); + for(AuraList::const_iterator j = AbsIgnoreAuras.begin();j != AbsIgnoreAuras.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & (*i)->GetModifier()->m_miscvalue) + currentAbsorb= float(currentAbsorb) * (float(100-(*j)->GetModifier()->m_amount)/100.0f); + } + RemainingDamage -= currentAbsorb; // Reduce shield amount @@ -2919,7 +2951,7 @@ float Unit::GetUnitBlockChance() const Player const* player = (Player const*)this; if(player->CanBlock() ) { - Item *tmpitem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item *tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block) return GetFloatValue(PLAYER_BLOCK_PERCENTAGE); } @@ -8595,7 +8627,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint AuraList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED); for(AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i) - if ((*i)->isAffectedOnSpell(spellProto)) + if (GetGUID()==(*i)->GetCasterGUID() && (*i)->isAffectedOnSpell(spellProto) ) TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f; heal = (heal + TakenTotal) * TakenTotalMod; @@ -11686,13 +11718,13 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry con { Item *item = NULL; if(attType == BASE_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); else if (attType == OFF_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); else - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); - if (!((Player*)this)->IsUseEquipedWeapon(attType==BASE_ATTACK)) + if (((Player*)this)->IsInFeralForm()) return false; if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) @@ -11701,7 +11733,7 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry con else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) { // Check if player is wearing shield - Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item *item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) return false; } diff --git a/src/game/Unit.h b/src/game/Unit.h index aa038ab1fb4..00ee9b90e58 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -544,6 +544,8 @@ enum UnitFlags2 UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip) UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, UNIT_FLAG2_FORCE_MOVE = 0x00000040, + UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, + UNIT_FLAG2_DISARM_RANGED = 0x00000400, //this does not disable ranged weapon display (maybe additional flag needed?) UNIT_FLAG2_REGENERATE_POWER = 0x00000800 }; @@ -1005,6 +1007,16 @@ class TRINITY_DLL_SPEC Unit : public WorldObject float GetUnitParryChance() const; float GetUnitBlockChance() const; float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const; + bool CanUseAttackType( uint8 attacktype ) const + { + switch(attacktype) + { + case BASE_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED); + case OFF_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2,UNIT_FLAG2_DISARM_OFFHAND); + case RANGED_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2,UNIT_FLAG2_DISARM_RANGED); + } + return true; + } virtual uint32 GetShieldBlockValue() const =0; uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } @@ -1414,7 +1426,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject // redefined in Creature uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType=MAX_ATTACK); - void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); + void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo = NULL); void UpdateSpeed(UnitMoveType mtype, bool forced); float GetSpeed( UnitMoveType mtype ) const; |