Index: extras/shaman_todo.txt =================================================================== --- extras/shaman_todo.txt (revision 3613) +++ extras/shaman_todo.txt (working copy) @@ -19,6 +19,14 @@ Flametongue Weapon and Frostbrand Weapon by $s2%. Windfury Weapon effect by $s3% +/* +Rockbiter - working - untested ?! +Windfury Weapon - working for main hand - untested +Bug: After every? equipment change one has to recast enchantmeants +(Details: Windfury on both weapons, removed off hand, windfury never triggered on main hand) +*/ + + [08:51:59] Spell::cast 3050, Unit: 7 [08:51:59] WORLD: Spell effect id = 49, damage = 0 [08:51:59] Unhandled spell effect 49 in spell 3050. Index: src/ascent-world/AIInterface.cpp =================================================================== --- src/ascent-world/AIInterface.cpp (revision 3613) +++ src/ascent-world/AIInterface.cpp (working copy) @@ -939,7 +939,7 @@ //we require to know if strike was succesfull. If there was no dmg then target cannot be dazed by it uint32 health_before_strike=m_nextTarget->GetUInt32Value(UNIT_FIELD_HEALTH); #endif - m_Unit->Strike( m_nextTarget, ( agent == AGENT_MELEE ? MELEE : RANGED ), NULL, 0, 0, 0, false, false ); + m_Unit->Strike( m_nextTarget, ( agent == AGENT_MELEE ? MELEE : RANGED ), NULL, 0, 0, 0, false, false, false ); #ifdef ENABLE_CREATURE_DAZE //now if the target is facing his back to us then we could just cast dazed on him :P //as far as i know dazed is casted by most of the creatures but feel free to remove this code if you think otherwise Index: src/ascent-world/Player.cpp =================================================================== --- src/ascent-world/Player.cpp (revision 3613) +++ src/ascent-world/Player.cpp (working copy) @@ -1011,7 +1011,7 @@ if (!GetOnMeleeSpell()) { - Strike( pVictim, ( offhand ? OFFHAND : MELEE ), NULL, 0, 0, 0, false, false ); + Strike( pVictim, ( offhand ? OFFHAND : MELEE ), NULL, 0, 0, 0, false, false, false ); } else { @@ -1094,7 +1094,7 @@ if (!m_CurrentCharm->GetOnMeleeSpell()) { - m_CurrentCharm->Strike( pVictim, MELEE, NULL, 0, 0, 0, false, false ); + m_CurrentCharm->Strike( pVictim, MELEE, NULL, 0, 0, 0, false, false, false ); } else { @@ -8635,59 +8635,76 @@ } -uint32 Player::GetMainMeleeDamage(uint32 AP_owerride) +uint32 Player::GetShamanMeleeDamage(uint32 AP_override, bool mainHand) { - float min_dmg,max_dmg; - float delta; - float r; - int ss = GetShapeShift(); -/////////////////MAIN HAND - float ap_bonus; - if(AP_owerride) - ap_bonus = AP_owerride/14000.0f; - else - ap_bonus = GetAP()/14000.0f; - delta = (float)GetUInt32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS ) - (float)GetUInt32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_NEG ); - if(IsInFeralForm()) + // Currently this is for windfury only + if( disarmed ) return 0; + + float weaponModifier = 1.0f; + float ap_bonus = (float)AP_override / 14000.0f; + + uint32 spellEffects = GetUInt32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS ) + - GetUInt32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_NEG ); + + + Item* weapon = NULL; + + if( mainHand ) { - uint32 lev = getLevel(); - if(ss == FORM_CAT) - r = lev + delta + ap_bonus * 1000.0f; - else - r = lev + delta + ap_bonus * 2500.0f; - min_dmg = r * 0.9f; - max_dmg = r * 1.1f; - return float2int32(std::max((min_dmg + max_dmg)/2.0f,0.0f)); + /* + main hand formula in CalcDamage() + ((Base0 + spellEffects + ap_bonus·Delay)·weaponModifier + (Base1 + spellEffects + ap_bonus·Delay)·weaponModifier)/2 + + Derive tells me this is the same as: + weaponModifier·(Base0 + Base1 + 2·(Delay·ap_bonus + spellEffects))/2 + */ + + weapon = GetItemInterface()->GetInventoryItem( EQUIPMENT_SLOT_MAINHAND ); } -//////no druid ss - uint32 speed=2000; - Item *it = GetItemInterface()->GetInventoryItem(EQUIPMENT_SLOT_MAINHAND); - if(!disarmed) - { - if(it) - speed = it->GetProto()->Delay; + else + { + /* + off hand forumla in CalcDamage() + ((Base0 + spellEffects + ap_bonus·Delay)·weaponModifier·offhand_dmg_mod + (Base1 + spellEffects + ap_bonus·Delay)·weaponModifier·offhand_dmg_mod)/2 + + and again Derive: + offhand_dmg_mod·weaponModifier·(Base0 + Base1 + 2·Delay·ap_bonus + 2·spellEffects)/2 + + as you can see this part is the same on both: + weaponModifier·(Base0 + Base1 + 2·(Delay·ap_bonus + spellEffects))/2 + + so I just "hide" offhand_dmg_mod inside weaponModifier :-) + */ + + weapon = GetItemInterface()->GetInventoryItem( EQUIPMENT_SLOT_OFFHAND ); + + // I hope this is correct + weaponModifier *= offhand_dmg_mod; } - float bonus=ap_bonus*speed; - float tmp = 1; + map::iterator i; for(i = damagedone.begin();i!=damagedone.end();i++) { if((i->second.wclass == (uint32)-1) || //any weapon - (it && ((1 << it->GetProto()->SubClass) & i->second.subclass) ) + (weapon && ((1 << weapon->GetProto()->SubClass) & i->second.subclass) ) ) - tmp+=i->second.value/100.0f; + weaponModifier += i->second.value / 100.0f; } - - r = BaseDamage[0]+delta+bonus; - r *= tmp; - min_dmg = r * 0.9f; - r = BaseDamage[1]+delta+bonus; - r *= tmp; - max_dmg = r * 1.1f; - return float2int32(std::max((min_dmg + max_dmg)/2.0f,0.0f)); + + // r = weaponModifier·(Base0 + Base1 + 2·(Delay·ap_bonus + spellEffects))/2 + int32 r = float2int32( + weaponModifier * (BaseDamage[0] + BaseDamage[1] + 2.0f * ((float)weapon->GetProto()->Delay * ap_bonus + (float)spellEffects)) / 2.0f ); + + // right now I'm just happy windfury works at all + // this is for someone else to fix. (Baldur) + sLog.outDebug("weapon mod %u not applied in GetShamanMeleeDamage. Someone might want to change this :)", + GetUInt32Value( PLAYER_RATING_MODIFIER_MELEE_MAIN_HAND_SKILL )); + + return (uint32) ( r > 0 ? r : 0 ); } + void Player::EventPortToGM(Player *p) { SafeTeleport(p->GetMapId(),p->GetInstanceID(),p->GetPosition()); Index: src/ascent-world/Player.h =================================================================== --- src/ascent-world/Player.h (revision 3613) +++ src/ascent-world/Player.h (working copy) @@ -981,7 +981,7 @@ return ( s == 1 || s == 5 || s == 8 ); } void CalcDamage(); - uint32 GetMainMeleeDamage(uint32 AP_owerride); //i need this for windfury + uint32 GetShamanMeleeDamage(uint32 AP_override, bool offHand); // for windfury const uint64& GetSelection( ) const { return m_curSelection; } const uint64& GetTarget( ) const { return m_curTarget; } Index: src/ascent-world/SpellEffects.cpp =================================================================== --- src/ascent-world/SpellEffects.cpp (revision 3613) +++ src/ascent-world/SpellEffects.cpp (working copy) @@ -419,7 +419,7 @@ else { if( u_caster != NULL ) - u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, 0, 0, dmg, pSpellId == 0, true ); + u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, 0, 0, dmg, pSpellId == 0, true, false ); } } } @@ -1497,13 +1497,13 @@ { float time = (m_caster->CalcDistance(unitTarget) * 1000.0f) / m_spellInfo->speed; if(time <= 100.0f) - u_caster->Strike( unitTarget, RANGED, m_spellInfo, 0, 0, 0, false, true ); + u_caster->Strike( unitTarget, RANGED, m_spellInfo, 0, 0, 0, false, true, false ); else sEventMgr.AddEvent(u_caster,&Unit::EventStrikeWithAbility,unitTarget->GetGUID(), m_spellInfo, (uint32)damage, EVENT_SPELL_DAMAGE_HIT, float2int32(time), 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT); } else - u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true ); + u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true, false ); } void Spell::SpellEffectAddExtraAttacks(uint32 i) // Add Extra Attacks @@ -2128,7 +2128,7 @@ u_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, dmg, false, false, false); } else - u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, add_damage, damage, 0, false, true ); + u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, add_damage, damage, 0, false, true, false ); } void Spell::SpellEffectTriggerMissile(uint32 i) // Trigger Missile @@ -3219,7 +3219,7 @@ add_damage += damage; return; } - u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true ); + u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true, false ); } void Spell::SpellEffectPowerBurn(uint32 i) // power burn @@ -4960,7 +4960,7 @@ if( m_spellInfo->NameHash == SPELL_HASH_MUTILATE && unitTarget->IsPoisoned() ) damage = damage + float2int32( (float)damage * 0.5f ); - u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true ); + u_caster->Strike( unitTarget, ( GetType() == SPELL_DMG_TYPE_RANGED ? RANGED : MELEE ), m_spellInfo, damage, 0, 0, false, true, false ); } void Spell::SpellEffectSpellSteal( uint32 i ) Index: src/ascent-world/Unit.cpp =================================================================== --- src/ascent-world/Unit.cpp (revision 3613) +++ src/ascent-world/Unit.cpp (working copy) @@ -1173,7 +1173,8 @@ if( !(CastingSpell->c_is_flags & SPELL_FLAG_IS_DAMAGING)) //healing wave continue; }break; - //shaman - windfurry weapon + //shaman - windfury weapon + //spell spells correct please! it took me hours to find this code case 8232: case 8235: case 10486: @@ -1184,12 +1185,35 @@ continue; //!! The wierd thing is that we need the spell thet trigegred this enchant spell in order to output logs ..we are using oldspell info too //we have to recalc the value of this spell - SpellEntry *spellInfo = dbcSpell.LookupEntry(origId); - uint32 AP_owerride=GetAP() + spellInfo->EffectBasePoints[0]+1; - uint32 dmg = static_cast< Player* >( this )->GetMainMeleeDamage(AP_owerride); SpellEntry *sp_for_the_logs = dbcSpell.LookupEntry(spellId); - Strike( victim, MELEE, sp_for_the_logs, dmg, 0, 0, true, false ); - Strike( victim, MELEE, sp_for_the_logs, dmg, 0, 0, true, false ); + + uint32 dmg = static_cast< Player* >( this ) + ->GetShamanMeleeDamage( GetAP() + ospinfo->EffectBasePoints[0] + 1, true ); + + + + Item* offHandWeapon = static_cast< Player* >( this )->GetItemInterface()->GetInventoryItem( EQUIPMENT_SLOT_OFFHAND ); + if( offHandWeapon != NULL + && offHandWeapon->GetProto() != NULL + && offHandWeapon->GetProto()->Class == ITEM_CLASS_WEAPON ) + { + // off hand equipped + // we don't know whether main or offhand triggered windfury + // avoid exploit (slow main, fast off hand) and use lowest possible damage + // this will make double wilding useless, unless you use same weapon, sry :-( + // (Baldur) + // everyone is welcome to fix this :) + + uint32 dmgOff = static_cast< Player* >( this ) + ->GetShamanMeleeDamage( GetAP() + ospinfo->EffectBasePoints[0] + 1, false ); + + if( dmgOff < dmg ) + dmg = dmgOff; + } + + + Strike( victim, MELEE, sp_for_the_logs, 0, 0, dmg, true, true, true ); + Strike( victim, MELEE, sp_for_the_logs, 0, 0, dmg, true, true, true ); //nothing else to be done for this trigger continue; }break; @@ -1690,7 +1714,7 @@ else { SpellEntry *ability=dbcSpell.LookupEntry((*i2).m_spellId); - this->Strike( attacker, RANGED, ability, 0, 0, (*i2).m_damage, true, false ); + this->Strike( attacker, RANGED, ability, 0, 0, (*i2).m_damage, true, false, false ); } } } @@ -2074,7 +2098,7 @@ return roll_results[r]; } -void Unit::Strike( Unit* pVictim, uint32 weapon_damage_type, SpellEntry* ability, int32 add_damage, int32 pct_dmg_mod, uint32 exclusive_damage, bool disable_proc, bool skip_hit_check ) +void Unit::Strike( Unit* pVictim, uint32 weapon_damage_type, SpellEntry* ability, int32 add_damage, int32 pct_dmg_mod, uint32 exclusive_damage, bool disable_proc, bool skip_hit_check, bool no_crit ) { //========================================================================================== //==============================Unacceptable Cases Processing=============================== @@ -2354,6 +2378,12 @@ dodge=parry=block=0.0f; } + if(no_crit) + { + crit = 0.0f; + } + + if( IsPlayer() && static_cast< Player* >( this )->m_finishingmovesdodge && ability && ( ability->EffectPointsPerComboPoint[0] > 0 || ability->EffectPointsPerComboPoint[1] > 0 || ability->EffectPointsPerComboPoint[2] > 0 ) ) // SPELL: Surprise Attacks dodge = 0.0f; @@ -3000,7 +3030,7 @@ while(extra_attacks > 0) { extra_attacks--; - Strike( pVictim, weapon_damage_type, NULL, 0, 0, 0, false, false); + Strike( pVictim, weapon_damage_type, NULL, 0, 0, 0, false, false, false); } m_extraAttackCounter = false; @@ -3019,7 +3049,7 @@ if((*itr) != pVictim && (*itr)->IsUnit() && CalcDistance(*itr) < 10.0f && isAttackable(this, (*itr)) && (*itr)->isInFront(this) && !((Unit*)(*itr))->IsPacified()) { - Strike( static_cast< Unit* >( *itr ), weapon_damage_type, ability, add_damage, pct_dmg_mod, exclusive_damage, false ,false ); + Strike( static_cast< Unit* >( *itr ), weapon_damage_type, ability, add_damage, pct_dmg_mod, exclusive_damage, false ,false, false ); --m_extra; } } @@ -5941,7 +5971,7 @@ { Unit * victim = m_mapMgr ? m_mapMgr->GetUnit(guid) : NULL; if(victim) - Strike( victim, RANGED, sp, 0, 0, 0, false, true ); + Strike( victim, RANGED, sp, 0, 0, 0, false, true, false ); } void Unit::DispelAll(bool positive) Index: src/ascent-world/Unit.h =================================================================== --- src/ascent-world/Unit.h (revision 3613) +++ src/ascent-world/Unit.h (working copy) @@ -706,7 +706,7 @@ // void DealDamage(Unit *pVictim, uint32 damage, uint32 targetEvent, uint32 unitEvent, uint32 spellId = 0); // to stop from falling, etc //void AttackerStateUpdate( Unit* pVictim, uint32 weapon_damage_type ); // weapon_damage_type: 0 = melee, 1 = offhand(dualwield), 2 = ranged uint32 GetSpellDidHitResult( Unit* pVictim, uint32 weapon_damage_type, SpellEntry* ability ); - void Strike( Unit* pVictim, uint32 weapon_damage_type, SpellEntry* ability, int32 add_damage, int32 pct_dmg_mod, uint32 exclusive_damage, bool disable_proc, bool skip_hit_check ); + void Strike( Unit* pVictim, uint32 weapon_damage_type, SpellEntry* ability, int32 add_damage, int32 pct_dmg_mod, uint32 exclusive_damage, bool disable_proc, bool skip_hit_check, bool no_crit ); // void PeriodicAuraLog(Unit *pVictim, SpellEntry* spellID, uint32 damage, uint32 damageType); //void SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage); uint32 m_procCounter; Index: src/ascent-world/World.cpp =================================================================== --- src/ascent-world/World.cpp (revision 3613) +++ src/ascent-world/World.cpp (working copy) @@ -6904,21 +6904,21 @@ if( sp != NULL ) sp->procFlags = PROC_ON_CAST_SPELL; - //windfury weapon changes. Start to hate these day by day + + // windfury weapon EnchantEntry* Enchantment; Enchantment = dbcEnchant.LookupEntryForced( 283 ); if( Enchantment != NULL ) { - Enchantment->spell[0] = 33757; //this is actually good + // Enchantment->spell[0] = 33757; //this is actually good sp = dbcSpell.LookupEntryForced( 33757 ); if( sp != NULL ) { - sp->EffectApplyAuraName[0] = 42; //who needs dummys anyway ? - sp->procFlags = PROC_ON_MELEE_ATTACK; //we do not need proc on spell ;) - sp->EffectTriggerSpell[0] = 8232; //for the logs and rest - sp->procChance = 20; - sp->proc_interval = 3000;//http://www.wowwiki.com/Windfury_Weapon + sp->EffectApplyAuraName[0] = 42; + sp->procFlags = PROC_ON_MELEE_ATTACK; // why is ascent not using PROC_ON_PHYSICAL_ATTACK_VICTIM? + sp->EffectTriggerSpell[0] = 8232; // fix dbc + sp->proc_interval = 3000; // http://www.wowwiki.com/Windfury_Weapon sp->maxstack = 1; } } @@ -6930,11 +6930,10 @@ sp = dbcSpell.LookupEntryForced( 33756 ); if( sp != NULL ) { - sp->EffectApplyAuraName[0] = 42; //who needs dummys anyway ? - sp->procFlags = PROC_ON_MELEE_ATTACK; //we do not need proc on spell ;) - sp->EffectTriggerSpell[0] = 8235; //for the logs and rest - sp->procChance = 20; - sp->proc_interval = 3000; //http://www.wowwiki.com/Windfury_Weapon + sp->EffectApplyAuraName[0] = 42; + sp->procFlags = PROC_ON_MELEE_ATTACK; // why is ascent not using PROC_ON_PHYSICAL_ATTACK_VICTIM? + sp->EffectTriggerSpell[0] = 8235; // fix dbc + sp->proc_interval = 3000; // http://www.wowwiki.com/Windfury_Weapon sp->maxstack = 1; } } @@ -6946,11 +6945,10 @@ sp = dbcSpell.LookupEntryForced( 33755 ); if( sp != NULL ) { - sp->EffectApplyAuraName[0] = 42; //who needs dummys anyway ? - sp->procFlags = PROC_ON_MELEE_ATTACK; //we do not need proc on spell ;) - sp->EffectTriggerSpell[0] = 10486; //for the logs and rest - sp->procChance = 20; - sp->proc_interval = 3000;//http://www.wowwiki.com/Windfury_Weapon + sp->EffectApplyAuraName[0] = 42; + sp->procFlags = PROC_ON_MELEE_ATTACK; // why is ascent not using PROC_ON_PHYSICAL_ATTACK_VICTIM? + sp->EffectTriggerSpell[0] = 10486; // fix dbc + sp->proc_interval = 3000; // http://www.wowwiki.com/Windfury_Weapon sp->maxstack = 1; } } @@ -6962,11 +6960,10 @@ sp = dbcSpell.LookupEntryForced( 33754 ); if( sp != NULL ) { - sp->EffectApplyAuraName[0] = 42; //who needs dummys anyway ? - sp->procFlags = PROC_ON_MELEE_ATTACK; //we do not need proc on spell ;) - sp->EffectTriggerSpell[0] = 16362; //for the logs and rest - sp->procChance = 20; - sp->proc_interval = 3000;//http://www.wowwiki.com/Windfury_Weapon + sp->EffectApplyAuraName[0] = 42; + sp->procFlags = PROC_ON_MELEE_ATTACK; // why is ascent not using PROC_ON_PHYSICAL_ATTACK_VICTIM? + sp->EffectTriggerSpell[0] = 16362; // fix dbc + sp->proc_interval = 3000; // http://www.wowwiki.com/Windfury_Weapon sp->maxstack = 1; } } @@ -6978,11 +6975,10 @@ sp = dbcSpell.LookupEntryForced( 33727 ); if( sp != NULL ) { - sp->EffectApplyAuraName[0] = 42; //who needs dummys anyway ? - sp->procFlags = PROC_ON_MELEE_ATTACK; //we do not need proc on spell ;) - sp->EffectTriggerSpell[0] = 25505; //for the logs and rest - sp->procChance = 20; - sp->proc_interval = 3000;//http://www.wowwiki.com/Windfury_Weapon + sp->EffectApplyAuraName[0] = 42; + sp->procFlags = PROC_ON_MELEE_ATTACK; // why is ascent not using PROC_ON_PHYSICAL_ATTACK_VICTIM? + sp->EffectTriggerSpell[0] = 25505; // fix dbc + sp->proc_interval = 3000; // http://www.wowwiki.com/Windfury_Weapon sp->maxstack = 1; } }