diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 33 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 23 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 10 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 126 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 1 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObjectData.h | 1 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 121 |
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() |
