From 3b4f585a5cd5e84550aa4f2c9c94987afb1ce02d Mon Sep 17 00:00:00 2001 From: Shush Date: Sat, 31 Oct 2026 00:10:50 +0200 Subject: [PATCH 1/4] Custom text message colors and duration --- code/taction.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/code/taction.cpp b/code/taction.cpp index b4427474c..3e274b71d 100644 --- a/code/taction.cpp +++ b/code/taction.cpp @@ -104,6 +104,7 @@ #include #include +#include DynamicVectorClass Actions; @@ -1160,10 +1161,20 @@ bool TActionClass::TAction_ALL_CHANGE_HOUSE(HouseClass * house, ObjectClass * , /// bool TActionClass::TAction_TEXT_TRIGGER(HouseClass * , ObjectClass * , TriggerClass * , Cell const & ) { - /* - ** Display a text message overlayed onto the tactical map. - */ - Session.Messages.Add_Message(NULL, 0, TutorialText.Fetch(Data.Value), 0, TextPrintType(TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW), Rule->MessageDelay * TICKS_PER_MINUTE); + int duration = TriggerRect.Y; + duration = std::max(0, duration); + if (duration == 0) { + duration = Rule->MessageDelay * TICKS_PER_MINUTE; + } else { + duration *= TIMER_SECOND; + } + + int color = TriggerRect.X * 2; + if (color < 0 || color >= ColorSchemes.Count()) { + color = PlayerPtr->Scheme; + } + + Session.Messages.Add_Message(NULL, 0, TutorialText.Fetch(Data.Value), color, TextPrintType(TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_FULLSHADOW), duration); return(true); } From 84b8e83d435893b97139d62160803692be7871c6 Mon Sep 17 00:00:00 2001 From: Shush Date: Sat, 31 Oct 2026 00:26:43 +0200 Subject: [PATCH 2/4] Add docs --- .../changes/text-trigger-color-and-duration.md | 13 +++++++++++++ .../internals/trigger-action-registry.md | 2 +- manual/content/keys/messagedelay.md | 2 +- manual/content/scripting/actions/11.md | 17 +++++++++++++---- 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 manual/changes/text-trigger-color-and-duration.md diff --git a/manual/changes/text-trigger-color-and-duration.md b/manual/changes/text-trigger-color-and-duration.md new file mode 100644 index 000000000..460cf2098 --- /dev/null +++ b/manual/changes/text-trigger-color-and-duration.md @@ -0,0 +1,13 @@ +--- +title: Choose a text trigger's color and display time +category: feature +release: 0.2.0 +targets: +- type: action + id: TACTION_TEXT_TRIGGER + effect: changed +credit: +- JoyfulShush +--- + +A Text Trigger action now takes its color and display duration from the first two of the four fields after the text line number. The first selects a color from `[Colors]`, counted from `0`; the second gives the display time in seconds. A map that leaves both fields at `0` keeps the first default color and `MessageDelay`. diff --git a/manual/content/internals/trigger-action-registry.md b/manual/content/internals/trigger-action-registry.md index 7ed6e7779..c0785dbc7 100644 --- a/manual/content/internals/trigger-action-registry.md +++ b/manual/content/internals/trigger-action-registry.md @@ -25,7 +25,7 @@ An `[Actions]` line holds `count` followed by one group of eight fields per acti | 1 | `Action` | The `TActionType` number | | 2 | parameter code | How field 3 is read: `0` a number into `Data`, `1` a TeamType, `2` a TriggerType, `3` a TagType, `4` a TeamType with field 8 as a time | | 3 | `Data`, `Team`, `Trigger` or `Tag` | The first parameter | -| 4 to 7 | `TriggerRect` | Resize Player View uses the rectangle. Give Credits uses `X` for the amount, and Create Building At uses `X` for the building type and `Y` for the force flag | +| 4 to 7 | `TriggerRect` | Resize Player View uses the rectangle. Give Credits uses `X` for the amount, Create Building At uses `X` for the building type and `Y` for the force flag, and Text Trigger uses `X` for a color position and `Y` for a display time in seconds | | 8 | `EffectLocation` | The waypoint, or the time under parameter code `4` | Under parameter codes `1` to `4`, field 3 names a type. `-1` names nothing, text of one or two characters is an index into that type list, and longer text is an ID. An ID that no type has yet creates a new type of that name. diff --git a/manual/content/keys/messagedelay.md b/manual/content/keys/messagedelay.md index 018d84c8c..12457a5e2 100644 --- a/manual/content/keys/messagedelay.md +++ b/manual/content/keys/messagedelay.md @@ -12,7 +12,7 @@ It sets how long these messages stay visible: - the low power warning; - alliance and defeat announcements; -- text shown by a trigger action; +- text shown by a [Text Trigger](/mapping/actions/taction-text-trigger/) action that does not set a positive display time; - notices about saving the game, such as the autosave announcement; - the difficulty announcement at the start of a campaign mission; - notices during network play, such as a player leaving or changing the game speed; diff --git a/manual/content/scripting/actions/11.md b/manual/content/scripting/actions/11.md index 0d7356353..f03d58d98 100644 --- a/manual/content/scripting/actions/11.md +++ b/manual/content/scripting/actions/11.md @@ -2,11 +2,14 @@ type: action id: TACTION_TEXT_TRIGGER title: Text Trigger... -summary: Prints one numbered line of tutorial text over the tactical view. +summary: Prints one numbered line of tutorial text over the tactical view in a chosen color and for a chosen time. valid_values: - The number of a line in the map's `[Tutorial]` section or in `TUTORIAL.INI`. + - A color's index in the rules' `[Colors]` list. + - A whole number of seconds for the display time. caveats: - - A number that neither holds prints nothing. The trigger's other actions still run. + - A text line number that neither the map nor `TUTORIAL.INI` holds prints nothing. The trigger's other actions still run. + - A color's index that does not match any color scheme uses the local player's color. - Tutorial lines share the on-screen message list with chat and game notices. The list shows six messages, and each new message after that removes the oldest, so later messages can take the line off the screen before its time is up. - A line too wide for the message area is split into several messages. Each part plays the incoming-message sound and can be pushed off the screen separately. related: @@ -26,9 +29,15 @@ The text comes from the numbered lines that [TUTORIAL.INI](/formats/tutorial-ini ```ini title="map file" [Tutorial] 120=Hold the bridge instead. +121=Fall back to the ridge. [Actions] -DemoText=1,11,0,120,0,0,0,0, ; prints the map's line 120, "Hold the bridge instead." +DemoText=1,11,0,120,0,0,0,0, ; line 120 in the first color, for the MessageDelay time +Brief=1,11,0,121,2,30,0,0, ; line 121 in the third color, for about 30 seconds ``` -The line stays on screen for [`MessageDelay`](/keys/messagedelay/) minutes unless later messages push it off. +The color goes in the first of the four fields after the text line number, and the display time in the second. The last two fields are unused; write `0` for both. + +Count the color position from `0`; `0` is the first entry of [`[Colors]`](/keys/color/). + +A display time of `0` or less keeps the line on screen for [`MessageDelay`](/keys/messagedelay/). A positive time keeps it for that many seconds. Later messages can still push the line off before that time ends. From 8e8f19212abca5400f222a5f03b76e4cc2898c75 Mon Sep 17 00:00:00 2001 From: Shush Date: Sat, 31 Oct 2026 08:59:11 +0200 Subject: [PATCH 3/4] Add credits --- manual/changes/text-trigger-color-and-duration.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/manual/changes/text-trigger-color-and-duration.md b/manual/changes/text-trigger-color-and-duration.md index 460cf2098..fc7b073e7 100644 --- a/manual/changes/text-trigger-color-and-duration.md +++ b/manual/changes/text-trigger-color-and-duration.md @@ -8,6 +8,9 @@ targets: effect: changed credit: - JoyfulShush +- ZivDero --- A Text Trigger action now takes its color and display duration from the first two of the four fields after the text line number. The first selects a color from `[Colors]`, counted from `0`; the second gives the display time in seconds. A map that leaves both fields at `0` keeps the first default color and `MessageDelay`. + +Credits to ZivDero for their original Vinifera implementation for this feature. From 7c7fdccb19f511c83e367768dfb8d94c116223e1 Mon Sep 17 00:00:00 2001 From: ZivDero Date: Sat, 14 Nov 2026 14:44:44 +0300 Subject: [PATCH 4/4] Clamp text trigger display time and tidy its docs --- code/taction.cpp | 17 ++++++++--------- .../changes/text-trigger-color-and-duration.md | 6 +++--- manual/content/scripting/actions/11.md | 7 ++++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/code/taction.cpp b/code/taction.cpp index 3e274b71d..d93496459 100644 --- a/code/taction.cpp +++ b/code/taction.cpp @@ -75,6 +75,7 @@ #include "rules.h" #include "savestream.h" #include "scenario.h" +#include "scheme.h" #include "session.h" #include "sun.h" #include "super.h" @@ -104,7 +105,6 @@ #include #include -#include DynamicVectorClass Actions; @@ -1156,17 +1156,16 @@ bool TActionClass::TAction_ALL_CHANGE_HOUSE(HouseClass * house, ObjectClass * , /// /// Displays a line of tutorial text to the player. -/// This routine handles the trigger action that posts a message onto the tactical map. The -/// message expires after the message delay specified in the rules. +/// TriggerRect.X picks the color by its position in [Colors], and an unknown position uses +/// the local player's color. A positive TriggerRect.Y sets the display time in seconds; +/// otherwise the message uses the rules' message delay. /// bool TActionClass::TAction_TEXT_TRIGGER(HouseClass * , ObjectClass * , TriggerClass * , Cell const & ) { - int duration = TriggerRect.Y; - duration = std::max(0, duration); - if (duration == 0) { - duration = Rule->MessageDelay * TICKS_PER_MINUTE; - } else { - duration *= TIMER_SECOND; + int duration = Rule->MessageDelay * TICKS_PER_MINUTE; + if (TriggerRect.Y > 0) { + // The message list adds the timeout to TickCount as an int, so leave room for that sum. + duration = std::min(TriggerRect.Y, std::numeric_limits::max() / 2 / TIMER_SECOND) * TIMER_SECOND; } int color = TriggerRect.X * 2; diff --git a/manual/changes/text-trigger-color-and-duration.md b/manual/changes/text-trigger-color-and-duration.md index fc7b073e7..68b2a7f81 100644 --- a/manual/changes/text-trigger-color-and-duration.md +++ b/manual/changes/text-trigger-color-and-duration.md @@ -1,7 +1,7 @@ --- title: Choose a text trigger's color and display time category: feature -release: 0.2.0 +release: 0.3.0 targets: - type: action id: TACTION_TEXT_TRIGGER @@ -11,6 +11,6 @@ credit: - ZivDero --- -A Text Trigger action now takes its color and display duration from the first two of the four fields after the text line number. The first selects a color from `[Colors]`, counted from `0`; the second gives the display time in seconds. A map that leaves both fields at `0` keeps the first default color and `MessageDelay`. +A Text Trigger action now takes its color and display duration from the first two of the four fields after the text line number. The first selects a color by its position in the rules' `[Colors]`, counted from `0`; the second gives the display time in seconds. A map that leaves both fields at `0` keeps the first default color and `MessageDelay`. -Credits to ZivDero for their original Vinifera implementation for this feature. +ZivDero is credited for the Vinifera implementation this follows. diff --git a/manual/content/scripting/actions/11.md b/manual/content/scripting/actions/11.md index f03d58d98..c5b1de28b 100644 --- a/manual/content/scripting/actions/11.md +++ b/manual/content/scripting/actions/11.md @@ -5,11 +5,12 @@ title: Text Trigger... summary: Prints one numbered line of tutorial text over the tactical view in a chosen color and for a chosen time. valid_values: - The number of a line in the map's `[Tutorial]` section or in `TUTORIAL.INI`. - - A color's index in the rules' `[Colors]` list. + - A color's position in the rules' `[Colors]` list, from `0` to one less than the number of entries. - A whole number of seconds for the display time. caveats: - A text line number that neither the map nor `TUTORIAL.INI` holds prints nothing. The trigger's other actions still run. - - A color's index that does not match any color scheme uses the local player's color. + - A negative color position, or one past the end of the color list, shows the line in each player's own color, so players in a multiplayer game see different colors. + - New colors that a map's own `[Colors]` section adds are counted after the rules' list, in the map's order. A name the rules already declare keeps its rules position and color. - Tutorial lines share the on-screen message list with chat and game notices. The list shows six messages, and each new message after that removes the oldest, so later messages can take the line off the screen before its time is up. - A line too wide for the message area is split into several messages. Each part plays the incoming-message sound and can be pushed off the screen separately. related: @@ -38,6 +39,6 @@ Brief=1,11,0,121,2,30,0,0, ; line 121 in the third color, for about 30 seconds The color goes in the first of the four fields after the text line number, and the display time in the second. The last two fields are unused; write `0` for both. -Count the color position from `0`; `0` is the first entry of [`[Colors]`](/keys/color/). +Count the color position from `0`; `0` is the first entry of [`[Colors]`](/keys/color/) in the rules. A display time of `0` or less keeps the line on screen for [`MessageDelay`](/keys/messagedelay/). A positive time keeps it for that many seconds. Later messages can still push the line off before that time ends.