X2CommunityCore / X2WOTCCommunityHighlander

https://steamcommunity.com/workshop/filedetails/?id=1134256495
MIT License
60 stars 69 forks source link

Updated OnUnitDied to properly kill gremlins when their owner dies #1362

Closed BlackDog86 closed 3 weeks ago

BlackDog86 commented 4 months ago

Fixes #367

Tested under 4 standard conditions:

Gremlin attached to specialist 1 - Kill specialist 1 - Gremlin dies Gremlin attached to another unit - Kill other unit - Gremlin returns to specialist 1 Gremlin attached to another unit - Kill specialist 1 - Gremlin dies Gremlin attached to specialist 1 - Kill other unit - No effect

And 4 non-standard conditions:

Specialist 1 uses aid protocol on specialist 2 - Kill specialist 2 - Gremlin 1 returns to Specialist 1, Gremlin 2 dies Specialist 1 uses aid protocol on specialist 2 - Kill specialist 1 - Gremlin 1 dies, Gremlin 2 no effect Specialist 1 & 2 use aid protocol on each other - Kill both specialists at once - Both gremlins die Specialist 1 & 2 use aid protocol on 2 different units - Kill both units at once - Both gremlins return

BlackDog86 commented 3 months ago

Should be sorted

Iridar commented 2 months ago

I've refactored the code, could you please redo your four tests with this code?

function EventListenerReturn OnUnitDied(Object EventData, Object EventSource, XComGameState GameState, Name Event, Object CallbackData)
{
    local XComGameStateHistory History;
    local XComGameState_Unit UnitState, CosmeticUnit;
    local XComGameState NewGameState;
    local XComGameState_Item ItemState;
    local vector NewLocation;
    local XComGameStateContext_ChangeContainer ChangeContext;

    // Variable for Issue #367
    local XComGameState_Unit OwnerUnitState;

    // Start Issue #367
    /// HL-Docs: ref:Bugfixes; issue:367
    /// Gremlins now correctly die when the Gremlin's owner dies while the Gremlin is attached to another unit.

    UnitState = XComGameState_Unit(EventData);
    if (UnitState == none)
        return ELR_NoInterrupt;

    if (UnitState.ObjectID == OwnerStateObject.ObjectID)
    {
        // Owner of the Gremlin died, kill the Gremlin.

        History = `XCOMHISTORY;
        CosmeticUnit = XComGameState_Unit(History.GetGameStateForObjectID(CosmeticUnitRef.ObjectID));

        if (CosmeticUnit != none)
        {
            NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Owner Unit Died");
            ChangeContext = XComGameStateContext_ChangeContainer(NewGameState.GetContext());
            ChangeContext.BuildVisualizationFn = ItemOwnerDeathVisualization;
            CosmeticUnit = XComGameState_Unit(NewGameState.ModifyStateObject(CosmeticUnit.Class, CosmeticUnit.ObjectID));
            CosmeticUnit.SetCurrentStat(eStat_HP, 0);
            `GAMERULES.SubmitGameState(NewGameState);
        }
    }
    else if (UnitState.ObjectID == AttachedUnitRef.ObjectID)
    {
        // Unit to whom the Gremlin is attached to has died, recall the Gremlin and re-attach to its owner.

        History = `XCOMHISTORY;
        CosmeticUnit = XComGameState_Unit(History.GetGameStateForObjectID(CosmeticUnitRef.ObjectID));
        OwnerUnitState = XComGameState_Unit(History.GetGameStateForObjectID(OwnerStateObject.ObjectID));

        if (OwnerUnitState != none && CosmeticUnit != none)
        {
            NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Attached Unit Died");
            ItemState = XComGameState_Item(NewGameState.ModifyStateObject(Class, ObjectID));
            ItemState.AttachedUnitRef = OwnerStateObject;
            `GAMERULES.SubmitGameState(NewGameState);

            if (CosmeticUnit.TileLocation != OwnerUnitState.TileLocation)
            {
                NewLocation = `XWORLD.GetPositionFromTileCoordinates(OwnerUnitState.TileLocation);
                XGUnit(CosmeticUnit.GetVisualizer()).MoveToLocation(NewLocation);
            }
        }
    }
    // End Issue #367

    return ELR_NoInterrupt;
}

The bug with the original code happened mostly because it was convoluted and hard to read. Bad code. I don't doubt that the code you submitted fixes the bug, but it's still hard to read, so I've simplified it as much as possible.

BlackDog86 commented 3 weeks ago

Refactored code testing:

Gremlin attached to specialist 1 - Kill specialist 1 - Gremlin dies CONFIRMED Gremlin attached to another unit - Kill other unit - Gremlin returns to specialist 1 CONFIRMED Gremlin attached to another unit - Kill specialist 1 - Gremlin dies CONFIRMED Gremlin attached to specialist 1 - Kill other unit - No effect CONFIRMED

And 4 non-standard conditions:

Specialist 1 uses aid protocol on specialist 2 - Kill specialist 2 - Gremlin 1 returns to Specialist 1, Gremlin 2 dies CONFIRMED Specialist 1 uses aid protocol on specialist 2 - Kill specialist 1 - Gremlin 1 dies, Gremlin 2 no effect CONFIRMED Specialist 1 & 2 use aid protocol on each other - Kill both specialists at once - Both gremlins die CONFIRMED Specialist 1 & 2 use aid protocol on 2 different units - Kill both units at once - Both gremlins return CONFIRMED

Looks like everything is fine with the refactor

Iridar commented 3 weeks ago

Thank you.