diff options
-rw-r--r-- | sql/updates/world/2014_05_07_00_world_creature_template.sql | 2 | ||||
-rw-r--r-- | sql/updates/world/2014_05_07_00_world_gossip_menu_option.sql | 1 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 84 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 3 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 48 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 3 |
7 files changed, 60 insertions, 82 deletions
diff --git a/sql/updates/world/2014_05_07_00_world_creature_template.sql b/sql/updates/world/2014_05_07_00_world_creature_template.sql new file mode 100644 index 00000000000..aa1a0511f18 --- /dev/null +++ b/sql/updates/world/2014_05_07_00_world_creature_template.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `unit_flags`=`unit_flags`|256, `flags_extra`=0 WHERE `entry`=30413; diff --git a/sql/updates/world/2014_05_07_00_world_gossip_menu_option.sql b/sql/updates/world/2014_05_07_00_world_gossip_menu_option.sql new file mode 100644 index 00000000000..2939237dc7d --- /dev/null +++ b/sql/updates/world/2014_05_07_00_world_gossip_menu_option.sql @@ -0,0 +1 @@ +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8903 AND `id`=1; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index dd018911a14..5f91755d527 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -47,6 +47,7 @@ GameObject::GameObject() : WorldObject(false), MapObject(), m_respawnTime = 0; m_respawnDelayTime = 300; m_lootState = GO_NOT_READY; + m_lootStateUnitGUID = 0; m_spawnedByDefault = true; m_usetimes = 0; m_spellId = 0; @@ -309,13 +310,13 @@ void GameObject::Update(uint32 diff) GameObjectTemplate const* goInfo = GetGOInfo(); // Bombs if (goInfo->trap.type == 2) - m_cooldownTime = time(NULL) + 10; // Hardcoded tooltip value + // Hardcoded tooltip value + m_cooldownTime = time(NULL) + 10; else if (Unit* owner = GetOwner()) - { if (owner->IsInCombat()) m_cooldownTime = time(NULL) + goInfo->trap.startDelay; - } - m_lootState = GO_READY; + + SetLootState(GO_READY); break; } case GAMEOBJECT_TYPE_TRANSPORT: @@ -396,7 +397,7 @@ void GameObject::Update(uint32 diff) if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day) SetRespawnTime(DAY); else - m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime)+urand(5, MINUTE); // else copy time from master and add a little + m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little SaveRespawnTime(); // also save to DB immediately return; } @@ -423,7 +424,7 @@ void GameObject::Update(uint32 diff) } case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: - //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) + // We need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) if (GetGoState() != GO_STATE_READY) ResetDoorOrButton(); break; @@ -435,13 +436,15 @@ void GameObject::Update(uint32 diff) break; } - if (!m_spawnedByDefault) // despawn timer + // Despawn timer + if (!m_spawnedByDefault) { - // can be despawned or destroyed + // Can be despawned or destroyed SetLootState(GO_JUST_DEACTIVATED); return; } - // respawn timer + + // Respawn timer uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0; if (poolid) sPoolMgr->UpdatePool<GameObject>(poolid, GetDBTableGUIDLow()); @@ -466,47 +469,35 @@ void GameObject::Update(uint32 diff) } // 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) { - // Cast in other case (at some triggering/linked go/etc explicit call) - if (goInfo->trap.cooldown != 3 || m_respawnTime > 0) + // Battleground traps: data2 == 0 && data5 == 3 + if (goInfo->trap.cooldown != 3) 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; /// @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) + if (Unit* owner = GetOwner()) { + // Hunter trap: Search units which are unfriendly to the trap's owner Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius); Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, target, checker); VisitNearbyGridObject(radius, searcher); if (!target) VisitNearbyWorldObject(radius, searcher); } - // Environmental trap: Any target else { - // Environmental damage spells already have around enemies targeting but this does not help in case of not existing GO casting support - // Affect only players + // Environmental trap: Any player Player* player = NULL; Trinity::AnyPlayerInObjectRangeCheck checker(this, radius); Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(this, player, checker); @@ -515,23 +506,8 @@ void GameObject::Update(uint32 diff) } if (target) - { - // Some traps do not have a spell but should be triggered - if (goInfo->trap.spellId) - CastSpell(target, goInfo->trap.spellId); - - // Template value or 4 seconds - m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4)); + SetLootState(GO_ACTIVATED, target); - if (goInfo->trap.type == 1) - SetLootState(GO_JUST_DEACTIVATED); - - // 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()) { @@ -580,11 +556,30 @@ void GameObject::Update(uint32 diff) case GAMEOBJECT_TYPE_TRAP: { GameObjectTemplate const* goInfo = GetGOInfo(); - if (goInfo->trap.spellId) + if (goInfo->trap.type == 2 && goInfo->trap.spellId) + { /// @todo NULL target won't work for target type 1 CastSpell(NULL, goInfo->trap.spellId); + SetLootState(GO_JUST_DEACTIVATED); + } + else if (Unit* target = Unit::GetUnit(*this, m_lootStateUnitGUID)) + { + // Some traps do not have a spell but should be triggered + if (goInfo->trap.spellId) + CastSpell(target, goInfo->trap.spellId); - SetLootState(GO_JUST_DEACTIVATED); + // 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); + + // Battleground gameobjects have data2 == 0 && data5 == 3 + if (!goInfo->trap.diameter && goInfo->trap.cooldown == 3) + if (Player* player = target->ToPlayer()) + if (Battleground* bg = player->GetBattleground()) + bg->HandleTriggerBuff(GetGUID()); + } break; } default: @@ -2014,6 +2009,7 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* void GameObject::SetLootState(LootState state, Unit* unit) { m_lootState = state; + m_lootStateUnitGUID = unit ? unit->GetGUID() : 0; AI()->OnStateChanged(state, unit); sScriptMgr->OnGameObjectLootStateChanged(this, state, unit); if (m_model) diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 7d4e6ed548f..640d5718186 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 diameter; //2 radius for trap activation + uint32 diameter; //2 diameter 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 @@ -842,6 +842,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map 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 LootState m_lootState; + uint64 m_lootStateUnitGUID; // GUID of the unit passed with SetLootState(LootState, Unit*) bool m_spawnedByDefault; time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction). // For traps this: spell casting cooldown, for doors/buttons: reset time. diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 74b33d9550b..93e42222048 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -573,6 +573,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; unitTarget = NULL; itemTarget = NULL; @@ -2808,9 +2809,15 @@ bool Spell::UpdateChanneledTargetList() void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura) { if (m_CastItem) + { m_castItemGUID = m_CastItem->GetGUID(); + m_castItemEntry = m_CastItem->GetEntry(); + } else + { m_castItemGUID = 0; + m_castItemEntry = 0; + } InitExplicitTargets(*targets); @@ -4299,6 +4306,7 @@ void Spell::TakeCastItem() m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; } } @@ -4538,6 +4546,7 @@ void Spell::TakeReagents() m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; } // if GetItemTarget is also spell reagent @@ -6371,43 +6380,8 @@ bool Spell::UpdatePointers() 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) + // check if the item is really the same, in case it has been wrapped for example + if (m_castItemEntry != m_CastItem->GetEntry()) return false; } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 94e1ea44ce7..2b026b77160 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -456,6 +456,7 @@ class Spell SpellInfo const* const m_spellInfo; Item* m_CastItem; uint64 m_castItemGUID; + uint32 m_castItemEntry; uint8 m_cast_count; uint32 m_glyphIndex; uint32 m_preCastSpell; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 041757d152d..9c6b69ef7d7 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1934,6 +1934,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; player->StoreItem(dest, pNewItem, true); return; @@ -1953,6 +1954,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; player->BankItem(dest, pNewItem, true); return; @@ -1976,6 +1978,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) m_CastItem = NULL; m_castItemGUID = 0; + m_castItemEntry = 0; player->EquipItem(dest, pNewItem, true); player->AutoUnequipOffhandIfNeed(); |