PDA

Просмотр полной версии : [patch] Creature Off Hand Attack


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;

SeT
11.07.2011, 18:47
вполне вероятно, что на мобов вешается аура, позволяющая бить им с 2х рук.

MaxXx2021
11.07.2011, 18:53
вполне вероятно, что на мобов вешается аура, позволяющая бить им с 2х рук.

Наврятли! Что бы каждому мобу, который носит офф хенд давать ауру, по мне очень бредово звучит.

Mayss
12.07.2011, 01:12
А если это аура которая определяет ap, скорость, уровень и ранг моба и по формуле высчитывает скорость и урон с оф хенда моба?

MaxXx2021
12.07.2011, 03:33
А если это аура которая определяет ap, скорость, уровень и ранг моба и по формуле высчитывает скорость и урон с оф хенда моба?

Вы предсталяеете давать такую ауру огромному кол-ву мобов, так же с уверенностью можно сказать, что базовая атака тоже идет от спелла и берет значения из базы :)

KiriX
12.07.2011, 09:03
Копипаст чтоли???
Первая часть патча - к чему вообще эти изменения?
Что было не так до этого?
m_attackTimer[type] = uint32((GetAttackTime(type) == 0 ? 1500 : GetAttackTime(type)) * m_modAttackSpeedPct[type]);
Неверно ну заменил ты ноль (на каком, кстати, основании? =)) на 1500, а модификатор кто будет применять?

PSZ
12.07.2011, 10:25
Все умножается, на скобки посмотри.

YuruY
12.07.2011, 10:45
1. Стоило лудше бы вынести значения в базу или же делать относительно базовой атаки?
Судя по сниффам, приходят данные:

UNIT_FIELD_MINOFFHANDDAMAGE
UNIT_FIELD_MAXOFFHANDDAMAGE
UNIT_FIELD_BASEATTACKTIME_2

p.s: Нарыл обсуждение у себя этого в хистори аськи аж от 21.01.11.))

Хотя на вторую руку и дальнобойное приходит больше полей:

UNIT_FIELD_MINDAMAGE
UNIT_FIELD_MAXDAMAGE
UNIT_FIELD_ATTACK_POWER
UNIT_FIELD_ATTACK_POWER_MULTIPLIER
UNIT_FIELD_BASEATTACKTIME

UNIT_FIELD_MINRANGEDDAMAGE
UNIT_FIELD_MAXRANGEDDAMAGE
UNIT_FIELD_RANGEDATTACKTIME
UNIT_FIELD_RANGED_ATTACK_POWER

MaxXx2021
12.07.2011, 10:58
Судя по сниффам, приходят данные:

UNIT_FIELD_MINOFFHANDDAMAGE
UNIT_FIELD_MAXOFFHANDDAMAGE
UNIT_FIELD_BASEATTACKTIME_2

p.s: Нарыл обсуждение у себя этого в хистори аськи аж от 21.01.11.))

Хотя на вторую руку и дальнобойное приходит больше полей:

UNIT_FIELD_MINDAMAGE
UNIT_FIELD_MAXDAMAGE
UNIT_FIELD_ATTACK_POWER
UNIT_FIELD_ATTACK_POWER_MULTIPLIER
UNIT_FIELD_BASEATTACKTIME

UNIT_FIELD_MINRANGEDDAMAGE
UNIT_FIELD_MAXRANGEDDAMAGE
UNIT_FIELD_RANGEDATTACKTIME
UNIT_FIELD_RANGED_ATTACK_POWER

те в базу выносить?

Копипаст чтоли???
Первая часть патча - к чему вообще эти изменения?
Что было не так до этого?

а то что значения GetAttackTime(OFF_ATTACK) нету в базе значит и придет 0. Поэтому и спрашиваю в базе делать новые поля?

UNIT_FIELD_MINOFFHANDDAMAGE
UNIT_FIELD_MAXOFFHANDDAMAGE
UNIT_FIELD_BASEATTACKTIME_2

Копипаст чтоли???

где вы тут копипаст нашли?

YuruY
12.07.2011, 11:22
Поэтому и спрашиваю в базе делать новые поля?
Я просто увидел обсуждение, уточнил что по сниффам видел, дальше решайте сами.

MaxXx2021
12.07.2011, 11:33
Я просто увидел обсуждение, уточнил что по сниффам видел, дальше решайте сами.

Ну если по сниффам приходит, значит будем делать через базу! Спасибо YuruY

KiriX
12.07.2011, 11:41
Скобки не заметил, сорри =)
А первая часть всё равно не понятно зачем изменяется. Я про этот файл: СreatureAI.cpp

