fix(Core/Spells): Implement SPELL_EFFECT_ACTIVATE_OBJECT (#11648)

Co-authored-by: jackpoz <giacomopoz@gmail.com>
This commit is contained in:
Nefertumm
2022-06-13 21:10:31 -03:00
committed by GitHub
parent 16d27f3449
commit 396fd35ed5
9 changed files with 182 additions and 39 deletions

View File

@@ -76,6 +76,8 @@ static FactionTeamMap sFactionTeamMap;
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
DBCStorage <GameObjectArtKitEntry> sGameObjectArtKitStore(GameObjectArtKitfmt);
DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt);
DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore(GlyphPropertiesfmt);
@@ -294,6 +296,7 @@ void LoadDBCStores(const std::string& dataPath)
LOAD_DBC(sEmotesTextStore, "EmotesText.dbc", "emotestext_dbc");
LOAD_DBC(sFactionStore, "Faction.dbc", "faction_dbc");
LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc", "factiontemplate_dbc");
LOAD_DBC(sGameObjectArtKitStore, "GameObjectArtKit.dbc", "gameobjectartkit_dbc");
LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc", "gameobjectdisplayinfo_dbc");
LOAD_DBC(sGemPropertiesStore, "GemProperties.dbc", "gemproperties_dbc");
LOAD_DBC(sGlyphPropertiesStore, "GlyphProperties.dbc", "glyphproperties_dbc");

View File

@@ -104,6 +104,7 @@ extern DBCStorage <EmotesEntry> sEmotesStore;
extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
extern DBCStorage <FactionEntry> sFactionStore;
extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
extern DBCStorage <GameObjectArtKitEntry> sGameObjectArtKitStore;
extern DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
extern DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore;

View File

@@ -25,6 +25,7 @@
#include "Object.h"
#include "SharedDefines.h"
#include "Unit.h"
#include <array>
class GameObjectAI;
class Transport;
@@ -676,6 +677,7 @@ struct GameObjectTemplateAddon
uint32 flags;
uint32 mingold;
uint32 maxgold;
std::array<uint32, 4> artKits = {};
};
// Benchmarked: Faster than std::map (insert/find)
@@ -736,6 +738,35 @@ enum GOState
#define MAX_GO_STATE 3
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
};
// from `gameobject`
struct GameObjectData
{

View File

@@ -7183,8 +7183,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
QueryResult result = WorldDatabase.Query("SELECT entry, faction, flags, mingold, maxgold, artkit0, artkit1, artkit2, artkit3 FROM gameobject_template_addon");
if (!result)
{
@@ -7215,6 +7215,21 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
gameObjectAddon.mingold = fields[3].Get<uint32>();
gameObjectAddon.maxgold = fields[4].Get<uint32>();
for (uint32 i = 0; i < gameObjectAddon.artKits.size(); i++)
{
uint32 artKitID = fields[5 + i].Get<uint32>();
if (!artKitID)
continue;
if (!sGameObjectArtKitStore.LookupEntry(artKitID))
{
LOG_ERROR("sql.sql", "GameObject (Entry: {}) has invalid `artkit{}` {} defined, set to zero instead.", entry, i, artKitID);
continue;
}
gameObjectAddon.artKits[i] = artKitID;
}
// checks
if (gameObjectAddon.faction && !sFactionTemplateStore.LookupEntry(gameObjectAddon.faction))
LOG_ERROR("sql.sql",

View File

@@ -4263,7 +4263,7 @@ void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/)
player->GetSession()->SendPacket(&data);
}
void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
void Spell::EffectActivateObject(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
@@ -4271,17 +4271,74 @@ void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
if (!gameObjTarget)
return;
Player* player = m_caster->GetTypeId() == TYPEID_PLAYER ? m_caster->ToPlayer() : m_caster->GetCharmerOrOwnerPlayerOrPlayerItself();
gameObjTarget->Use(player ? player : m_caster);
GameObjectActions action = GameObjectActions(m_spellInfo->Effects[effIndex].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();
//ScriptInfo activateCommand;
//activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
uint32 artKitIndex = uint32(action) - uint32(GameObjectActions::UseArtKit0);
// int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research
uint32 artKitValue = 0;
if (templateAddon)
artKitValue = templateAddon->artKits[artKitIndex];
// xinef: pass player to allow gossip scripts to work
//
//gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, player ? player : m_caster, gameObjTarget);
if (artKitValue == 0)
LOG_ERROR("sql.sql", "GameObject {} hit by spell {} needs `artkit{}` in `gameobject_template_addon`", gameObjTarget->GetEntry(), m_spellInfo->Id, artKitIndex);
else
gameObjTarget->SetGoArtKit(artKitValue);
break;
}
case GameObjectActions::None:
LOG_FATAL("spell", "Spell {} has action type NONE in effect {}", m_spellInfo->Id, int32(effIndex));
break;
default:
LOG_ERROR("spell", "Spell {} has unhandled action {} in effect {}", m_spellInfo->Id, int32(action), int32(effIndex));
break;
}
}
void Spell::EffectApplyGlyph(SpellEffIndex effIndex)

View File

@@ -783,37 +783,9 @@ public:
}
};
class spell_banging_the_gong : public SpellScriptLoader
{
public:
spell_banging_the_gong() : SpellScriptLoader("spell_banging_the_gong") { }
class spell_banging_the_gong_SpellScript : public SpellScript
{
PrepareSpellScript(spell_banging_the_gong_SpellScript);
void Activate(SpellEffIndex index)
{
PreventHitDefaultEffect(index);
GetHitGObj()->SendCustomAnim(0);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_banging_the_gong_SpellScript::Activate, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_banging_the_gong_SpellScript();
}
};
void AddSC_zulaman()
{
new npc_forest_frog();
new npc_zulaman_hostage();
new npc_harrison_jones();
new spell_banging_the_gong();
}

View File

@@ -979,6 +979,13 @@ struct FactionTemplateEntry
[[nodiscard]] bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_ATTACK_PVP_ACTIVE_PLAYERS) != 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

View File

@@ -50,6 +50,7 @@ char constexpr EmotesEntryfmt[] = "nxxiiix";
char constexpr EmotesTextEntryfmt[] = "nxixxxxxxxxxxxxxxxx";
char constexpr FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char constexpr FactionTemplateEntryfmt[] = "niiiiiiiiiiiii";
char constexpr GameObjectArtKitfmt[] = "nxxxxxxx";
char constexpr GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffx";
char constexpr GemPropertiesEntryfmt[] = "nixxi";
char constexpr GlyphPropertiesfmt[] = "niii";