Core/GameObject: Solve some TODOs related to traps in GameObject::Update and improve logic.

Some more changes, TODO solutions and a fix for traps like those in #1359 or #6388 will follow.
This commit is contained in:
Gacko
2014-05-04 22:15:11 +02:00
parent 6ecbc03955
commit 24ef7dbdf4
2 changed files with 55 additions and 46 deletions

View File

@@ -451,84 +451,83 @@ void GameObject::Update(uint32 diff)
if (isSpawned())
{
// traps can have time and can not have
GameObjectTemplate const* goInfo = GetGOInfo();
if (goInfo->type == GAMEOBJECT_TYPE_TRAP)
{
if (m_cooldownTime >= time(NULL))
return;
break;
// Type 2 - Bomb (will go away after casting it's spell)
// Type 2 (bomb) does not need to be triggered by a unit and despawns after casting its spell.
if (goInfo->trap.type == 2)
{
if (goInfo->trap.spellId)
CastSpell(NULL, goInfo->trap.spellId); // FIXME: null target won't work for target type 1
SetLootState(GO_JUST_DEACTIVATED);
SetLootState(GO_ACTIVATED);
break;
}
// Type 0 and 1 - trap (type 0 will not get removed after casting a spell)
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 = (float)(goInfo->trap.radius)/3*2; /// @todo rename radius to diameter (goInfo->trap.radius) should be (goInfo->trap.diameter)
if (!radius)
// Type 0 despawns after being triggered, type 1 does not.
bool isBattlegroundTrap;
/// @todo This is activation radius. Casting radius must be selected from spell data.
/// @todo Move activated state code to GO_ACTIVATED, in this place just check for activation and set state.
float radius;
if (!goInfo->trap.diameter)
{
if (goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call)
return;
else
{
if (m_respawnTime > 0)
break;
// Cast in other case (at some triggering/linked go/etc explicit call)
if (goInfo->trap.cooldown != 3 || m_respawnTime > 0)
break;
radius = (float)goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
IsBattlegroundTrap = true;
if (!radius)
return;
}
// Battleground gameobjects have data2 == 0 && data5 == 3
isBattlegroundTrap = true;
radius = 3.f;
} else {
isBattlegroundTrap = false;
radius = goInfo->trap.diameter / 2.f;
}
// Note: this hack with search required until GO casting not implemented
// search unfriendly creature
if (owner) // hunter trap
Unit* owner = GetOwner();
// Pointer to appropriate target if found any
Unit* target = NULL;
/// @todo this hack with search required until GO casting not implemented
// Hunter trap: Search units which are unfriendly to the trap's owner
if (owner)
{
Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, ok, checker);
Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, target, checker);
VisitNearbyGridObject(radius, searcher);
if (!ok) VisitNearbyWorldObject(radius, searcher);
if (!target)
VisitNearbyWorldObject(radius, searcher);
}
else // environmental trap
// Environmental trap: Any target
else
{
// environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support
// affect only players
// Environmental damage spells already have around enemies targeting but this does not help in case of not existing GO casting support
// Affect only players
Player* player = NULL;
Trinity::AnyPlayerInObjectRangeCheck checker(this, radius);
Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(this, player, checker);
VisitNearbyWorldObject(radius, searcher);
ok = player;
target = player;
}
if (ok)
if (target)
{
// some traps do not have spell but should be triggered
// Some traps do not have a spell but should be triggered
if (goInfo->trap.spellId)
CastSpell(ok, goInfo->trap.spellId);
CastSpell(target, goInfo->trap.spellId);
m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4)); // template or 4 seconds
// Template value or 4 seconds
m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
if (goInfo->trap.type == 1)
SetLootState(GO_JUST_DEACTIVATED);
if (IsBattlegroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
{
//Battleground gameobjects case
if (ok->ToPlayer()->InBattleground())
if (Battleground* bg = ok->ToPlayer()->GetBattleground())
// Battleground gameobjects case
if (isBattlegroundTrap)
if (Player* player = target->ToPlayer())
if (Battleground* bg = player->GetBattleground())
bg->HandleTriggerBuff(GetGUID());
}
}
}
else if (uint32 max_charges = goInfo->GetCharges())
@@ -574,6 +573,16 @@ void GameObject::Update(uint32 diff)
}
else m_groupLootTimer -= diff;
}
case GAMEOBJECT_TYPE_TRAP:
{
GameObjectTemplate const* goInfo = GetGOInfo();
if (goInfo->trap.spellId)
/// @todo NULL target won't work for target type 1
CastSpell(NULL, goInfo->trap.spellId);
SetLootState(GO_JUST_DEACTIVATED);
break;
}
default:
break;
}

View File

@@ -123,7 +123,7 @@ struct GameObjectTemplate
{
uint32 lockId; //0 -> Lock.dbc
uint32 level; //1
uint32 radius; //2 radius for trap activation
uint32 diameter; //2 radius for trap activation
uint32 spellId; //3
uint32 type; //4 0 trap with no despawn after cast. 1 trap despawns after cast. 2 bomb casts on spawn.
uint32 cooldown; //5 time in secs