In the comment, base damage is prescribed as
# The base damage is "attacker.attack * action.multiplier - defender.defense".
which would calculate as (attacker.attack * action.multiplier) first, then less defender.defence.
The function coded updates damage akin to (attacker.attack - defender.defence) * action.multiplier. The result would be different.
If the intention was as described, just swap those last two lines around so damage *= multiplier, then damage -= defender.defence. Otherwise the describing comment needs correcting.
Looking at the code, it seems to me it matches the comment:
static func calculate_base_damage(action_data, attacker, defender) -> int:
var damage: float = calculate_potential_damage(action_data, attacker)
damage -= defender.stats.defense
Looking at it again with fresher eyes and mind, and the code makes sense. I'd noticed the weakness modifier as a multiplication within a few short adjacent lines affecting the damage variable and jumped at the usual BODMAS order of operations for math. But in this context, it's simply that the weakness is being applied as a scale after the regular base damage is calculated - essentially as a second calculation. So it is correct.
I've fixed it in my code with a new note to myself and keen to continue.
# (attacker.attack * action.multiplier) - defender.defence THEN scaled for element weakness
Thanks all the great content and support!