aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp33
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp23
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h10
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp126
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h1
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp121
7 files changed, 177 insertions, 138 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 2be17b16857..6475dd55081 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -2465,6 +2465,24 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
targetUnit->SetHealth(targetUnit->CountPctFromMaxHealth(e.action.setHealthPct.percent));
break;
}
+ case SMART_ACTION_CREATE_CONVERSATION:
+ {
+ WorldObject* baseObject = GetBaseObject();
+
+ for (WorldObject* const target : targets)
+ {
+ if (Player* playerTarget = target->ToPlayer())
+ {
+ Conversation* conversation = Conversation::CreateConversation(e.action.conversation.id, playerTarget,
+ *playerTarget, playerTarget->GetGUID(), nullptr);
+ if (!conversation)
+ TC_LOG_WARN("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CREATE_CONVERSATION: id %u, baseObject %s, target %s - failed to create conversation",
+ e.action.conversation.id, !baseObject ? "" : baseObject->GetName().c_str(), playerTarget->GetName().c_str());
+ }
+ }
+
+ break;
+ }
case SMART_ACTION_SET_IMMUNE_PC:
{
for (WorldObject* target : targets)
@@ -2507,22 +2525,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
break;
}
- case SMART_ACTION_CREATE_CONVERSATION:
+ case SMART_ACTION_ACTIVATE_GAMEOBJECT:
{
- WorldObject* baseObject = GetBaseObject();
-
- for (WorldObject* const target : targets)
+ for (WorldObject* target : targets)
{
- if (Player* playerTarget = target->ToPlayer())
+ if (GameObject* targetGo = target->ToGameObject())
{
- Conversation* conversation = Conversation::CreateConversation(e.action.conversation.id, playerTarget,
- *playerTarget, playerTarget->GetGUID(), nullptr);
- if (!conversation)
- TC_LOG_WARN("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CREATE_CONVERSATION: id %u, baseObject %s, target %s - failed to create conversation",
- e.action.conversation.id, !baseObject ? "" : baseObject->GetName().c_str(), playerTarget->GetName().c_str());
+ targetGo->ActivateObject(GameObjectActions(e.action.activateGameObject.gameObjectAction), e.action.activateGameObject.param);
}
}
-
break;
}
case SMART_ACTION_ADD_TO_STORED_TARGET_LIST:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 6bf316b8342..2e0173f5389 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1015,7 +1015,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::raw);
+ case SMART_ACTION_ACTIVATE_GAMEOBJECT: return sizeof(SmartAction::activateGameObject);
case SMART_ACTION_ADD_TO_STORED_TARGET_LIST: return sizeof(SmartAction::addToStoredTargets);
case SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER: return sizeof(SmartAction::becomePersonalClone);
default:
@@ -2291,6 +2291,16 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
TC_SAI_IS_BOOLEAN_VALID(e, e.action.setHealthRegen.regenHealth);
break;
}
+ case SMART_ACTION_CREATE_CONVERSATION:
+ {
+ if (!sConversationDataStore->GetConversationTemplate(e.action.conversation.id))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: SMART_ACTION_CREATE_CONVERSATION Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.conversation.id);
+ return false;
+ }
+
+ break;
+ }
case SMART_ACTION_SET_IMMUNE_PC:
{
TC_SAI_IS_BOOLEAN_VALID(e, e.action.setImmunePC.immunePC);
@@ -2306,14 +2316,17 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
TC_SAI_IS_BOOLEAN_VALID(e, e.action.setUninteractible.uninteractible);
break;
}
- case SMART_ACTION_CREATE_CONVERSATION:
+ case SMART_ACTION_ACTIVATE_GAMEOBJECT:
{
- if (!sConversationDataStore->GetConversationTemplate(e.action.conversation.id))
+ if (!NotNULL(e, e.action.activateGameObject.gameObjectAction))
+ return false;
+
+ if (e.action.activateGameObject.gameObjectAction >= uint32(GameObjectActions::Max))
{
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: SMART_ACTION_CREATE_CONVERSATION Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.conversation.id);
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " 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:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 5d4278b5b4b..769d306ca2c 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1217,6 +1217,11 @@ struct SmartAction
struct
{
+ uint32 id;
+ } conversation;
+
+ struct
+ {
SAIBool immunePC;
} setImmunePC;
@@ -1232,8 +1237,9 @@ struct SmartAction
struct
{
- uint32 id;
- } conversation;
+ uint32 gameObjectAction;
+ uint32 param;
+ } activateGameObject;
struct
{
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 5f1ba8f1172..6f1dd21e014 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1637,6 +1637,132 @@ 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, int32 param, WorldObject* spellCaster /*= nullptr*/, uint32 spellId /*= 0*/, int32 effectIndex /*= -1*/)
+{
+ 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:
+ RemoveFlag(GO_FLAG_LOCKED);
+ break;
+ case GameObjectActions::Lock:
+ AddFlag(GO_FLAG_LOCKED);
+ break;
+ case GameObjectActions::Close:
+ case GameObjectActions::Rebuild:
+ ResetDoorOrButton();
+ break;
+ case GameObjectActions::Despawn:
+ DespawnOrUnsummon();
+ break;
+ case GameObjectActions::MakeInert:
+ AddFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ case GameObjectActions::MakeActive:
+ RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ break;
+ case GameObjectActions::CloseAndLock:
+ ResetDoorOrButton();
+ AddFlag(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:
+ case GameObjectActions::UseArtKit4:
+ {
+ GameObjectTemplateAddon const* templateAddon = GetTemplateAddon();
+
+ uint32 artKitIndex = action != GameObjectActions::UseArtKit4 ? uint32(action) - uint32(GameObjectActions::UseArtKit0) : 4;
+
+ 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::GoTo1stFloor:
+ case GameObjectActions::GoTo2ndFloor:
+ case GameObjectActions::GoTo3rdFloor:
+ case GameObjectActions::GoTo4thFloor:
+ case GameObjectActions::GoTo5thFloor:
+ case GameObjectActions::GoTo6thFloor:
+ case GameObjectActions::GoTo7thFloor:
+ case GameObjectActions::GoTo8thFloor:
+ case GameObjectActions::GoTo9thFloor:
+ case GameObjectActions::GoTo10thFloor:
+ if (GetGoType() == GAMEOBJECT_TYPE_TRANSPORT)
+ SetTransportState(GO_STATE_TRANSPORT_STOPPED, uint32(action) - uint32(GameObjectActions::GoTo1stFloor));
+ else
+ TC_LOG_ERROR("spell", "Spell %d targeted non-transport gameobject for transport only action \"Go to Floor\" %d in effect %d", spellId, int32(action), effectIndex);
+ break;
+ case GameObjectActions::PlayAnimKit:
+ SetAnimKitId(param, false);
+ break;
+ case GameObjectActions::OpenAndPlayAnimKit:
+ if (unitCaster)
+ UseDoorOrButton(0, false, unitCaster);
+ SetAnimKitId(param, false);
+ break;
+ case GameObjectActions::CloseAndPlayAnimKit:
+ ResetDoorOrButton();
+ SetAnimKitId(param, false);
+ break;
+ case GameObjectActions::PlayOneShotAnimKit:
+ SetAnimKitId(param, true);
+ break;
+ case GameObjectActions::StopAnimKit:
+ SetAnimKitId(0, false);
+ break;
+ case GameObjectActions::OpenAndStopAnimKit:
+ if (unitCaster)
+ UseDoorOrButton(0, false, unitCaster);
+ SetAnimKitId(0, false);
+ break;
+ case GameObjectActions::CloseAndStopAnimKit:
+ ResetDoorOrButton();
+ SetAnimKitId(0, false);
+ break;
+ case GameObjectActions::PlaySpellVisual:
+ SetSpellVisualId(param, Object::GetGUID(spellCaster));
+ break;
+ case GameObjectActions::StopSpellVisual:
+ SetSpellVisualId(0);
+ 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)
{
SetUpdateFieldValue(m_values.ModifyValue(&GameObject::m_gameObjectData).ModifyValue(&UF::GameObjectData::ArtKit), kit);
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index ca7f2a5c8fb..ee73ba521d4 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -266,6 +266,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, int32 param, 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 f6fe8f5681a..66ab069abeb 100644
--- a/src/server/game/Entities/GameObject/GameObjectData.h
+++ b/src/server/game/Entities/GameObject/GameObjectData.h
@@ -1165,6 +1165,7 @@ enum class GameObjectActions : uint32
PlaySpellVisual = 42, // Play Spell Visual "{SpellVisual}"
StopSpellVisual = 43, // Stop Spell Visual
SetTappedToChallengePlayers = 44, // Set Tapped to Challenge Players
+ Max
};
#endif // GameObjectData_h__
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 21ea77c8122..b4db1a2a4f1 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3317,126 +3317,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:
- gameObjTarget->RemoveFlag(GO_FLAG_LOCKED);
- break;
- case GameObjectActions::Lock:
- gameObjTarget->AddFlag(GO_FLAG_LOCKED);
- break;
- case GameObjectActions::Close:
- case GameObjectActions::Rebuild:
- gameObjTarget->ResetDoorOrButton();
- break;
- case GameObjectActions::Despawn:
- gameObjTarget->DespawnOrUnsummon();
- break;
- case GameObjectActions::MakeInert:
- gameObjTarget->AddFlag(GO_FLAG_NOT_SELECTABLE);
- break;
- case GameObjectActions::MakeActive:
- gameObjTarget->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
- break;
- case GameObjectActions::CloseAndLock:
- gameObjTarget->ResetDoorOrButton();
- gameObjTarget->AddFlag(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:
- case GameObjectActions::UseArtKit4:
- {
- GameObjectTemplateAddon const* templateAddon = gameObjTarget->GetTemplateAddon();
-
- uint32 artKitIndex = action != GameObjectActions::UseArtKit4 ? uint32(action) - uint32(GameObjectActions::UseArtKit0) : 4;
-
- 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::GoTo1stFloor:
- case GameObjectActions::GoTo2ndFloor:
- case GameObjectActions::GoTo3rdFloor:
- case GameObjectActions::GoTo4thFloor:
- case GameObjectActions::GoTo5thFloor:
- case GameObjectActions::GoTo6thFloor:
- case GameObjectActions::GoTo7thFloor:
- case GameObjectActions::GoTo8thFloor:
- case GameObjectActions::GoTo9thFloor:
- case GameObjectActions::GoTo10thFloor:
- if (gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_TRANSPORT)
- gameObjTarget->SetTransportState(GO_STATE_TRANSPORT_STOPPED, uint32(action) - uint32(GameObjectActions::GoTo1stFloor));
- else
- TC_LOG_ERROR("spell", "Spell %d targeted non-transport gameobject for transport only action \"Go to Floor\" %d in effect %d", m_spellInfo->Id, int32(action), int32(effectInfo->EffectIndex));
- break;
- case GameObjectActions::PlayAnimKit:
- gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false);
- break;
- case GameObjectActions::OpenAndPlayAnimKit:
- if (Unit* unitCaster = m_caster->ToUnit())
- gameObjTarget->UseDoorOrButton(0, false, unitCaster);
- gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false);
- break;
- case GameObjectActions::CloseAndPlayAnimKit:
- gameObjTarget->ResetDoorOrButton();
- gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false);
- break;
- case GameObjectActions::PlayOneShotAnimKit:
- gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, true);
- break;
- case GameObjectActions::StopAnimKit:
- gameObjTarget->SetAnimKitId(0, false);
- break;
- case GameObjectActions::OpenAndStopAnimKit:
- if (Unit* unitCaster = m_caster->ToUnit())
- gameObjTarget->UseDoorOrButton(0, false, unitCaster);
- gameObjTarget->SetAnimKitId(0, false);
- break;
- case GameObjectActions::CloseAndStopAnimKit:
- gameObjTarget->ResetDoorOrButton();
- gameObjTarget->SetAnimKitId(0, false);
- break;
- case GameObjectActions::PlaySpellVisual:
- gameObjTarget->SetSpellVisualId(effectInfo->MiscValueB, m_originalCasterGUID);
- break;
- case GameObjectActions::StopSpellVisual:
- gameObjTarget->SetSpellVisualId(0);
- 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, effectInfo->MiscValueB, m_caster, m_spellInfo->Id, int32(effectInfo->EffectIndex));
}
void Spell::EffectApplyGlyph()