[8205] Really use trap GO charges and avoid casting in despawned state.

* 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.
This commit is contained in:
VladimirMangos 2009-07-19 07:34:18 +04:00
parent 349216d5d7
commit 39833b0069
3 changed files with 96 additions and 83 deletions

View file

@ -50,7 +50,6 @@ GameObject::GameObject() : WorldObject()
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;
@ -156,10 +155,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
SetGoAnimProgress(animprogress); SetGoAnimProgress(animprogress);
// Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER)
m_charges = goinfo->spellcaster.charges;
//Notify the map's instance data. //Notify the map's instance data.
//Only works if you create the object in it, not if it is moves to that map. //Only works if you create the object in it, not if it is moves to that map.
//Normally non-players do not teleport to other maps. //Normally non-players do not teleport to other maps.
@ -282,99 +277,107 @@ 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)
{ {
if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call) if(m_cooldownTime >= time(NULL))
return; return;
else
{
if(m_respawnTime > 0)
break;
radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3 // traps
IsBattleGroundTrap = true; Unit* owner = GetOwner();
Unit* ok = NULL; // pointer to appropriate target if found any
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)
{
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;
}
} }
}
bool NeedDespawn = (goInfo->trap.charges != 0); CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); // Note: this hack with search required until GO casting not implemented
Cell cell(p); // search unfriendly creature
cell.data.Part.reserved = ALL_DISTRICT; if(owner && goInfo->trap.charges > 0) // hunter trap
// Note: this hack with search required until GO casting not implemented
// search unfriendly creature
if(owner && NeedDespawn) // hunter trap
{
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check);
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
// or unfriendly player/pet
if(!ok)
{ {
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check);
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
// or unfriendly player/pet
if(!ok)
{
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
}
}
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* p_ok = NULL;
MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check);
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
ok = p_ok;
}
if (ok)
{
Unit *caster = owner ? owner : ok;
caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
m_cooldownTime = time(NULL) + 4; // 4 seconds
// count charges
if(goInfo->trap.charges > 0)
AddUse();
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
{
//BattleGround gameobjects case
if(((Player*)ok)->InBattleGround())
if(BattleGround *bg = ((Player*)ok)->GetBattleGround())
bg->HandleTriggerBuff(GetGUID());
}
} }
} }
else // environmental trap
if(uint32 max_charges = goInfo->GetCharges())
{ {
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support if (m_usetimes >= max_charges)
// affect only players
Player* p_ok = NULL;
MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check);
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
ok = p_ok;
}
if (ok)
{
Unit *caster = owner ? owner : ok;
caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID());
m_cooldownTime = time(NULL) + 4; // 4 seconds
if(NeedDespawn)
SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
{ {
//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:

View file

@ -442,6 +442,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)
@ -663,7 +674,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
bool isActiveObject() const { return false; } bool isActiveObject() const { return false; }
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

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8204" #define REVISION_NR "8205"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__