PDA

Просмотр полной версии : [patch/dev] Невидимость vs магия


Insider42
12.05.2010, 14:46
Достаточно давно роги (они же Разбойники) (и друиды тоже) стали жаловаться, что при уходе, например в "ванишу" (оно же Исчезновение), в них всё равно прилетает спел, если он наносит урон моментально. В итоге с помощью Чародейской вспышки или Чародейских стрел (особенно любимый магами спел для того чтобы мучать разбойников.
В данный момент стот ревизия 9880 и проблема всё ещё есть.

По-моему вот этот участок кода в spell.cpp должен отвечать за это дело
// update pointers base at GUIDs to prevent access to non-existed already object
UpdatePointers();

// cancel at lost main target unit
if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID())
{
cancel();
m_caster->DecreaseCastCounter();
SetExecutedCurrently(false);
return;
}
И нужно добавить проверку на IsVisibleForOrDetect()

У кого-то есть другие идеи по реализации? Пишите, пока я не начал реализацию того, что задумал :)

Ещё есть вариант поработать с этой функцией
void SpellCastTargets::Update(Unit* caster)
{
m_GOTarget = !m_GOTargetGUID.IsEmpty() ? caster->GetMap()->GetGameObject(m_GOTargetGUID) : NULL;
m_unitTarget = !m_unitTargetGUID.IsEmpty() ?
( m_unitTargetGUID == caster->GetObjectGuid() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID) ) :
NULL;

m_itemTarget = NULL;
if(caster->GetTypeId() == TYPEID_PLAYER)
{
if(m_targetMask & TARGET_FLAG_ITEM)
m_itemTarget = ((Player*)caster)->GetItemByGuid(m_itemTargetGUID);
else if(m_targetMask & TARGET_FLAG_TRADE_ITEM)
{
Player* pTrader = ((Player*)caster)->GetTrader();
if(pTrader && m_itemTargetGUID.GetRawValue() < TRADE_SLOT_COUNT)
m_itemTarget = pTrader->GetItemByPos(pTrader->GetItemPosByTradeSlot(uint32(m_itemTargetGUID.GetR awValue())));
}
if(m_itemTarget)
m_itemTargetEntry = m_itemTarget->GetEntry();
}
}

патч V1
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index fd69f8d..cba440c 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -188,6 +188,10 @@ void SpellCastTargets::Update(Unit* caster)
( m_unitTargetGUID == caster->GetObjectGuid() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID) ) :
NULL;

+ if (m_unitTarget && m_unitTargetGUID != caster->GetObjectGuid() &&
+ !m_unitTarget->isVisibleForOrDetect(caster, caster, false))
+ m_unitTarget = NULL;
+
m_itemTarget = NULL;
if(caster->GetTypeId() == TYPEID_PLAYER)
{

Сразу возникла проблема - патч выполяет то, для чего он писался, НО не выводит никаких сообщений и обрабатывается даже раньше чем
// for delayed spells ignore not visible explicit target
if (m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() &&
!unit->isVisibleForOrDetect(m_caster, m_caster, false))
{
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
ResetEffectDamageAndHeal();
return;
} в том же spell.cpp, следовательно последний кусок тупо отпадает.

Поставлю на игровой сервер, посмотрим что ещё найдут :P

Laise
12.05.2010, 18:06
SpellCastTargets::Update - может зря туда? Update в нескольких местах используется..
if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID()) может туда уже добавить как еще одно условие ? а не просто обнулять unitTarget?

Insider42
12.05.2010, 18:56
SpellCastTargets::Update - может зря туда? Update в нескольких местах используется..

Но ведь не логично стрелять в цель которую мы не видим... где бы оно ни происходило и не использовалось

if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID()) может туда уже добавить как еще одно условие ? а не просто обнулять unitTarget?

Тогда каст будет срываться только в самом конце, т.е. полоска дойдёт до конца, а эффект не произойдёт.
Нам же нужно прервать заклинание именно в тот момент когда цель стала недоступна

Everheit
13.05.2010, 04:25
логично то логично, но этот баг есть и на офе. близы пытались его фиксить во времена траев ик-ивк, но безуспешно

Deamon
13.05.2010, 20:31
логично то логично, но этот баг есть и на офе. близы пытались его фиксить во времена траев ик-ивк, но безуспешно

Там другие глюки. Глюки связанные с петами. И этот глюк таки пофиксили тогда, но бляззы посчитали, что это слишком круто для рог, и вернули все обратно =)))

Insider42
15.05.2010, 22:59
С патчем в первом посте проблема:
Ловушки охотников при попадании в них невидимых разбойников - прерываются, в прямом смысле слова.

Загвоздка в том, что m_spellinfo нельзя (или я незнаю как) вызвать из функции, которую меняет патч, так возможно бы сделал исключение...

Новая версия патча в более корректном месте
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 16fd1f4..8a59d86 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -3109,6 +3105,9 @@ void Spell::update(uint32 difftime)
{
if(m_timer)
{
+ if (m_targets.getUnitTarget() && !m_targets.getUnitTarget()->isVisibleForOrDetect(m_caster, m_caster, false))
+ cancel();
+
if(difftime >= m_timer)
m_timer = 0;
else

Не смог обнаружить никаких багов из вышеперечисленных
Пожалуй, это окончательная версия

Insider42
15.06.2010, 09:16
Нашёл баг в предыдущей версии патча, из-за которого некоторые невидимые НПС, такие как Хранители душ на БГ, иногда не воскрешали игроков
Новая версия патча не должна иметь данной проблемы, там всего лишь нехватало проверки на IsAlive, ведь мертвый по определению невидим.
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 16fd1f4..8a59d86 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -3109,6 +3105,9 @@ void Spell::update(uint32 difftime)
{
if(m_timer)
{
+ if (m_targets.getUnitTarget() && m_targets.getUnitTarget()->isAlive() && !m_targets.getUnitTarget()->isVisibleForOrDetect(m_caster, m_caster, false))
+ cancel();
+
if(difftime >= m_timer)
m_timer = 0;
else

Пока не тестировал, о проблеме доложил Wowka321.