vfx replacer?
This commit is contained in:
parent
acc9464e43
commit
19f7b889ed
|
@ -8,7 +8,7 @@ using OrangeGuidanceTomestone.Helpers;
|
||||||
namespace OrangeGuidanceTomestone;
|
namespace OrangeGuidanceTomestone;
|
||||||
|
|
||||||
internal class Messages : IDisposable {
|
internal class Messages : IDisposable {
|
||||||
private const string VfxPath = "bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1d_o.avfx";
|
internal const string VfxPath = "bg/ffxiv/fst_f1/common/vfx/eff/b0941trp1d_o.avfx";
|
||||||
|
|
||||||
private Plugin Plugin { get; }
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
|
5
client/MiniPenumbra/MiniFunctions.cs
Normal file
5
client/MiniPenumbra/MiniFunctions.cs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
namespace OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
|
||||||
|
internal class MiniFunctions {
|
||||||
|
|
||||||
|
}
|
19
client/MiniPenumbra/SeFileDescriptor.cs
Normal file
19
client/MiniPenumbra/SeFileDescriptor.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal unsafe struct SeFileDescriptor {
|
||||||
|
[FieldOffset(0x00)]
|
||||||
|
public SeFileMode FileMode;
|
||||||
|
|
||||||
|
[FieldOffset(0x30)]
|
||||||
|
public void* FileDescriptor;
|
||||||
|
|
||||||
|
[FieldOffset(0x50)]
|
||||||
|
public ResourceHandle* ResourceHandle;
|
||||||
|
|
||||||
|
[FieldOffset(0x70)]
|
||||||
|
public char Utf16FileName;
|
||||||
|
}
|
10
client/MiniPenumbra/SeFileMode.cs
Normal file
10
client/MiniPenumbra/SeFileMode.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
|
||||||
|
internal enum SeFileMode : byte {
|
||||||
|
LoadUnpackedResource = 0,
|
||||||
|
LoadFileResource = 1, // The config files in MyGames use this.
|
||||||
|
|
||||||
|
// Probably debug options only.
|
||||||
|
LoadIndexResource = 0xA, // load index/index2
|
||||||
|
LoadSqPackResource = 0xB,
|
||||||
|
}
|
70
client/MiniPenumbra/VfxReplacer.cs
Normal file
70
client/MiniPenumbra/VfxReplacer.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
using Dalamud.Hooking;
|
||||||
|
using Dalamud.Utility.Signatures;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
|
||||||
|
internal unsafe class VfxReplacer : IDisposable {
|
||||||
|
private delegate byte ReadSqPackDelegate(void* resourceManager, SeFileDescriptor* pFileDesc, int priority, bool isSync);
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? EB 05 E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3", DetourName = nameof(ReadSqPackDetour))]
|
||||||
|
private Hook<ReadSqPackDelegate> _readSqPackHook;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3 BA 05")]
|
||||||
|
private delegate* unmanaged<void*, SeFileDescriptor*, int, bool, byte> _readFile;
|
||||||
|
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
internal VfxReplacer(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
SignatureHelper.Initialise(this);
|
||||||
|
|
||||||
|
this._readSqPackHook!.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
this._readSqPackHook.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte ReadSqPackDetour(void* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync) {
|
||||||
|
if (!this.Plugin.Config.RemoveGlow) {
|
||||||
|
goto Original;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileDescriptor == null || fileDescriptor->ResourceHandle == null) {
|
||||||
|
goto Original;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = fileDescriptor->ResourceHandle->FileName.ToString();
|
||||||
|
if (path != Messages.VfxPath) {
|
||||||
|
goto Original;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.DefaultRootedResourceLoad(this.Plugin.AvfxFilePath, resourceManager, fileDescriptor, priority, isSync);
|
||||||
|
|
||||||
|
Original:
|
||||||
|
return this._readSqPackHook.Original(resourceManager, fileDescriptor, priority, isSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the resource from a path on the users hard drives.
|
||||||
|
private byte DefaultRootedResourceLoad(string gamePath, void* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync) {
|
||||||
|
// Specify that we are loading unpacked files from the drive.
|
||||||
|
// We need to copy the actual file path in UTF16 (Windows-Unicode) on two locations,
|
||||||
|
// but since we only allow ASCII in the game paths, this is just a matter of upcasting.
|
||||||
|
fileDescriptor->FileMode = SeFileMode.LoadUnpackedResource;
|
||||||
|
|
||||||
|
var fd = stackalloc byte[0x20 + 2 * gamePath.Length + 0x16];
|
||||||
|
fileDescriptor->FileDescriptor = fd;
|
||||||
|
var fdPtr = (char*) (fd + 0x21);
|
||||||
|
for (var i = 0; i < gamePath.Length; ++i) {
|
||||||
|
(&fileDescriptor->Utf16FileName)[i] = gamePath[i];
|
||||||
|
fdPtr[i] = gamePath[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
(&fileDescriptor->Utf16FileName)[gamePath.Length] = '\0';
|
||||||
|
fdPtr[gamePath.Length] = '\0';
|
||||||
|
|
||||||
|
// Use the SE ReadFile function.
|
||||||
|
var ret = this._readFile(resourceManager, fileDescriptor, priority, isSync);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
BIN
client/MiniPenumbra/b0941trp1d_o.avfx
Normal file
BIN
client/MiniPenumbra/b0941trp1d_o.avfx
Normal file
Binary file not shown.
|
@ -67,6 +67,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="../server/packs/*.yaml" LinkBase="packs" />
|
<EmbeddedResource Include="../server/packs/*.yaml" LinkBase="packs" />
|
||||||
<EmbeddedResource Remove="../server/packs/*_old*.yaml" />
|
<EmbeddedResource Remove="../server/packs/*_old*.yaml" />
|
||||||
|
<None Remove="MiniPenumbra\b0941trp1d_o.avfx" />
|
||||||
|
<EmbeddedResource Include="MiniPenumbra\b0941trp1d_o.avfx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Dalamud.Game.Command;
|
||||||
using Dalamud.Game.Gui;
|
using Dalamud.Game.Gui;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
|
||||||
namespace OrangeGuidanceTomestone;
|
namespace OrangeGuidanceTomestone;
|
||||||
|
|
||||||
|
@ -37,13 +38,19 @@ public class Plugin : IDalamudPlugin {
|
||||||
internal Vfx Vfx { get; }
|
internal Vfx Vfx { get; }
|
||||||
internal PluginUi Ui { get; }
|
internal PluginUi Ui { get; }
|
||||||
internal Messages Messages { get; }
|
internal Messages Messages { get; }
|
||||||
|
internal VfxReplacer VfxReplacer { get; }
|
||||||
internal Commands Commands { get; }
|
internal Commands Commands { get; }
|
||||||
|
|
||||||
|
internal string AvfxFilePath { get; }
|
||||||
|
|
||||||
public Plugin() {
|
public Plugin() {
|
||||||
|
this.AvfxFilePath = this.CopyAvfxFile();
|
||||||
|
|
||||||
this.Config = this.Interface!.GetPluginConfig() as Configuration ?? new Configuration();
|
this.Config = this.Interface!.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
this.Vfx = new Vfx();
|
this.Vfx = new Vfx();
|
||||||
this.Messages = new Messages(this);
|
this.Messages = new Messages(this);
|
||||||
this.Ui = new PluginUi(this);
|
this.Ui = new PluginUi(this);
|
||||||
|
this.VfxReplacer = new VfxReplacer(this);
|
||||||
this.Commands = new Commands(this);
|
this.Commands = new Commands(this);
|
||||||
|
|
||||||
if (this.Config.ApiKey == string.Empty) {
|
if (this.Config.ApiKey == string.Empty) {
|
||||||
|
@ -59,6 +66,7 @@ public class Plugin : IDalamudPlugin {
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.Commands.Dispose();
|
this.Commands.Dispose();
|
||||||
|
this.VfxReplacer.Dispose();
|
||||||
this.Ui.Dispose();
|
this.Ui.Dispose();
|
||||||
this.Messages.Dispose();
|
this.Messages.Dispose();
|
||||||
this.Vfx.Dispose();
|
this.Vfx.Dispose();
|
||||||
|
@ -67,4 +75,13 @@ public class Plugin : IDalamudPlugin {
|
||||||
internal void SaveConfig() {
|
internal void SaveConfig() {
|
||||||
this.Interface.SavePluginConfig(this.Config);
|
this.Interface.SavePluginConfig(this.Config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string CopyAvfxFile() {
|
||||||
|
var configDir = this.Interface!.GetPluginConfigDirectory();
|
||||||
|
Directory.CreateDirectory(configDir);
|
||||||
|
var stream = Resourcer.Resource.AsStream("MiniPenumbra/b0941trp1d_o.avfx");
|
||||||
|
var path = Path.Join(configDir, "sign.avfx");
|
||||||
|
stream.CopyTo(File.Create(path));
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user