MaxXx2021
12.07.2011, 13:08
Скобки не заметил, сорри =)
А первая часть всё равно не понятно зачем изменяется. Я про этот файл: СreatureAI.cpp

А то что, там только BASE_ATTACK идет и все. А нам нудно и левой рукой что бы бил :)

Добавлено через 1 час 23 минуты
Я просто увидел обсуждение, уточнил что по сниффам видел, дальше решайте сами.
YuruY А у вас не будет пару сниффов, о содержании этих полей. Надо значение mindmg, maxdmg и minoffdmg, maxoffdmg что бы я мог примерно всем мобам в базе выставить приближенные значения для начала, относильно базового урона. А там уже дело сбора инфы :)
П.С. и скорости тоже.

YuruY
12.07.2011, 13:25
Те про которые писал, там снифф чисто без боя (мобов которые дерутся с обоих рук тоже не так много), все поля по нулям кроме "UNIT_FIELD_BASEATTACKTIME_Х" (оно всегда заполнено почемуто, не важно бой был с мобом или нет), позже эти поля в сниффах не изучал больше. Если нужно могу для изучения кинуть снифф какогонибудь данжа к примеру, там сами смотрите (версию уточните только 4.0.6, 4.1.0, 4.2.0).

virusav
12.07.2011, 13:30
Смотрел снифф выполнения квеста "Перемирие?", там есть данные боя, но везде, где смотрел, UNIT_FIELD_BASEATTACKTIME_2=UNIT_FIELD_BASEATTACKT IME=2000.

Возможно, по кодам нпц будет проще искать по сниффам, т.к. хз, у кого есть offhand, а у кого - нет.

MaxXx2021
12.07.2011, 13:32
Те про которые писал, там снифф чисто без боя (мобов которые дерутся с обоих рук тоже не так много), все поля по нулям кроме "UNIT_FIELD_BASEATTACKTIME_Х" (оно всегда заполнено почемуто, не важно бой был с мобом или нет), позже эти поля в сниффах не изучал больше. Если нужно могу для изучения кинуть снифф какогонибудь данжа к примеру, там сами смотрите (версию уточните только 4.0.6, 4.1.0, 4.2.0).

От сниффа не откажусь :) . Любую версию можно.

Можно снифф черного хранителя в долине эха. В испытании крестоносца у рога два вепона. Испытание чемпиона у Иллюзии Ванклифа. Битва за подгород (Орда Сильвана с двумя мечами). Битва За Подгород (Альянс, король Рин с двумя мечами). Дарион Могрейн в Акерусе с двумя мечами. Если кто сможет сделать данные сниффы буду рад :)

YuruY
12.07.2011, 19:23
Смотрел снифф выполнения квеста "Перемирие?", там есть данные боя, но везде, где смотрел, UNIT_FIELD_BASEATTACKTIME_2=UNIT_FIELD_BASEATTACKT IME=2000.
Тоже заметил, изучал много тогда, разные значения ооочень редко встречал.
Возможно, по кодам нпц будет проще искать по сниффам, т.к. хз, у кого есть offhand, а у кого - нет.

Я искал по экипировке, насчет второго оружия в руке. ;)

Можно снифф черного хранителя в долине эха. В испытании крестоносца у рога два вепона. Испытание чемпиона у Иллюзии Ванклифа. Битва за подгород (Орда Сильвана с двумя мечами). Битва За Подгород (Альянс, король Рин с двумя мечами). Дарион Могрейн в Акерусе с двумя мечами. Если кто сможет сделать данные сниффы буду рад
До этого не добрался еще. Глянь ПМ. =)

virusav
12.07.2011, 20:49
Пересмотрел несколько сниффов, нашел только один случай, где значения разные, но это оказался игрок.

MaxXx2021
13.07.2011, 11:35
Обновил патч, патч работает без базы! Данные берутся относительно базовой атаки. Так как некоторая инфа в ядре уже есть по этому поводу.
Патч, готов! Теперь ждем ответа от DEVs :)

Mayss
14.07.2011, 18:26
Почему-то не обращают внимания, на данный патч, в виду того что не до него?, думаю вполне нужный патч.

MaxXx2021
10.08.2011, 11:59
Внес кое какие изменения: По просьбе Владимира убрал новый UnitField и сделал по аналогии плееров удары двумя руками. Патч в аттаче поменяю позже.

https://github.com/bwsrv/mangos/commit/79f72032f3ecc7eeed27833aafc2c67855b52a42