Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v1.6.1.0 - 2026-07-09
### Added
- Time variables: your aliases can now react to the clock. `{time}` shows your local time (like 3:45 PM), `{time24}` shows it in 24-hour form (15:45), and `{date}`, `{day}`, `{hour}`, and `{minute}` fill in the rest. `{daypart}` gives morning, afternoon, evening, or night, so a venue greeter can open with something like `Good {daypart}, welcome in!`
- `{utc}` and `{utcdate}` give the UTC (server) time and date, handy for lining things up with people in other time zones
- The 24-hour and date variables are made to be compared in conditions, so you can gate lines by the clock, for example `:if {time24} >= 17:00` to switch to an evening greeting. Use `{time}` for showing the time and `{time24}` (or `{hour}`) when comparing it

## v1.6.0.0 - 2026-07-09
### Added
- Emote variables: `{emoting}` tells you whether you are holding an emote or pose, `{emote}` gives its name, and `{pose}` gives the pose number. They appear in the Variables tab alongside the other built-ins
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ Variables let you insert live game values into a line using curly brace syntax.
/say I am {character}, a level {level} {job} from {world}!
```

Silkstring includes variables for your character, job, HP and MP, combat state, target, currency, emote and pose state, and more, and the list keeps growing. For the full, always-current list with live values, open the Variables tab of the help window (`/silkstring help`). The command tester at the top of that window shows resolved output as you type.
Silkstring includes variables for your character, job, HP and MP, combat state, target, currency, emote and pose state, the time and date, and more, and the list keeps growing. For the full, always-current list with live values, open the Variables tab of the help window (`/silkstring help`). The command tester at the top of that window shows resolved output as you type.

The time variables come in two flavors: `{time}` (like 3:45 PM) is for showing the time, while `{time24}` (like 15:45), `{date}`, `{hour}`, and `{minute}` are made for comparing, so you can gate lines by the clock (see Conditionals below). There is also `{daypart}`, which is simply morning, afternoon, evening, or night, and `{utc}` and `{utcdate}` for UTC (server) time.

You can also define your own variables with `/silkstring variables` and use them just like the built-in ones (see User Variables below).

Expand Down Expand Up @@ -135,8 +137,11 @@ A condition compares values with `==`, `!=`, `<`, `>`, `<=`, `>=`, and you can c
:if {incombat} && {hpp} < 50
:if {job} == WHM || {job} == SCH
:if {0} == on
:if {time24} >= 17:00 || {time24} <= 05:00
```

That last line reacts to the clock: because `{time24}` and `{date}` are written with leading zeros (like 09:00 and 2026-07-09), they sort in the right order and can be compared with `<`, `>`, `<=`, and `>=`. This is why `{time24}` is the one to compare against, while `{time}` (like 3:45 PM) is just for showing.

Text comparisons are case-insensitive, and numbers compare as numbers. The `:if`, `:else`, and `:endif` lines are never sent to chat, and the alias editor warns you if a block is left open or a condition cannot be understood.

You can also pause between lines with `:wait`, followed by a number of seconds:
Expand Down
2 changes: 2 additions & 0 deletions Silkstring/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using ECommons;
using Silkstring.Services;
using Silkstring.Services.Variables;
using Silkstring.Services.Variables.Providers;
using Silkstring.UI;
using Silkstring.Windows;

Expand Down Expand Up @@ -72,6 +73,7 @@ public Plugin()
new CombatVariablesProvider(Condition, TargetManager),
new CurrencyVariablesProvider(),
new EmoteVariablesProvider(ClientState, DataManager),
new TimeVariablesProvider(),
];

var reserved = builtIn.SelectMany(p => p.GetVariables()).Select(v => v.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Plugin.Services;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class CombatVariablesProvider : IVariableProvider
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using FFXIVClientStructs.FFXIV.Client.Game;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class CurrencyVariablesProvider : IVariableProvider
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Lumina.Excel.Sheets;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class EmoteVariablesProvider : IVariableProvider
{
Expand Down Expand Up @@ -39,7 +39,7 @@
private unsafe string? EmoteName()
{
var character = Local();
if (character is null || character->Mode is not CharacterModes.InPositionLoop or CharacterModes.EmoteLoop) return null;

Check warning on line 42 in Silkstring/Services/Variables/Providers/EmoteVariablesProvider.cs

View workflow job for this annotation

GitHub Actions / build

The pattern is redundant.

Check warning on line 42 in Silkstring/Services/Variables/Providers/EmoteVariablesProvider.cs

View workflow job for this annotation

GitHub Actions / build

The pattern is redundant.
var mode = _dataManager.GetExcelSheet<EmoteMode>().GetRowOrDefault(character->ModeParam);
if (mode is null) return null;
var emote = mode.Value.StartEmote;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using Dalamud.Plugin.Services;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class PlayerVariableProvider : IVariableProvider
{
Expand Down
30 changes: 30 additions & 0 deletions Silkstring/Services/Variables/Providers/TimeVariablesProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;

namespace Silkstring.Services.Variables.Providers;

public sealed class TimeVariablesProvider : IVariableProvider
{
public IEnumerable<VariableDescriptor> GetVariables()
{
yield return new("time", "Current local time, for example 3:45 PM (display only, do not compare)", "Time", () => DateTime.Now.ToString("h:mm tt"));
yield return new("time24", "Current local time in 24-hour form, for example 15:45 (compares with < <= > >=)", "Time", () => DateTime.Now.ToString("HH:mm"));
yield return new("hour", "Current hour of the day, 0 to 23", "Time", () => DateTime.Now.Hour.ToString());
yield return new("minute", "Current minute, 00 to 59", "Time", () => DateTime.Now.Minute.ToString("D2"));
yield return new("date", "Current local date, for example 2026-07-09 (compares chronologically)", "Time", () => DateTime.Now.ToString("yyyy-MM-dd"));
yield return new("day", "Current day of the week, for example Thursday", "Time", () => DateTime.Now.DayOfWeek.ToString());
yield return new("daypart", "morning, afternoon, evening, or night", "Time", DayPart);
yield return new("utc", "Current UTC (server) time in 24-hour form, for example 19:45", "Time", () => DateTime.UtcNow.ToString("HH:mm"));
yield return new("utcdate", "Current UTC (server) date, for example 2026-07-09", "Time", () => DateTime.UtcNow.ToString("yyyy-MM-dd"));
}

private static string DayPart()
{
var h = DateTime.Now.Hour;
if (h < 5) return "night";
if (h < 12) return "morning";
if (h < 17) return "afternoon";
if (h < 21) return "evening";
return "night";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Linq;
using Silkstring.Models;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class UserVariableProvider : IVariableProvider
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Dalamud.Plugin.Services;
using ECommons.DalamudServices.Legacy;

namespace Silkstring.Services.Variables;
namespace Silkstring.Services.Variables.Providers;

public sealed class VitalsVariablesProvider : IVariableProvider
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/UserVariableProviderTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Silkstring.Models;
using Silkstring.Services;
using Silkstring.Services.Variables;
using Silkstring.Services.Variables.Providers;

public class UserVariableProviderTests
{
Expand Down
Loading