mirror of
https://github.com/araxiaonline/TrinityCore2.git
synced 2026-06-19 14:29:33 -04:00
Update aura system:
* Change system logic - unify Auras, AreaAuras and PersistentAreaAuras: * Aura has now its owner - which is the WorldObject, which applies aura (creates AuraApplication object) dependant on aura radius, and effect type * Owner can be Dynobj (DynObjAura class) for PersistentAreaAuras, or Unit (UnitAura class) for Area and nonArea auras * Aura data is shared for all units which have AuraApplication of the Aura * Because of that AuraEffect handlers , and periodic tick functions can't modify AuraEffect object (they are const now) * Remove spell source and AreaAuraEffect classes * Add AuraEffect::UpdatePeriodic function, to allow periodic aura object modification (target independant) * Add AuraEffect::CalculateAmount and AuraEffect::CalculateSpellMod function, to allow non-default amount calculation * AreaAura updates are done in owner _UpdateSpells cycle * Since now you don't need to wait an aura update cycle to get area aura applied on it's correct target list * And you can access area aura target list * Add basic support for aura amount recalculation * Save recalculation state and base amount of auras to db * Add AuraEffect::CalculatePeriodic function to determine if aura is periodic, and to set correct tick number after aura is loaded from db * Add ChangeAmount function in addition to SetAmount function, to allow easy reapplication of AuraEffect handlers on all targets * Sort aura effect handlers in SpellAuras.cpp and .h by their use * Add check for already existing aura of that type to some AuraEffect handlers, to prevent incorrect effect removal * SPELL_AURA_CONVERT_RUNE and MOD_POWER_REGEN and MOD_REGEN hacky handlers are now implemented correctly * Send aura application client update only once per unit update - prevent unnecesary packet spam * Fix ByteBuffer::appendPackGUID function - it added additionall 0s at the end of the packet * Fix memory leak at player creation (not deleted auras) * Updated some naming conventions (too many to mention) * Added Unit::GetAuraOfRankedSpell() function * Remove procflags on aura remove, use Aura::HandleAuraSpecificMods instead * Added functions to maintain owned auras (GetOwnedAuras, GetOwnedAura, RemoveOwnedAura, etc) * Implement AURA_INTERRUPT_FLAG_LANDING * Implement EffectPlayerNotification (thanks to Spp) * Remove wrong aura 304 handler * Add better handler for death runes * Remove unnecesary variables from DynamicObject class, and cleanup related code, link dynobj duration with aura * Add GetAuraEffectTriggerTarget function in CreatureAi for special target selection for periodic trigger auras used in a script * Add many assert() procection from idiots using some functions in wrong way * I am to lazy to write here anything more Thanks to Visagalis for testing this patch PS: Do not make patches like this, please --HG-- branch : trunk
This commit is contained in:
+48
-49
@@ -36,6 +36,9 @@ DynamicObject::DynamicObject() : WorldObject()
|
||||
m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION);
|
||||
|
||||
m_valuesCount = DYNAMICOBJECT_END;
|
||||
|
||||
m_aura = 0;
|
||||
m_duration = 0;
|
||||
}
|
||||
|
||||
void DynamicObject::AddToWorld()
|
||||
@@ -70,13 +73,13 @@ void DynamicObject::RemoveFromWorld()
|
||||
}
|
||||
}
|
||||
|
||||
bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32 effMask, const Position &pos, int32 duration, float radius, bool active)
|
||||
bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active)
|
||||
{
|
||||
SetMap(caster->GetMap());
|
||||
Relocate(pos);
|
||||
if(!IsPositionValid())
|
||||
{
|
||||
sLog.outError("DynamicObject (spell %u eff %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,effMask,GetPositionX(),GetPositionY());
|
||||
sLog.outError("DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,GetPositionX(),GetPositionY());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -85,17 +88,11 @@ bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32
|
||||
SetEntry(spellId);
|
||||
SetFloatValue( OBJECT_FIELD_SCALE_X, 1 );
|
||||
SetUInt64Value( DYNAMICOBJECT_CASTER, caster->GetGUID() );
|
||||
SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 );
|
||||
SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 ); // effectMask?
|
||||
SetUInt32Value( DYNAMICOBJECT_SPELLID, spellId );
|
||||
SetFloatValue( DYNAMICOBJECT_RADIUS, radius);
|
||||
SetFloatValue( DYNAMICOBJECT_RADIUS, radius );
|
||||
SetUInt32Value( DYNAMICOBJECT_CASTTIME, getMSTime() ); // new 2.4.0
|
||||
|
||||
m_aliveDuration = duration;
|
||||
m_radius = radius;
|
||||
m_effMask = effMask;
|
||||
m_spellId = spellId;
|
||||
m_updateTimer = 0;
|
||||
|
||||
m_isWorldObject = active;
|
||||
return true;
|
||||
}
|
||||
@@ -116,45 +113,25 @@ void DynamicObject::Update(uint32 p_time)
|
||||
return;
|
||||
}
|
||||
|
||||
bool deleteThis = false;
|
||||
bool expired = false;
|
||||
|
||||
if(m_aliveDuration > int32(p_time))
|
||||
m_aliveDuration -= p_time;
|
||||
if (m_aura)
|
||||
{
|
||||
if (!m_aura->IsRemoved())
|
||||
m_aura->UpdateOwner(p_time, this);
|
||||
|
||||
if (m_aura->IsRemoved() || m_aura->IsExpired())
|
||||
expired = true;
|
||||
}
|
||||
else
|
||||
deleteThis = true;
|
||||
|
||||
/*
|
||||
// have radius and work as persistent effect
|
||||
if(m_radius)
|
||||
{
|
||||
// TODO: make a timer and update this in larger intervals
|
||||
CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::DynamicObjectUpdater notifier(*this, caster);
|
||||
|
||||
TypeContainerVisitor<Trinity::DynamicObjectUpdater, WorldTypeMapContainer > world_object_notifier(notifier);
|
||||
TypeContainerVisitor<Trinity::DynamicObjectUpdater, GridTypeMapContainer > grid_object_notifier(notifier);
|
||||
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap(), *this, m_radius);
|
||||
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap(), *this, m_radius);
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_effMask)
|
||||
{
|
||||
if (m_updateTimer < p_time)
|
||||
{
|
||||
Trinity::DynamicObjectUpdater notifier(*this,caster);
|
||||
VisitNearbyObject(GetRadius(), notifier);
|
||||
m_updateTimer = 500; // is this official-like?
|
||||
} else m_updateTimer -= p_time;
|
||||
if(GetDuration() > int32(p_time))
|
||||
m_duration -= p_time;
|
||||
else
|
||||
expired = true;
|
||||
}
|
||||
|
||||
if (deleteThis)
|
||||
if (expired)
|
||||
{
|
||||
caster->RemoveDynObjectWithGUID(GetGUID());
|
||||
Delete();
|
||||
@@ -163,21 +140,43 @@ void DynamicObject::Update(uint32 p_time)
|
||||
|
||||
void DynamicObject::Delete()
|
||||
{
|
||||
if (m_aura)
|
||||
{
|
||||
// dynObj may be removed in Aura::Remove - we cannot delete there
|
||||
// so recheck aura here
|
||||
if (!m_aura->IsRemoved())
|
||||
m_aura->_Remove(AURA_REMOVE_BY_DEFAULT);
|
||||
delete m_aura;
|
||||
m_aura = NULL;
|
||||
}
|
||||
SendObjectDeSpawnAnim(GetGUID());
|
||||
RemoveFromWorld();
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
int32 DynamicObject::GetDuration() const
|
||||
{
|
||||
if (!m_aura)
|
||||
return m_duration;
|
||||
else
|
||||
return m_aura->GetDuration();
|
||||
}
|
||||
|
||||
void DynamicObject::SetDuration(int32 newDuration)
|
||||
{
|
||||
if (!m_aura)
|
||||
m_duration = newDuration;
|
||||
else
|
||||
m_aura->SetDuration(newDuration);
|
||||
}
|
||||
|
||||
void DynamicObject::Delay(int32 delaytime)
|
||||
{
|
||||
m_aliveDuration -= delaytime;
|
||||
for (AffectedSet::iterator iunit = m_affected.begin(); iunit != m_affected.end(); ++iunit)
|
||||
if (*iunit)
|
||||
(*iunit)->DelayAura(m_spellId, GetCaster()->GetGUID(), delaytime);
|
||||
SetDuration(GetDuration() - delaytime);
|
||||
}
|
||||
|
||||
bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const
|
||||
{
|
||||
return IsInWorld() && u->IsInWorld()
|
||||
&& (IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user