diff options
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 11 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 14 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 8 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 73 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObjectData.h | 49 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 69 |
7 files changed, 132 insertions, 93 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 7eae8e1d039..b24f7b76773 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2381,6 +2381,17 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } break; } + case SMART_ACTION_ACTIVATE_GAMEOBJECT: + { + for (WorldObject* target : targets) + { + if (GameObject* targetGo = target->ToGameObject()) + { + targetGo->ActivateObject(GameObjectActions(e.action.activateGameObject.gameObjectAction)); + } + } + break; + } default: TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 6f8299c22da..578b1f958fe 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -943,6 +943,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_SET_IMMUNE_PC: return sizeof(SmartAction::setImmunePC); case SMART_ACTION_SET_IMMUNE_NPC: return sizeof(SmartAction::setImmuneNPC); case SMART_ACTION_SET_UNINTERACTIBLE: return sizeof(SmartAction::setUninteractible); + case SMART_ACTION_ACTIVATE_GAMEOBJECT: return sizeof(SmartAction::activateGameObject); default: TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -2123,6 +2124,19 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) TC_SAI_IS_BOOLEAN_VALID(e, e.action.setUninteractible.uninteractible); break; } + case SMART_ACTION_ACTIVATE_GAMEOBJECT: + { + if (!NotNULL(e, e.action.activateGameObject.gameObjectAction)) + return false; + + if (e.action.activateGameObject.gameObjectAction >= uint32(GameObjectActions::Max)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has gameObjectAction parameter out of range (max allowed %u, current value %u), skipped.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), uint32(GameObjectActions::Max), e.action.activateGameObject.gameObjectAction); + return false; + } + break; + } case SMART_ACTION_FOLLOW: case SMART_ACTION_SET_ORIENTATION: case SMART_ACTION_STORE_TARGET_LIST: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index d422377b628..7d3600f51a4 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -589,8 +589,9 @@ enum SMART_ACTION SMART_ACTION_SET_IMMUNE_PC = 144, // 0/1 SMART_ACTION_SET_IMMUNE_NPC = 145, // 0/1 SMART_ACTION_SET_UNINTERACTIBLE = 146, // 0/1 + SMART_ACTION_ACTIVATE_GAMEOBJECT = 147, // GameObjectActions - SMART_ACTION_END = 147 + SMART_ACTION_END = 148 }; enum class SmartActionSummonCreatureFlags @@ -1197,6 +1198,11 @@ struct SmartAction SAIBool uninteractible; } setUninteractible; + struct + { + uint32 gameObjectAction; + } activateGameObject; + //! Note for any new future actions //! All parameters must have type uint32 diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 4a290700fc4..2df3f55d7fa 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1432,6 +1432,79 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f m_cooldownTime = time_to_restore ? (GameTime::GetGameTimeMS() + time_to_restore) : 0; } +void GameObject::ActivateObject(GameObjectActions action, WorldObject* spellCaster, uint32 spellId, int32 effectIndex) +{ + Unit* unitCaster = spellCaster ? spellCaster->ToUnit() : nullptr; + + switch (action) + { + case GameObjectActions::AnimateCustom0: + case GameObjectActions::AnimateCustom1: + case GameObjectActions::AnimateCustom2: + case GameObjectActions::AnimateCustom3: + SendCustomAnim(uint32(action) - uint32(GameObjectActions::AnimateCustom0)); + break; + case GameObjectActions::Disturb: // What's the difference with Open? + case GameObjectActions::Open: + if (unitCaster) + Use(unitCaster); + break; + case GameObjectActions::OpenAndUnlock: + if (unitCaster) + UseDoorOrButton(0, false, unitCaster); + [[fallthrough]]; + case GameObjectActions::Unlock: + case GameObjectActions::Lock: + ApplyModFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED, action == GameObjectActions::Lock); + break; + case GameObjectActions::Close: + case GameObjectActions::Rebuild: + ResetDoorOrButton(); + break; + case GameObjectActions::Despawn: + DespawnOrUnsummon(); + break; + case GameObjectActions::MakeInert: + case GameObjectActions::MakeActive: + ApplyModFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE, action == GameObjectActions::MakeInert); + break; + case GameObjectActions::CloseAndLock: + ResetDoorOrButton(); + SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + break; + case GameObjectActions::Destroy: + if (unitCaster) + UseDoorOrButton(0, true, unitCaster); + break; + case GameObjectActions::UseArtKit0: + case GameObjectActions::UseArtKit1: + case GameObjectActions::UseArtKit2: + case GameObjectActions::UseArtKit3: + { + GameObjectTemplateAddon const* templateAddon = GetTemplateAddon(); + + uint32 artKitIndex = uint32(action) - uint32(GameObjectActions::UseArtKit0); + + uint32 artKitValue = 0; + if (templateAddon != nullptr) + artKitValue = templateAddon->artKits[artKitIndex]; + + if (artKitValue == 0) + TC_LOG_ERROR("sql.sql", "GameObject %d hit by spell %d needs `artkit%d` in `gameobject_template_addon`", GetEntry(), spellId, artKitIndex); + else + SetGoArtKit(artKitValue); + + break; + } + case GameObjectActions::None: + TC_LOG_FATAL("spell", "Spell %d has action type NONE in effect %d", spellId, effectIndex); + break; + default: + TC_LOG_ERROR("spell", "Spell %d has unhandled action %d in effect %d", spellId, int32(action), effectIndex); + break; + } +} + void GameObject::SetGoArtKit(uint8 kit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, kit); diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index f06a4fcbdd3..ec0547c2aaa 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -226,6 +226,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void UseDoorOrButton(uint32 time_to_restore = 0, bool alternative = false, Unit* user = nullptr); // 0 = use `gameobject`.`spawntimesecs` void ResetDoorOrButton(); + void ActivateObject(GameObjectActions action, WorldObject* spellCaster = nullptr, uint32 spellId = 0, int32 effectIndex = -1); void TriggeringLinkedGameObject(uint32 trapEntry, Unit* target); diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h index ef7c95035e0..087eb8c18bd 100644 --- a/src/server/game/Entities/GameObject/GameObjectData.h +++ b/src/server/game/Entities/GameObject/GameObjectData.h @@ -675,30 +675,31 @@ struct GameObjectData : public SpawnData enum class GameObjectActions : uint32 { // Name from client executable // Comments - None, // -NONE- - AnimateCustom0, // Animate Custom0 - AnimateCustom1, // Animate Custom1 - AnimateCustom2, // Animate Custom2 - AnimateCustom3, // Animate Custom3 - Disturb, // Disturb // Triggers trap - Unlock, // Unlock // Resets GO_FLAG_LOCKED - Lock, // Lock // Sets GO_FLAG_LOCKED - Open, // Open // Sets GO_STATE_ACTIVE - OpenAndUnlock, // Open + Unlock // Sets GO_STATE_ACTIVE and resets GO_FLAG_LOCKED - Close, // Close // Sets GO_STATE_READY - ToggleOpen, // Toggle Open - Destroy, // Destroy // Sets GO_STATE_DESTROYED - Rebuild, // Rebuild // Resets from GO_STATE_DESTROYED - Creation, // Creation - Despawn, // Despawn - MakeInert, // Make Inert // Disables interactions - MakeActive, // Make Active // Enables interactions - CloseAndLock, // Close + Lock // Sets GO_STATE_READY and sets GO_FLAG_LOCKED - UseArtKit0, // Use ArtKit0 // 46904: 121 - UseArtKit1, // Use ArtKit1 // 36639: 81, 46903: 122 - UseArtKit2, // Use ArtKit2 - UseArtKit3, // Use ArtKit3 - SetTapList, // Set Tap List + None = 0, // -NONE- + AnimateCustom0 = 1, // Animate Custom0 + AnimateCustom1 = 2, // Animate Custom1 + AnimateCustom2 = 3, // Animate Custom2 + AnimateCustom3 = 4, // Animate Custom3 + Disturb = 5, // Disturb // Triggers trap + Unlock = 6, // Unlock // Resets GO_FLAG_LOCKED + Lock = 7, // Lock // Sets GO_FLAG_LOCKED + Open = 8, // Open // Sets GO_STATE_ACTIVE + OpenAndUnlock = 9, // Open + Unlock // Sets GO_STATE_ACTIVE and resets GO_FLAG_LOCKED + Close = 10, // Close // Sets GO_STATE_READY + ToggleOpen = 11, // Toggle Open + Destroy = 12, // Destroy // Sets GO_STATE_DESTROYED + Rebuild = 13, // Rebuild // Resets from GO_STATE_DESTROYED + Creation = 14, // Creation + Despawn = 15, // Despawn + MakeInert = 16, // Make Inert // Disables interactions + MakeActive = 17, // Make Active // Enables interactions + CloseAndLock = 18, // Close + Lock // Sets GO_STATE_READY and sets GO_FLAG_LOCKED + UseArtKit0 = 19, // Use ArtKit0 // 46904: 121 + UseArtKit1 = 20, // Use ArtKit1 // 36639: 81, 46903: 122 + UseArtKit2 = 21, // Use ArtKit2 + UseArtKit3 = 22, // Use ArtKit3 + SetTapList = 23, // Set Tap List + Max }; #endif // GameObjectData_h__ diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1a910fc16d1..720aadbb2d0 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3762,74 +3762,7 @@ void Spell::EffectActivateObject() GameObjectActions action = GameObjectActions(effectInfo->MiscValue); - switch (action) - { - case GameObjectActions::AnimateCustom0: - case GameObjectActions::AnimateCustom1: - case GameObjectActions::AnimateCustom2: - case GameObjectActions::AnimateCustom3: - gameObjTarget->SendCustomAnim(uint32(action) - uint32(GameObjectActions::AnimateCustom0)); - break; - case GameObjectActions::Disturb: // What's the difference with Open? - case GameObjectActions::Open: - if (Unit* unitCaster = m_caster->ToUnit()) - gameObjTarget->Use(unitCaster); - break; - case GameObjectActions::OpenAndUnlock: - if (Unit* unitCaster = m_caster->ToUnit()) - gameObjTarget->UseDoorOrButton(0, false, unitCaster); - [[fallthrough]]; - case GameObjectActions::Unlock: - case GameObjectActions::Lock: - gameObjTarget->ApplyModFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED, action == GameObjectActions::Lock); - break; - case GameObjectActions::Close: - case GameObjectActions::Rebuild: - gameObjTarget->ResetDoorOrButton(); - break; - case GameObjectActions::Despawn: - gameObjTarget->DespawnOrUnsummon(); - break; - case GameObjectActions::MakeInert: - case GameObjectActions::MakeActive: - gameObjTarget->ApplyModFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE, action == GameObjectActions::MakeInert); - break; - case GameObjectActions::CloseAndLock: - gameObjTarget->ResetDoorOrButton(); - gameObjTarget->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); - break; - case GameObjectActions::Destroy: - if (Unit* unitCaster = m_caster->ToUnit()) - gameObjTarget->UseDoorOrButton(0, true, unitCaster); - break; - case GameObjectActions::UseArtKit0: - case GameObjectActions::UseArtKit1: - case GameObjectActions::UseArtKit2: - case GameObjectActions::UseArtKit3: - { - GameObjectTemplateAddon const* templateAddon = gameObjTarget->GetTemplateAddon(); - - uint32 artKitIndex = uint32(action) - uint32(GameObjectActions::UseArtKit0); - - uint32 artKitValue = 0; - if (templateAddon != nullptr) - artKitValue = templateAddon->artKits[artKitIndex]; - - if (artKitValue == 0) - TC_LOG_ERROR("sql.sql", "GameObject %d hit by spell %d needs `artkit%d` in `gameobject_template_addon`", gameObjTarget->GetEntry(), m_spellInfo->Id, artKitIndex); - else - gameObjTarget->SetGoArtKit(artKitValue); - - break; - } - case GameObjectActions::None: - TC_LOG_FATAL("spell", "Spell %d has action type NONE in effect %d", m_spellInfo->Id, int32(effectInfo->EffectIndex)); - break; - default: - TC_LOG_ERROR("spell", "Spell %d has unhandled action %d in effect %d", m_spellInfo->Id, int32(action), int32(effectInfo->EffectIndex)); - break; - } - + gameObjTarget->ActivateObject(action, m_caster, m_spellInfo->Id, int32(effectInfo->EffectIndex)); } void Spell::EffectApplyGlyph() |