Skill Base Values - MSUTeam/MSU GitHub Wiki

Description

In vanilla BB, skills are often tightly coupled, so if one skill wants to modify a parameter in another skill, the two are tightly coupled via a function. Secondly, in vanilla BB, many parameters of skills cannot be changed in increments e.g. ActionPointCost. If a skill changes its ActionPointCost via an increment e.g. += 1 during its onUpdate or onAfterUpdate function, then the value of the ActionPointCost will continue to increase indefinitely every time that function is called.

Let's take a random attack skill, Thrust, as an example. Let's say we have a skill that modifies the AP cost of Thrust by -1. The way to do this in vanilla would be:

function onAfterUpdate( _properties )
{
    this.m.ActionPointCost = this.getContainer().hasSkill("ourSkill") ? 3 : 4;
}

Such a value is very hard for modders to modify without changing the entire onAfterUpdate function.

MSU's Automated Resetting feature allows overcoming both of these problems in an elegant way, allowing you to write clean code for example like this:

// in ourSkill
function onAfterUpdate( _properties )
{
    local thrust = this.getContainer().getSkillByID("actives.thrust");
    if (thrust != null)
    {
        thrust.m.ActionPointCost -= 1;
    }
}

This method keeps things encapsulated. Thrust doesn't need to know anything about whether ourSkill exists or not. Furthermore, it allows modders to modify the parameters of Thrust without breaking compatibility.

Storing and setting base values

MSU stores the base values of a skill's m table immediately when a container is assigned to the skill via the setContainer function (which happens during the skill container's add function). MSU provides several functions to reset the m table of a skill back to its base values.

  • Soft reset
  • Hard reset
  • Resetting a particular field

Soft reset

<skill>.softReset();

This function resets the following fields of the skill's m table, but more fields can be added or removed by modders.

  • ActionPointCost
  • FatigueCost
  • FatigueCostMult
  • MinRange
  • MaxRange

softReset() is automatically called during the update() function of the skill_container before any skills' onUpdate or onAfterUpdate are called.

Hard reset

<skill>.hardReset( _exclude = null );
// _exclude is an array of strings which are keys in a skill's m table

This function is never automatically called, but can be manually called to reset every value in the m table back to its original value except the Order, Type, and IsNew fields and any field names passed in the optional _exclude array.

Reset a field

<skill>.resetField( _field );
// _field is a string which is a key in the skill's m table

This function can be used to reset a particular field back to its base value e.g. <skill>.resetField(“Description”).

Get a field's base value

<skill>.getBaseValue( _field );
// _field is a string which is a key in the skill's m table

Returns the stored base value of the _field slot in the skill's m table.

Set a field's base value

<skill>.setBaseValue( _field, _value );
// _field is a string which is a key in the skill's m table
// _value can be any data type

Sets the stored base value of the _field slot in the skill's m table to _value.

Automated Resetting

  • softReset() is called for all skills during the skill_container's update() function before any skill's onUpdate is called.
  • The HitChanceBonus, AdditionalAccuracy and AdditionalHitChance fields of a skill are reset during a call to the skill container's buildPropertiesForUse function using this skill. This allows other skills to modify these fields of the skill in increments without having to worry about infinite runaway changes. As these values are used in the generation of tooltips as well, this helps ensure that the tooltips are properly generated.

Example

This system allows changing a value in a skill’s m table in increments rather than assigning it particular values, which opens up possibilities for flexible and compatible modding. For example, now you can do:

function onAfterUpdate( _properties )
{
    this.m.ActionPointCost -= 1;
}

In the original game, doing this will cause the action point cost of the skill to continue to reduce indefinitely on every call to this function. However, with the MSU resetting system, this will ensure that the skill’s action point cost is only reduced by 1 compared to its base cost. Another mod can then hook the same function and add or subtract from the cost in further increments.

Scheduled Changes

Skills in Battle Brothers are updated in the order of their SkillOrder. Imagine we have two skills:

  • Skill A with this.m.SkillOrder = this.Const.SkillOrder.First
  • Skill B with this.m.SkillOrder = this.Const.SkillOrder.Any

Whenever the skill_container runs its update() or buildPropertiesForUse (which calls the onAnySkillUsed function in skills) functions, the respective functions are called on the skills in the order of their SkillOrder. Hence, skill A will update before skill B in the above example.

If you want skill A to modify something in skill B after skill B’s update, you would have to change the order of skill A to be something later than that of skill B e.g. set skill A’s order to this.Const.SkillOrder.Last. Usually this is quite doable. However, there may be cases where you absolutely want skill A to be updated before skill B but still want skill A to be able to change something in skill B when skill B is updated. MSU allows you to do this via the scheduleChange function.

Multiple changes to the same skill can be scheduled by using the function multiple times. Scheduled changes are executed in the update() function of skill_container after the onAfterUpdate functions for all skills have run.

Usage

<skill>.scheduleChange( _field, _change, _set = false );
// _field is a string which is a key in the skill's m table
// _change can be a string, boolean or integer depending on the type of the field's value
// _set is a boolean

If _set is true, sets the value of _field to _change and if false and if _field points to an integer or string value, adds _change to the value of _field.

The following code is written in skill A and will reduce the action point cost of skill B by 1 even if skill A updates before skill B:

function onUpdate( _properties )
{
    skillB.scheduleChange(“ActionPointCost”, -1);
}
⚠️ **GitHub.com Fallback** ⚠️