long-war-2 / lwotc

Port of Long War 2 to XCOM 2's War of the Chosen expansion
344 stars 90 forks source link

Enhancement: mark Commanding Officer in squad select #1524

Open Iridar opened 2 years ago

Iridar commented 2 years ago

Marking the commanding officer in squad select is something that my Cosmetic Rank Replacer already does, but it doesn't work as good in LWOTC, because my mod uses soldier rank to determine which officer is the commanding one, which may not necessarily hold true in LWOTC, where officer rank is separate from soldier rank. I plan to disable this functionality of my mod if LWOTC is present.

Displaying additional info on squad select for each soldier is very easy; it's made possible by robojumper's Squad Select. To do so, listen to the rjSquadSelect_ExtraInfo event, with a listener similar to this:

static function EventListenerReturn OnrjSquadSelect_ExtraInfo(Object EventData, Object EventSource, XComGameState GameState, Name EventID, Object CallbackObject)
{
    local LWTuple   Tuple;
    local LWTuple   NoteTuple;
    local LWTValue  Value;
    local int       SlotIndex;

    Tuple = LWTuple(EventData);

    if (Tuple == none || Tuple.Id != 'rjSquadSelect_ExtraInfo') return ELR_NoInterrupt;

    // This is the slot index of the soldier. Use it to determine if this particular soldier is the commanding officer.
    SlotIndex = Tuple.Data[0].i; 

    if (SlotIndex == FindCommandingOfficerSquadSlotIndex())
    {
        Value.kind = LWTVObject;

        NoteTuple = new class'LWTuple';
        NoteTuple.Data.Length = 3;

        NoteTuple.Data[0].kind = LWTVString;
        NoteTuple.Data[0].s = "Commanding Officer"; // Use a localized string here

        NoteTuple.Data[1].kind = LWTVString;
        NoteTuple.Data[1].s = class'UIUtilities_Colors'.const.HILITE_TEXT_HTML_COLOR; // Text color

        NoteTuple.Data[2].kind = LWTVString;
        NoteTuple.Data[2].s = "FFD700"; // Background color. Gold, in this case.

        Value.o = NoteTuple;
        Tuple.Data.AddItem(Value);
    }

    return ELR_NoInterrupt;
}

My function for determining which slot index has the commanding officer in it is as follows:

static final function int FindCommandingOfficerSquadSlotIndex()
{
    local XComGameState_HeadquartersXCom    XComHQ;
    local XComGameState_Unit                UnitState;
    local int                               iCommandingOfficerIndex;
    local int                               iCommandingOfficerRank;
    local XComGameStateHistory              History;
    local int i;

    History = `XCOMHISTORY;
    XComHQ = `XCOMHQ;
    iCommandingOfficerIndex = -1;

    for (i = 0; i < XComHQ.Squad.Length; i++)
    {
        UnitState = XComGameState_Unit(History.GetGameStateForObjectID(XComHQ.Squad[i].ObjectID));
        if (UnitState != none && IsUnitOfficer(UnitState) && UnitState.GetRank() > iCommandingOfficerRank)
        {
            iCommandingOfficerRank = UnitState.GetRank();
            iCommandingOfficerIndex = i;
        }
    }
    return iCommandingOfficerIndex;
}

Obviously it will be different for LWOTC, particularly you would want to use your own function that returns unit's officer rank instead of UnitState.GetRank().

Grobobobo commented 2 years ago

That does sound like something worth doing at some point.