diff options
Diffstat (limited to 'src')
4 files changed, 98 insertions, 47 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 27250e6c82a..dd018911a14 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -452,84 +452,85 @@ 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) - { - if (goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call) - return; - else - { - if (m_respawnTime > 0) - break; + // Type 0 despawns after being triggered, type 1 does not. - radius = (float)goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3 - IsBattlegroundTrap = true; + bool isBattlegroundTrap; - if (!radius) - return; - } + /// @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) + { + // Cast in other case (at some triggering/linked go/etc explicit call) + if (goInfo->trap.cooldown != 3 || m_respawnTime > 0) + break; + + // Battleground gameobjects have data2 == 0 && data5 == 3 + isBattlegroundTrap = true; + radius = 3.f; } + else + { + isBattlegroundTrap = false; + radius = goInfo->trap.diameter / 2.f; + } + + Unit* owner = GetOwner(); + // Pointer to appropriate target if found any + Unit* target = NULL; - // Note: this hack with search required until GO casting not implemented - // search unfriendly creature - if (owner) // hunter trap + /// @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()) @@ -575,6 +576,17 @@ void GameObject::Update(uint32 diff) } else m_groupLootTimer -= diff; } + break; + 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; } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index dacc44c27ad..7d4e6ed548f 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -124,7 +124,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 diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index a9961e06cbc..74b33d9550b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6370,6 +6370,45 @@ bool Spell::UpdatePointers() // cast item not found, somehow the item is no longer where we expected if (!m_CastItem) return false; + + // check if the retrieved item can even cast the spell + ItemTemplate const* proto = m_CastItem->GetTemplate(); + bool spellFound = false; + for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + { + if (uint32(proto->Spells[i].SpellId) == GetSpellInfo()->Id) + { + spellFound = true; + break; + } + } + + // check enchantment if the spell wasn't found in item proto + if (!spellFound) + { + for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot) + { + uint32 enchant_id = m_CastItem->GetEnchantmentId(EnchantmentSlot(e_slot)); + SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if (!pEnchant) + continue; + + for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s) + { + if (pEnchant->spellid[s] == GetSpellInfo()->Id) + { + spellFound = true; + break; + } + } + + if (spellFound) + break; + } + } + + if (!spellFound) + return false; } m_targets.Update(m_caster); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index bd446c60c90..67500382758 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1196,7 +1196,7 @@ class spell_algalon_big_bang : public SpellScriptLoader bool Load() override { _targetCount = 0; - return true; + return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled; } void CountTargets(std::list<WorldObject*>& targets) |
