extends Node2D const PLAYER := preload("res://scenes/game/player_ship.tscn") const AFFIX := preload("res://resources/items/affixes/luck_percent.tres") const GENERATOR := preload("res://scripts/items/item_generator.gd") func lucky_item(definition: ItemDefinition, amount: float) -> ItemInstance: var item := ItemInstance.new() item.definition = definition var modifier := ItemStatModifier.new() modifier.affix = AFFIX modifier.stat_key = "luck_percent" modifier.value = amount item.additional_modifiers.append(modifier) return item func _ready() -> void: GameState.start_new_run() assert(AFFIX.get_value_range(1).is_equal_approx(Vector2(0.5, 1.0))) assert(AFFIX.get_value_range(1000).is_equal_approx(Vector2(3.0, 6.0))) var last := Vector2.ZERO for level in [1, 10, 100, 500, 1000]: var bounds := AFFIX.get_value_range(level) assert(bounds.x >= last.x and bounds.y >= last.y) for index in 100: var roll := AFFIX.roll_value(level) assert(roll >= bounds.x and roll <= bounds.y) last = bounds assert(AFFIX.can_roll(preload("res://resources/items/plasma_cannon.tres"), 1)) assert(not AFFIX.can_roll(preload("res://resources/items/cloak.tres"), 1)) var ship := PLAYER.instantiate() as CharacterBody2D ship.name = "PlayerShip" add_child(ship) ship.set_physics_process(false) ship.get_node("WeaponController").set_physics_process(false) var inventory := ship.get_node("ShipInventory") as ShipInventory var item := lucky_item(preload("res://resources/items/compact_generator.tres"), 0.75) assert(item.get_tooltip_text().contains("Szczęście: +0.75 %")) assert(inventory.add_item(item)) assert(ship.call("get_luck_chance") == 0.0) # Cargo does not grant stats. assert(inventory.move_item("cargo", inventory.cargo.find(item), "module", 3)) assert(is_equal_approx(float(ship.call("get_luck_chance")), 0.0075)) GameState.captain.skills["lucky"] = 1 assert(is_equal_approx(float(ship.call("get_luck_chance")), 0.0575)) assert(GameState.captain.roll_loot_level(10, 0.0574, float(ship.get("luck_percent"))) == 11) assert(GameState.captain.roll_loot_level(10, 0.0575, float(ship.get("luck_percent"))) == 10) assert(inventory.move_item("module", 3, "cargo", inventory.cargo.find(null))) assert(is_equal_approx(float(ship.call("get_luck_chance")), 0.05)) # Combine strong equipment and rank III, with exactly one shared 60% cap. var reactor := lucky_item(preload("res://resources/items/compact_generator.tres"), 30.0) var engine := lucky_item(preload("res://resources/items/engine_extension.tres"), 30.0) for equipped in [reactor, engine]: assert(inventory.add_item(equipped)) var slot := ShipInventory.MODULE_CATEGORIES.find(equipped.definition.category) assert(inventory.move_item("cargo", inventory.cargo.find(equipped), "module", slot)) GameState.captain.skills["lucky"] = 3 assert(is_equal_approx(float(ship.call("get_luck_chance")), 0.6)) assert(GameState.captain.roll_loot_level(10, 0.59999, 60.0) == 11) assert(GameState.captain.roll_loot_level(10, 0.6, 60.0) == 10) assert(GameState.captain.roll_loot_level(1000, 0.0, 60.0) == 1000) assert(is_equal_approx(GameState.captain.get_luck_chance(100000.0), 0.6)) var stronger := lucky_item(reactor.definition, 50.0) var comparisons := inventory.get_item_comparison(stronger, reactor) for row in comparisons: assert(row["key"] != "luck_percent") # Already capped: no fictitious gain. seed(42) var upgrades := 0 for index in 1000: var loot := GENERATOR.generate_loot(10, 0, preload("res://resources/items/plasma_cannon.tres"), float(ship.get("luck_percent"))) if loot.item_level == 11: upgrades += 1 assert(upgrades >= 550 and upgrades <= 650) inventory.preserve_for_restart() var restored := PLAYER.instantiate() as CharacterBody2D add_child(restored) restored.set_physics_process(false) restored.get_node("WeaponController").set_physics_process(false) assert(is_equal_approx(float(restored.call("get_luck_chance")), 0.6)) print("LUCK_AFFIX_TEST: PASS (roll bounds/scaling, categories, cargo/equipment, skill stacking, strict 60% cap, thresholds, tooltips/comparison, 1000 drops, persistence)") get_tree().quit()