MaxXx2021
11.07.2011, 18:28
Сейчас ситуация такая: NPC имея в левой руке какое либо оружие, не бьют ей. Данный патч поправляет данную ситуацию.
Автор: Я
патч на гите: https://github.com/bwsrv/mangos/commit/c6c041d1309076e9d0063876505e400e19930cfc
Дополнение к патчу:
https://github.com/bwsrv/mangos/commit/79f72032f3ecc7eeed27833aafc2c67855b52a42
патч файлом: в аттаче!
diff:
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 928c956..68fe6b0 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -355,8 +355,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;
@@ -1180,8 +1194,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 30b03d9..695697b 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -122,22 +122,30 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
return CAST_FAIL_IS_CASTING;
}
+bool CreatureAI::AttackByType(WeaponAttackType attType)
+{
+ // Make sure our attack is ready before checking distance
+ if (m_creature->isAttackReady(attType) && m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim(), attType);
+ m_creature->resetAttackTimer(attType);
+ WeaponAttackType attTypeTwo = (attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK);
+ if (m_creature->getAttackTimer(attTypeTwo) < 500)
+ m_creature->setAttackTimer(attTypeTwo, 500);
+ return true;
+ }
+
+ return false;
+}
+
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;
+ if (AttackByType(BASE_ATTACK))
+ return true;
- m_creature->AttackerStateUpdate(m_creature->getVictim());
- m_creature->resetAttackTimer();
+ if (m_creature->haveOffhandWeapon())
+ return AttackByType(OFF_ATTACK);
- return true;
+ return false;
}
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 78ec0b0..5f46f34 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;
@@ -163,6 +164,7 @@ class MANGOS_DLL_SPEC CreatureAI
virtual bool canReachByRangeAttack(Unit*) { return false; }
///== Helper functions =============================
+ bool AttackByType(WeaponAttackType attType = BASE_ATTACK);
bool DoMeleeAttackIfReady();
CanCastResult DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, ObjectGuid uiOriginalCasterGUID = ObjectGuid());
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index 99f0975..20e55a8 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -901,18 +901,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;
@@ -922,14 +924,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 15372cd..c27f3e8 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -239,7 +239,8 @@ Unit::Unit() :
m_auraModifiersGroup[i][NONSTACKING_VALUE] = 0.0f;
m_auraModifiersGroup[i][NONSTACKING_PCT] = 0.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)
@@ -372,6 +373,11 @@ 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) );
+ }
+
// update abilities available only for fraction of time
UpdateReactives( update_diff );
@@ -390,7 +396,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;
+ }
}
@@ -3079,7 +3093,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;
Автор: Я
патч на гите: https://github.com/bwsrv/mangos/commit/c6c041d1309076e9d0063876505e400e19930cfc
Дополнение к патчу:
https://github.com/bwsrv/mangos/commit/79f72032f3ecc7eeed27833aafc2c67855b52a42
патч файлом: в аттаче!
diff:
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 928c956..68fe6b0 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -355,8 +355,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;
@@ -1180,8 +1194,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 30b03d9..695697b 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -122,22 +122,30 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
return CAST_FAIL_IS_CASTING;
}
+bool CreatureAI::AttackByType(WeaponAttackType attType)
+{
+ // Make sure our attack is ready before checking distance
+ if (m_creature->isAttackReady(attType) && m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim(), attType);
+ m_creature->resetAttackTimer(attType);
+ WeaponAttackType attTypeTwo = (attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK);
+ if (m_creature->getAttackTimer(attTypeTwo) < 500)
+ m_creature->setAttackTimer(attTypeTwo, 500);
+ return true;
+ }
+
+ return false;
+}
+
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;
+ if (AttackByType(BASE_ATTACK))
+ return true;
- m_creature->AttackerStateUpdate(m_creature->getVictim());
- m_creature->resetAttackTimer();
+ if (m_creature->haveOffhandWeapon())
+ return AttackByType(OFF_ATTACK);
- return true;
+ return false;
}
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 78ec0b0..5f46f34 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;
@@ -163,6 +164,7 @@ class MANGOS_DLL_SPEC CreatureAI
virtual bool canReachByRangeAttack(Unit*) { return false; }
///== Helper functions =============================
+ bool AttackByType(WeaponAttackType attType = BASE_ATTACK);
bool DoMeleeAttackIfReady();
CanCastResult DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, ObjectGuid uiOriginalCasterGUID = ObjectGuid());
diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp
index 99f0975..20e55a8 100644
--- a/src/game/StatSystem.cpp
+++ b/src/game/StatSystem.cpp
@@ -901,18 +901,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;
@@ -922,14 +924,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 15372cd..c27f3e8 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -239,7 +239,8 @@ Unit::Unit() :
m_auraModifiersGroup[i][NONSTACKING_VALUE] = 0.0f;
m_auraModifiersGroup[i][NONSTACKING_PCT] = 0.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)
@@ -372,6 +373,11 @@ 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) );
+ }
+
// update abilities available only for fraction of time
UpdateReactives( update_diff );
@@ -390,7 +396,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;
+ }
}
@@ -3079,7 +3093,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;