Core/Spells: Implement SPELL_EFFECT_ACTIVATE_OBJECT. (#23)

Original research by @xvwyh.
This commit is contained in:
Warpten authored and Ovah committed 2020-01-04 15:05:22 +01:00
1 parent 3910218a9b
commit c69627f4b4
11 files changed
+208 -58

No files matched your search

+8 -4
View File
@@ -93,6 +93,9 @@ static FactionTeamMap sFactionTeamMap;
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
// Used exclusively for data validation
DBCStorage <GameObjectArtKitEntry> sGameObjectArtKitStore(GameObjectArtKitfmt);
DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt);
DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore(GlyphPropertiesfmt);
@@ -138,10 +141,10 @@ DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore(ItemDama
DBCStorage <ItemDamageEntry> sItemDamageWandStore(ItemDamagefmt);
DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore(ItemDisenchantLootfmt);
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
DBCStorage <LFGDungeonEntry> sLFGDungeonStore(LFGDungeonEntryfmt);
DBCStorage <LFGDungeonsGroupingMapEntry> sLFGDungeonsGroupingMapStore(LFGDungeonsGroupingMapfmt);
@@ -374,6 +377,7 @@ void LoadDBCStores(const std::string& dataPath)
LOAD_DBC(sEmotesTextStore, "EmotesText.dbc");//15595
LOAD_DBC(sFactionStore, "Faction.dbc");//15595
LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc");//15595
LOAD_DBC(sGameObjectArtKitStore, "GameObjectArtKit.dbc");//15595
LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc");//15595
LOAD_DBC(sGemPropertiesStore, "GemProperties.dbc");//15595
LOAD_DBC(sGlyphPropertiesStore, "GlyphProperties.dbc");//15595
+1
View File
@@ -129,6 +129,7 @@ TC_GAME_API extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
TC_GAME_API extern DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore;
TC_GAME_API extern DBCStorage <FactionEntry> sFactionStore;
TC_GAME_API extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
TC_GAME_API extern DBCStorage <GameObjectArtKitEntry> sGameObjectArtKitStore;
TC_GAME_API extern DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
TC_GAME_API extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
TC_GAME_API extern DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore;
@@ -1195,6 +1195,13 @@ struct FactionTemplateEntry
bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
};
struct GameObjectArtKitEntry
{
uint32 ID; // 0
//char* TextureVariation[3] // 1-3 m_textureVariations[3]
//char* AttachModel[4] // 4-8 m_attachModels[4]
};
struct GameObjectDisplayInfoEntry
{
uint32 Displayid; // 0 m_ID
+1
View File
@@ -62,6 +62,7 @@ char const EmotesTextEntryfmt[] = "nxixxxxxxxxxxxxxxxx";
char const EmotesTextSoundEntryfmt[] = "niiii";
char const FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixsxi";
char const FactionTemplateEntryfmt[] = "niiiiiiiiiiiii";
char const GameObjectArtKitfmt[] = "nxxxxxxx";
char const GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffxxx";
char const GemPropertiesEntryfmt[] = "nixxii";
char const GlyphPropertiesfmt[] = "niii";
@@ -1277,6 +1277,32 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f
m_cooldownTime = time_to_restore ? (GameTime::GetGameTimeMS() + time_to_restore) : 0;
}
void GameObject::PlayAnimKit(int32 animKit)
{
WorldPacket data(SMSG_GAME_OBJECT_ACTIVATE_ANIM_KIT, 4 + 2);
ObjectGuid guid = GetGUID();
data.WriteBit(guid[5]);
data.WriteBit(guid[1]);
data.WriteBit(guid[0]);
data.WriteBit(guid[4]);
data.WriteBit(guid[7]);
data.WriteBit(guid[2]);
data.WriteBit(guid[3]);
data.WriteBit(guid[6]);
data.WriteByteSeq(guid[5]);
data.WriteByteSeq(guid[1]);
data.WriteByteSeq(guid[0]);
data.WriteByteSeq(guid[3]);
data.WriteByteSeq(guid[4]);
data.WriteByteSeq(guid[6]);
data.WriteByteSeq(guid[2]);
data.WriteByteSeq(guid[7]);
data << int32(animKit);
SendMessageToSet(&data, nullptr);
}
void GameObject::SetGoArtKit(uint8 kit)
{
SetByteValue(GAMEOBJECT_BYTES_1, 2, kit);
@@ -169,6 +169,8 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
static void SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid = 0);
void PlayAnimKit(int32 animKit);
void EnableCollision(bool enable);
void Use(Unit* user);
@@ -22,10 +22,11 @@
#include "SharedDefines.h"
#include "SpawnData.h"
#include "WorldPacket.h"
#include <array>
#include <string>
#include <vector>
#define MAX_GAMEOBJECT_QUEST_ITEMS 6
// from `gameobject_template`
@@ -597,6 +598,7 @@ struct GameObjectTemplateAddon
uint32 flags;
uint32 mingold;
uint32 maxgold;
std::array<uint32, 5> artKits;
};
struct GameObjectLocale
@@ -634,4 +636,47 @@ struct GameObjectData : public SpawnData
uint8 artKit = 0;
};
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
GoTo1stFloor, // Go to 1st floor
GoTo2ndFloor, // Go to 2nd floor
GoTo3rdFloor, // Go to 3rd floor
GoTo4thFloor, // Go to 4th floor
GoTo5thFloor, // Go to 5th floor
GoTo6thFloor, // Go to 6th floor
GoTo7thFloor, // Go to 7th floor
GoTo8thFloor, // Go to 8th floor
GoTo9thFloor, // Go to 9th floor
GoTo10thFloor, // Go to 10th floor
UseArtKit4, // Use ArtKit4
PlayAnimKit, // Play Anim Kit "%s" // MiscValueB -> Anim Kit ID
OpenAndPlayAnimKit, // Open + Play Anim Kit "%s" // MiscValueB -> Anim Kit ID
CloseAndPlayAnimKit, // Close + Play Anim Kit "%s" // MiscValueB -> Anim Kit ID
};
#endif // GameObjectData_h__
+19 -2
View File
@@ -7488,8 +7488,8 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
{
uint32 oldMSTime = getMSTime();
// 0 1 2 3 4
QueryResult result = WorldDatabase.Query("SELECT entry, faction, flags, mingold, maxgold FROM gameobject_template_addon");
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase.Query("SELECT entry, faction, flags, mingold, maxgold, artkit0, artkit1, artkit2, artkit3, artkit4 FROM gameobject_template_addon");
if (!result)
{
@@ -7517,6 +7517,9 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
gameObjectAddon.mingold = fields[3].GetUInt32();
gameObjectAddon.maxgold = fields[4].GetUInt32();
for (uint32 i = 0; i < gameObjectAddon.artKits.size(); ++i)
gameObjectAddon.artKits[i] = fields[5 + i].GetUInt32();
// checks
if (gameObjectAddon.faction && !sFactionTemplateStore.LookupEntry(gameObjectAddon.faction))
TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has invalid faction (%u) defined in `gameobject_template_addon`.", entry, gameObjectAddon.faction);
@@ -7534,6 +7537,20 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
}
}
uint32 artKitIndex = 0;
for (uint32& artKitID : gameObjectAddon.artKits)
{
++artKitIndex;
if (!artKitID)
continue;
if (!sGameObjectArtKitStore.LookupEntry(artKitID))
{
TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has invalid `artkit%d` (%d) defined, set to zero instead.", entry, artKitIndex - 1, artKitID);
artKitID = 0;
}
}
++count;
}
while (result->NextRow());
+98 -5
View File
@@ -3729,7 +3729,7 @@ void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/)
unitTarget->ToPlayer()->SendSummonRequestFrom(m_caster);
}
void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
void Spell::EffectActivateObject(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
@@ -3737,12 +3737,105 @@ void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
if (!gameObjTarget)
return;
ScriptInfo activateCommand;
activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
GameObjectActions action = GameObjectActions(m_spellInfo->Effects[effIndex].MiscValue);
// int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research
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:
gameObjTarget->Use(m_caster);
break;
case GameObjectActions::OpenAndUnlock:
gameObjTarget->UseDoorOrButton(0, false, m_caster);
// no break
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:
gameObjTarget->UseDoorOrButton(0, true, m_caster);
break;
case GameObjectActions::UseArtKit0:
case GameObjectActions::UseArtKit1:
case GameObjectActions::UseArtKit2:
case GameObjectActions::UseArtKit3:
case GameObjectActions::UseArtKit4:
{
GameObjectTemplateAddon const* templateAddon = gameObjTarget->GetTemplateAddon();
uint32 artKitIndex = uint32(action) - uint32(GameObjectActions::UseArtKit0);
// Non-sequential here
if (action == GameObjectActions::UseArtKit4)
artKitIndex = 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::PlayAnimKit:
gameObjTarget->PlayAnimKit(m_spellInfo->Effects[effIndex].MiscValueB);
break;
break;
case GameObjectActions::OpenAndPlayAnimKit:
gameObjTarget->Use(m_caster);
gameObjTarget->PlayAnimKit(m_spellInfo->Effects[effIndex].MiscValueB);
break;
case GameObjectActions::CloseAndPlayAnimKit:
gameObjTarget->ResetDoorOrButton();
gameObjTarget->PlayAnimKit(m_spellInfo->Effects[effIndex].MiscValueB);
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:
{
// Cast is kind of loose but it'll do
if (Transport* transportTarget = gameObjTarget->ToTransport())
transportTarget->SetTransportState(GO_STATE_TRANSPORT_STOPPED, uint32_t(action) - uint32(GameObjectActions::GoTo1stFloor));
break;
}
case GameObjectActions::None:
TC_LOG_FATAL("spell", "Spell %d has action type NONE in effect %d", m_spellInfo->Id, int32(effIndex));
break;
default:
TC_LOG_ERROR("spell", "Spell %d has unhandled action %d in effect %d", m_spellInfo->Id, int32(action), int32(effIndex));
break;
}
gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget);
}
void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
@@ -469,26 +469,8 @@ private:
bool _firstGuardian;
};
// 45226 - Banging the Gong
class spell_banging_the_gong : public SpellScript
{
PrepareSpellScript(spell_banging_the_gong);
void Activate(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
GetHitGObj()->SendCustomAnim(0);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_banging_the_gong::Activate, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
}
};
void AddSC_zulaman()
{
RegisterZulAamanCreatureAI(npc_zulaman_voljin);
RegisterZulAamanCreatureAI(npc_zulaman_amanishi_guardian);
RegisterSpellScript(spell_banging_the_gong);
}
@@ -422,33 +422,6 @@ class spell_anhuur_disable_beacon_beams : public SpellScript
}
};
// 76599 - Activate Beacons
// 76600 - Deactivate Beacons
class spell_anhuur_handle_beacons : public SpellScript
{
PrepareSpellScript(spell_anhuur_handle_beacons);
void HandleEffect(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
int32 script = GetSpellInfo()->Effects[effIndex].MiscValue;
GameObject* beacon = GetHitGObj();
if (!beacon)
return;
if (script == 16) // 16 => Disable
beacon->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
else if (script == 17) // 17 => Activate
beacon->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_anhuur_handle_beacons::HandleEffect, EFFECT_0, SPELL_EFFECT_ACTIVATE_OBJECT);
}
};
class spell_anhuur_burning_light_forcecast : public SpellScript
{
PrepareSpellScript(spell_anhuur_burning_light_forcecast);
@@ -493,7 +466,6 @@ void AddSC_boss_temple_guardian_anhuur()
RegisterSpellScript(spell_anhuur_shield_of_light),
RegisterAuraScript(spell_anhuur_reverberating_hymn);
RegisterSpellScript(spell_anhuur_disable_beacon_beams);
RegisterSpellScript(spell_anhuur_handle_beacons);
RegisterSpellScript(spell_anhuur_burning_light_forcecast);
new achievement_i_hate_that_song();
}