class_name UpgradeDef extends Resource ## One upgrade, as data. Every field here is a modifier the simulation already ## knows how to apply, so adding an upgrade is a table entry and never a branch ## in [SimWorld] -- the same rule bosses follow. ## ## Note what is NOT here: the flat +5% damage every upgrade carries. That is a ## property of *taking an upgrade*, not of any particular one, so it lives in ## [PlayerStats] where it is applied once per upgrade held. Baking it into each ## definition would mean seven places to change it and seven places to get it ## wrong. enum Rarity { COMMON, UNCOMMON, RARE, LEGENDARY } @export var id: StringName = &"upgrade" @export var display_name: String = "Upgrade" ## Shown on the choice card. Says what it does, in the player's terms. @export var description: String = "" @export var rarity: Rarity = Rarity.COMMON # --- Damage ----------------------------------------------------------------- ## Added to the additive pool: base x (1 + sum of these) x product of the ## multiplicative ones. Negative for the upgrades that trade damage away. @export var damage_add: float = 0.0 ## Multiplied in after the pool. Sniper is the only thing that uses this, and ## the brief calls it out as multiplicative specifically so it stays sharp no ## matter how many additive percentages have piled up. @export var damage_mult: float = 1.0 # --- Everything else -------------------------------------------------------- ## Multiplies the character's levelled maximum health, so the cost of trading ## health away scales instead of fading out by level 15. @export var max_hp_mult: float = 1.0 ## Below 1.0 means slower. Applied to the cooldown as a division, so 0.5 here is ## genuinely half the shots per second. @export var fire_rate_mult: float = 1.0 @export var bullet_speed_mult: float = 1.0 ## Extra projectiles fanned out to the sides of the aim. @export var side_shots: int = 0 ## Extra projectiles parallel to the aim, offset sideways. @export var parallel_shots: int = 0 ## How many times one shot may split on hitting something. The brief's "cannot ## split twice unless the upgrade is taken again" is exactly this being a count ## rather than a flag. @export var split_charges: int = 0 ## Fraction of a hit's damage dealt again over the poison window. @export var poison_fraction: float = 0.0 ## Chance, per tick, that a shot deletes an enemy projectile it is passing ## through. @export var erase_chance: float = 0.0 static func rarity_name(r: Rarity) -> String: match r: Rarity.COMMON: return "common" Rarity.UNCOMMON: return "uncommon" Rarity.RARE: return "rare" Rarity.LEGENDARY: return "legendary" return "?"