diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj
index c1313a741..0ac4cccf8 100644
--- a/Dalamud.Injector/Dalamud.Injector.csproj
+++ b/Dalamud.Injector/Dalamud.Injector.csproj
@@ -14,16 +14,16 @@
true
- 4.1.0.8
- 4.1.0.8
+ 4.3.1.0
+ 4.3.1.0
XIVLauncher addon injection
- 4.1.0.8
+ 4.3.1.0
-
+
diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs
index bee8895c9..5f92d857d 100644
--- a/Dalamud/Configuration/CustomComboPreset.cs
+++ b/Dalamud/Configuration/CustomComboPreset.cs
@@ -7,13 +7,19 @@ using System.Threading.Tasks;
namespace XIVLauncher.Dalamud
{
- //CURRENT HIGHEST FLAG IS 44
+ //CURRENT HIGHEST FLAG IS 46
[Flags]
public enum CustomComboPreset : long
{
None = 0,
// DRAGOON
+ [CustomComboInfo("Jump + Mirage Dive", "Replace Jump with Mirage Dive when Dive Ready", 22)]
+ DragoonJumpFeature = 1L << 44,
+
+ [CustomComboInfo("BOTD Into Stardiver", "Replace Blood of the Dragon with Stardiver when in Life of the Dragon", 22)]
+ DragoonBOTDFeature = 1L << 46,
+
[CustomComboInfo("Coerthan Torment Combo", "Replace Coerthan Torment with its combo chain", 22)]
DragoonCoerthanTormentCombo = 1L << 0,
@@ -77,19 +83,22 @@ namespace XIVLauncher.Dalamud
[CustomComboInfo("Hakke Mujinsatsu Combo", "Replace Hakke Mujinsatsu with its combo chain", 30)]
NinjaHakkeMujinsatsuCombo = 1L << 19,
+ [CustomComboInfo("Dream to Assassinate", "Replace Dream Within a Dream with Assassinate when Assassinate Ready", 30)]
+ NinjaAssassinateFeature = 1L << 45,
+
// GUNBREAKER
[CustomComboInfo("Solid Barrel Combo", "Replace Solid Barrel with its combo chain", 37)]
GunbreakerSolidBarrelCombo = 1L << 20,
- [CustomComboInfo("Gnashing Fang Combo", "Replace Gnashing Fang with its combo chain", 37)]
+ [CustomComboInfo("Gnashing Fang Combo", "Replace Wicked Talon with its combo chain", 37)]
GunbreakerGnashingFangCombo = 1L << 21,
[CustomComboInfo("Demon Slaughter Combo", "Replace Demon Slaughter with its combo chain", 37)]
GunbreakerDemonSlaughterCombo = 1L << 22,
// MACHINIST
- [CustomComboInfo("Heated Clan Shot Combo/Heat", "Replace Heated Clan Shot with its combo chain or with Heat Blast when overheated.", 31)]
- MachinistHeatedClanShotFeature = 1L << 23,
+ [CustomComboInfo("(Heated) Shot Combo", "Replace UNHEATED Split Shot with its combo chain or with Heat Blast when overheated.", 31)]
+ MachinistMainCombo = 1L << 23,
[CustomComboInfo("Spread Shot Heat", "Replace Spread Shot with Auto Crossbow when overheated.", 31)]
MachinistSpreadShotFeature = 1L << 24,
@@ -112,10 +121,10 @@ namespace XIVLauncher.Dalamud
[CustomComboInfo("Brand of Purgatory Combo", "Replaces Fountain of Fire with Brand of Purgatory when under the affect of Hellish Conduit.", 27)]
SummonerBoPCombo = 1L << 38,
- [CustomComboInfo("ED Fester", "Change Energy Drain into Fester while you have Aetherflow stacks.", 27)]
+ [CustomComboInfo("ED Fester", "Change Fester into Energy Drain when out of Aetherflow stacks.", 27)]
SummonerEDFesterCombo = 1L << 39,
- [CustomComboInfo("ES Painflare", "Change Energy Siphon into Painflare while you have Aetherflow stacks.", 27)]
+ [CustomComboInfo("ES Painflare", "Change Painflare into Energy Syphon when out of Aetherflow stacks.", 27)]
SummonerESPainflareCombo = 1L << 40,
[CustomComboInfo("DWT", "DWT.", 27)]
diff --git a/Dalamud/Configuration/DalamudConfiguration.cs b/Dalamud/Configuration/DalamudConfiguration.cs
index 6bbce4d8a..ceb3fd84e 100644
--- a/Dalamud/Configuration/DalamudConfiguration.cs
+++ b/Dalamud/Configuration/DalamudConfiguration.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using Dalamud.Configuration;
using Dalamud.DiscordBot;
using Newtonsoft.Json;
using XIVLauncher.Dalamud;
@@ -31,6 +32,8 @@ namespace Dalamud
public string LastVersion { get; set; }
+ public Dictionary PluginConfigurations { get; set; }
+
public static DalamudConfiguration Load(string path) {
return JsonConvert.DeserializeObject(File.ReadAllText(path));
}
diff --git a/Dalamud/Configuration/IPluginConfiguration.cs b/Dalamud/Configuration/IPluginConfiguration.cs
new file mode 100644
index 000000000..f2a782960
--- /dev/null
+++ b/Dalamud/Configuration/IPluginConfiguration.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Dalamud.Configuration
+{
+ public interface IPluginConfiguration
+ {
+ int Version { get; set; }
+ }
+}
diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 64f25c9e1..17cbbba04 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -183,7 +183,7 @@ namespace Dalamud {
CommandManager.AddHandler("/xlitem", new CommandInfo(OnItemLinkCommand)
{
- HelpMessage = "Link an item by name. Usage: /xlitem - "
+ HelpMessage = "Link an item by name. Usage: /xlitem
- . For matching an item exactly, use /xlitem +
- "
});
#if DEBUG
@@ -196,7 +196,7 @@ namespace Dalamud {
CommandManager.AddHandler("/xlbonus", new CommandInfo(OnRouletteBonusNotifyCommand)
{
- HelpMessage = "Notify when a roulette has a bonus you specified. Usage: /xlitem "
+ HelpMessage = "Notify when a roulette has a bonus you specified. Run without parameters for more info. Usage: /xlbonus "
});
}
@@ -396,9 +396,16 @@ namespace Dalamud {
}
private void OnItemLinkCommand(string command, string arguments) {
+ var exactSearch = false;
+ if (arguments.StartsWith("+"))
+ {
+ exactSearch = true;
+ arguments = arguments.Substring(1);
+ }
+
Task.Run(async () => {
try {
- dynamic results = await XivApi.Search(arguments, "Item", 1);
+ dynamic results = await XivApi.Search(arguments, "Item", 1, exactSearch);
var itemId = (short) results.Results[0].ID;
var itemName = (string)results.Results[0].Name;
@@ -473,7 +480,7 @@ namespace Dalamud {
InvalidArgs:
Framework.Gui.Chat.PrintError("Unrecognized arguments.");
Framework.Gui.Chat.Print("Possible values for roulette: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\n" +
- "Possible values for role: tank, dps, healer, all");
+ "Possible values for role: tank, dps, healer, all, none/reset");
}
private int RouletteSlugToKey(string slug) => slug.ToLower() switch {
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 537b7db8d..f447ac7ac 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -14,9 +14,9 @@
true
- 4.3.0.0
- 4.3.0.0
- 4.3.0.0
+ 4.3.1.0
+ 4.3.1.0
+ 4.3.1.0
diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
index 04838b2c9..08f858d0c 100644
--- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
+++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs
@@ -13,9 +13,9 @@ namespace Dalamud.Game.ClientState
public IntPtr JobGaugeData { get; set; }
protected override void Setup64Bit(SigScanner sig) {
- ActorTable = sig.Module.BaseAddress + 0x1BFBA38;
+ ActorTable = sig.Module.BaseAddress + 0x1BFFD90;
LocalContentId = sig.Module.BaseAddress + 0x1C2E000;
- JobGaugeData = sig.Module.BaseAddress + 0x1C00110;
+ JobGaugeData = sig.Module.BaseAddress + 0x1BFB110;
}
}
}
diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs
index 16c89702e..a84928dc2 100644
--- a/Dalamud/Game/Internal/Gui/IconReplacer.cs
+++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs
@@ -36,11 +36,11 @@ namespace Dalamud.Game.Internal.Gui {
this.Address.Setup(scanner);
this.byteBase = scanner.Module.BaseAddress;
- this.comboTimer = byteBase + 0x1BB8B50;
+ this.comboTimer = byteBase + 0x1BB3B50;
//this.comboTimer = scanner.ScanText("E8 ?? ?? ?? ?? 80 7E 21 00") + 0x178;
this.lastComboMove = this.comboTimer + 0x4;
- this.playerLevel = byteBase + 0x1C30FA8 + 0x78;
+ this.playerLevel = byteBase + 0x1C2BFA8 + 0x78;
//this.playerLevel = scanner.ScanText("E8 ?? ?? ?? ?? 88 45 EF") + 0x4D;
CustomIDs = new HashSet();
@@ -107,7 +107,29 @@ namespace Dalamud.Game.Internal.Gui {
var level = Marshal.ReadByte(this.playerLevel);
// DRAGOON
- // TODO: Jump/High Jump into Mirage Dive
+
+ // Change Jump/High Jump into Mirage Dive when Dive Ready
+ if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonJumpFeature)) {
+ if (actionID == 92) {
+ if (SearchBuffArray(1243)) {
+ return 7399;
+ }
+ if (level >= 74) return 16478;
+ return 92;
+ }
+ }
+
+ // Change Blood of the Dragon into Stardiver when in Life of the Dragon
+ if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonBOTDFeature)) {
+ if (actionID == 3553) {
+ if (level >= 80) {
+ if (this.dalamud.ClientState.JobGauges.Get().BOTDState == BOTDState.LOTD) {
+ return 16480;
+ }
+ }
+ return 3553;
+ }
+ }
// Replace Coerthan Torment with Coerthan Torment combo chain
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) {
@@ -345,6 +367,14 @@ namespace Dalamud.Game.Internal.Gui {
}
}
+ //Replace Dream Within a Dream with Assassinate when Assassinate Ready
+ if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAssassinateFeature)) {
+ if(actionID == 3566) {
+ if (SearchBuffArray(1955)) return 2246;
+ return 3566;
+ }
+ }
+
// GUNBREAKER
// Replace Solid Barrel with Solid Barrel combo
@@ -358,10 +388,10 @@ namespace Dalamud.Game.Internal.Gui {
}
}
- // Replace Gnashing Fang with Gnashing Fang combo
+ // Replace Wicked Talon with Gnashing Fang combo
// TODO: Potentially add Contuation moves as well?
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) {
- if (actionID == 16146) {
+ if (actionID == 16150) {
byte ammoComboState = this.dalamud.ClientState.JobGauges.Get().AmmoComboStepNumber;
if (ammoComboState == 1) return 16147;
if (ammoComboState == 2) return 16150;
@@ -381,11 +411,11 @@ namespace Dalamud.Game.Internal.Gui {
// MACHINIST
- // Replace Heated Clean Shot with Heated Clean Shot combo
+ // Replace Clean Shot with Heated Clean Shot combo
// Or with Heat Blast when overheated.
// For some reason the shots use their unheated IDs as combo moves
- if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistHeatedClanShotFeature)) {
- if (actionID == 7413) {
+ if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistMainCombo)) {
+ if (actionID == 2873) {
MCHGauge gauge = this.dalamud.ClientState.JobGauges.Get();
// End overheat slightly early to prevent eager button mashing clipping your gcd with a fake 6th HB.
if (gauge.IsOverheated() && level >= 35 && gauge.OverheatTimeRemaining > 30) return 7410;
@@ -399,7 +429,8 @@ namespace Dalamud.Game.Internal.Gui {
if (level >= 26) return 2873;
}
}
- return 7411;
+ if (level >= 54) return 7411;
+ return 2866;
}
}
@@ -482,7 +513,10 @@ namespace Dalamud.Game.Internal.Gui {
}
else {
if (gauge.IsBahamutReady()) return 7427;
- if (gauge.IsPhoenixReady()) return 16513;
+ if (gauge.IsPhoenixReady()) {
+ if (level == 80) return 16549;
+ return 16513;
+ }
return 3581;
}
}
@@ -524,20 +558,21 @@ namespace Dalamud.Game.Internal.Gui {
}
}
- // Change Energy Drain into Fester
+ // Change Fester into Energy Drain
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerEDFesterCombo)) {
- if (actionID == 16508) {
- if (this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks())
- return 181;
- return 16508;
+ if (actionID == 181) {
+ if (!this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks())
+ return 16508;
+ return 181;
}
}
- //Change Energy Siphon into Painflare
+ //Change Painflare into Energy Syphon
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerESPainflareCombo)) {
- if (actionID == 16510) {
- if (this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks())
- if (level >= 52) return 3578;
+ if (actionID == 3578) {
+ if (!this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks())
+ return 16510;
+ if (level >= 52) return 3578;
return 16510;
}
}
@@ -849,7 +884,7 @@ namespace Dalamud.Game.Internal.Gui {
private unsafe delegate int* getArray(long* address);
private unsafe IntPtr FindBuffAddress() {
- IntPtr randomAddress = byteBase + 0x1C07BE0;
+ IntPtr randomAddress = byteBase + 0x1C02BE0;
IntPtr num = Marshal.ReadIntPtr(randomAddress);
IntPtr step2 = (IntPtr)(Marshal.ReadInt64(num) + 0x248);
IntPtr step3 = Marshal.ReadIntPtr(step2);
@@ -879,7 +914,7 @@ namespace Dalamud.Game.Internal.Gui {
CustomIDs.Add(2255);
CustomIDs.Add(16488);
CustomIDs.Add(16145);
- CustomIDs.Add(16146);
+ CustomIDs.Add(16150);
CustomIDs.Add(16149);
CustomIDs.Add(7413);
CustomIDs.Add(2870);
@@ -889,8 +924,8 @@ namespace Dalamud.Game.Internal.Gui {
CustomIDs.Add(3582);
CustomIDs.Add(3581);
CustomIDs.Add(163);
- CustomIDs.Add(16508);
- CustomIDs.Add(16510);
+ CustomIDs.Add(181);
+ CustomIDs.Add(3578);
CustomIDs.Add(16543);
CustomIDs.Add(167);
CustomIDs.Add(15994);
@@ -904,6 +939,10 @@ namespace Dalamud.Game.Internal.Gui {
CustomIDs.Add(16525);
CustomIDs.Add(16524);
CustomIDs.Add(7516);
+ CustomIDs.Add(3566);
+ CustomIDs.Add(92);
+ CustomIDs.Add(3553);
+ CustomIDs.Add(2873);
VanillaIDs.Add(0x3e75);
VanillaIDs.Add(0x3e76);
VanillaIDs.Add(0x3e77);
@@ -1064,7 +1103,6 @@ namespace Dalamud.Game.Internal.Gui {
VanillaIDs.Add(0xb32);
VanillaIDs.Add(0xb34);
VanillaIDs.Add(0xb38);
- VanillaIDs.Add(0xb39);
VanillaIDs.Add(0xb3e);
VanillaIDs.Add(0x12d);
VanillaIDs.Add(0x15);
@@ -1072,7 +1110,6 @@ namespace Dalamud.Game.Internal.Gui {
VanillaIDs.Add(0x31);
VanillaIDs.Add(0x33);
VanillaIDs.Add(0x4b);
- VanillaIDs.Add(0x5c);
VanillaIDs.Add(0x62);
VanillaIDs.Add(0x64);
VanillaIDs.Add(0x71);
diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs
index cf71e43c4..4613e03de 100644
--- a/Dalamud/Game/Network/NetworkHandlers.cs
+++ b/Dalamud/Game/Network/NetworkHandlers.cs
@@ -221,12 +221,12 @@ namespace Dalamud.Game.Network {
}
private enum ZoneOpCode {
- CfNotifyPop = 0x135,
- CfPreferredRole = 0x2a2,
- MarketTaxRates = 0x16a,
- MarketBoardItemRequestStart = 0x349,
- MarketBoardOfferings = 0x130,
- MarketBoardHistory = 0x1f7
+ CfNotifyPop = 0x1F8,
+ CfPreferredRole = 0x32A,
+ MarketTaxRates = 0x25E,
+ MarketBoardItemRequestStart = 0x328,
+ MarketBoardOfferings = 0x15F,
+ MarketBoardHistory = 0x113
}
private DalamudConfiguration.PreferredRole RoleKeyToPreferredRole(int key) => key switch
diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs
index 8c2cb38eb..38be7d39c 100644
--- a/Dalamud/Plugin/DalamudPluginInterface.cs
+++ b/Dalamud/Plugin/DalamudPluginInterface.cs
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
+using Dalamud.Configuration;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command;
using Dalamud.Game.Internal;
@@ -29,14 +32,51 @@ namespace Dalamud.Plugin
///
public readonly Framework Framework;
+ private readonly Dalamud dalamud;
+ private readonly string pluginName;
+
///
/// Set up the interface and populate all fields needed.
///
///
- public DalamudPluginInterface(Dalamud dalamud) {
+ public DalamudPluginInterface(Dalamud dalamud, string pluginName) {
this.CommandManager = dalamud.CommandManager;
this.Framework = dalamud.Framework;
this.ClientState = dalamud.ClientState;
+
+ this.dalamud = dalamud;
+ this.pluginName = pluginName;
+ }
+
+ ///
+ /// Save a plugin configuration(inheriting IPluginConfiguration).
+ ///
+ /// The current configuration.
+ public void SavePluginConfig(IPluginConfiguration currentConfig) {
+ if (this.dalamud.Configuration.PluginConfigurations == null)
+ this.dalamud.Configuration.PluginConfigurations = new Dictionary();
+
+ if (this.dalamud.Configuration.PluginConfigurations.ContainsKey(this.pluginName)) {
+ this.dalamud.Configuration.PluginConfigurations[this.pluginName] = currentConfig;
+ return;
+ }
+
+ this.dalamud.Configuration.PluginConfigurations.Add(this.pluginName, currentConfig);
+ this.dalamud.Configuration.Save(this.dalamud.StartInfo.ConfigurationPath);
+ }
+
+ ///
+ /// Get a previously saved plugin configuration or null if none was saved before.
+ ///
+ /// A previously saved config or null if none was saved before.
+ public IPluginConfiguration GetPluginConfig() {
+ if (this.dalamud.Configuration.PluginConfigurations == null)
+ this.dalamud.Configuration.PluginConfigurations = new Dictionary();
+
+ if (!this.dalamud.Configuration.PluginConfigurations.ContainsKey(this.pluginName))
+ return null;
+
+ return this.dalamud.Configuration.PluginConfigurations[this.pluginName];
}
}
}
diff --git a/Dalamud/Plugin/PluginManager.cs b/Dalamud/Plugin/PluginManager.cs
index 370bbae54..204931dfe 100644
--- a/Dalamud/Plugin/PluginManager.cs
+++ b/Dalamud/Plugin/PluginManager.cs
@@ -14,16 +14,12 @@ namespace Dalamud.Plugin
private readonly string pluginDirectory;
private readonly string defaultPluginDirectory;
- private readonly DalamudPluginInterface dalamudInterface;
-
private List plugins;
public PluginManager(Dalamud dalamud, string pluginDirectory, string defaultPluginDirectory) {
this.dalamud = dalamud;
this.pluginDirectory = pluginDirectory;
this.defaultPluginDirectory = defaultPluginDirectory;
-
- this.dalamudInterface = new DalamudPluginInterface(dalamud);
}
public void UnloadPlugins() {
@@ -79,7 +75,10 @@ namespace Dalamud.Plugin
foreach (var pluginType in foundImplementations)
{
var plugin = (IDalamudPlugin)Activator.CreateInstance(pluginType);
- plugin.Initialize(this.dalamudInterface);
+
+ var dalamudInterface = new DalamudPluginInterface(this.dalamud, pluginType.Assembly.GetName().Name);
+
+ plugin.Initialize(dalamudInterface);
Log.Information("Loaded plugin: {0}", plugin.Name);
this.plugins.Add(plugin);
}
diff --git a/Dalamud/XivApi.cs b/Dalamud/XivApi.cs
index dc5e5fa8b..9d2374281 100644
--- a/Dalamud/XivApi.cs
+++ b/Dalamud/XivApi.cs
@@ -49,10 +49,16 @@ namespace Dalamud
return await Get("ContentFinderCondition/" + contentFinderCondition);
}
- public static async Task Search(string query, string indexes, int limit = 100) {
+ public static async Task Search(string query, string indexes, int limit = 100, bool exact = false) {
query = System.Net.WebUtility.UrlEncode(query);
- return await Get("search" + $"?string={query}&indexes={indexes}&limit={limit}");
+ var queryString = $"?string={query}&indexes={indexes}&limit={limit}";
+ if (exact)
+ {
+ queryString += "&string_algo=match";
+ }
+
+ return await Get("search" + queryString);
}
public static async Task GetMarketInfoWorld(int itemId, string worldName) {