[8205] Really use trap GO charges and avoid casting in despawned state. Author: VladimirMangos
* Drop horribale hack with stored charges amount, use instead GO info charges data as expected.
* Count trap activations as charge uses if it have limited charges.
* Check trap reactions only in ready spawned state.
--HG--
branch : trunk
This commit is contained in:
+74
-71
@@ -54,7 +54,6 @@ GameObject::GameObject() : WorldObject(), m_goValue(new GameObjectValue)
|
|||||||
m_spawnedByDefault = true;
|
m_spawnedByDefault = true;
|
||||||
m_usetimes = 0;
|
m_usetimes = 0;
|
||||||
m_spellId = 0;
|
m_spellId = 0;
|
||||||
m_charges = 5;
|
|
||||||
m_cooldownTime = 0;
|
m_cooldownTime = 0;
|
||||||
m_goInfo = NULL;
|
m_goInfo = NULL;
|
||||||
m_goData = NULL;
|
m_goData = NULL;
|
||||||
@@ -188,9 +187,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
|
|||||||
|
|
||||||
switch(goinfo->type)
|
switch(goinfo->type)
|
||||||
{
|
{
|
||||||
case GAMEOBJECT_TYPE_SPELLCASTER:
|
|
||||||
m_charges = goinfo->spellcaster.charges;
|
|
||||||
break;
|
|
||||||
case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
|
case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
|
||||||
m_goValue->building.health = goinfo->building.intactNumHits + goinfo->building.damagedNumHits;
|
m_goValue->building.health = goinfo->building.intactNumHits + goinfo->building.damagedNumHits;
|
||||||
break;
|
break;
|
||||||
@@ -309,87 +305,94 @@ void GameObject::Update(uint32 /*p_time*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// traps can have time and can not have
|
if(isSpawned())
|
||||||
GameObjectInfo const* goInfo = GetGOInfo();
|
|
||||||
if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
|
|
||||||
{
|
{
|
||||||
// traps
|
// traps can have time and can not have
|
||||||
Unit* owner = GetOwner();
|
GameObjectInfo const* goInfo = GetGOInfo();
|
||||||
Unit* ok = NULL; // pointer to appropriate target if found any
|
if(goInfo->type == GAMEOBJECT_TYPE_TRAP)
|
||||||
|
|
||||||
if(m_cooldownTime >= time(NULL))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool IsBattleGroundTrap = false;
|
|
||||||
//FIXME: this is activation radius (in different casting radius that must be selected from spell data)
|
|
||||||
//TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
|
|
||||||
float radius = goInfo->trap.radius;
|
|
||||||
if(!radius) // i think this is a hack, spell radius is determined by trap radius (spell itself does not have radius)
|
|
||||||
if(const SpellEntry *spellEntry = sSpellStore.LookupEntry(m_spellId))
|
|
||||||
radius = goInfo->trap.radius;
|
|
||||||
if(!radius)
|
|
||||||
{
|
{
|
||||||
if(goInfo->trap.cooldown == 3) // cast in other case (at some triggering/linked go/etc explicit call)
|
if(m_cooldownTime >= time(NULL))
|
||||||
{
|
|
||||||
if(m_respawnTime > 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
|
|
||||||
IsBattleGroundTrap = true;
|
|
||||||
}
|
|
||||||
if(!radius)
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Note: this hack with search required until GO casting not implemented
|
// traps
|
||||||
// search unfriendly creature
|
Unit* owner = GetOwner();
|
||||||
if(owner) // hunter trap
|
Unit* ok = NULL; // pointer to appropriate target if found any
|
||||||
{
|
|
||||||
Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
|
|
||||||
Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, ok, checker);
|
|
||||||
VisitNearbyGridObject(radius, searcher);
|
|
||||||
if(!ok) VisitNearbyWorldObject(radius, searcher);
|
|
||||||
}
|
|
||||||
else // environmental trap
|
|
||||||
{
|
|
||||||
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support
|
|
||||||
// affect only players
|
|
||||||
Player* player = NULL;
|
|
||||||
MaNGOS::AnyPlayerInObjectRangeCheck checker(this, radius);
|
|
||||||
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> searcher(this, player, checker);
|
|
||||||
VisitNearbyWorldObject(radius, searcher);
|
|
||||||
ok = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok)
|
bool IsBattleGroundTrap = false;
|
||||||
{
|
//FIXME: this is activation radius (in different casting radius that must be selected from spell data)
|
||||||
// some traps do not have spell but should be triggered
|
//TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
|
||||||
if(goInfo->trap.spellId)
|
float radius = goInfo->trap.radius;
|
||||||
CastSpell(ok, goInfo->trap.spellId);
|
if(!radius)
|
||||||
//Unit *caster = owner ? owner : ok;
|
{
|
||||||
//caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
|
if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_respawnTime > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
|
||||||
|
IsBattleGroundTrap = true;
|
||||||
|
|
||||||
|
if(!radius)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this hack with search required until GO casting not implemented
|
||||||
|
// search unfriendly creature
|
||||||
|
if(owner) // hunter trap
|
||||||
|
{
|
||||||
|
Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
|
||||||
|
Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, ok, checker);
|
||||||
|
VisitNearbyGridObject(radius, searcher);
|
||||||
|
if(!ok) VisitNearbyWorldObject(radius, searcher);
|
||||||
|
}
|
||||||
|
else // environmental trap
|
||||||
|
{
|
||||||
|
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support
|
||||||
|
// affect only players
|
||||||
|
Player* player = NULL;
|
||||||
|
MaNGOS::AnyPlayerInObjectRangeCheck checker(this, radius);
|
||||||
|
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> searcher(this, player, checker);
|
||||||
|
VisitNearbyWorldObject(radius, searcher);
|
||||||
|
ok = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
// some traps do not have spell but should be triggered
|
||||||
|
if(goInfo->trap.spellId)
|
||||||
|
CastSpell(ok, goInfo->trap.spellId);
|
||||||
|
|
||||||
if(goInfo->trap.cooldown)
|
|
||||||
m_cooldownTime = time(NULL) + goInfo->trap.cooldown;
|
|
||||||
else
|
|
||||||
m_cooldownTime = time(NULL) + 4; // 4 seconds
|
m_cooldownTime = time(NULL) + 4; // 4 seconds
|
||||||
|
|
||||||
if(owner)
|
// count charges
|
||||||
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
//if(goInfo->trap.charges > 0)
|
||||||
|
// AddUse();
|
||||||
|
|
||||||
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
|
if(owner)
|
||||||
|
SetLootState(GO_JUST_DEACTIVATED);
|
||||||
|
|
||||||
|
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
//BattleGround gameobjects case
|
||||||
|
if(((Player*)ok)->InBattleGround())
|
||||||
|
if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
|
||||||
|
bg->HandleTriggerBuff(GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(uint32 max_charges = goInfo->GetCharges())
|
||||||
|
{
|
||||||
|
if (m_usetimes >= max_charges)
|
||||||
{
|
{
|
||||||
//BattleGround gameobjects case
|
m_usetimes = 0;
|
||||||
if(((Player*)ok)->InBattleGround())
|
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
||||||
if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
|
|
||||||
bg->HandleTriggerBuff(GetGUID());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_charges && m_usetimes >= m_charges)
|
|
||||||
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GO_ACTIVATED:
|
case GO_ACTIVATED:
|
||||||
|
|||||||
+11
-1
@@ -444,6 +444,17 @@ struct GameObjectInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 GetCharges() const // despawn at uses amount
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
//case GAMEOBJECT_TYPE_TRAP: return trap.charges;
|
||||||
|
case GAMEOBJECT_TYPE_GUARDPOST: return guardpost.charges;
|
||||||
|
case GAMEOBJECT_TYPE_SPELLCASTER: return spellcaster.charges;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 GetLinkedGameObjectEntry() const
|
uint32 GetLinkedGameObjectEntry() const
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
@@ -692,7 +703,6 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject
|
|||||||
|
|
||||||
uint64 GetRotation() const { return m_rotation; }
|
uint64 GetRotation() const { return m_rotation; }
|
||||||
protected:
|
protected:
|
||||||
uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
|
|
||||||
uint32 m_spellId;
|
uint32 m_spellId;
|
||||||
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
|
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
|
||||||
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
|
||||||
|
|||||||
Reference in New Issue
Block a user