Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57291e925d | |||
| 8e9332ac8c |
@@ -145,6 +145,7 @@ public class Configuration : IPluginConfiguration
|
||||
public bool HideWhenUiHidden = true;
|
||||
public bool HideInLoadingScreens;
|
||||
public bool HideInBattle;
|
||||
public bool HideInNewGamePlusMenu;
|
||||
public bool HideWhenInactive;
|
||||
public int InactivityHideTimeout = 10;
|
||||
public bool InactivityHideActiveDuringBattle = true;
|
||||
@@ -221,6 +222,7 @@ public class Configuration : IPluginConfiguration
|
||||
public float TooltipOffset;
|
||||
public float WindowAlpha = 100f;
|
||||
public Dictionary<ChatType, uint> ChatColours = new();
|
||||
public bool ColorSelectedInputChannelButton = true;
|
||||
public List<Tab> Tabs = [];
|
||||
|
||||
public bool OverrideStyle;
|
||||
@@ -241,6 +243,7 @@ public class Configuration : IPluginConfiguration
|
||||
HideWhenUiHidden = other.HideWhenUiHidden;
|
||||
HideInLoadingScreens = other.HideInLoadingScreens;
|
||||
HideInBattle = other.HideInBattle;
|
||||
HideInNewGamePlusMenu = other.HideInNewGamePlusMenu;
|
||||
HideWhenInactive = other.HideWhenInactive;
|
||||
InactivityHideTimeout = other.InactivityHideTimeout;
|
||||
InactivityHideActiveDuringBattle = other.InactivityHideActiveDuringBattle;
|
||||
@@ -288,6 +291,7 @@ public class Configuration : IPluginConfiguration
|
||||
TooltipOffset = other.TooltipOffset;
|
||||
WindowAlpha = other.WindowAlpha;
|
||||
ChatColours = other.ChatColours.ToDictionary(entry => entry.Key, entry => entry.Value);
|
||||
ColorSelectedInputChannelButton = other.ColorSelectedInputChannelButton;
|
||||
|
||||
// Hellion Chat — Auto-Tell-Tabs are session-only and therefore
|
||||
// never present in a disk-loaded copy. Keep the live temp tabs of
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace HellionChat.GameFunctions;
|
||||
|
||||
internal unsafe class GameFunctions : IDisposable
|
||||
{
|
||||
internal const string NewGamePlusAddonName = "QuestRedo";
|
||||
|
||||
#region Hooks
|
||||
[Signature("E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B D0 49 8D 4F", DetourName = nameof(ResolveTextCommandPlaceholderDetour))]
|
||||
private Hook<ResolveTextCommandPlaceholderDelegate>? ResolveTextCommandPlaceholderHook = null!;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
0.1.0 is our bootstrap release; the underlying Chat 2 base is
|
||||
called out in the yaml changelog so users can see what it
|
||||
derives from. -->
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.0.2</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<!-- Honor packages.lock.json on restore so floating version ranges
|
||||
don't silently drift between machines or CI runs. -->
|
||||
|
||||
@@ -49,6 +49,24 @@ tags:
|
||||
- Replacement
|
||||
- Privacy
|
||||
changelog: |-
|
||||
**Hellion Chat 1.0.2 — Polish patch**
|
||||
|
||||
- New: optionally hide chat (and every other plugin window) while the
|
||||
New Game+ menu is open. Toggle in Settings → Window → Frame, default
|
||||
off. Closing the menu restores all windows.
|
||||
- New: optionally tint the channel selector button next to the input
|
||||
field with the currently active channel's colour. Toggle in
|
||||
Settings → Appearance → Colours, default on. Matches the existing
|
||||
input-text tint and respects ExtraChat overrides.
|
||||
- Fix: status, item and other inline hover icons keep their original
|
||||
aspect ratio. Debuff icons with non-square dimensions are no longer
|
||||
visually squished into a 32×32 box.
|
||||
- Diagnostic: hide-state transitions (battle, cutscene, user-hide,
|
||||
cutscene override) are now logged on Verbose level for easier bug
|
||||
reports — off by default, enable with `/xllog set HellionChat verbose`.
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
**Hellion Chat 1.0.1 — Window Position Recovery**
|
||||
|
||||
- Automatic bounds check on the first draw after plugin load.
|
||||
@@ -214,76 +232,6 @@ changelog: |-
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
**Hellion Chat 0.6.0 — UX Polish: Pop-Out Input + Colour Presets**
|
||||
|
||||
Two opt-in UX features land in the same release. Existing users see
|
||||
no change unless they enable the new toggles.
|
||||
|
||||
Pop-out input bar:
|
||||
|
||||
- New global master switch in Settings → Window → Frame: "Enable input
|
||||
in pop-outs". Default OFF so existing behaviour is preserved
|
||||
- When enabled, every pop-out window grows a compact input bar at the
|
||||
bottom (channel-coloured icon button left, text input right). The
|
||||
auto-translate picker is intentionally not part of the compact bar
|
||||
in v0.6.0 — typical pop-out workflows (FC greeter, club hostess)
|
||||
rarely need it there
|
||||
- Each pop-out keeps an independent text buffer and history cursor;
|
||||
channel changes still apply globally because that is how the FFXIV
|
||||
channel API works
|
||||
- Up/Down navigates a shared input history singleton across the main
|
||||
window and every open pop-out
|
||||
- First pop-out opening after the upgrade shows a one-time hint
|
||||
banner pointing users to the new toggle
|
||||
|
||||
Chat colour presets:
|
||||
|
||||
- Seven built-in presets above the per-channel colour list in
|
||||
Settings → Appearance → Colours: ChatTwo Default, High-Contrast,
|
||||
Pastell, Dark-Mode-Tuned, Hellion (brand-coloured, blue/orange
|
||||
Arctic Cyan + Ember Glow palette from the Hellion Online Media
|
||||
branding spec), plus two bonus mood presets — Night Blue (royal
|
||||
blue, classic-cool) and Indigo Violet (royal violet, glitter-mystic)
|
||||
- Apply is immediate and overwrites the channels covered by the
|
||||
preset; battle-channel colours are left alone so combat tuning
|
||||
stays intact
|
||||
|
||||
Configuration migrates from v10 to v11 with a diagnostic log entry;
|
||||
no data is reset. Bilingual (English/German) for both new sections.
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
**Hellion Chat 0.5.4 — WrapText hardening**
|
||||
|
||||
Replaces the unsafe pointer-arithmetic in ImGuiUtil.WrapText with
|
||||
Span- and index-based control flow. Closes the persistent CodeQL
|
||||
Critical alert "unvalidated local pointer arithmetic" that kept
|
||||
re-firing on every shape of the previous fix.
|
||||
|
||||
Hardening:
|
||||
|
||||
- WrapText now allocates a buffer sized by Encoding.UTF8.GetMaxByteCount
|
||||
via ArrayPool, validates the actual encoded length against that
|
||||
ceiling, and threads the rest of the algorithm through int offsets
|
||||
instead of raw byte pointers
|
||||
- Pointer arithmetic only happens inside two small private helpers
|
||||
(CalcWordWrap and DrawText) that take the pinned base pointer plus
|
||||
int offsets sourced from the plugin's own logic, not from any
|
||||
virtual-method return
|
||||
- Added a 16 KiB upper bound on the buffer rent to prevent a
|
||||
pathological input from triggering an unbounded ArrayPool allocation
|
||||
|
||||
No user-visible behaviour change. Word-wrap output is byte-identical
|
||||
to v0.5.3.
|
||||
|
||||
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
|
||||
|
||||
**Hellion Chat 0.5.3 — Pointer arithmetic hardening**
|
||||
|
||||
Closed CodeQL Critical alert in ImGuiUtil.WrapText by validating the
|
||||
encoded byte buffer length via GetByteCount before pointer
|
||||
arithmetic. Single-fix patch on top of v0.5.2.
|
||||
|
||||
---
|
||||
|
||||
Earlier history: https://github.com/JonKazama-Hellion/HellionChat/releases
|
||||
|
||||
@@ -332,10 +332,19 @@ public sealed class PayloadHandler
|
||||
atkBase->SetPosition((short) x, (short) y);
|
||||
}
|
||||
|
||||
private const float MaxInlineIconSize = 32f;
|
||||
|
||||
private static void InlineIcon(IDalamudTextureWrap icon)
|
||||
{
|
||||
if (icon.Size.X <= 0 || icon.Size.Y <= 0)
|
||||
return;
|
||||
|
||||
var width = (float) icon.Size.X;
|
||||
var height = (float) icon.Size.Y;
|
||||
var scale = Math.Min(1f, Math.Min(MaxInlineIconSize / width, MaxInlineIconSize / height));
|
||||
var size = ImGuiHelpers.ScaledVector2(width * scale, height * scale);
|
||||
|
||||
var cursor = ImGui.GetCursorPos();
|
||||
var size = ImGuiHelpers.ScaledVector2(32, 32);
|
||||
ImGui.Image(icon.Handle, size);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPos(cursor + new Vector2(size.X + 4, size.Y - ImGui.GetTextLineHeightWithSpacing()));
|
||||
|
||||
@@ -571,6 +571,16 @@ public sealed class Plugin : IDalamudPlugin
|
||||
return;
|
||||
}
|
||||
|
||||
// v1.0.2 — global skip while the New Game+ menu (QuestRedo addon) is
|
||||
// open. Hides every plugin window in one shot (chat log, pop-outs,
|
||||
// settings, db viewer, etc.), matching the LoadingScreens pattern.
|
||||
if (Config.HideInNewGamePlusMenu && GameFunctions.GameFunctions.IsAddonInteractable(GameFunctions.GameFunctions.NewGamePlusAddonName))
|
||||
{
|
||||
ChatLogWindow.FinalizeFrame();
|
||||
TypingIpc.Update();
|
||||
return;
|
||||
}
|
||||
|
||||
ChatLogWindow.HideStateCheck();
|
||||
|
||||
Interface.UiBuilder.DisableUserUiHide = !Config.HideWhenUiHidden;
|
||||
|
||||
+36
@@ -2148,6 +2148,24 @@ namespace HellionChat.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The channel selector button next to the input field is tinted with the currently active channel's colour. Matches the tinting of the input text itself..
|
||||
/// </summary>
|
||||
internal static string Options_ColorSelectedInputChannelButton_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Options_ColorSelectedInputChannelButton_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tint channel selector with channel colour.
|
||||
/// </summary>
|
||||
internal static string Options_ColorSelectedInputChannelButton_Name {
|
||||
get {
|
||||
return ResourceManager.GetString("Options_ColorSelectedInputChannelButton_Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Chat colours.
|
||||
/// </summary>
|
||||
@@ -2661,6 +2679,24 @@ namespace HellionChat.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hide the chat while the New Game+ menu is open. Closing the menu shows the chat again..
|
||||
/// </summary>
|
||||
internal static string Options_HideInNewGamePlusMenu_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Options_HideInNewGamePlusMenu_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hide while New Game+ menu is open.
|
||||
/// </summary>
|
||||
internal static string Options_HideInNewGamePlusMenu_Name {
|
||||
get {
|
||||
return ResourceManager.GetString("Options_HideInNewGamePlusMenu_Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hide {0} during loading screens..
|
||||
/// </summary>
|
||||
|
||||
Generated
+12
@@ -208,6 +208,12 @@
|
||||
<data name="Options_ChatColours_Import">
|
||||
<value>Vom Spiel importieren</value>
|
||||
</data>
|
||||
<data name="Options_ColorSelectedInputChannelButton_Name" xml:space="preserve">
|
||||
<value>Channel-Auswahl-Knopf in Channel-Farbe</value>
|
||||
</data>
|
||||
<data name="Options_ColorSelectedInputChannelButton_Description" xml:space="preserve">
|
||||
<value>Der Channel-Auswahl-Knopf neben dem Eingabefeld bekommt die Farbe des aktuell aktiven Channels. Konsistent zur Färbung des Eingabetextes selbst.</value>
|
||||
</data>
|
||||
<data name="Options_Tabs_Tab">
|
||||
<value>Kanäle</value>
|
||||
</data>
|
||||
@@ -1190,6 +1196,12 @@ Sie wurden gewarnt.</value>
|
||||
<data name="Options_HideInBattle_Description" xml:space="preserve">
|
||||
<value>Blende den Chat während der Kämpfe aus.</value>
|
||||
</data>
|
||||
<data name="Options_HideInNewGamePlusMenu_Name" xml:space="preserve">
|
||||
<value>Während des New-Game+ Menüs ausblenden</value>
|
||||
</data>
|
||||
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
|
||||
<value>Blendet den Chat aus, solange das New-Game+ Menü geöffnet ist. Schließen des Menüs blendet den Chat wieder ein.</value>
|
||||
</data>
|
||||
<data name="Options_Emote_EmoteStats" xml:space="preserve">
|
||||
<value>Emote-Statistik</value>
|
||||
</data>
|
||||
|
||||
@@ -208,6 +208,12 @@
|
||||
<data name="Options_ChatColours_Import">
|
||||
<value>Import from game</value>
|
||||
</data>
|
||||
<data name="Options_ColorSelectedInputChannelButton_Name" xml:space="preserve">
|
||||
<value>Tint channel selector with channel colour</value>
|
||||
</data>
|
||||
<data name="Options_ColorSelectedInputChannelButton_Description" xml:space="preserve">
|
||||
<value>The channel selector button next to the input field is tinted with the currently active channel's colour. Matches the tinting of the input text itself.</value>
|
||||
</data>
|
||||
<data name="Options_Tabs_Tab">
|
||||
<value>Tabs</value>
|
||||
</data>
|
||||
@@ -1189,6 +1195,12 @@
|
||||
<data name="Options_HideInBattle_Description" xml:space="preserve">
|
||||
<value>Hide the chat during battles.</value>
|
||||
</data>
|
||||
<data name="Options_HideInNewGamePlusMenu_Name" xml:space="preserve">
|
||||
<value>Hide while New Game+ menu is open</value>
|
||||
</data>
|
||||
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
|
||||
<value>Hide the chat while the New Game+ menu is open. Closing the menu shows the chat again.</value>
|
||||
</data>
|
||||
<data name="Options_Emote_EmoteStats" xml:space="preserve">
|
||||
<value>Emote Stats</value>
|
||||
</data>
|
||||
|
||||
@@ -278,9 +278,11 @@ public sealed class ChatLogWindow : Window
|
||||
{
|
||||
case "hide":
|
||||
CurrentHideState = HideState.User;
|
||||
Plugin.Log.Verbose("HideState: → User (chat hide command)");
|
||||
break;
|
||||
case "show":
|
||||
CurrentHideState = HideState.None;
|
||||
Plugin.Log.Verbose("HideState: → None (chat show command)");
|
||||
break;
|
||||
case "toggle":
|
||||
CurrentHideState = CurrentHideState switch
|
||||
@@ -290,6 +292,7 @@ public sealed class ChatLogWindow : Window
|
||||
HideState.None => HideState.User,
|
||||
_ => CurrentHideState,
|
||||
};
|
||||
Plugin.Log.Verbose($"HideState: → {CurrentHideState} (chat toggle command)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -406,30 +409,48 @@ public sealed class ChatLogWindow : Window
|
||||
{
|
||||
// if the chat has no hide state set, and the player has entered battle, we hide chat if they have configured it
|
||||
if (Plugin.Config.HideInBattle && CurrentHideState == HideState.None && Plugin.InBattle)
|
||||
{
|
||||
CurrentHideState = HideState.Battle;
|
||||
Plugin.Log.Verbose("HideState: None → Battle");
|
||||
}
|
||||
|
||||
// If the chat is hidden because of battle, we reset it here
|
||||
if (CurrentHideState is HideState.Battle && !Plugin.InBattle)
|
||||
{
|
||||
CurrentHideState = HideState.None;
|
||||
Plugin.Log.Verbose("HideState: Battle → None");
|
||||
}
|
||||
|
||||
// if the chat has no hide state and in a cutscene, set the hide state to cutscene
|
||||
if (Plugin.Config.HideDuringCutscenes && CurrentHideState == HideState.None && (Plugin.CutsceneActive || Plugin.GposeActive))
|
||||
{
|
||||
if (Plugin.Functions.Chat.CheckHideFlags())
|
||||
{
|
||||
CurrentHideState = HideState.Cutscene;
|
||||
Plugin.Log.Verbose("HideState: None → Cutscene");
|
||||
}
|
||||
}
|
||||
|
||||
// if the chat is hidden because of a cutscene and no longer in a cutscene, set the hide state to none
|
||||
if (CurrentHideState is HideState.Cutscene or HideState.CutsceneOverride && !Plugin.CutsceneActive && !Plugin.GposeActive)
|
||||
{
|
||||
Plugin.Log.Verbose($"HideState: {CurrentHideState} → None (cutscene/gpose ended)");
|
||||
CurrentHideState = HideState.None;
|
||||
}
|
||||
|
||||
// if the chat is hidden because of a cutscene and the chat has been activated, show chat
|
||||
if (CurrentHideState == HideState.Cutscene && Activate)
|
||||
{
|
||||
CurrentHideState = HideState.CutsceneOverride;
|
||||
Plugin.Log.Verbose("HideState: Cutscene → CutsceneOverride (user activate)");
|
||||
}
|
||||
|
||||
// if the user hid the chat and is now activating chat, reset the hide state
|
||||
if (CurrentHideState == HideState.User && Activate)
|
||||
{
|
||||
CurrentHideState = HideState.None;
|
||||
Plugin.Log.Verbose("HideState: User → None (activate)");
|
||||
}
|
||||
|
||||
if (CurrentHideState is HideState.Cutscene or HideState.User or HideState.Battle || (Plugin.Config.HideWhenNotLoggedIn && !Plugin.ClientState.IsLoggedIn))
|
||||
{
|
||||
@@ -600,9 +621,40 @@ public sealed class ChatLogWindow : Window
|
||||
DrawChannelName(activeTab);
|
||||
}
|
||||
|
||||
// v1.0.2 — compute inputColour up front so the channel selector button
|
||||
// can also tint with it (existing input-text push remains below).
|
||||
var inputType = activeTab.CurrentChannel.UseTempChannel ? activeTab.CurrentChannel.TempChannel.ToChatType() : activeTab.CurrentChannel.Channel.ToChatType();
|
||||
var isCommand = Chat.Trim().StartsWith('/');
|
||||
if (isCommand)
|
||||
{
|
||||
var command = Chat.Split(' ')[0];
|
||||
if (TextCommandChannels.TryGetValue(command, out var channel))
|
||||
inputType = channel;
|
||||
|
||||
if (!IsValidCommand(command))
|
||||
inputType = ChatType.Error;
|
||||
}
|
||||
|
||||
var inputColour = Plugin.Config.ChatColours.TryGetValue(inputType, out var inputCol) ? inputCol : inputType.DefaultColor();
|
||||
|
||||
if (!isCommand && Plugin.ExtraChat.ChannelOverride is var (_, overrideColour))
|
||||
inputColour = overrideColour;
|
||||
|
||||
if (isCommand && Plugin.ExtraChat.ChannelCommandColours.TryGetValue(Chat.Split(' ')[0], out var ecColour))
|
||||
inputColour = ecColour;
|
||||
|
||||
var beforeIcon = ImGui.GetCursorPos();
|
||||
|
||||
var tintSelector = Plugin.Config.ColorSelectedInputChannelButton && inputColour.HasValue;
|
||||
var selectorAbgr = tintSelector ? ColourUtil.RgbaToAbgr(inputColour!.Value) : 0u;
|
||||
|
||||
using (ImRaii.PushColor(ImGuiCol.Button, selectorAbgr, tintSelector))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, ColourUtil.AdjustBrightness(selectorAbgr, 1.15f), tintSelector))
|
||||
using (ImRaii.PushColor(ImGuiCol.ButtonActive, ColourUtil.AdjustBrightness(selectorAbgr, 0.85f), tintSelector))
|
||||
{
|
||||
if (ImGuiUtil.IconButton(FontAwesomeIcon.Comment) && activeTab.Channel is null)
|
||||
ImGui.OpenPopup(ChatChannelPicker);
|
||||
}
|
||||
|
||||
if (activeTab.Channel is not null && ImGui.IsItemHovered())
|
||||
ImGuiUtil.Tooltip(Language.ChatLog_SwitcherDisabled);
|
||||
@@ -626,27 +678,7 @@ public sealed class ChatLogWindow : Window
|
||||
var buttonsRight = (showNovice ? 1 : 0) + (Plugin.Config.ShowHideButton ? 1 : 0);
|
||||
var inputWidth = ImGui.GetContentRegionAvail().X - buttonWidth * (1 + buttonsRight);
|
||||
|
||||
var inputType = activeTab.CurrentChannel.UseTempChannel ? activeTab.CurrentChannel.TempChannel.ToChatType() : activeTab.CurrentChannel.Channel.ToChatType();
|
||||
var isCommand = Chat.Trim().StartsWith('/');
|
||||
if (isCommand)
|
||||
{
|
||||
var command = Chat.Split(' ')[0];
|
||||
if (TextCommandChannels.TryGetValue(command, out var channel))
|
||||
inputType = channel;
|
||||
|
||||
if (!IsValidCommand(command))
|
||||
inputType = ChatType.Error;
|
||||
}
|
||||
|
||||
var normalColor = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
var inputColour = Plugin.Config.ChatColours.TryGetValue(inputType, out var inputCol) ? inputCol : inputType.DefaultColor();
|
||||
|
||||
if (!isCommand && Plugin.ExtraChat.ChannelOverride is var (_, overrideColour))
|
||||
inputColour = overrideColour;
|
||||
|
||||
if (isCommand && Plugin.ExtraChat.ChannelCommandColours.TryGetValue(Chat.Split(' ')[0], out var ecColour))
|
||||
inputColour = ecColour;
|
||||
|
||||
var push = inputColour != null;
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, push ? ColourUtil.RgbaToAbgr(inputColour!.Value) : 0, push))
|
||||
{
|
||||
|
||||
@@ -229,30 +229,48 @@ internal class Popout : Window
|
||||
{
|
||||
// if the chat has no hide state set, and the player has entered battle, we hide chat if they have configured it
|
||||
if (Tab.HideInBattle && CurrentHideState == HideState.None && Plugin.InBattle)
|
||||
{
|
||||
CurrentHideState = HideState.Battle;
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: None → Battle");
|
||||
}
|
||||
|
||||
// If the chat is hidden because of battle, we reset it here
|
||||
if (CurrentHideState is HideState.Battle && !Plugin.InBattle)
|
||||
{
|
||||
CurrentHideState = HideState.None;
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: Battle → None");
|
||||
}
|
||||
|
||||
// if the chat has no hide state and in a cutscene, set the hide state to cutscene
|
||||
if (Tab.HideDuringCutscenes && CurrentHideState == HideState.None && (Plugin.CutsceneActive || Plugin.GposeActive))
|
||||
{
|
||||
if (ChatLogWindow.Plugin.Functions.Chat.CheckHideFlags())
|
||||
{
|
||||
CurrentHideState = HideState.Cutscene;
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: None → Cutscene");
|
||||
}
|
||||
}
|
||||
|
||||
// if the chat is hidden because of a cutscene and no longer in a cutscene, set the hide state to none
|
||||
if (CurrentHideState is HideState.Cutscene or HideState.CutsceneOverride && !Plugin.CutsceneActive && !Plugin.GposeActive)
|
||||
{
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: {CurrentHideState} → None (cutscene/gpose ended)");
|
||||
CurrentHideState = HideState.None;
|
||||
}
|
||||
|
||||
// if the chat is hidden because of a cutscene and the chat has been activated, show chat
|
||||
if (CurrentHideState == HideState.Cutscene && ChatLogWindow.Activate)
|
||||
{
|
||||
CurrentHideState = HideState.CutsceneOverride;
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: Cutscene → CutsceneOverride (user activate)");
|
||||
}
|
||||
|
||||
// if the user hid the chat and is now activating chat, reset the hide state
|
||||
if (CurrentHideState == HideState.User && ChatLogWindow.Activate)
|
||||
{
|
||||
CurrentHideState = HideState.None;
|
||||
Plugin.Log.Verbose($"Popout HideState [{Tab.Name}]: User → None (activate)");
|
||||
}
|
||||
|
||||
return CurrentHideState is HideState.Cutscene or HideState.User or HideState.Battle || (Tab.HideWhenNotLoggedIn && !Plugin.ClientState.IsLoggedIn);
|
||||
}
|
||||
|
||||
@@ -236,6 +236,10 @@ internal sealed class Appearance : ISettingsTab
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
|
||||
ImGui.Checkbox(Language.Options_ColorSelectedInputChannelButton_Name, ref Mutable.ColorSelectedInputChannelButton);
|
||||
ImGuiUtil.HelpMarker(Language.Options_ColorSelectedInputChannelButton_Description);
|
||||
ImGui.Spacing();
|
||||
|
||||
foreach (var (_, types) in ChatTypeExt.SortOrder)
|
||||
{
|
||||
foreach (var type in types)
|
||||
|
||||
@@ -56,6 +56,9 @@ internal sealed class Window : ISettingsTab
|
||||
|
||||
ImGui.Checkbox(Language.Options_HideInBattle_Name, ref Mutable.HideInBattle);
|
||||
ImGuiUtil.HelpMarker(Language.Options_HideInBattle_Description);
|
||||
|
||||
ImGui.Checkbox(Language.Options_HideInNewGamePlusMenu_Name, ref Mutable.HideInNewGamePlusMenu);
|
||||
ImGuiUtil.HelpMarker(Language.Options_HideInNewGamePlusMenu_Description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,4 +48,18 @@ internal static class ColourUtil {
|
||||
|
||||
internal static uint ComponentsToRgba(byte red, byte green, byte blue, byte alpha = 0xFF)
|
||||
=> alpha | (uint) (red << 24) | (uint) (green << 16) | (uint) (blue << 8);
|
||||
|
||||
internal static uint AdjustBrightness(uint abgr, float factor)
|
||||
{
|
||||
var a = (byte) ((abgr & 0xFF000000) >> 24);
|
||||
var b = (byte) ((abgr & 0x00FF0000) >> 16);
|
||||
var g = (byte) ((abgr & 0x0000FF00) >> 8);
|
||||
var r = (byte) (abgr & 0x000000FF);
|
||||
|
||||
var nr = (byte) Math.Clamp(r * factor, 0f, 255f);
|
||||
var ng = (byte) Math.Clamp(g * factor, 0f, 255f);
|
||||
var nb = (byte) Math.Clamp(b * factor, 0f, 255f);
|
||||
|
||||
return ((uint) a << 24) | ((uint) nb << 16) | ((uint) ng << 8) | nr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
[](https://dotnet.microsoft.com/)
|
||||
[](https://www.finalfantasyxiv.com/)
|
||||
|
||||
**Version 1.0.0** — DSGVO-bewusster Chat-Ersatz für FINAL FANTASY XIV / Dalamud, basierend auf [Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2).
|
||||
**Version 1.0.2** — DSGVO-bewusster Chat-Ersatz für FINAL FANTASY XIV / Dalamud, basierend auf [Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2).
|
||||
|
||||
Hellion Chat ergänzt das ursprüngliche Chat-2-Fundament um Datenschutz- und Daten-Handling-Kontrollen, die mit den Datenschutz-Regeln in der EU, den USA und Japan im Einklang sind. Alle aus Chat 2 übernommenen Funktionen, Befehle und Tastenkürzel funktionieren unverändert. Eigenständiger Plugin-Slot, eigene Konfiguration, eigene Datenbank.
|
||||
|
||||
|
||||
@@ -12,6 +12,33 @@ und verlinkt für Details auf die Release-Pages.
|
||||
|
||||
---
|
||||
|
||||
## [1.0.2] — 2026-05-04 — Polish patch
|
||||
|
||||
Vier kleine Polish-Items aus dem Backlog gebündelt:
|
||||
|
||||
- **Hide bei New Game+ Menü**: Optionaler globaler Toggle der Hellion
|
||||
Chat (und alle weiteren Plugin-Fenster wie Settings, DB-Viewer,
|
||||
Pop-Outs) ausblendet, solange das NG+-Menü offen ist. Settings →
|
||||
Fenster → Rahmen, Default aus. Skipt analog zum bestehenden
|
||||
LoadingScreens-Pattern den gesamten `WindowSystem.Draw()`-Pfad.
|
||||
- **Channel-Selector-Färbung**: Optionales Tinting des
|
||||
Channel-Auswahl-Knopfs (Comment-Icon) neben dem Eingabefeld in der
|
||||
aktuellen Channel-Farbe. Settings → Aussehen → Chat-Farben, Default
|
||||
an. Konsistent zur bestehenden Eingabetext-Färbung, ExtraChat-Override
|
||||
wird übernommen.
|
||||
- **(De)Buff-Icon Aspect-Ratio-Fix**: `PayloadHandler.InlineIcon` quetschte
|
||||
alle Hover-Icons auf 32×32. Status-Icons mit nicht-quadratischen
|
||||
Dimensionen (Debuffs mit Pfeil-Indikator) sind jetzt aspekt-erhaltend
|
||||
geshrinkt. Eigenständige Float-Math-Implementierung mit Zero-Size-Guard
|
||||
statt Cherry-Pick aus dem offenen ChatTwo PR #157 (der hatte eine
|
||||
int-Division-Falle).
|
||||
- **HideState-Logging-Sweep**: Alle HideState-Transitions
|
||||
(Battle/Cutscene/User/Override plus die Pop-Out-Spiegelung) loggen sich
|
||||
auf Verbose-Level. Aus by default, Aktivierung via
|
||||
`/xllog set HellionChat verbose` für Bug-Report-Diagnose.
|
||||
|
||||
[Release-Notes 1.0.2](https://github.com/JonKazama-Hellion/HellionChat/releases/tag/v1.0.2)
|
||||
|
||||
## [1.0.1] — 2026-05-04 — Window Position Recovery
|
||||
|
||||
Fixes an off-screen-window scenario the user could end up in after a
|
||||
|
||||
Reference in New Issue
Block a user