Skip to content

[Lib] TraitReplace

DasKeifer edited this page Jun 10, 2026 · 2 revisions

Overview

This library allows for easily adding UI trait icons and texts by hijacking vanilla traits. I referenced some earlier work on replacing the flying icon to create this library to do so in a generic and flexible way while retaining the original icon and allowing it to be displayed. It supports and cycles between multiple icons. If you want the icon displayed on the board, consider using the trait library.

Any issues or concerns? Join the Redacted Rice Discord and @Das Keifer

Multiple Traits and Cycling

When multiple custom traits apply to the same pawn with a vanilla trait, the library handles them intelligently:

Icon Cycling: All applicable icons (vanilla + custom) will automatically cycle every 1.25 seconds on the game board. The cycling is synchronized across all trait types for a consistent visual experience.

Tooltip Descriptions: When hovering over a unit with multiple active traits, all trait descriptions (vanilla + custom) are combined and shown in a single tooltip with the heading "Extra Pawn Traits".

Priority Order: When multiple custom traits match a pawn, they are shown in this order:

  1. Vanilla trait icon (always shown first in cycle)
  2. func traits (highest priority)
  3. pilotSkill traits
  4. pawnType traits (lowest priority)

Within each category, traits are ordered by creation order (first created appears first in the cycle).

API

 

traitReplace

A library providing functionality for replacing and extending vanilla pawn traits with custom icons and descriptions.

This library allows you to add custom trait variations that cycle alongside the vanilla trait icon. When multiple custom traits apply to a pawn with a vanilla trait (like Massive or Flying), the icons will cycle every 1.25 seconds, and all descriptions will be combined in the tooltip.

The "massive" trait is registered by default as it is the best candidate for mechs, so you can immediately use traitReplace:add() without registering it first for massive. Other traits will need to be defined first

Note: This works great for massive but has some issues with flying as it does not account for the other UI flying icon appears on

 

registerTrait

Argument name Type Description
config table A table with fields describing the vanilla trait to register for replacement

The config object, passed as first argument, can have the following fields:

Field Type Description
id string The unique identifier for this trait (e.g., "massive", "flying")
checkMethod string The pawn method name to call to check if this trait applies (e.g., "IsMassive", "IsFlying")
iconFilename string The vanilla icon filename in img/combat/icons/ (e.g., "icon_massive.png")
descTitle string The text key for the vanilla trait title (e.g., "Status_massive_Title")
descText string The text key for the vanilla trait description (e.g., "Status_massive_Text")

 

Registers a vanilla trait to be replaced or extended with custom icons. This must be called before adding custom traits to a target trait. The "massive" trait is registered automatically by default.

Example:

local traitReplace = require(self.scriptPath.."traitReplace")

-- Register the flying trait for replacement
traitReplace:registerTrait({
    id = "flying",
    checkMethod = "IsFlying",
    iconFilename = "icon_flying.png",
    descTitle = "Status_Flying_Title",
    descText = "Status_Flying_Text",
})

 

add

Argument name Type Description
trait table A table with fields describing the custom trait being added

The trait object, passed as first argument, can have the following fields:

Field Type Description
targetTrait string (optional) The registered trait to add this custom trait to - defaults to "massive"
pawnType string (optional*) The pawn type to apply this custom trait to
pilotSkill string (optional*) The pilot skill to associate with this custom trait
func function (optional*) Function describing when to apply this custom trait to a unit
icon string Path to icon - relative to mod, or path to asset in resource.dat
desc_title string Displayed description title for custom trait
desc_text string Displayed description text for custom trait
desc table (optional) Alternative way to specify description as {title, text} or {title = "...", text = "..."}. If provided, overrides desc_title and desc_text

 

Adds a custom trait that will be displayed alongside the vanilla trait. The trait will cycle with the vanilla icon every 1.25 seconds, and the description will be combined in the tooltip.

Note*: Exactly one of func, pilotSkill and pawnType must be specified. If func is specified, pilotSkill and pawnType will be ignored. Likewise, if pilotSkill is specified, pawnType will be ignored.

If func is specified, the custom trait will be applied to a pawn if the function provided returns true for a pawn. The function will be called on every UI update. func has the following signature: func(trait, pawn, loc) where trait is the trait table of the trait being analyzed and pawn is the pawn being checked.

If pilotSkill is specified, the custom trait will be applied to any pawn that has a pilot with this pilot skill.

If pawnType is specified, the custom trait will be applied to any pawn of this type.

Example:

local traitReplace = require(self.scriptPath.."traitReplace")

-- Add a custom trait for massive mechs with a specific weapon
traitReplace:add({
    targetTrait = "massive",  -- optional, defaults to "massive"
    icon = "img/combat/icons/icon_shield.png",
    desc = { "Armored Massive", "This massive mech has additional armor plating" },
    func = function(trait, pawn)
        return pawn:GetMechName() == "TechnoVek_Mech" and pawn:GetWeaponCount() > 2
    end
})

-- Add a custom trait for all flying units with a specific pilot
traitReplace:add({
    targetTrait = "flying",
    icon = "img/combat/icons/icon_ace.png",
    desc_title = "Ace Pilot",
    desc_text = "This flying unit is piloted by an ace",
    pilotSkill = "AcePilot"
})

 

addStateful

Argument name Type Description
statefulTrait table A stateful trait definition with multiple visual states

The statefulTrait object can have the following fields:

Field Type Description
targetTrait string (optional) Registered vanilla trait to extend — defaults to "massive"
func function Required. Returns the active state index (1, 2, …) for the pawn, or nil/falsy if inactive
states table Required. Array of state objects (at least one)

Each entry in states supports:

Field Type Description
icon string Icon path for this state
desc_title string Tooltip title for this state
desc_text string Tooltip body for this state
desc table (optional) Shorthand {title, text} or {title = "...", text = "..."}

addStateful registers one underlying trait per state. The user's func is wrapped so only the matching state's icon/description is shown. Useful for traits that change appearance after use (e.g. Cheap Plating consumed).

Must be called before mod initialization completes (same timing as add — queued if called early).

Example:

local traitReplace = require(self.scriptPath.."traitReplace")

traitReplace:addStateful({
    targetTrait = "massive",
    func = function(trait, pawn)
        if not GAME or not GAME.myMod or not GAME.myMod.used[pawn:GetId()] then
            return 1  -- active / unused state
        end
        return 2      -- used state
    end,
    states = {
        {
            icon = "img/combat/icons/icon_armor_active.png",
            desc = { "Cheap Plating", "First hit this mission deals -3 damage." },
        },
        {
            icon = "img/combat/icons/icon_armor_used.png",
            desc = { "Cheap Plating (used)", "Already triggered this mission." },
        },
    },
})

Clone this wiki locally