Skill Base Values - MSUTeam/MSU GitHub Wiki
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.
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
<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.
<skill>.hardReset( _exclude = null );
// _exclude is an array of strings which are keys in a skill's m tableThis 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.
<skill>.resetField( _field );
// _field is a string which is a key in the skill's m tableThis function can be used to reset a particular field back to its base value e.g. <skill>.resetField(“Description”).
<skill>.getBaseValue( _field );
// _field is a string which is a key in the skill's m tableReturns the stored base value of the _field slot in the skill's m table.
<skill>.setBaseValue( _field, _value );
// _field is a string which is a key in the skill's m table
// _value can be any data typeSets the stored base value of the _field slot in the skill's m table to _value.
-
softReset()is called for all skills during the skill_container'supdate()function before any skill'sonUpdateis called. - The
HitChanceBonus,AdditionalAccuracyandAdditionalHitChancefields of a skill are reset during a call to the skill container'sbuildPropertiesForUsefunction 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.
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.
Vanilla added properties.SkillCostAdjustments in version 1.5.1. That system works similar to the Scheduled Changes system below, and has marked limitations compared to the base values system added by MSU. Therefore, MSU completely redirects the vanilla SkillCostAdjustments system to use the Base Values resetting system above. We recommend using the base values system instead of the vanilla one.
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.
<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 booleanIf _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);
}