feat(emotes): add /emoteid command

This commit is contained in:
Anna 2021-05-31 01:03:27 -04:00
parent d10ba6ff80
commit c8780e2e12
1 changed files with 41 additions and 0 deletions

View File

@ -1,6 +1,8 @@
#if ILLEGAL
using System;
using System.Runtime.InteropServices;
using Dalamud.Game.Command;
using Dalamud.Hooking;
using ImGuiNET;
@ -8,27 +10,46 @@ namespace RoleplayersToolbox.Tools.Illegal.Emote {
internal class EmoteTool : BaseTool, IDisposable {
private static class Signatures {
internal const string SetActionOnHotbar = "E8 ?? ?? ?? ?? 4C 39 6F 08";
internal const string RunEmote = "E8 ?? ?? ?? ?? 40 84 ED 74 18";
internal const string RunEmoteFirstArg = "48 8D 0D ?? ?? ?? ?? 0F 45 C5 88 44 24 31 E8";
internal const string RunEmoteThirdArg = "48 8D 05 ?? ?? ?? ?? 33 DB 48 89 44 24 ?? B8";
}
private delegate IntPtr SetActionOnHotbarDelegate(IntPtr a1, IntPtr a2, byte actionType, uint actionId);
private delegate byte RunEmoteDelegate(IntPtr a1, ushort emoteId, IntPtr a3);
public override string Name => "Emotes";
private Plugin Plugin { get; }
private Hook<SetActionOnHotbarDelegate>? SetActionOnHotbarHook { get; }
private RunEmoteDelegate? RunEmoteFunction { get; }
private readonly IntPtr _runEmoteFirstArg;
private readonly IntPtr _runEmoteThirdArg;
private bool Custom { get; set; }
private Emote? Emote { get; set; }
internal EmoteTool(Plugin plugin) {
this.Plugin = plugin;
this.Plugin.Interface.CommandManager.AddHandler("/emoteid", new CommandInfo(this.EmoteIdCommand));
if (this.Plugin.Interface.TargetModuleScanner.TryScanText(Signatures.SetActionOnHotbar, out var setPtr)) {
this.SetActionOnHotbarHook = new Hook<SetActionOnHotbarDelegate>(setPtr, new SetActionOnHotbarDelegate(this.SetActionOnHotbarDetour));
this.SetActionOnHotbarHook.Enable();
}
if (this.Plugin.Interface.TargetModuleScanner.TryScanText(Signatures.RunEmote, out var runEmotePtr)) {
this.RunEmoteFunction = Marshal.GetDelegateForFunctionPointer<RunEmoteDelegate>(runEmotePtr);
}
this.Plugin.Interface.TargetModuleScanner.TryGetStaticAddressFromSig(Signatures.RunEmoteFirstArg, out this._runEmoteFirstArg);
this.Plugin.Interface.TargetModuleScanner.TryGetStaticAddressFromSig(Signatures.RunEmoteThirdArg, out this._runEmoteThirdArg);
}
public void Dispose() {
this.SetActionOnHotbarHook?.Dispose();
this.Plugin.Interface.CommandManager.RemoveHandler("/emoteid");
}
public override void DrawSettings(ref bool anyChanged) {
@ -62,6 +83,10 @@ namespace RoleplayersToolbox.Tools.Illegal.Emote {
this.Custom = false;
this.Emote = null;
}
ImGui.Separator();
ImGui.TextUnformatted("This tool also adds the /emoteid command, allowing you to run an emote based on its ID. This does NOT allow you to use emotes you do not have unlocked. For example, to use the sleep emote, run /emoteid 88.");
}
private IntPtr SetActionOnHotbarDetour(IntPtr a1, IntPtr a2, byte actionType, uint actionId) {
@ -74,6 +99,22 @@ namespace RoleplayersToolbox.Tools.Illegal.Emote {
this.Emote = null;
return this.SetActionOnHotbarHook!.Original(a1, a2, 6, (uint) emote);
}
private void EmoteIdCommand(string command, string arguments) {
if (ushort.TryParse(arguments, out var emoteId)) {
this.RunEmote(emoteId);
}
}
private unsafe void RunEmote(ushort emoteId) {
if (this.RunEmoteFunction == null || this._runEmoteFirstArg == IntPtr.Zero || this._runEmoteThirdArg == IntPtr.Zero) {
return;
}
fixed (void* thirdArg = &this._runEmoteThirdArg) {
this.RunEmoteFunction(this._runEmoteFirstArg, emoteId, (IntPtr) thirdArg);
}
}
}
}