PDA

Просмотр полной версии : [crash fix] Aura::PeriodicTick


Insider42
23.04.2010, 14:01
Оригинальная тема тут http://getmangos.com/community/showthread.php?13636 :declare:

Тут не проверяется есть ли цель в игре, по-моему более правильно ничего не делать с целью которая находится вне игры. По крайней мере ниразу не слышал от игроков с оффа чтобы что-то происходило с их персонажами когда они вышли из игры+их персонаж выгрузился из мира (как уже было обнаружено, на оффе персонаж ещё некоторое время стоит в игре после того как игрок уже вышел из игры. Возможно это происходит только если он был в бою).

diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 59b037f..d9af2ae 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -7284,13 +7284,32 @@ void Aura::PeriodicTick()
{
switch(m_modifier.m_auraname)
{
+ // don't do anything to target that isn't in world or dead, possible death persistent effects
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- {
- // don't damage target if not alive, possible death persistent effects
- if (!m_target->isAlive())
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
+ case SPELL_AURA_PERIODIC_HEAL:
+ case SPELL_AURA_OBS_MOD_HEALTH:
+ case SPELL_AURA_PERIODIC_MANA_LEECH:
+ case SPELL_AURA_POWER_BURN_MANA:
+ case SPELL_AURA_PERIODIC_ENERGIZE:
+ case SPELL_AURA_OBS_MOD_MANA:
+ case SPELL_AURA_MOD_REGEN:
+ case SPELL_AURA_MOD_POWER_REGEN:
+ if (!m_target || !m_target->IsInWorld() || !m_target->isAlive())
return;
+ break;
+ default:
+ break;
+ }

+ switch(m_modifier.m_auraname)
+ {
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
+ {
Unit *pCaster = GetCaster();
if(!pCaster)
return;
@@ -7427,10 +7446,6 @@ void Aura::PeriodicTick()
case SPELL_AURA_PERIODIC_LEECH:
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
{
- // don't damage target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
Unit *pCaster = GetCaster();
if(!pCaster)
return;
@@ -7516,10 +7531,6 @@ void Aura::PeriodicTick()
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH:
{
- // don't heal target if not alive, mostly death persistent effects from items
- if (!m_target->isAlive())
- return;
-
Unit *pCaster = GetCaster();
if(!pCaster)
return;
@@ -7618,10 +7629,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_PERIODIC_MANA_LEECH:
{
- // don't damage target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS)
return;

@@ -7695,10 +7702,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_PERIODIC_ENERGIZE:
{
- // don't energize target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
// ignore non positive values (can be result apply spellmods to aura damage
uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;

@@ -7724,10 +7727,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_OBS_MOD_MANA:
{
- // don't energize target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
// ignore non positive values (can be result apply spellmods to aura damage
uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;

@@ -7750,10 +7749,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_POWER_BURN_MANA:
{
- // don't mana burn target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
Unit *pCaster = GetCaster();
if(!pCaster)
return;
@@ -7800,10 +7795,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_MOD_REGEN:
{
- // don't heal target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
if (Unit *caster = GetCaster())
m_target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
@@ -7811,10 +7802,6 @@ void Aura::PeriodicTick()
}
case SPELL_AURA_MOD_POWER_REGEN:
{
- // don't energize target if not alive, possible death persistent effects
- if (!m_target->isAlive())
- return;
-
Powers pt = m_target->getPowerType();
if(int32(pt) != m_modifier.m_miscvalue)
return;

Вынес в отдельный switch для обобщения условия :yes3:

Insider42
23.04.2010, 16:55
добавил проверку "есть ли вообще" цель. Патч обновлен

Vladimir
23.04.2010, 20:11
if (!m_target Чистой воды хак: m_target не может быть NULL без бага - m_target - это наком наложена аура и аура удаляется раньше чем сам носитель, _всегда_

!m_target->IsInWorld() Хак. Обновление ауры не вызывается для юнитов вне мира, так как обновление вызывается для карты включая играков.

Конечно это все в чистом мангосе.

Insider42
23.04.2010, 20:33
Но ведь этот краш происходит и на чистом мангосе ... где-то явно бага закопалась

Как можно отследить?

Vladimir
23.04.2010, 23:11
ну как всегда - поймать в отладчике и отследить причину если получится...

Mr.Grom
24.04.2010, 14:02
Может одна проверка на 11 аур меньше грузит ядро чем 11 проверок на 11 аур?
Так же можно попробовать и с проверками
Unit *pCaster = GetCaster();
if(!pCaster)
return;

В патче 1 строка повтор.
+ case SPELL_AURA_POWER_BURN_MANA:

Insider42
24.04.2010, 14:23
Может одна проверка на 11 аур меньше грузит ядро чем 11 проверок на 11 аур?

обрабатываться будет точно также, просто меньше хлама.

Vladimir
24.04.2010, 20:42
у вас 2 раза select - что не одно тоже что один - что медленнее (хотя этот и не сильная разница), но что более неприятно - можно забыть добавить проверку когда будет добавляться новый вариант в отсновной выбор.