5 Commits

Author SHA1 Message Date
KnackAtNite dd3f464860 v0.0.3.11: Separate Player AutoAttack Dealt and Taken config
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled
Release Build and Publish / Release Build against Staging Dalamud and deploy to MyDalamudPlugins (release) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 23:08:45 -05:00
KnackAtNite 496137b293 Bump version to 0.0.3.10
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled
Release Build and Publish / Release Build against Staging Dalamud and deploy to MyDalamudPlugins (release) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 22:45:00 -05:00
KnackAtNite 67ccf6c413 Separate Player Damage Dealt and Player Damage Taken configuration
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 22:42:23 -05:00
KnackAtNite 3bc13734d5 Allow icon size up to 64 (was 32), bump to 0.0.3.9
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled
Release Build and Publish / Release Build against Staging Dalamud and deploy to MyDalamudPlugins (release) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 14:25:01 -05:00
KnackAtNite 743bb74bd5 Extend font size range to 14-64 (was 14-32), bump to 0.0.3.8
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled
Release Build and Publish / Release Build against Staging Dalamud and deploy to MyDalamudPlugins (release) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 14:16:43 -05:00
10 changed files with 245 additions and 26 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<Authors>cultbaus</Authors>
<Company>-</Company>
<Version>0.0.3.7</Version>
<Version>0.0.3.11</Version>
<Description>This plugin manipulates flytext.</Description>
<Copyright>-</Copyright>
<PackageProjectUrl>https://github.com/cultbaus/CBT</PackageProjectUrl>
+18 -7
View File
@@ -3,6 +3,7 @@ namespace CBT.FlyText.Animations;
using System;
using System.Numerics;
using CBT.FlyText.Configuration;
using CBT.Types;
using FFXIVClientStructs;
@@ -53,29 +54,35 @@ public enum FlyTextAlignment
/// </summary>
public abstract class FlyTextAnimation
{
/// <summary>
/// When set, animation properties (Duration, Speed, Reversed, Alignment) are read from this config instead of FlyTextKinds.
/// Used for Player Damage Taken so it can have different animation settings than Dealt.
/// </summary>
internal FlyTextConfiguration? EventConfig { get; set; }
/// <summary>
/// Gets the Animation duration.
/// </summary>
public float Duration
=> Service.Configuration.FlyTextKinds[this.FlyTextKind].Animation.Duration;
=> (this.EventConfig ?? Service.Configuration.FlyTextKinds[this.FlyTextKind]).Animation.Duration;
/// <summary>
/// Gets the Animation speed.
/// </summary>
public float Speed
=> Service.Configuration.FlyTextKinds[this.FlyTextKind].Animation.Speed;
=> (this.EventConfig ?? Service.Configuration.FlyTextKinds[this.FlyTextKind]).Animation.Speed;
/// <summary>
/// Gets a value indicating whether the animation direction should be reversed.
/// </summary>
public bool Reversed
=> Service.Configuration.FlyTextKinds[this.FlyTextKind].Animation.Reversed;
=> (this.EventConfig ?? Service.Configuration.FlyTextKinds[this.FlyTextKind]).Animation.Reversed;
/// <summary>
/// Gets the alignment of an element.
/// </summary>
public FlyTextAlignment Alignment
=> Service.Configuration.FlyTextKinds[this.FlyTextKind].Animation.Alignment;
=> (this.EventConfig ?? Service.Configuration.FlyTextKinds[this.FlyTextKind]).Animation.Alignment;
/// <summary>
/// Gets or sets the FlyAnimationKind.
@@ -126,17 +133,21 @@ public abstract class FlyTextAnimation
/// Create an instance of a FlyTextAnimation type.
/// </summary>
/// <param name="flyTextKind">FlyTextKind determines the animation type.</param>
/// <param name="eventConfig">Optional config for this event (e.g. Player Damage Taken). When set, animation reads from this instead of FlyTextKinds.</param>
/// <returns>FlyTextAnimation implementation.</returns>
/// <exception cref="ArgumentOutOfRangeException">Exception thrown when an invalid kind is received.</exception>
public static FlyTextAnimation Create(FlyTextKind flyTextKind)
public static FlyTextAnimation Create(FlyTextKind flyTextKind, FlyTextConfiguration? eventConfig = null)
{
FlyTextAnimationKind animationKind = Service.Configuration.FlyTextKinds[flyTextKind].Animation.Kind;
return animationKind switch
var config = eventConfig ?? Service.Configuration.FlyTextKinds[flyTextKind];
FlyTextAnimationKind animationKind = config.Animation.Kind;
FlyTextAnimation animation = animationKind switch
{
FlyTextAnimationKind.None => new None(flyTextKind),
FlyTextAnimationKind.LinearFade => new LinearFade(flyTextKind),
_ => throw new ArgumentOutOfRangeException(nameof(flyTextKind), animationKind, null),
};
animation.EventConfig = eventConfig;
return animation;
}
/// <summary>
+1 -1
View File
@@ -94,7 +94,7 @@ public unsafe partial class FlyTextReceiver : IDisposable
{
try
{
var kindConfig = PluginManager.GetConfigForKind(kind);
var kindConfig = PluginManager.GetConfigForEvent(kind, source, target);
var effects = GetEffects(target->GetActionEffectHandler());
var sourceObjectID = GetGameObjectId(target->GetActionEffectHandler());
+1 -1
View File
@@ -50,7 +50,7 @@ public class FontManager : IDisposable
.ToList()
.ForEach(file =>
{
Enumerable.Range(14, 32 - 14 + 1)
Enumerable.Range(14, 64 - 14 + 1)
.Where(i => i % 2 == 0)
.ToList()
.ForEach(size =>
+35
View File
@@ -3,6 +3,7 @@ namespace CBT.Interface.Tabs;
using System.Collections.Generic;
using System.Linq;
using CBT.Types;
using Dalamud.Bindings.ImGui;
/// <summary>
/// CatgeoryTab configures settings for FlyTextKinds.
@@ -30,6 +31,40 @@ public class KindTab : Tab
this.DrawCurrentConfigurations(KindPickerValues);
if (this.Current.InCategory(FlyTextCategory.AbilityDamage))
{
GuiArtist.DrawLabelPrefix("Configure for", sameLine: false);
ImGui.SameLine();
var isTaken = this.UsePlayerDamageTakenConfig;
if (ImGui.RadioButton("Player Damage Dealt", !isTaken))
{
this.UsePlayerDamageTakenConfig = false;
}
ImGui.SameLine();
if (ImGui.RadioButton("Player Damage Taken", isTaken))
{
this.UsePlayerDamageTakenConfig = true;
}
}
if (this.Current.InCategory(FlyTextCategory.AutoAttack))
{
GuiArtist.DrawLabelPrefix("Configure for", sameLine: false);
ImGui.SameLine();
var isTaken = this.UsePlayerAutoAttackTakenConfig;
if (ImGui.RadioButton("Player AutoAttack Dealt", !isTaken))
{
this.UsePlayerAutoAttackTakenConfig = false;
}
ImGui.SameLine();
if (ImGui.RadioButton("Player AutoAttack Taken", isTaken))
{
this.UsePlayerAutoAttackTakenConfig = true;
}
}
if (this.CurrentEnabled)
{
this.DrawFontConfigurations();
+40 -6
View File
@@ -27,6 +27,16 @@ public abstract class Tab
/// </summary>
protected abstract FlyTextKind Current { get; set; }
/// <summary>
/// When true and current kind is AbilityDamage, configuration edits apply to Player Damage Taken instead of Dealt.
/// </summary>
protected bool UsePlayerDamageTakenConfig { get; set; }
/// <summary>
/// When true and current kind is AutoAttack, configuration edits apply to Player AutoAttack Taken instead of Dealt.
/// </summary>
protected bool UsePlayerAutoAttackTakenConfig { get; set; }
/// <summary>
/// Gets or sets a value indicating whether.
/// </summary>
@@ -235,6 +245,26 @@ public abstract class Tab
/// </summary>
public abstract void OnClose();
/// <summary>
/// Gets the config dictionary to use for the current kind (FlyTextKinds or the appropriate Player * Taken dict when editing Taken).
/// </summary>
protected Dictionary<FlyTextKind, FlyTextConfiguration> GetCurrentConfigDictionary()
{
if (this.Current.InCategory(FlyTextCategory.AbilityDamage) && this.UsePlayerDamageTakenConfig
&& Service.Configuration.FlyTextKindsPlayerDamageTaken != null)
{
return Service.Configuration.FlyTextKindsPlayerDamageTaken;
}
if (this.Current.InCategory(FlyTextCategory.AutoAttack) && this.UsePlayerAutoAttackTakenConfig
&& Service.Configuration.FlyTextKindsPlayerAutoAttackTaken != null)
{
return Service.Configuration.FlyTextKindsPlayerAutoAttackTaken;
}
return Service.Configuration.FlyTextKinds;
}
/// <summary>
/// Get a configuration value.
/// </summary>
@@ -243,7 +273,8 @@ public abstract class Tab
/// <returns>The value.</returns>
protected T GetValue<T>(Func<FlyTextConfiguration, T> selector)
{
return Service.Configuration.FlyTextKinds.TryGetValue(this.Current, out var currentConfig)
var dict = this.GetCurrentConfigDictionary();
return dict.TryGetValue(this.Current, out var currentConfig)
? selector(currentConfig)
: selector(Service.Configuration.FlyTextKinds[this.Current]);
}
@@ -256,10 +287,13 @@ public abstract class Tab
/// <param name="value">The value to set.</param>
protected void SetValue<T>(Action<FlyTextConfiguration, T> setter, T value)
{
if (!Service.Configuration.FlyTextKinds.TryGetValue(this.Current, out var currentConfig))
var dict = this.GetCurrentConfigDictionary();
if (!dict.TryGetValue(this.Current, out var currentConfig))
{
currentConfig = new FlyTextConfiguration(Service.Configuration.FlyTextKinds[this.Current]);
Service.Configuration.FlyTextKinds[this.Current] = currentConfig;
currentConfig = Service.Configuration.FlyTextKinds.TryGetValue(this.Current, out var baseConfig)
? new FlyTextConfiguration(baseConfig)
: new FlyTextConfiguration();
dict[this.Current] = currentConfig;
}
setter(currentConfig, value);
@@ -281,7 +315,7 @@ public abstract class Tab
if (this.CurrentEnabled)
{
if (Service.Configuration.FlyTextKinds.TryGetValue(this.Current, out var currentConfig))
if (this.GetCurrentConfigDictionary().TryGetValue(this.Current, out var currentConfig))
{
if (this.Current.ShouldAllow(FlyTextFilter.Self))
{
@@ -354,7 +388,7 @@ public abstract class Tab
if (this.CurrentIconEnabled)
{
GuiArtist.DrawLabelPrefix("Select Icon Size", sameLine: false);
GuiArtist.DrawInputInt($"Icon Size_{this.Name}", sameLine: true, (int)this.CurrentIconSize, 14, 32, size => { this.CurrentIconSize = size; });
GuiArtist.DrawInputInt($"Icon Size_{this.Name}", sameLine: true, (int)this.CurrentIconSize, 14, 64, size => { this.CurrentIconSize = size; });
GuiArtist.DrawSubTitle("Icon Outline Configurations");
{
+42
View File
@@ -3,6 +3,8 @@ namespace CBT;
using System.IO;
using System.Reflection;
using CBT.FlyText;
using CBT.FlyText.Configuration;
using CBT.Types;
using CBT.Helpers;
using CBT.Interface;
using Dalamud.Game;
@@ -54,6 +56,7 @@ public sealed partial class Plugin : IDalamudPlugin
ShowInHelp = true,
});
Service.Configuration = pluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration();
MigratePlayerDamageTakenConfig();
Service.Fonts = new FontManager(Path.GetDirectoryName(assemblyLocation) + "\\Media\\Fonts\\");
Service.Interface.UiBuilder.OpenConfigUi += this.OnOpenConfigUi;
Service.Interface.UiBuilder.OpenMainUi += this.OnOpenConfigUi;
@@ -88,6 +91,45 @@ public sealed partial class Plugin : IDalamudPlugin
private void OnOpenConfigUi()
=> this.configWindow.IsOpen = true;
/// <summary>
/// Migrates existing config: ensures FlyTextKindsPlayerDamageTaken and FlyTextKindsPlayerAutoAttackTaken are populated (e.g. from older saves).
/// </summary>
private static void MigratePlayerDamageTakenConfig()
{
var config = Service.Configuration;
if (config.FlyTextKindsPlayerDamageTaken == null || config.FlyTextKindsPlayerDamageTaken.Count == 0)
{
config.FlyTextKindsPlayerDamageTaken = [];
foreach (var kind in FlyTextCategoryExtension.GetKindsFor(FlyTextCategory.AbilityDamage))
{
if (config.FlyTextKinds.TryGetValue(kind, out var existing))
{
config.FlyTextKindsPlayerDamageTaken[kind] = new FlyTextConfiguration(existing);
}
else
{
config.FlyTextKindsPlayerDamageTaken[kind] = new FlyTextConfiguration();
}
}
}
if (config.FlyTextKindsPlayerAutoAttackTaken == null || config.FlyTextKindsPlayerAutoAttackTaken.Count == 0)
{
config.FlyTextKindsPlayerAutoAttackTaken = [];
foreach (var kind in FlyTextCategoryExtension.GetKindsFor(FlyTextCategory.AutoAttack))
{
if (config.FlyTextKinds.TryGetValue(kind, out var existing))
{
config.FlyTextKindsPlayerAutoAttackTaken[kind] = new FlyTextConfiguration(existing);
}
else
{
config.FlyTextKindsPlayerAutoAttackTaken[kind] = new FlyTextConfiguration();
}
}
}
}
/// <summary>
/// OnCommand reacts to commands received via <see cref="Command"/>.
/// </summary>
+75
View File
@@ -62,6 +62,18 @@ public class PluginConfiguration : IPluginConfiguration
kind => kind,
kind => new FlyTextConfiguration());
this.FlyTextKindsPlayerDamageTaken = FlyTextCategoryExtension
.GetKindsFor(FlyTextCategory.AbilityDamage)
.ToDictionary(
kind => kind,
kind => new FlyTextConfiguration());
this.FlyTextKindsPlayerAutoAttackTaken = FlyTextCategoryExtension
.GetKindsFor(FlyTextCategory.AutoAttack)
.ToDictionary(
kind => kind,
kind => new FlyTextConfiguration());
FlyTextCategory.AbilityDamage
.ForEachKind(kind =>
{
@@ -71,6 +83,12 @@ public class PluginConfiguration : IPluginConfiguration
this.FlyTextKinds[kind].Positionals = true;
this.FlyTextKinds[kind].Font.ColorSuccess = new Vector4(0.4f, 1, 0.4f, 1);
this.FlyTextKinds[kind].Font.ColorFailed = new Vector4(1, 0.4f, 0.4f, 1);
this.FlyTextKindsPlayerDamageTaken[kind].Font.Color = new Vector4(1, 1, 0, 1);
this.FlyTextKindsPlayerDamageTaken[kind].Font.Size = 24f;
this.FlyTextKindsPlayerDamageTaken[kind].Positionals = true;
this.FlyTextKindsPlayerDamageTaken[kind].Font.ColorSuccess = new Vector4(0.4f, 1, 0.4f, 1);
this.FlyTextKindsPlayerDamageTaken[kind].Font.ColorFailed = new Vector4(1, 0.4f, 0.4f, 1);
});
FlyTextCategory.AutoAttack
@@ -78,6 +96,9 @@ public class PluginConfiguration : IPluginConfiguration
{
this.FlyTextKinds[kind].Font.Color = new Vector4(1, 1, 1, 1);
this.FlyTextKinds[kind].Font.Size = 18f;
this.FlyTextKindsPlayerAutoAttackTaken[kind].Font.Color = new Vector4(1, 1, 1, 1);
this.FlyTextKindsPlayerAutoAttackTaken[kind].Font.Size = 18f;
});
FlyTextCategory.AbilityHealing
@@ -146,6 +167,48 @@ public class PluginConfiguration : IPluginConfiguration
this.FlyTextKinds[kind].Filter.Self = false;
}
});
FlyTextCategoryExtension
.GetKindsFor(FlyTextCategory.AbilityDamage)
.ToList()
.ForEach(kind =>
{
if (kind.ShouldFilter(FlyTextFilter.Party))
{
this.FlyTextKindsPlayerDamageTaken[kind].Filter.Party = false;
}
if (kind.ShouldFilter(FlyTextFilter.Enemy))
{
this.FlyTextKindsPlayerDamageTaken[kind].Filter.Enemy = false;
}
if (kind.ShouldFilter(FlyTextFilter.Self))
{
this.FlyTextKindsPlayerDamageTaken[kind].Filter.Self = false;
}
});
FlyTextCategoryExtension
.GetKindsFor(FlyTextCategory.AutoAttack)
.ToList()
.ForEach(kind =>
{
if (kind.ShouldFilter(FlyTextFilter.Party))
{
this.FlyTextKindsPlayerAutoAttackTaken[kind].Filter.Party = false;
}
if (kind.ShouldFilter(FlyTextFilter.Enemy))
{
this.FlyTextKindsPlayerAutoAttackTaken[kind].Filter.Enemy = false;
}
if (kind.ShouldFilter(FlyTextFilter.Self))
{
this.FlyTextKindsPlayerAutoAttackTaken[kind].Filter.Self = false;
}
});
}
/// <summary>
@@ -158,6 +221,18 @@ public class PluginConfiguration : IPluginConfiguration
/// </summary>
public Dictionary<FlyTextKind, FlyTextConfiguration> FlyTextKinds { get; set; } = [];
/// <summary>
/// Gets or sets the configuration for ability damage when the player is the target (damage taken).
/// When the player deals damage, <see cref="FlyTextKinds"/> is used; when the player takes damage, this is used.
/// </summary>
public Dictionary<FlyTextKind, FlyTextConfiguration> FlyTextKindsPlayerDamageTaken { get; set; } = [];
/// <summary>
/// Gets or sets the configuration for auto attack when the player is the target (auto attack taken).
/// When the player deals auto attack, <see cref="FlyTextKinds"/> is used; when the player takes auto attack, this is used.
/// </summary>
public Dictionary<FlyTextKind, FlyTextConfiguration> FlyTextKindsPlayerAutoAttackTaken { get; set; } = [];
/// <summary>
/// Gets or sets the FlyTextCategory Category Configuration options.
/// </summary>
+27
View File
@@ -103,6 +103,33 @@ public unsafe partial class PluginManager
public static FlyTextConfiguration? GetConfigForKind(FlyTextKind kind)
=> Service.Configuration.FlyTextKinds.TryGetValue(kind, out var config) ? config : null;
/// <summary>
/// Get the config for an event. For AbilityDamage kinds, returns Player Damage Taken config when the player is the target; for AutoAttack, returns Player AutoAttack Taken config when the player is the target; otherwise the normal (Dealt) config.
/// </summary>
/// <param name="kind">Kind of the event.</param>
/// <param name="source">Source character.</param>
/// <param name="target">Target character.</param>
/// <returns>The configuration to use for this event.</returns>
public static FlyTextConfiguration? GetConfigForEvent(FlyTextKind kind, Character* source, Character* target)
{
if (target != null && IsPlayerCharacter(target))
{
if (kind.InCategory(FlyTextCategory.AbilityDamage)
&& Service.Configuration.FlyTextKindsPlayerDamageTaken?.TryGetValue(kind, out var damageTakenConfig) == true)
{
return damageTakenConfig;
}
if (kind.InCategory(FlyTextCategory.AutoAttack)
&& Service.Configuration.FlyTextKindsPlayerAutoAttackTaken?.TryGetValue(kind, out var autoAttackTakenConfig) == true)
{
return autoAttackTakenConfig;
}
}
return GetConfigForKind(kind);
}
/// <summary>
/// Is the target an enemy.
/// </summary>
+5 -10
View File
@@ -7,6 +7,7 @@ using System.Numerics;
using CBT.FlyText.Animations;
using CBT.FlyText.Configuration;
using CBT.Helpers;
using CBT;
using Dalamud.Interface.Textures;
using Dalamud.Interface.Textures.TextureWraps;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
@@ -111,14 +112,7 @@ public unsafe partial class FlyTextEvent
{
if (this.configuredOffset == null)
{
if (Service.Configuration.FlyTextKinds.TryGetValue(this.Kind, out var kindConfig))
{
this.configuredOffset = kindConfig.Offset;
}
else
{
this.configuredOffset = Vector2.Zero;
}
this.configuredOffset = this.Config?.Offset ?? Vector2.Zero;
}
return (Vector2)this.configuredOffset;
@@ -413,8 +407,9 @@ public unsafe partial class FlyTextEvent
// This is a special case for HP Regen attribution.
this.SourceID = sourceID;
this.Config = new FlyTextConfiguration(kind);
this.Animation = FlyTextAnimation.Create(kind);
var eventConfig = PluginManager.GetConfigForEvent(kind, source, target);
this.Config = new FlyTextConfiguration(eventConfig ?? Service.Configuration.FlyTextKinds[kind]);
this.Animation = FlyTextAnimation.Create(kind, this.Config);
}
// TODO @cultbaus: I want to use string formatting and text tags instead of this, but for now this can be a placeholder.