Skip to content

Instantly share code, notes, and snippets.

@SilverIce
Last active September 27, 2015 14:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SilverIce/1288005 to your computer and use it in GitHub Desktop.
Save SilverIce/1288005 to your computer and use it in GitHub Desktop.
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp
index 03f0b75..3c812de 100644
--- a/src/game/AggressorAI.cpp
+++ b/src/game/AggressorAI.cpp
@@ -127,8 +127,6 @@ AggressorAI::UpdateAI(const uint32 /*diff*/)
return;
i_victimGuid = m_creature->getVictim()->GetObjectGuid();
-
- DoMeleeAttackIfReady();
}
bool
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 35de032..682a670 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -350,8 +350,10 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData *data /*=
SetUInt32Value(UNIT_NPC_FLAGS,GetCreatureInfo()->npcflag);
- SetAttackTime(BASE_ATTACK, GetCreatureInfo()->baseattacktime);
- SetAttackTime(OFF_ATTACK, GetCreatureInfo()->baseattacktime);
+ uint32 attackTimer = GetCreatureInfo()->baseattacktime;
+
+ SetAttackTime(BASE_ATTACK, attackTimer);
+ SetAttackTime(OFF_ATTACK, attackTimer - attackTimer/4);
SetAttackTime(RANGED_ATTACK,GetCreatureInfo()->rangeattacktime);
uint32 unitFlags = GetCreatureInfo()->unit_flags;
@@ -1178,8 +1180,11 @@ void Creature::SelectLevel(const CreatureInfo *cinfo, float percentHealth, float
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
- SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,cinfo->minrangedmg * damagemod);
- SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,cinfo->maxrangedmg * damagemod);
+ SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
+ SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
+
+ SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->minrangedmg * damagemod);
+ SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->maxrangedmg * damagemod);
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod);
}
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index fd0829c..21a8953 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -120,20 +120,5 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
bool CreatureAI::DoMeleeAttackIfReady()
{
- // Check target
- if (!m_creature->getVictim())
- return false;
-
- // Make sure our attack is ready before checking distance
- if (!m_creature->isAttackReady())
- return false;
-
- // If we are within range melee the target
- if (!m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
- return false;
-
- m_creature->AttackerStateUpdate(m_creature->getVictim());
- m_creature->resetAttackTimer();
-
- return true;
+ return false;
}
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 251696f..2ea6897 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -25,6 +25,7 @@
#include "Dynamic/ObjectRegistry.h"
#include "Dynamic/FactoryHolder.h"
#include "ObjectGuid.h"
+#include "Unit.h"
class WorldObject;
class GameObject;
@@ -248,7 +249,6 @@ class MANGOS_DLL_SPEC CreatureAI
virtual bool canReachByRangeAttack(Unit*) { return false; }
///== Helper functions =============================
-
/// This function is used to do the actual melee damage (if possible)
bool DoMeleeAttackIfReady();
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index f75a4ac..b5f2286 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -617,6 +617,10 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
case ACTION_T_AUTO_ATTACK:
m_MeleeEnabled = action.auto_attack.state != 0;
+ if (m_MeleeEnabled)
+ m_creature->addUnitState(UNIT_STAT_MELEE_ATTACKING);
+ else
+ m_creature->clearUnitState(UNIT_STAT_MELEE_ATTACKING);
break;
case ACTION_T_COMBAT_MOVEMENT:
// ignore no affect case
@@ -1204,10 +1208,6 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
m_EventUpdateTime -= diff;
}
}
-
- //Melee Auto-Attack
- if (Combat && m_MeleeEnabled)
- DoMeleeAttackIfReady();
}
bool CreatureEventAI::IsVisible(Unit *pl) const
diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp
index d65cea4..95fb86e 100644
--- a/src/game/GuardAI.cpp
+++ b/src/game/GuardAI.cpp
@@ -111,8 +111,6 @@ void GuardAI::UpdateAI(const uint32 /*diff*/)
return;
i_victimGuid = m_creature->getVictim()->GetObjectGuid();
-
- DoMeleeAttackIfReady();
}
bool GuardAI::IsVisible(Unit *pl) const
diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
index 8bf2595..3d3921f 100644
--- a/src/game/PetAI.cpp
+++ b/src/game/PetAI.cpp
@@ -161,9 +161,9 @@ void PetAI::UpdateAI(const uint32 diff)
// not required to be stopped case
else if (m_creature->isAttackReady() && meleeReach)
{
- m_creature->AttackerStateUpdate(m_creature->getVictim());
+ //m_creature->AttackerStateUpdate(m_creature->getVictim());
- m_creature->resetAttackTimer();
+ //m_creature->resetAttackTimer();
if (!m_creature->getVictim())
return;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index e97826e..b2e1c71 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -1233,68 +1233,6 @@ void Player::Update( uint32 update_diff, uint32 p_time )
Unit *pVictim = getVictim();
if (pVictim && !IsNonMeleeSpellCasted(false))
{
- // default combat reach 10
- // TODO add weapon,skill check
-
- if (isAttackReady(BASE_ATTACK))
- {
- if (!CanReachWithMeleeAttack(pVictim))
- {
- setAttackTimer(BASE_ATTACK,100);
- if (m_swingErrorMsg != 1) // send single time (client auto repeat)
- {
- SendAttackSwingNotInRange();
- m_swingErrorMsg = 1;
- }
- }
- //120 degrees of radiant range
- else if (!HasInArc(2*M_PI_F/3, pVictim))
- {
- setAttackTimer(BASE_ATTACK,100);
- if (m_swingErrorMsg != 2) // send single time (client auto repeat)
- {
- SendAttackSwingBadFacingAttack();
- m_swingErrorMsg = 2;
- }
- }
- else
- {
- m_swingErrorMsg = 0; // reset swing error state
-
- // prevent base and off attack in same time, delay attack at 0.2 sec
- if (haveOffhandWeapon())
- {
- uint32 off_att = getAttackTimer(OFF_ATTACK);
- if(off_att < ATTACK_DISPLAY_DELAY)
- setAttackTimer(OFF_ATTACK,ATTACK_DISPLAY_DELAY);
- }
- AttackerStateUpdate(pVictim, BASE_ATTACK);
- resetAttackTimer(BASE_ATTACK);
- }
- }
-
- if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
- {
- if (!CanReachWithMeleeAttack(pVictim))
- {
- setAttackTimer(OFF_ATTACK,100);
- }
- else if (!HasInArc(2*M_PI_F/3, pVictim))
- {
- setAttackTimer(OFF_ATTACK,100);
- }
- else
- {
- // prevent base and off attack in same time, delay attack at 0.2 sec
- uint32 base_att = getAttackTimer(BASE_ATTACK);
- if(base_att < ATTACK_DISPLAY_DELAY)
- setAttackTimer(BASE_ATTACK,ATTACK_DISPLAY_DELAY);
- // do attack
- AttackerStateUpdate(pVictim, OFF_ATTACK);
- resetAttackTimer(OFF_ATTACK);
- }
- }
-
Player *vOwner = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself();
if (vOwner && vOwner->IsPvP() && !IsInDuelWith(vOwner))
{
diff --git a/src/game/Player.h b/src/game/Player.h
index 4c8669b..b180350 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1821,6 +1821,9 @@ class MANGOS_DLL_SPEC Player : public Unit
void DestroyForPlayer( Player *target, bool anim = false ) const;
void SendLogXPGain(uint32 GivenXP,Unit* victim,uint32 RestXP);
+ uint8 SwingErrorMsg() const { return m_swingErrorMsg; }
+ void SwingErrorMsg(uint8 val) { m_swingErrorMsg = val; }
+
// notifiers
void SendAttackSwingCantAttack();
void SendAttackSwingCancelAttack();
diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp
index 0a32c86..ed87cd2 100644
--- a/src/game/ReactorAI.cpp
+++ b/src/game/ReactorAI.cpp
@@ -72,8 +72,6 @@ ReactorAI::UpdateAI(const uint32 /*time_diff*/)
return;
i_victimGuid = m_creature->getVictim()->GetObjectGuid();
-
- DoMeleeAttackIfReady();
}
void
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index e8eea70..3fc450f 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -870,7 +870,7 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
- if(ranged)
+ if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
@@ -885,18 +885,20 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
- if(ranged)
+ if (ranged)
return;
+
//automatically update weapon damage after attack power modification
UpdateDamagePhysical(BASE_ATTACK);
+ UpdateDamagePhysical(OFF_ATTACK);
}
void Creature::UpdateDamagePhysical(WeaponAttackType attType)
{
- if(attType > BASE_ATTACK)
+ if (attType > OFF_ATTACK)
return;
- UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND;
+ UnitMods unitMod = (attType == BASE_ATTACK ? UNIT_MOD_DAMAGE_MAINHAND : UNIT_MOD_DAMAGE_OFFHAND);
/* difference in AP between current attack power and base value from DB */
float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->attackpower;
@@ -906,14 +908,14 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType)
float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
float dmg_multiplier = GetCreatureInfo()->dmg_multiplier;
- float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
- float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
+ float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE);
+ float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE);
float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct;
float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct;
- SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage);
- SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage);
+ SetStatFloatValue(attType == BASE_ATTACK ? UNIT_FIELD_MINDAMAGE : UNIT_FIELD_MINOFFHANDDAMAGE, mindamage);
+ SetStatFloatValue(attType == BASE_ATTACK ? UNIT_FIELD_MAXDAMAGE : UNIT_FIELD_MAXOFFHANDDAMAGE, maxdamage);
}
/*#######################################
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 5bbeb13..0e4d65c 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -234,7 +234,8 @@ Unit::Unit() :
m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
}
- // implement 50% base damage from offhand
+
+ // implement 50% base damage from offhand
m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
for (int i = 0; i < MAX_ATTACK; ++i)
@@ -341,6 +342,14 @@ void Unit::Update( uint32 update_diff, uint32 p_time )
setAttackTimer(BASE_ATTACK, (update_diff >= base_att ? 0 : base_att - update_diff) );
}
+ if (uint32 base_att = getAttackTimer(OFF_ATTACK))
+ {
+ setAttackTimer(OFF_ATTACK, (update_diff >= base_att ? 0 : base_att - update_diff) );
+ }
+
+ if (hasUnitState(UNIT_STAT_MELEE_ATTACKING))
+ UpdateMeleeAttackingState();
+
// update abilities available only for fraction of time
UpdateReactives( update_diff );
@@ -351,6 +360,76 @@ void Unit::Update( uint32 update_diff, uint32 p_time )
i_motionMaster.UpdateMotion(p_time);
}
+void Unit::UpdateMeleeAttackingState()
+{
+ uint8 swingErrorMsg = 0;
+ Unit *pVictim = getVictim();
+ if (pVictim && !IsNonMeleeSpellCasted(false))
+ {
+ // default combat reach 10
+ // TODO add weapon,skill check
+ if (isAttackReady(BASE_ATTACK))
+ {
+ if (!CanReachWithMeleeAttack(pVictim))
+ {
+ setAttackTimer(BASE_ATTACK,100);
+ swingErrorMsg = 1; // SendAttackSwingNotInRange
+ }
+ //120 degrees of radiant range
+ else if (!HasInArc(2*M_PI_F/3, pVictim))
+ {
+ setAttackTimer(BASE_ATTACK,100);
+ swingErrorMsg = 2; // SendAttackSwingBadFacingAttack
+ }
+ else
+ {
+ swingErrorMsg = 0; // reset swing error state
+ // prevent base and off attack in same time, delay attack at 0.2 sec
+ if (haveOffhandWeapon())
+ {
+ uint32 off_att = getAttackTimer(OFF_ATTACK);
+ if (off_att < ATTACK_DISPLAY_DELAY)
+ setAttackTimer(OFF_ATTACK,ATTACK_DISPLAY_DELAY);
+ }
+ AttackerStateUpdate(pVictim, BASE_ATTACK);
+ resetAttackTimer(BASE_ATTACK);
+ }
+
+ Player* player = (GetTypeId() == TYPEID_PLAYER ? (Player*)this : NULL);
+ if (player && swingErrorMsg != player->SwingErrorMsg())
+ {
+ if (swingErrorMsg == 1)
+ player->SendAttackSwingNotInRange();
+ else if (swingErrorMsg == 2)
+ player->SendAttackSwingBadFacingAttack();
+ player->SwingErrorMsg(swingErrorMsg);
+ }
+ }
+
+ if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
+ {
+ if (!CanReachWithMeleeAttack(pVictim))
+ {
+ setAttackTimer(OFF_ATTACK,100);
+ }
+ else if (!HasInArc(2*M_PI_F/3, pVictim))
+ {
+ setAttackTimer(OFF_ATTACK,100);
+ }
+ else
+ {
+ // prevent base and off attack in same time, delay attack at 0.2 sec
+ uint32 base_att = getAttackTimer(BASE_ATTACK);
+ if (base_att < ATTACK_DISPLAY_DELAY)
+ setAttackTimer(BASE_ATTACK,ATTACK_DISPLAY_DELAY);
+ // do attack
+ AttackerStateUpdate(pVictim, OFF_ATTACK);
+ resetAttackTimer(OFF_ATTACK);
+ }
+ }
+ }
+}
+
bool Unit::haveOffhandWeapon() const
{
if (!CanUseEquippedWeapon(OFF_ATTACK))
@@ -359,7 +438,15 @@ bool Unit::haveOffhandWeapon() const
if(GetTypeId() == TYPEID_PLAYER)
return ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true,true);
else
+ {
+ uint32 ItemId = GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1);
+ ItemEntry const* itemInfo = sItemStore.LookupEntry(ItemId);
+
+ if (itemInfo && itemInfo->Class == ITEM_CLASS_WEAPON)
+ return true;
+
return false;
+ }
}
void Unit::SendHeartBeat()
@@ -2690,7 +2777,6 @@ uint32 Unit::CalculateDamage (WeaponAttackType attType, bool normalized)
min_damage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE);
max_damage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE);
break;
- // Just for good manner
default:
min_damage = 0.0f;
max_damage = 0.0f;
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 9ab3045..b4636e9 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1960,6 +1960,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
private:
void CleanupDeletedAuras();
void UpdateSplineMovement(uint32 t_diff);
+ void UpdateMeleeAttackingState();
// player or player's pet
float GetCombatRatingReduction(CombatRating cr) const;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment