mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
commit
a2e55e1cd5
33 changed files with 1666 additions and 91 deletions
172
Dalamud/Configuration/CustomComboPreset.cs
Normal file
172
Dalamud/Configuration/CustomComboPreset.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace XIVLauncher.Dalamud
|
||||
{
|
||||
|
||||
//CURRENT HIGHEST FLAG IS 44
|
||||
[Flags]
|
||||
public enum CustomComboPreset : long
|
||||
{
|
||||
None = 0,
|
||||
|
||||
// DRAGOON
|
||||
[CustomComboInfo("Coerthan Torment Combo", "Replace Coerthan Torment with its combo chain", 22)]
|
||||
DragoonCoerthanTormentCombo = 1L << 0,
|
||||
|
||||
[CustomComboInfo("Chaos Thrust Combo", "Replace Chaos Thrust with its combo chain", 22)]
|
||||
DragoonChaosThrustCombo = 1L << 1,
|
||||
|
||||
[CustomComboInfo("Full Thrust Combo", "Replace Full Thrust with its combo chain", 22)]
|
||||
DragoonFullThrustCombo = 1L << 2,
|
||||
|
||||
// DARK KNIGHT
|
||||
[CustomComboInfo("Souleater Combo", "Replace Souleater with its combo chain", 32)]
|
||||
DarkSouleaterCombo = 1L << 3,
|
||||
|
||||
[CustomComboInfo("Stalwart Soul Combo", "Replace Stalwart Soul with its combo chain", 32)]
|
||||
DarkStalwartSoulCombo = 1L << 4,
|
||||
|
||||
// PALADIN
|
||||
[CustomComboInfo("Goring Blade Combo", "Replace Goring Blade with its combo chain", 19)]
|
||||
PaladinGoringBladeCombo = 1L << 5,
|
||||
|
||||
[CustomComboInfo("Royal Authority Combo", "Replace Royal Authority with its combo chain", 19)]
|
||||
PaladinRoyalAuthorityCombo = 1L << 6,
|
||||
|
||||
[CustomComboInfo("Prominence Combo", "Replace Prominence with its combo chain", 19)]
|
||||
PaladinProminenceCombo = 1L << 7,
|
||||
|
||||
// WARRIOR
|
||||
[CustomComboInfo("Storms Path Combo", "Replace Storms Path with its combo chain", 21)]
|
||||
WarriorStormsPathCombo = 1L << 8,
|
||||
|
||||
[CustomComboInfo("Storms Eye Combo", "Replace Storms Eye with its combo chain", 21)]
|
||||
WarriorStormsEyeCombo = 1L << 9,
|
||||
|
||||
[CustomComboInfo("Mythril Tempest Combo", "Replace Mythril Tempest with its combo chain", 21)]
|
||||
WarriorMythrilTempestCombo = 1L << 10,
|
||||
|
||||
// SAMURAI
|
||||
[CustomComboInfo("Yukikaze Combo", "Replace Yukikaze with its combo chain", 34)]
|
||||
SamuraiYukikazeCombo = 1L << 11,
|
||||
|
||||
[CustomComboInfo("Gekko Combo", "Replace Gekko with its combo chain", 34)]
|
||||
SamuraiGekkoCombo = 1L << 12,
|
||||
|
||||
[CustomComboInfo("Kasha Combo", "Replace Kasha with its combo chain", 34)]
|
||||
SamuraiKashaCombo = 1L << 13,
|
||||
|
||||
[CustomComboInfo("Mangetsu Combo", "Replace Mangetsu with its combo chain", 34)]
|
||||
SamuraiMangetsuCombo = 1L << 14,
|
||||
|
||||
[CustomComboInfo("Oka Combo", "Replace Oka with its combo chain", 34)]
|
||||
SamuraiOkaCombo = 1L << 15,
|
||||
|
||||
|
||||
// NINJA
|
||||
[CustomComboInfo("Armor Crush Combo", "Replace Armor Crush with its combo chain", 30)]
|
||||
NinjaArmorCrushCombo = 1L << 17,
|
||||
|
||||
[CustomComboInfo("Aeolian Edge Combo", "Replace Aeolian Edge with its combo chain", 30)]
|
||||
NinjaAeolianEdgeCombo = 1L << 18,
|
||||
|
||||
[CustomComboInfo("Hakke Mujinsatsu Combo", "Replace Hakke Mujinsatsu with its combo chain", 30)]
|
||||
NinjaHakkeMujinsatsuCombo = 1L << 19,
|
||||
|
||||
// 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)]
|
||||
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("Spread Shot Heat", "Replace Spread Shot with Auto Crossbow when overheated.", 31)]
|
||||
MachinistSpreadShotFeature = 1L << 24,
|
||||
|
||||
// BLACK MAGE
|
||||
[CustomComboInfo("Enochian Stance Switcher", "Change Enochian to Fire 4 or Blizzard 4 depending on stance.", 25)]
|
||||
BlackEnochianFeature = 1L << 25,
|
||||
|
||||
[CustomComboInfo("Umbral Soul/Transpose Switcher", "Change between Umbral Soul and Transpose automatically.", 25)]
|
||||
BlackManaFeature = 1L << 26,
|
||||
|
||||
// ASTROLOGIAN
|
||||
[CustomComboInfo("Draw on Play", "Play turns into Draw when no card is drawn, as well as the usual Play behavior.", 33)]
|
||||
AstrologianCardsOnDrawFeature = 1L << 27,
|
||||
|
||||
// SUMMONER
|
||||
[CustomComboInfo("Demi-summon combiners", "Dreadwyrm Trance, Summon Bahamut, and Firebird Trance are now one button. Deathflare, Enkindle Bahamut, and Enkindle Phoenix are now one button.", 27)]
|
||||
SummonerDemiCombo = 1L << 28,
|
||||
|
||||
[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)]
|
||||
SummonerEDFesterCombo = 1L << 39,
|
||||
|
||||
[CustomComboInfo("ES Painflare", "Change Energy Siphon into Painflare while you have Aetherflow stacks.", 27)]
|
||||
SummonerESPainflareCombo = 1L << 40,
|
||||
|
||||
// SCHOLAR
|
||||
[CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)]
|
||||
ScholarSeraphConsolationFeature = 1L << 29,
|
||||
|
||||
[CustomComboInfo("ED Aetherflow", "Change Energy Drain into Aetherflow when you have no more Aetherflow stacks.", 28)]
|
||||
ScholarEnergyDrainFeature = 1L << 37,
|
||||
|
||||
// DANCER
|
||||
[CustomComboInfo("AoE GCD procs", "Replaces all AoE GCDs with their procced version when available.", 38)]
|
||||
DancerAoeGcdFeature = 1L << 32,
|
||||
|
||||
[CustomComboInfo("Fan Dance Combos", "Change Fan Dance and Fan Dance 2 into Fan Dance 3 while flourishing.", 38)]
|
||||
DancerFanDanceCombo = 1L << 33,
|
||||
|
||||
// WHITE MAGE
|
||||
[CustomComboInfo("Solace into Misery", "Replaces Afflatus Solace with Afflatus Misery when Misery is ready to be used.", 24)]
|
||||
WhiteMageSolaceMiseryFeature = 1L << 35,
|
||||
|
||||
[CustomComboInfo("Rapture into Misery", "Replaces Afflatus Rapture with Afflatus Misery when Misery is ready to be used.", 24)]
|
||||
WhiteMageRaptureMiseryFeature = 1L << 36,
|
||||
|
||||
// BARD
|
||||
[CustomComboInfo("Wanderer's into Pitch Perfect", "Replaces Wanderer's Minuet with Pitch Perfect while in WM.", 23)]
|
||||
BardWandererPPFeature = 1L << 41,
|
||||
|
||||
[CustomComboInfo("Heavy Shot into Straight Shot", "Replaces Heavy Shot/Burst Shot with Straight Shot/Refulgent Arrow when procced.", 23)]
|
||||
BardStraightShotUpgradeFeature = 1L << 42,
|
||||
|
||||
// MONK
|
||||
|
||||
// RED MAGE
|
||||
[CustomComboInfo("Red Mage AoE Combo", "Replaces Veraero/thunder 2 with Impact when Dualcast or Swiftcast are active.", 35)]
|
||||
RedMageAoECombo = 1L << 48,
|
||||
|
||||
[CustomComboInfo("Redoublement combo", "Replaces Redoublement with its combo chain, following enchantment rules.", 35)]
|
||||
RedMageMeleeCombo = 1L << 49
|
||||
}
|
||||
|
||||
public class CustomComboInfoAttribute : Attribute
|
||||
{
|
||||
internal CustomComboInfoAttribute(string fancyName, string description, byte classJob)
|
||||
{
|
||||
FancyName = fancyName;
|
||||
Description = description;
|
||||
ClassJob = classJob;
|
||||
}
|
||||
|
||||
public string FancyName { get; }
|
||||
public string Description { get; }
|
||||
public byte ClassJob { get; }
|
||||
}
|
||||
}
|
||||
37
Dalamud/Configuration/DalamudConfiguration.cs
Normal file
37
Dalamud/Configuration/DalamudConfiguration.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Dalamud.DiscordBot;
|
||||
using Newtonsoft.Json;
|
||||
using XIVLauncher.Dalamud;
|
||||
|
||||
namespace Dalamud
|
||||
{
|
||||
[Serializable]
|
||||
public class DalamudConfiguration
|
||||
{
|
||||
public DiscordFeatureConfiguration DiscordFeatureConfig { get; set; }
|
||||
|
||||
public bool OptOutMbCollection { get; set; } = false;
|
||||
|
||||
public CustomComboPreset ComboPresets { get; set; }
|
||||
|
||||
public List<string> BadWords { get; set; }
|
||||
|
||||
public class FateInfo {
|
||||
public string Name { get; set; }
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
public List<FateInfo> Fates;
|
||||
|
||||
|
||||
public static DalamudConfiguration Load(string path) {
|
||||
return JsonConvert.DeserializeObject<DalamudConfiguration>(File.ReadAllText(path));
|
||||
}
|
||||
|
||||
public void Save(string path) {
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,10 +11,11 @@ using Dalamud.Game.ClientState.Actors.Types;
|
|||
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Game.Internal;
|
||||
using Dalamud.Game.Internal.Gui;
|
||||
using Dalamud.Game.Network;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Settings;
|
||||
using Serilog;
|
||||
using XIVLauncher.Dalamud;
|
||||
|
||||
namespace Dalamud {
|
||||
public sealed class Dalamud : IDisposable {
|
||||
|
|
@ -39,8 +40,13 @@ namespace Dalamud {
|
|||
|
||||
public readonly DalamudStartInfo StartInfo;
|
||||
|
||||
public readonly IconReplacer IconReplacer;
|
||||
|
||||
public readonly DalamudConfiguration Configuration;
|
||||
|
||||
public Dalamud(DalamudStartInfo info) {
|
||||
this.StartInfo = info;
|
||||
this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath);
|
||||
|
||||
this.baseDirectory = info.WorkingDirectory;
|
||||
|
||||
|
|
@ -58,14 +64,16 @@ namespace Dalamud {
|
|||
SetupCommands();
|
||||
|
||||
ChatHandlers = new ChatHandlers(this);
|
||||
NetworkHandlers = new NetworkHandlers(this, info.OptOutMbCollection);
|
||||
NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
|
||||
|
||||
this.ClientState = new ClientState(this, info, this.sigScanner, this.targetModule);
|
||||
|
||||
this.BotManager = new DiscordBotManager(this, info.DiscordFeatureConfig);
|
||||
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
||||
|
||||
this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory);
|
||||
|
||||
this.IconReplacer = new IconReplacer(this, this.sigScanner);
|
||||
|
||||
try {
|
||||
this.PluginManager.LoadPlugins();
|
||||
} catch (Exception ex) {
|
||||
|
|
@ -79,6 +87,8 @@ namespace Dalamud {
|
|||
Framework.Enable();
|
||||
|
||||
this.BotManager.Start();
|
||||
|
||||
this.IconReplacer.Enable();
|
||||
}
|
||||
|
||||
public void Unload() {
|
||||
|
|
@ -95,6 +105,8 @@ namespace Dalamud {
|
|||
this.BotManager.Dispose();
|
||||
|
||||
this.unloadSignal.Dispose();
|
||||
|
||||
this.IconReplacer.Dispose();
|
||||
}
|
||||
|
||||
private void SetupCommands() {
|
||||
|
|
@ -113,6 +125,11 @@ namespace Dalamud {
|
|||
ShowInHelp = false
|
||||
});
|
||||
|
||||
CommandManager.AddHandler("/xldcombo", new CommandInfo(OnCommandDebugCombo) {
|
||||
HelpMessage = "COMBO debug",
|
||||
ShowInHelp = false
|
||||
});
|
||||
|
||||
CommandManager.AddHandler("/xlhelp", new CommandInfo(OnCommandHelp) {
|
||||
HelpMessage = "Shows list of commands available."
|
||||
});
|
||||
|
|
@ -200,8 +217,8 @@ namespace Dalamud {
|
|||
}
|
||||
|
||||
private void OnFateWatchAdd(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.Fates == null)
|
||||
PersistentSettings.Instance.Fates = new List<PersistentSettings.FateInfo>();
|
||||
if (this.Configuration.Fates == null)
|
||||
this.Configuration.Fates = new List<DalamudConfiguration.FateInfo>();
|
||||
|
||||
dynamic candidates = XivApi.Search(arguments, "Fate").GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -210,32 +227,36 @@ namespace Dalamud {
|
|||
return;
|
||||
}
|
||||
|
||||
var fateInfo = new PersistentSettings.FateInfo {
|
||||
var fateInfo = new DalamudConfiguration.FateInfo {
|
||||
Id = candidates.Results[0].ID,
|
||||
Name = candidates.Results[0].Name
|
||||
};
|
||||
|
||||
PersistentSettings.Instance.Fates.Add(fateInfo);
|
||||
this.Configuration.Fates.Add(fateInfo);
|
||||
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
Framework.Gui.Chat.Print($"Added fate \"{fateInfo.Name}\".");
|
||||
}
|
||||
|
||||
private void OnFateWatchList(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.Fates == null)
|
||||
PersistentSettings.Instance.Fates = new List<PersistentSettings.FateInfo>();
|
||||
if (this.Configuration.Fates == null)
|
||||
this.Configuration.Fates = new List<DalamudConfiguration.FateInfo>();
|
||||
|
||||
if (PersistentSettings.Instance.Fates.Count == 0) {
|
||||
if (this.Configuration.Fates.Count == 0) {
|
||||
Framework.Gui.Chat.Print("No fates on your watchlist.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var fate in PersistentSettings.Instance.Fates)
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
foreach (var fate in this.Configuration.Fates)
|
||||
Framework.Gui.Chat.Print($"Fate {fate.Id}: {fate.Name}");
|
||||
}
|
||||
|
||||
private void OnFateWatchRemove(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.Fates == null)
|
||||
PersistentSettings.Instance.Fates = new List<PersistentSettings.FateInfo>();
|
||||
if (this.Configuration.Fates == null)
|
||||
this.Configuration.Fates = new List<DalamudConfiguration.FateInfo>();
|
||||
|
||||
dynamic candidates = XivApi.Search(arguments, "Fate").GetAwaiter().GetResult();
|
||||
|
||||
|
|
@ -244,37 +265,45 @@ namespace Dalamud {
|
|||
return;
|
||||
}
|
||||
|
||||
PersistentSettings.Instance.Fates.RemoveAll(x => x.Id == candidates.Results[0].ID);
|
||||
this.Configuration.Fates.RemoveAll(x => x.Id == candidates.Results[0].ID);
|
||||
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
Framework.Gui.Chat.Print($"Removed fate \"{candidates.Results[0].Name}\".");
|
||||
}
|
||||
|
||||
private void OnBadWordsAdd(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.BadWords == null)
|
||||
PersistentSettings.Instance.BadWords = new List<string>();
|
||||
if (this.Configuration.BadWords == null)
|
||||
this.Configuration.BadWords = new List<string>();
|
||||
|
||||
PersistentSettings.Instance.BadWords.Add(arguments);
|
||||
this.Configuration.BadWords.Add(arguments);
|
||||
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
Framework.Gui.Chat.Print($"Muted \"{arguments}\".");
|
||||
}
|
||||
|
||||
private void OnBadWordsList(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.BadWords == null)
|
||||
PersistentSettings.Instance.BadWords = new List<string>();
|
||||
if (this.Configuration.BadWords == null)
|
||||
this.Configuration.BadWords = new List<string>();
|
||||
|
||||
if (PersistentSettings.Instance.BadWords.Count == 0) {
|
||||
if (this.Configuration.BadWords.Count == 0) {
|
||||
Framework.Gui.Chat.Print("No muted words or sentences.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var word in PersistentSettings.Instance.BadWords) Framework.Gui.Chat.Print($"\"{word}\"");
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
foreach (var word in this.Configuration.BadWords) Framework.Gui.Chat.Print($"\"{word}\"");
|
||||
}
|
||||
|
||||
private void OnBadWordsRemove(string command, string arguments) {
|
||||
if (PersistentSettings.Instance.BadWords == null)
|
||||
PersistentSettings.Instance.BadWords = new List<string>();
|
||||
if (this.Configuration.BadWords == null)
|
||||
this.Configuration.BadWords = new List<string>();
|
||||
|
||||
PersistentSettings.Instance.BadWords.RemoveAll(x => x == arguments);
|
||||
this.Configuration.BadWords.RemoveAll(x => x == arguments);
|
||||
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
|
||||
Framework.Gui.Chat.Print($"Unmuted \"{arguments}\".");
|
||||
}
|
||||
|
|
@ -311,6 +340,75 @@ namespace Dalamud {
|
|||
}
|
||||
}
|
||||
|
||||
private void OnCommandDebugCombo(string command, string arguments) {
|
||||
var argumentsParts = arguments.Split();
|
||||
|
||||
switch (argumentsParts[0]) {
|
||||
case "setall": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
if (value == CustomComboPreset.None)
|
||||
continue;
|
||||
|
||||
this.Configuration.ComboPresets |= value;
|
||||
}
|
||||
|
||||
Framework.Gui.Chat.Print("all SET");
|
||||
}
|
||||
break;
|
||||
case "unsetall": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
this.Configuration.ComboPresets &= value;
|
||||
}
|
||||
|
||||
Framework.Gui.Chat.Print("all UNSET");
|
||||
}
|
||||
break;
|
||||
case "set": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
if (value.ToString().ToLower() != argumentsParts[1].ToLower())
|
||||
continue;
|
||||
|
||||
this.Configuration.ComboPresets |= value;
|
||||
Framework.Gui.Chat.Print(argumentsParts[1] + " SET");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "toggle": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
if (value.ToString().ToLower() != argumentsParts[1].ToLower())
|
||||
continue;
|
||||
|
||||
this.Configuration.ComboPresets ^= value;
|
||||
Framework.Gui.Chat.Print(argumentsParts[1] + " TOGGLE");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "unset": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
if (value.ToString().ToLower() != argumentsParts[1].ToLower())
|
||||
continue;
|
||||
|
||||
this.Configuration.ComboPresets &= ~value;
|
||||
Framework.Gui.Chat.Print(argumentsParts[1] + " UNSET");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "list": {
|
||||
foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast<CustomComboPreset>()) {
|
||||
if (this.Configuration.ComboPresets.HasFlag(value))
|
||||
Framework.Gui.Chat.Print(value.ToString());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: Framework.Gui.Chat.Print("Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
||||
}
|
||||
|
||||
private void OnBotJoinCommand(string command, string arguments) {
|
||||
if (this.BotManager != null && this.BotManager.IsConnected)
|
||||
Process.Start(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<PropertyGroup Label="Target">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<TargetFramework>net471</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Build">
|
||||
|
|
@ -64,4 +64,7 @@
|
|||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Configuration\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -3,15 +3,14 @@ using Dalamud.DiscordBot;
|
|||
|
||||
namespace Dalamud {
|
||||
[Serializable]
|
||||
public sealed class DalamudStartInfo {
|
||||
public sealed class DalamudStartInfo
|
||||
{
|
||||
public string WorkingDirectory;
|
||||
public string ConfigurationPath;
|
||||
|
||||
public string PluginDirectory;
|
||||
public string DefaultPluginDirectory;
|
||||
public ClientLanguage Language;
|
||||
|
||||
public DiscordFeatureConfiguration DiscordFeatureConfig { get; set; }
|
||||
|
||||
public bool OptOutMbCollection { get; set; } = false;
|
||||
}
|
||||
|
||||
public enum ClientLanguage
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Game.Chat;
|
||||
using Dalamud.Settings;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game {
|
||||
|
|
@ -81,8 +80,8 @@ namespace Dalamud.Game {
|
|||
|
||||
var originalMessage = string.Copy(message);
|
||||
|
||||
if (PersistentSettings.Instance.BadWords != null &&
|
||||
PersistentSettings.Instance.BadWords.Any(x => originalMessage.Contains(x))) {
|
||||
if (this.dalamud.Configuration.BadWords != null &&
|
||||
this.dalamud.Configuration.BadWords.Any(x => originalMessage.Contains(x))) {
|
||||
// This seems to be in the user block list - let's not show it
|
||||
Log.Debug("Blocklist triggered");
|
||||
isHandled = true;
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ namespace Dalamud.Game.ClientState.Actors {
|
|||
|
||||
var actorStruct = Marshal.PtrToStructure<Structs.Actor>(offset);
|
||||
|
||||
Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"),
|
||||
actorStruct.ObjectKind.ToString());
|
||||
//Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"),
|
||||
// actorStruct.ObjectKind.ToString());
|
||||
|
||||
switch (actorStruct.ObjectKind) {
|
||||
case ObjectKind.Player: return new PlayerCharacter(actorStruct);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||
using Dalamud.Game.ClientState.Actors;
|
||||
using Dalamud.Game.ClientState.Actors.Types;
|
||||
using Dalamud.Game.Internal;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.ClientState
|
||||
{
|
||||
|
|
@ -38,6 +39,11 @@ namespace Dalamud.Game.ClientState
|
|||
/// </summary>
|
||||
public ulong LocalContentId => (ulong) Marshal.ReadInt64(Address.LocalContentId);
|
||||
|
||||
/// <summary>
|
||||
/// The class facilitating Job Gauge data access
|
||||
/// </summary>
|
||||
public JobGauges JobGauges;
|
||||
|
||||
/// <summary>
|
||||
/// Set up client state access.
|
||||
/// </summary>
|
||||
|
|
@ -49,9 +55,13 @@ namespace Dalamud.Game.ClientState
|
|||
Address = new ClientStateAddressResolver();
|
||||
Address.Setup(scanner);
|
||||
|
||||
Log.Verbose("===== C L I E N T S T A T E =====");
|
||||
|
||||
this.ClientLanguage = startInfo.Language;
|
||||
|
||||
this.Actors = new ActorTable(Address);
|
||||
|
||||
this.JobGauges = new JobGauges(Address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ namespace Dalamud.Game.ClientState
|
|||
public sealed class ClientStateAddressResolver : BaseAddressResolver {
|
||||
public IntPtr ActorTable { get; private set; }
|
||||
public IntPtr LocalContentId { get; private set; }
|
||||
public IntPtr JobGaugeData { get; set; }
|
||||
|
||||
protected override void Setup64Bit(SigScanner sig) {
|
||||
ActorTable = sig.Module.BaseAddress + 0x1B29B40;
|
||||
LocalContentId = sig.Module.BaseAddress + 0x1B58B60;
|
||||
JobGaugeData = sig.Module.BaseAddress + 0x1BFD110;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
Dalamud/Game/ClientState/JobGauge.cs
Normal file
20
Dalamud/Game/ClientState/JobGauge.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.ClientState {
|
||||
public class JobGauges {
|
||||
private ClientStateAddressResolver Address { get; }
|
||||
|
||||
public JobGauges(ClientStateAddressResolver addressResolver) {
|
||||
Address = addressResolver;
|
||||
|
||||
Log.Verbose("JobGaugeData address {JobGaugeData}", Address.ActorTable);
|
||||
}
|
||||
|
||||
// Should only be called with the gauge types in
|
||||
// ClientState.Structs.JobGauge
|
||||
public T Get<T>() {
|
||||
return Marshal.PtrToStructure<T>(Address.JobGaugeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs
Normal file
26
Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct ASTGauge {
|
||||
[FieldOffset(4)] private CardType Card;
|
||||
[FieldOffset(5)] private unsafe fixed byte Seals[3];
|
||||
|
||||
public CardType DrawnCard() {
|
||||
return Card;
|
||||
}
|
||||
|
||||
public unsafe bool ContainsSeal(SealType seal) {
|
||||
if (Seals[0] == (byte)seal) return true;
|
||||
if (Seals[1] == (byte)seal) return true;
|
||||
if (Seals[2] == (byte)seal) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs
Normal file
34
Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct BLMGauge {
|
||||
[FieldOffset(0)] public short TimeUntilNextPolyglot; //eno timer (ms)
|
||||
[FieldOffset(2)] public short ElementTimeRemaining; //ui/af timer
|
||||
[FieldOffset(4)] private byte ElementStance; //ui/af
|
||||
[FieldOffset(5)] public byte NumUmbralHearts; //number of umbral hearts
|
||||
[FieldOffset(6)] public byte NumPolyglotStacks; //number of polyglot stacks
|
||||
[FieldOffset(7)] private byte EnoState; //eno active?
|
||||
|
||||
public bool InUmbralIce() {
|
||||
return ElementStance > 4;
|
||||
}
|
||||
|
||||
public bool InAstralFire() {
|
||||
return ElementStance > 0 && ElementStance < 4;
|
||||
}
|
||||
|
||||
public bool IsEnoActive() {
|
||||
return EnoState > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
16
Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs
Normal file
16
Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct BRDGauge {
|
||||
[FieldOffset(0)] public short SongTimer;
|
||||
[FieldOffset(2)] public byte NumSongStacks;
|
||||
[FieldOffset(4)] public CurrentSong ActiveSong;
|
||||
}
|
||||
}
|
||||
25
Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs
Normal file
25
Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public unsafe struct DNCGauge {
|
||||
[FieldOffset(0)] public byte NumFeathers;
|
||||
[FieldOffset(1)] public byte Esprit;
|
||||
[FieldOffset(2)] private fixed byte StepOrder[4];
|
||||
[FieldOffset(6)] public byte NumCompleteSteps;
|
||||
|
||||
public bool IsDancing() {
|
||||
return StepOrder[0] != 0;
|
||||
}
|
||||
|
||||
public ulong NextStep() {
|
||||
return (ulong)(15999 + StepOrder[NumCompleteSteps] - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs
Normal file
16
Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct DRGGauge {
|
||||
[FieldOffset(0)] public short BOTDTimer;
|
||||
[FieldOffset(2)] public BOTDState BOTDState;
|
||||
[FieldOffset(3)] public byte EyeCount;
|
||||
}
|
||||
}
|
||||
20
Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs
Normal file
20
Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct DRKGauge {
|
||||
[FieldOffset(0)] public byte Blood;
|
||||
[FieldOffset(2)] public short DarksideTimeRemaining;
|
||||
[FieldOffset(4)] private byte DarkArtsState;
|
||||
[FieldOffset(6)] public short ShadowTimeRemaining;
|
||||
|
||||
public bool HasDarkArts() {
|
||||
return DarkArtsState > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs
Normal file
16
Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct GNBGauge {
|
||||
[FieldOffset(0)] public byte NumAmmo;
|
||||
[FieldOffset(2)] public short MaxTimerDuration;
|
||||
[FieldOffset(4)] public byte AmmoComboStepNumber;
|
||||
}
|
||||
}
|
||||
67
Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs
Normal file
67
Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
public enum SealType : byte {
|
||||
NONE = 0,
|
||||
SUN,
|
||||
MOON,
|
||||
CELESTIAL
|
||||
}
|
||||
|
||||
public enum CardType : byte {
|
||||
NONE = 0,
|
||||
BALANCE,
|
||||
BOLE,
|
||||
ARROW,
|
||||
SPEAR,
|
||||
EWER,
|
||||
SPIRE,
|
||||
LORD = 0x70,
|
||||
LADY = 0x80
|
||||
}
|
||||
|
||||
public enum SummonPet : byte {
|
||||
NONE = 0,
|
||||
IFRIT = 3,
|
||||
TITAN,
|
||||
GARUDA
|
||||
}
|
||||
|
||||
public enum PetGlam : byte {
|
||||
NONE = 0,
|
||||
EMERALD,
|
||||
TOPAZ,
|
||||
RUBY
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Sen : byte {
|
||||
NONE = 0,
|
||||
SETSU = 1 << 0,
|
||||
GETSU = 1 << 1,
|
||||
KA = 1 << 2
|
||||
}
|
||||
|
||||
public enum BOTDState : byte {
|
||||
NONE = 0,
|
||||
BOTD,
|
||||
LOTD
|
||||
}
|
||||
|
||||
public enum CurrentSong : byte {
|
||||
MAGE = 5,
|
||||
ARMY = 0xA,
|
||||
WANDERER = 0xF
|
||||
}
|
||||
|
||||
public enum DismissedFairy : byte {
|
||||
EOS = 6,
|
||||
SELENE
|
||||
}
|
||||
|
||||
public enum Mudras : byte {
|
||||
TEN = 1,
|
||||
CHI = 2,
|
||||
JIN = 3
|
||||
}
|
||||
}
|
||||
27
Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs
Normal file
27
Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct MCHGauge{
|
||||
|
||||
[FieldOffset(0)] public short OverheatTimeRemaining;
|
||||
[FieldOffset(2)] public short RobotTimeRemaining;
|
||||
[FieldOffset(4)] public byte Heat;
|
||||
[FieldOffset(5)] public byte Battery;
|
||||
[FieldOffset(6)] public byte LastRobotBatteryPower;
|
||||
[FieldOffset(7)] private byte TimerActive;
|
||||
|
||||
public bool IsOverheated() {
|
||||
return (TimerActive & 1) != 0;
|
||||
}
|
||||
public bool IsRobotActive() {
|
||||
return (TimerActive & 2) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs
Normal file
21
Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct MNKGauge {
|
||||
[FieldOffset(0)] public byte GLTimer;
|
||||
[FieldOffset(2)] public byte NumGLStacks;
|
||||
[FieldOffset(3)] public byte NumChakra;
|
||||
[FieldOffset(4)] private byte GLTimerFreezeState;
|
||||
|
||||
public bool IsGLTimerFroze() {
|
||||
return GLTimerFreezeState > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs
Normal file
17
Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct NINGauge {
|
||||
[FieldOffset(0)] public int HutonTimeLeft;
|
||||
[FieldOffset(4)] public byte TCJMudrasUsed; //some sort of mask
|
||||
[FieldOffset(5)] public byte Ninki;
|
||||
[FieldOffset(6)] public byte NumHutonManualCasts; //wtf
|
||||
}
|
||||
}
|
||||
14
Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs
Normal file
14
Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct PLDGauge {
|
||||
[FieldOffset(0)] public byte GaugeAmount;
|
||||
}
|
||||
}
|
||||
15
Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs
Normal file
15
Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct RDMGauge {
|
||||
[FieldOffset(0)] public byte WhiteGauge;
|
||||
[FieldOffset(1)] public byte BlackGauge;
|
||||
}
|
||||
}
|
||||
16
Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs
Normal file
16
Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct SAMGauge {
|
||||
|
||||
[FieldOffset(3)] public byte Kenki;
|
||||
[FieldOffset(4)] public Sen Sen;
|
||||
}
|
||||
}
|
||||
17
Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs
Normal file
17
Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct SCHGauge {
|
||||
[FieldOffset(2)] public byte NumAetherflowStacks;
|
||||
[FieldOffset(3)] public byte FairyGaugeAmount;
|
||||
[FieldOffset(4)] public short SeraphTimer;
|
||||
[FieldOffset(6)] public DismissedFairy DismissedFairy;
|
||||
}
|
||||
}
|
||||
31
Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs
Normal file
31
Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct SMNGauge {
|
||||
|
||||
//Unfinished
|
||||
[FieldOffset(0)] public short TimerRemaining;
|
||||
[FieldOffset(2)] public SummonPet ReturnSummon;
|
||||
[FieldOffset(3)] public PetGlam ReturnSummonGlam;
|
||||
[FieldOffset(4)] public byte NumStacks;
|
||||
|
||||
public bool IsPhoenixReady() {
|
||||
return (NumStacks & 0x10) > 0;
|
||||
}
|
||||
|
||||
public bool IsBahamutReady() {
|
||||
return (NumStacks & 8) > 0;
|
||||
}
|
||||
|
||||
public bool HasAetherflowStacks() {
|
||||
return (NumStacks & 3) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs
Normal file
14
Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct WARGauge {
|
||||
[FieldOffset(0)] public byte BeastGaugeAmount;
|
||||
}
|
||||
}
|
||||
16
Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs
Normal file
16
Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct WHMGauge {
|
||||
[FieldOffset(2)] public short LilyTimer; //Counts to 30k = 30s
|
||||
[FieldOffset(4)] public byte NumLilies;
|
||||
[FieldOffset(5)] public byte NumBloodLily;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Settings;
|
||||
using Dalamud.Game.Internal.Gui;
|
||||
using Dalamud.Game.Internal.Libc;
|
||||
using Dalamud.Game.Internal.Network;
|
||||
|
|
@ -56,7 +55,7 @@ namespace Dalamud.Game.Internal {
|
|||
|
||||
Network = new GameNetwork(dalamud, scanner);
|
||||
|
||||
Resource = new ResourceManager(dalamud, scanner);
|
||||
//Resource = new ResourceManager(dalamud, scanner);
|
||||
}
|
||||
|
||||
private void HookVTable() {
|
||||
|
|
@ -100,7 +99,7 @@ namespace Dalamud.Game.Internal {
|
|||
} catch (Exception ex) {
|
||||
Log.Error(ex, "Exception while dispatching Framework::Update event.");
|
||||
}
|
||||
|
||||
|
||||
return this.updateHook.Original(framework);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
862
Dalamud/Game/Internal/Gui/IconReplacer.cs
Normal file
862
Dalamud/Game/Internal/Gui/IconReplacer.cs
Normal file
|
|
@ -0,0 +1,862 @@
|
|||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Actors.Types;
|
||||
using Dalamud.Game.ClientState.Structs.JobGauge;
|
||||
using Dalamud.Hooking;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using XIVLauncher.Dalamud;
|
||||
|
||||
namespace Dalamud.Game.Internal.Gui {
|
||||
public class IconReplacer {
|
||||
public delegate ulong OnGetIconDelegate(byte param1, uint param2);
|
||||
public delegate ulong OnCheckIsIconReplaceableDelegate(int actionID);
|
||||
|
||||
private Hook<OnGetIconDelegate> iconHook;
|
||||
private Hook<OnCheckIsIconReplaceableDelegate> checkerHook;
|
||||
|
||||
private IconReplacerAddressResolver Address;
|
||||
|
||||
private IntPtr comboTimer;
|
||||
private IntPtr lastComboMove;
|
||||
private IntPtr activeBuffArray = IntPtr.Zero;
|
||||
private IntPtr jobInfo;
|
||||
private IntPtr byteBase;
|
||||
private Dalamud dalamud;
|
||||
private PlayerCharacter localCharacter = null;
|
||||
|
||||
public unsafe IconReplacer(Dalamud dalamud, SigScanner scanner) {
|
||||
this.dalamud = dalamud;
|
||||
this.Address = new IconReplacerAddressResolver();
|
||||
this.Address.Setup(scanner);
|
||||
|
||||
this.byteBase = scanner.Module.BaseAddress;
|
||||
this.comboTimer = byteBase + 0x1BB5B50;
|
||||
this.lastComboMove = byteBase + 0x1BB5B54;
|
||||
|
||||
Log.Verbose("===== H O T B A R S =====");
|
||||
Log.Verbose("IsIconReplaceable address {IsIconReplaceable}", Address.IsIconReplaceable);
|
||||
Log.Verbose("GetIcon address {GetIcon}", Address.GetIcon);
|
||||
|
||||
this.iconHook = new Hook<OnGetIconDelegate>(this.Address.GetIcon, new OnGetIconDelegate(GetIconDetour), this);
|
||||
this.checkerHook = new Hook<OnCheckIsIconReplaceableDelegate>(this.Address.IsIconReplaceable, new OnCheckIsIconReplaceableDelegate(CheckIsIconReplaceableDetour), this);
|
||||
}
|
||||
|
||||
public void Enable() {
|
||||
this.iconHook.Enable();
|
||||
this.checkerHook.Enable();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
this.iconHook.Dispose();
|
||||
this.checkerHook.Dispose();
|
||||
}
|
||||
|
||||
// I hate this function. This is the dumbest function to exist in the game. Just return 1.
|
||||
// Determines which abilities are allowed to have their icons updated.
|
||||
private ulong CheckIsIconReplaceableDetour(int actionID) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace an ability with another ability
|
||||
/// actionID is the original ability to be "used"
|
||||
/// Return either actionID (itself) or a new Action table ID as the
|
||||
/// ability to take its place.
|
||||
/// I tend to make the "combo chain" button be the last move in the combo
|
||||
/// For example, Souleater combo on DRK happens by dragging Souleater
|
||||
/// onto your bar and mashing it.
|
||||
/// </summary>
|
||||
private unsafe ulong GetIconDetour(byte self, uint actionID) {
|
||||
|
||||
// TODO: More jobs, level checking for everything.
|
||||
|
||||
// Check if player is loaded in by trying to get their buffs.
|
||||
// If not, skip everything until we are (game will crash cause I'm lazy).
|
||||
if (activeBuffArray == IntPtr.Zero) {
|
||||
try {
|
||||
activeBuffArray = FindBuffAddress();
|
||||
Log.Verbose("ActiveBuffArray address: {ActiveBuffArray}", activeBuffArray);
|
||||
}
|
||||
catch (Exception e) {
|
||||
activeBuffArray = IntPtr.Zero;
|
||||
return this.iconHook.Original(self, actionID);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this is currently broken
|
||||
// As it stands, don't rely on localCharacter.level for anything.
|
||||
/*
|
||||
if (localCharacter == null) {
|
||||
try {
|
||||
localCharacter = dalamud.ClientState.LocalPlayer;
|
||||
}
|
||||
catch(Exception e) {
|
||||
localCharacter = null;
|
||||
return this.iconHook.Original(self, actionID);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Don't clutter the spaghetti any worse than it already is.
|
||||
int lastMove = Marshal.ReadInt32(lastComboMove);
|
||||
float comboTime = (float)Marshal.ReadInt32(comboTimer);
|
||||
//localCharacter = dalamud.ClientState.LocalPlayer;
|
||||
//byte level = localCharacter.Level;
|
||||
byte level = 80;
|
||||
|
||||
// DRAGOON
|
||||
// TODO: Jump/High Jump into Mirage Dive
|
||||
|
||||
// Replace Coerthan Torment with Coerthan Torment combo chain
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) {
|
||||
if (actionID == 16477) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 86 && level >= 62) return 7397;
|
||||
if (lastMove == 7397 && level >= 72) return 16477;
|
||||
}
|
||||
return 86;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Replace Chaos Thrust with the Chaos Thrust combo chain
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonChaosThrustCombo)) {
|
||||
if (actionID == 88) {
|
||||
if (comboTime > 0) {
|
||||
if ((lastMove == 75 || lastMove == 16479) && level >= 18) return 87;
|
||||
if (lastMove == 87 && level >= 50) return 88;
|
||||
}
|
||||
if (SearchBuffArray(802) && level >= 56) return 3554;
|
||||
if (SearchBuffArray(803) && level >= 58) return 3556;
|
||||
if (SearchBuffArray(1863) && level >= 76) return 16479;
|
||||
|
||||
return 75;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Replace Full Thrust with the Full Thrust combo chain
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonFullThrustCombo)) {
|
||||
if (actionID == 84) {
|
||||
if (comboTime > 0) {
|
||||
if ((lastMove == 75 || lastMove == 16479) && level >= 4) return 78;
|
||||
if (lastMove == 78 && level >= 26) return 84;
|
||||
}
|
||||
if (SearchBuffArray(802) && level >= 56) return 3554;
|
||||
if (SearchBuffArray(803) && level >= 58) return 3556;
|
||||
if (SearchBuffArray(1863) && level >= 76) return 16479;
|
||||
|
||||
return 75;
|
||||
}
|
||||
}
|
||||
|
||||
// DARK KNIGHT
|
||||
|
||||
// Replace Souleater with Souleater combo chain
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkSouleaterCombo)) {
|
||||
if (actionID == 3632) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 3617 && level >= 2) return 3623;
|
||||
if (lastMove == 3623 && level >= 26) return 3632;
|
||||
}
|
||||
|
||||
return 3617;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Stalwart Soul with Stalwart Soul combo chain
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkStalwartSoulCombo)) {
|
||||
if (actionID == 16468) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 3621 && level >= 72) return 16468;
|
||||
}
|
||||
|
||||
return 3621;
|
||||
}
|
||||
}
|
||||
|
||||
// PALADIN
|
||||
|
||||
// Replace Goring Blade with Goring Blade combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinGoringBladeCombo)) {
|
||||
if (actionID == 3538) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 9 && level >= 4) return 15;
|
||||
if (lastMove == 15 && level >= 54) return 3538;
|
||||
}
|
||||
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Royal Authority with Royal Authority combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinRoyalAuthorityCombo)) {
|
||||
if (actionID == 3539) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 9 && level >= 4) return 15;
|
||||
if (lastMove == 15) {
|
||||
if (level >= 60) return 3539;
|
||||
if (level >= 26) return 21;
|
||||
}
|
||||
}
|
||||
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Prominence with Prominence combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinProminenceCombo)) {
|
||||
if (actionID == 16457) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7381 && level >= 40) return 16457;
|
||||
}
|
||||
|
||||
return 7381;
|
||||
}
|
||||
}
|
||||
|
||||
// WARRIOR
|
||||
|
||||
// Replace Storm's Path with Storm's Path combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsPathCombo)) {
|
||||
if (actionID == 42) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 31 && level >= 4) return 37;
|
||||
if (lastMove == 37 && level >= 26) return 42;
|
||||
}
|
||||
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Storm's Eye with Storm's Eye combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsEyeCombo)) {
|
||||
if (actionID == 45) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 31 && level >= 4) return 37;
|
||||
if (lastMove == 37 && level >= 50) return 45;
|
||||
}
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Mythril Tempest with Mythril Tempest combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorMythrilTempestCombo)) {
|
||||
if (actionID == 16462) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 41 && level >= 40) return 16462;
|
||||
}
|
||||
return 41;
|
||||
}
|
||||
}
|
||||
|
||||
// SAMURAI
|
||||
|
||||
// Replace Yukikaze with Yukikaze combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiYukikazeCombo)) {
|
||||
if (actionID == 7480) {
|
||||
if (SearchBuffArray(1233)) return 7480;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7477 && level >= 50) return 7480;
|
||||
}
|
||||
return 7477;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Gekko with Gekko combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiGekkoCombo)) {
|
||||
if (actionID == 7481) {
|
||||
if (SearchBuffArray(1233)) return 7481;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7477 && level >= 4) return 7478;
|
||||
if (lastMove == 7478 && level >= 30) return 7481;
|
||||
}
|
||||
return 7477;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Kasha with Kasha combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiKashaCombo)) {
|
||||
if (actionID == 7482) {
|
||||
if (SearchBuffArray(1233)) return 7482;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7477 && level >= 18) return 7479;
|
||||
if (lastMove == 7479 && level >= 40) return 7482;
|
||||
}
|
||||
return 7477;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Mangetsu with Mangetsu combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiMangetsuCombo)) {
|
||||
if (actionID == 7484) {
|
||||
if (SearchBuffArray(1233)) return 7484;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7483 && level >= 35) return 7484;
|
||||
}
|
||||
return 7483;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Oka with Oka combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiOkaCombo)) {
|
||||
if (actionID == 7485) {
|
||||
if (SearchBuffArray(1233)) return 7485;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 7483 && level >= 45) return 7485;
|
||||
}
|
||||
return 7483;
|
||||
}
|
||||
}
|
||||
|
||||
// NINJA
|
||||
|
||||
// Replace Armor Crush with Armor Crush combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) {
|
||||
if (actionID == 3563) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 2240 && level >= 4) return 2242;
|
||||
if (lastMove == 2242 && level >= 54) return 3563;
|
||||
}
|
||||
return 2240;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Aeolian Edge with Aeolian Edge combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) {
|
||||
if (actionID == 2255) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 2240 && level >= 4) return 2242;
|
||||
if (lastMove == 2242 && level >= 26) return 2255;
|
||||
}
|
||||
return 2240;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Hakke Mujinsatsu with Hakke Mujinsatsu combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaHakkeMujinsatsuCombo)) {
|
||||
if (actionID == 16488) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 2254 && level >= 52) return 16488;
|
||||
}
|
||||
return 2254;
|
||||
}
|
||||
}
|
||||
|
||||
// GUNBREAKER
|
||||
|
||||
// Replace Solid Barrel with Solid Barrel combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerSolidBarrelCombo)) {
|
||||
if (actionID == 16145) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 16137 && level >= 4) return 16139;
|
||||
if (lastMove == 16139 && level >= 26) return 16145;
|
||||
}
|
||||
return 16137;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Gnashing Fang with Gnashing Fang combo
|
||||
// TODO: Potentially add Contuation moves as well?
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) {
|
||||
if (actionID == 16146) {
|
||||
byte ammoComboState = this.dalamud.ClientState.JobGauges.Get<GNBGauge>().AmmoComboStepNumber;
|
||||
if (ammoComboState == 1) return 16147;
|
||||
if (ammoComboState == 2) return 16150;
|
||||
return 16146;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Demon Slaughter with Demon Slaughter combo
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerDemonSlaughterCombo)) {
|
||||
if (actionID == 16149) {
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 16141 && level >= 40) return 16149;
|
||||
}
|
||||
return 16141;
|
||||
}
|
||||
}
|
||||
|
||||
// MACHINIST
|
||||
|
||||
// Replace Heated 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) {
|
||||
MCHGauge gauge = this.dalamud.ClientState.JobGauges.Get<MCHGauge>();
|
||||
// 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;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 2866) {
|
||||
if (level >= 60) return 7412;
|
||||
if (level >= 2) return 2868;
|
||||
}
|
||||
if (lastMove == 2868) {
|
||||
if (level >= 64) return 7413;
|
||||
if (level >= 26) return 2873;
|
||||
}
|
||||
}
|
||||
return 7411;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Spread Shot with Auto Crossbow when overheated.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistSpreadShotFeature)) {
|
||||
if (actionID == 2870) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<MCHGauge>().IsOverheated() && level >= 52) return 16497;
|
||||
return 2870;
|
||||
}
|
||||
}
|
||||
|
||||
// BLACK MAGE
|
||||
|
||||
// Enochian changes to B4 or F4 depending on stance.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackEnochianFeature)) {
|
||||
if (actionID == 3575) {
|
||||
BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get<BLMGauge>();
|
||||
if (jobInfo.IsEnoActive()) {
|
||||
if (jobInfo.InUmbralIce() && level >= 58) return 3576;
|
||||
if (level >= 60) return 3577;
|
||||
}
|
||||
return 3575;
|
||||
}
|
||||
}
|
||||
|
||||
// Umbral Soul and Transpose
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackManaFeature)) {
|
||||
if (actionID == 149) {
|
||||
BLMGauge gauge = this.dalamud.ClientState.JobGauges.Get<BLMGauge>();
|
||||
if (gauge.InUmbralIce() && gauge.IsEnoActive() && level >= 76) return 16506;
|
||||
return 149;
|
||||
}
|
||||
}
|
||||
|
||||
// ASTROLOGIAN
|
||||
|
||||
// Make cards on the same button as play
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.AstrologianCardsOnDrawFeature)) {
|
||||
if (actionID == 17055) {
|
||||
ASTGauge gauge = this.dalamud.ClientState.JobGauges.Get<ASTGauge>();
|
||||
switch (gauge.DrawnCard()) {
|
||||
case CardType.BALANCE:
|
||||
return 4401;
|
||||
case CardType.BOLE:
|
||||
return 4404;
|
||||
case CardType.ARROW:
|
||||
return 4402;
|
||||
case CardType.SPEAR:
|
||||
return 4403;
|
||||
case CardType.EWER:
|
||||
return 4405;
|
||||
case CardType.SPIRE:
|
||||
return 4406;
|
||||
/*
|
||||
case CardType.LORD:
|
||||
return 7444;
|
||||
case CardType.LADY:
|
||||
return 7445;
|
||||
*/
|
||||
default:
|
||||
return 3590;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SUMMONER
|
||||
|
||||
// DWT changes.
|
||||
// Now contains DWT, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.
|
||||
// What a monster of a button.
|
||||
/*
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDwtCombo)) {
|
||||
if (actionID == 3581) {
|
||||
SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get<SMNGauge>();
|
||||
if (gauge.TimerRemaining > 0) {
|
||||
if (gauge.ReturnSummon > 0) {
|
||||
if (gauge.IsPhoenixReady()) return 16516;
|
||||
return 7429;
|
||||
}
|
||||
if (level >= 60) return 3582;
|
||||
}
|
||||
else {
|
||||
if (gauge.IsBahamutReady()) return 7427;
|
||||
if (gauge.IsPhoenixReady()) return 16513;
|
||||
return 3581;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDemiCombo)) {
|
||||
// Replace Deathflare with demi enkindles
|
||||
if (actionID == 3582) {
|
||||
SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get<SMNGauge>();
|
||||
if (gauge.IsPhoenixReady()) return 16516;
|
||||
if (gauge.TimerRemaining > 0 && gauge.ReturnSummon != SummonPet.NONE) return 7429;
|
||||
return 3582;
|
||||
}
|
||||
|
||||
//Replace DWT with demi summons
|
||||
if (actionID == 3581) {
|
||||
SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get<SMNGauge>();
|
||||
if (gauge.IsBahamutReady()) return 7427;
|
||||
if (gauge.IsPhoenixReady() ||
|
||||
(gauge.TimerRemaining > 0 && gauge.ReturnSummon != SummonPet.NONE)) return 16513;
|
||||
return 3581;
|
||||
}
|
||||
}
|
||||
|
||||
// Ruin 1 now upgrades to Brand of Purgatory in addition to Ruin 3 and Fountain of Fire
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerBoPCombo)) {
|
||||
if (actionID == 163) {
|
||||
SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get<SMNGauge>();
|
||||
if (gauge.TimerRemaining > 0) {
|
||||
if (gauge.IsPhoenixReady()) {
|
||||
if (SearchBuffArray(1867)) {
|
||||
return 16515;
|
||||
}
|
||||
return 16514;
|
||||
}
|
||||
}
|
||||
if (level >= 54) return 3579;
|
||||
return 163;
|
||||
}
|
||||
}
|
||||
|
||||
// Change Energy Drain into Fester
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerEDFesterCombo)) {
|
||||
if (actionID == 16508) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<SMNGauge>().HasAetherflowStacks())
|
||||
return 181;
|
||||
return 16508;
|
||||
}
|
||||
}
|
||||
|
||||
//Change Energy Siphon into Painflare
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerESPainflareCombo)) {
|
||||
if (actionID == 16510) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<SMNGauge>().HasAetherflowStacks())
|
||||
if (level >= 52) return 3578;
|
||||
return 16510;
|
||||
}
|
||||
}
|
||||
|
||||
// SCHOLAR
|
||||
|
||||
// Change Fey Blessing into Consolation when Seraph is out.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarSeraphConsolationFeature)) {
|
||||
if (actionID == 16543) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<SCHGauge>().SeraphTimer > 0) return 16546;
|
||||
return 16543;
|
||||
}
|
||||
}
|
||||
|
||||
// Change Energy Drain into Aetherflow when you have no more Aetherflow stacks.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarEnergyDrainFeature)) {
|
||||
if (actionID == 167) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<SCHGauge>().NumAetherflowStacks == 0) return 166;
|
||||
return 167;
|
||||
}
|
||||
}
|
||||
|
||||
// DANCER
|
||||
|
||||
/*
|
||||
|
||||
// Standard Step is one button.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) {
|
||||
if (actionID == 15997) {
|
||||
DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get<DNCGauge>();
|
||||
if (gauge.IsDancing()) {
|
||||
if (gauge.NumCompleteSteps == 2) {
|
||||
return 16192;
|
||||
}
|
||||
else {
|
||||
// C# can't implicitly cast from int to ulong.
|
||||
return gauge.NextStep();
|
||||
}
|
||||
}
|
||||
return 15997;
|
||||
}
|
||||
}
|
||||
|
||||
// Technical Step is one button.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerTechnicalStepCombo)) {
|
||||
if (actionID == 15998) {
|
||||
DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get<DNCGauge>();
|
||||
if (gauge.IsDancing()) {
|
||||
if (gauge.NumCompleteSteps == 4) {
|
||||
return 16196;
|
||||
}
|
||||
else {
|
||||
// C# can't implicitly cast from int to ulong.
|
||||
return gauge.NextStep();
|
||||
}
|
||||
}
|
||||
return 15998;
|
||||
}
|
||||
}
|
||||
|
||||
// Fountain changes into Fountain combo, prioritizing procs over combo,
|
||||
// and Fountainfall over Reverse Cascade.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFountainCombo)) {
|
||||
if (actionID == 15990) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<DNCGauge>().IsDancing()) return 15999;
|
||||
if (SearchBuffArray(1815)) return 15992;
|
||||
if (SearchBuffArray(1814)) return 15991;
|
||||
if (comboTime > 0) {
|
||||
if (lastMove == 15989 && level >= 2) return 15990;
|
||||
}
|
||||
return 15989;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// AoE GCDs are split into two buttons, because priority matters
|
||||
// differently in different single-target moments. Thanks yoship.
|
||||
// Replaces each GCD with its procced version.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerAoeGcdFeature)) {
|
||||
if (actionID == 15994) {
|
||||
if (SearchBuffArray(1817)) return 15996;
|
||||
return 15994;
|
||||
}
|
||||
|
||||
if (actionID == 15993) {
|
||||
if (SearchBuffArray(1816)) return 15995;
|
||||
return 15993;
|
||||
}
|
||||
}
|
||||
|
||||
// Fan Dance changes into Fan Dance 3 while flourishing.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFanDanceCombo)) {
|
||||
if (actionID == 16007) {
|
||||
if (SearchBuffArray(1820)) return 16009;
|
||||
|
||||
return 16007;
|
||||
}
|
||||
|
||||
// Fan Dance 2 changes into Fan Dance 3 while flourishing.
|
||||
if (actionID == 16008) {
|
||||
if (SearchBuffArray(1820)) return 16009;
|
||||
return 16008;
|
||||
}
|
||||
}
|
||||
|
||||
// WHM
|
||||
|
||||
// Replace Solace with Misery when full blood lily
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WhiteMageSolaceMiseryFeature)) {
|
||||
if (actionID == 16531) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<WHMGauge>().NumBloodLily == 3)
|
||||
return 16535;
|
||||
return 16531;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Solace with Misery when full blood lily
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WhiteMageRaptureMiseryFeature)) {
|
||||
if (actionID == 16534) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<WHMGauge>().NumBloodLily == 3)
|
||||
return 16535;
|
||||
return 16534;
|
||||
}
|
||||
}
|
||||
|
||||
// BARD
|
||||
|
||||
// Replace Wanderer's Minuet with PP when in WM.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BardWandererPPFeature)) {
|
||||
if (actionID == 3559) {
|
||||
if (this.dalamud.ClientState.JobGauges.Get<BRDGauge>().ActiveSong == CurrentSong.WANDERER) {
|
||||
return 7404;
|
||||
}
|
||||
return 3559;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace HS/BS with SS/RA when procced.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BardStraightShotUpgradeFeature)) {
|
||||
if (actionID == 97) {
|
||||
if (SearchBuffArray(122)) {
|
||||
if (level >= 70) return 7409;
|
||||
return 98;
|
||||
}
|
||||
if (level >= 76) return 16495;
|
||||
return 97;
|
||||
}
|
||||
}
|
||||
|
||||
// MONK
|
||||
|
||||
/*
|
||||
|
||||
// Replace Snap Punch with flank positional combo.
|
||||
// During PB, Snap (with sub-max stacks) > Twin (with no active Twin) > DK
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkFlankCombo)) {
|
||||
if (actionID == 56) {
|
||||
if (SearchBuffArray(110)) {
|
||||
MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get<MNKGauge>();
|
||||
if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) {
|
||||
return 56;
|
||||
}
|
||||
else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) {
|
||||
return 56;
|
||||
}
|
||||
else if (!SearchBuffArray(101)) return 61;
|
||||
else return 74;
|
||||
}
|
||||
else {
|
||||
if (SearchBuffArray(107) && level >= 50) return 74;
|
||||
if (SearchBuffArray(108) && level >= 18) return 61;
|
||||
if (SearchBuffArray(109) && level >= 6) return 56;
|
||||
return 74;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Demolish with rear positional combo.
|
||||
// During PB, Demo (with sub-max stacks) > Bootshine.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkRearCombo)) {
|
||||
if (actionID == 66) {
|
||||
if (SearchBuffArray(110)) {
|
||||
MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get<MNKGauge>();
|
||||
if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) {
|
||||
return 66;
|
||||
}
|
||||
else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) {
|
||||
return 66;
|
||||
}
|
||||
else return 53;
|
||||
}
|
||||
else {
|
||||
if (SearchBuffArray(107)) return 53;
|
||||
if (SearchBuffArray(108) && level >= 4) return 54;
|
||||
if (SearchBuffArray(109) && level >= 30) return 66;
|
||||
return 53;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Rockbreaker with AoE combo.
|
||||
// During PB, RB (with sub-max stacks) > Twin Snakes (if not applied) > RB.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkAoECombo)) {
|
||||
if (actionID == 70) {
|
||||
if (SearchBuffArray(110)) {
|
||||
MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get<MNKGauge>();
|
||||
if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) {
|
||||
return 70;
|
||||
}
|
||||
else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) {
|
||||
return 70;
|
||||
}
|
||||
else if (!SearchBuffArray(101)) return 61;
|
||||
else return 70;
|
||||
}
|
||||
else {
|
||||
if (SearchBuffArray(107)) return 62;
|
||||
if (SearchBuffArray(108)) {
|
||||
if (!SearchBuffArray(101)) return 61;
|
||||
if (level >= 45) return 16473;
|
||||
}
|
||||
if (SearchBuffArray(109) && level >= 30) return 70;
|
||||
return 62;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// RED MAGE
|
||||
|
||||
/*
|
||||
|
||||
// Replace Verstone with White Magic spells. Priority order:
|
||||
// Scorch > Verholy > Verstone = Veraero (with Dualcast active) > opener Veraero > Jolt
|
||||
// Impact is not the first available spell to allow for precast openers.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageWhiteMagicFeature)) {
|
||||
if (actionID == 7511) {
|
||||
if ((lastMove == 7526 || lastMove == 7525) && level >= 80) return 16530;
|
||||
if (lastMove == 7529 && level >= 70) return 7526;
|
||||
if ((SearchBuffArray(1249) || SearchBuffArray(167)) && level >= 10) return 7507;
|
||||
if (SearchBuffArray(1235) && level >= 30) return 7511;
|
||||
RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get<RDMGauge>();
|
||||
if ((gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) && level >= 10) return 7507;
|
||||
if (level >= 62) return 7524;
|
||||
return 7503;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace Verfire with Black Magic spells. Priority order:
|
||||
// Scorch > Verflare> Verfire = Verthunder (with Dualcast active) > opener Verthunder > Jolt
|
||||
// Impact is not the first available spell to allow for precast openers.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageBlackMagicFeature)) {
|
||||
if (actionID == 7510) {
|
||||
if ((lastMove == 7526 || lastMove == 7525) && level >= 80) return 16530;
|
||||
if (lastMove == 7529 && level >= 68) return 7525;
|
||||
if ((SearchBuffArray(1249) || SearchBuffArray(167)) && level >= 4) return 7505;
|
||||
if (SearchBuffArray(1234) && level >= 26) return 7510;
|
||||
RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get<RDMGauge>();
|
||||
if ((gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) && level >= 4) return 7505;
|
||||
if (level >= 62) return 7524;
|
||||
return 7503;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Replace Veraero/thunder 2 with Impact when Dualcast is active
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageAoECombo)) {
|
||||
if (actionID == 16525) {
|
||||
if (level >= 66 && (SearchBuffArray(1249) || SearchBuffArray(167))) return 16526;
|
||||
return 16525;
|
||||
}
|
||||
|
||||
if (actionID == 16524) {
|
||||
if (level >= 66 && (SearchBuffArray(1249) || SearchBuffArray(167))) return 16526;
|
||||
return 16524;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Replace Redoublement with Redoublement combo, Enchanted if possible.
|
||||
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageMeleeCombo)) {
|
||||
if (actionID == 7516) {
|
||||
RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get<RDMGauge>();
|
||||
if ((lastMove == 7504 || lastMove == 7527) && level >= 35) {
|
||||
if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7528;
|
||||
return 7512;
|
||||
}
|
||||
if (lastMove == 7512 && level >= 50) {
|
||||
if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7529;
|
||||
return 7516;
|
||||
}
|
||||
if (gauge.BlackGauge >= 30 && gauge.WhiteGauge >= 30) return 7527;
|
||||
return 7516;
|
||||
}
|
||||
}
|
||||
|
||||
return this.iconHook.Original(self, actionID);
|
||||
}
|
||||
|
||||
private bool SearchBuffArray(short needle) {
|
||||
for (int i = 0; i < 60; i++) {
|
||||
if (Marshal.ReadInt16(activeBuffArray + 4 * i) == needle) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe delegate int* getArray(long* address);
|
||||
|
||||
private unsafe IntPtr FindBuffAddress() {
|
||||
IntPtr randomAddress = byteBase + 0x1c04be0;
|
||||
IntPtr num = Marshal.ReadIntPtr(randomAddress);
|
||||
IntPtr step2 = (IntPtr)(Marshal.ReadInt64(num) + 0x248);
|
||||
IntPtr step3 = Marshal.ReadIntPtr(step2);
|
||||
var callback = Marshal.GetDelegateForFunctionPointer<getArray>(step3);
|
||||
return (IntPtr)callback((long*)num);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs
Normal file
17
Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.Internal.Gui {
|
||||
class IconReplacerAddressResolver : BaseAddressResolver {
|
||||
public IntPtr GetIcon { get; private set; }
|
||||
public IntPtr IsIconReplaceable { get; private set; }
|
||||
|
||||
protected override void Setup64Bit(SigScanner sig) {
|
||||
this.GetIcon = sig.ScanText("48 89 5c 24 08 48 89 6c 24 10 48 89 74 24 18 57 48 83 ec 30 8b da be dd 1c 00 00 bd d3 0d 00 00");
|
||||
this.IsIconReplaceable = sig.ScanText("81 f9 2e 01 00 00 7f 39 81 f9 2d 01 00 00 0f 8d 11 02 00 00 83 c1 eb");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
|||
using Dalamud.Game.Network.MarketBoardUploaders;
|
||||
using Dalamud.Game.Network.Structures;
|
||||
using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
|
||||
using Dalamud.Settings;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Network {
|
||||
|
|
@ -46,14 +45,14 @@ namespace Dalamud.Game.Network {
|
|||
}
|
||||
|
||||
if (opCode == ZoneOpCode.FateSpawn) {
|
||||
if (PersistentSettings.Instance.Fates == null)
|
||||
if (this.dalamud.Configuration.Fates == null)
|
||||
return;
|
||||
|
||||
var data = new byte[64];
|
||||
Marshal.Copy(dataPtr, data, 0, 64);
|
||||
|
||||
var fateId = data[16];
|
||||
if (PersistentSettings.Instance.Fates.Any(x => x.Id == fateId) &&
|
||||
if (this.dalamud.Configuration.Fates.Any(x => x.Id == fateId) &&
|
||||
this.dalamud.BotManager.IsConnected)
|
||||
Task.Run(() => this.dalamud.BotManager.ProcessFate(fateId));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Settings
|
||||
{
|
||||
public class PersistentSettings {
|
||||
private static PersistentSettings _instance = null;
|
||||
|
||||
private static readonly string ConfigPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "settings.json");
|
||||
|
||||
public static PersistentSettings Instance {
|
||||
get {
|
||||
if (_instance == null) {
|
||||
if (!File.Exists(ConfigPath)) {
|
||||
_instance = new PersistentSettings();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
_instance = JsonConvert.DeserializeObject<PersistentSettings>(File.ReadAllText(ConfigPath));
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public class FateInfo {
|
||||
public string Name { get; set; }
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
public List<FateInfo> Fates;
|
||||
|
||||
public List<string> BadWords;
|
||||
|
||||
public void Save() {
|
||||
File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(this));
|
||||
}
|
||||
|
||||
public static void Reset() {
|
||||
_instance = new PersistentSettings();
|
||||
Instance.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue