Last active
September 27, 2015 14:58
-
-
Save SilverIce/1288005 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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