class_name ArtifactMods extends RefCounted ## Artifact modification system. Applies trade-off modifiers to ability parameters. ## Artifacts are horizontal progression: they change HOW abilities work, not raw power. ## Represents a single artifact's modifier effect. class Modifier: var target_ability_id: String = "" # Which ability this modifies ("", or specific id) var stat_name: String = "" # What stat/param to modify (e.g., "damage_mult", "cooldown", "gcd_duration") var modification_type: int = 0 # 0 = additive, 1 = multiplicative var value: float = 0.0 var description: String = "" func _init(target: String, stat: String, mod_type: int, val: float, desc: String = ""): target_ability_id = target stat_name = stat modification_type = mod_type value = val description = desc ## Represents an equipped artifact. class EquippedArtifact: var id: String = "" var name: String = "" var slot: int = -1 # 0=Charm, 1=Ring, 2=Talisman, 3=Sigil var rarity: int = 0 # 0=Common, 1=Uncommon, 2=Rare, 3=Epic var modifiers: Array[Modifier] = [] func _init(id: String, name: String, slot: int, rarity: int): self.id = id self.name = name self.slot = slot self.rarity = rarity ## The modifier stack applies all equipped artifacts' modifications to base values. var _equipped: Array[EquippedArtifact] = [] # Max 4 (one per slot) ## Equips an artifact into its slot. Replaces any existing artifact in that slot. ## Returns true if successfully equipped, false if slot is invalid. func equip(artifact: EquippedArtifact) -> bool: if artifact.slot < 0 or artifact.slot > 3: return false # Remove existing artifact in this slot for i in _equipped.size(): if _equipped[i].slot == artifact.slot: _equipped[i] = artifact return true _equipped.append(artifact) return true ## Unequips an artifact by slot. func unequip(slot: int) -> void: for i in _equipped.size(): if _equipped[i].slot == slot: _equipped.remove_at(i) return ## Returns the equipped artifact for a given slot, or null. func get_artifact_for_slot(slot: int) -> EquippedArtifact: for art in _equipped: if art.slot == slot: return art return null ## Applies all relevant modifiers to a base value. ## ability_id: The ability being modified ("" = global modifiers like GCD). ## stat_name: Which stat to modify (e.g., "damage_mult", "cooldown", "gcd_duration"). ## base_value: The unmodified value. ## Returns the modified value. func apply_modifiers(ability_id: String, stat_name: String, base_value: float) -> float: var result := base_value for art in _equipped: for mod in art.modifiers: # Match: modifier targets this ability (or is global with "") if mod.target_ability_id != "" and mod.target_ability_id != ability_id: continue if mod.stat_name != stat_name: continue # Apply modification match mod.modification_type: 0: result += mod.value # Additive 1: result *= mod.value # Multiplicative return result ## Returns a summary of all active modifiers (for UI display). func get_modifier_summary() -> Array[Dictionary]: var summary: Array[Dictionary] = [] for art in _equipped: for mod in art.modifiers: summary.append({ "artifact_name": art.name, "stat": mod.stat_name, "type": "additive" if mod.modification_type == 0 else "multiplicative", "value": mod.value, "description": mod.description }) return summary ## Clears all equipped artifacts. func clear_all() -> void: _equipped.clear()