mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/SAI: Add SMART_ACTION_ACTIVATE_GAMEOBJECT action (#27216)
Closes #27196
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user