MSUTeam / MSU

Modding Standards and Utilities for Battle Brothers
21 stars 4 forks source link

Affordability preview improved 2 #354

Open LordMidas opened 3 months ago

LordMidas commented 3 months ago

Should be used instead of #346 because this implements it in a way where the affordability preview is inherently usable in all pre-existing functions instead of introducing new functions.

Contains a few perf and refactor changes. But primarily:

The meat of this PR is the singular feat commit so you may wanna look at the diff of that commit to understand how the new system works.

This is a massive improvement over the current Affordability Preview system we have in MSU which I implemented in #88. That system is convoluted to work with from the user's perspective and is also limited in certain aspects. The new system is far more intuitive and in fact covers some edge cases which the old system failed in.

Old System (the one this PR deprecates):

New System:

Example: Let's say I have a skill which after at least 2 tiles reduces the AP cost of all attacks by 1. But this effect expires when you use any skill.

Old System usage:

function onAfterUpdate( _properties )
{
    if (this.getContainer().getActor().getTile().getDistanceTo(this.m.StartingTile) >= 2)
    {
        foreach (skill in this.getContainer().getAllSkillsOfType(::Const.SkillType.Active))
        {
            if (skill.isAttack() && skill.m.ActionPointCost > 1) // Notice we only want to decrease the AP cost if it is 2 or more
                skill.m.ActionPointCost -= 1;
        }
    }
}

function onAffordablePreview( _skill, _movementTile )
{
    // The character is previewing the usage of a skill, so we want to remove the AP cost reduction
    if (_skill != null)
    {
        foreach (skill in this.getContainer().getAllSkillsOfType(::Const.SkillType.Active))
        {           
            this.modifyPreviewField(skill, "ActionPointCost", 0, false);
        }
    }
    // The character is previewing a movement, so we want to apply the AP cost reduction if applicable
    else if (_movementTile != null)
    {
        // If we have already traveled at least 2 tiles this turn, we don't want to reduce the AP cost further
        if (this.getContainer().getActor().getTile().getDistanceTo(this.m.StartingTile) >= 2)
            return;

        if (_movementTile.getDistanceTo(this.getContainer().getActor().getTile()) >= 2)
        {
            foreach (skill in this.getContainer().getAllSkillsOfType(::Const.SkillType.Active))
            {   
                // Notice there is no way for us to first check here if the skill's AP cost         
                // is actually 2 or more at this point in the update cycle, because this onAffordablePreview function
                // doesn't work like that
            if (skill.isAttack())
                this.modifyPreviewField(skill, "ActionPointCost", -1 , false);
            }
        }
    }
}

New System:

function onAfterUpdate( _properties )
{
    local actor = this.getContainer().getActor();
    local isValid = false;
    if (actor.isPreviewing())
    {
        isValid = actor.getPreviewMovement() != null && actor.getPreviewMovement().End.getDistanceTo(this.m.StartingTile) >= 2;
    }
    else
    {
        isValid = actor.getTile().getDistanceTo(this.m.StartingTile) >= 2;
    }

    if (isValid)
    {
        foreach (skill in this.getContainer().getAllSkillsOfType(::Const.SkillType.Active))
        {
            if (skill.isAttack() && skill.m.ActionPointCost > 1) // Notice we only want to decrease the AP cost if it is 2 or more
                skill.m.ActionPointCost -= 1;
        }
    }
}

Help needed: One thing that I need Taro/Enduriel to improve in this system is that if the affordability preview would make a skill that is currently unaffordable affordable again, then we need to convey this information somehow. Currently, that skill's icon stays black&white because the vanilla affordability preview system only considers the case of currently affordable skills potentially becoming unaffordable and hence puts a "prohibited" icon on them. It does not expect currently unaffordable skills to become affordable. An idea for this case could be to put a green check mark on such skills to counter the red prohibited sign.

Relevant functions for achieving this are:

// in `turnsequencebar_module.js`:
TacticalScreenTurnSequenceBarModule.prototype.addSkillToList
TacticalScreenTurnSequenceBarModule.prototype.updateEntitySkillsPreview

// in `turn_sequence_bar.nut:`
setActiveEntityCostsPreview
resetActiveEntityCostsPreview
LordMidas commented 1 month ago

Postponed as I am going to first implement, test and polish this system over at the Modular Vanilla mod.