extends Node2D const PLAYER := preload("res://scenes/game/player_ship.tscn") const RECIPES := preload("res://scripts/items/crafting_recipes.gd") func _ready() -> void: GameState.start_new_run() 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 cargo_item := ItemInstance.new() cargo_item.definition = preload("res://resources/items/plasma_cannon.tres") inventory.cargo.fill(cargo_item) GameState.captain.parts = 100 GameState.captain.credits = 500 for id in RECIPES.IDS: var cost: Dictionary = RECIPES.DATA[id]["cost"] # Each missing ingredient must block the whole transaction. for missing in cost: GameState.captain.minerals.clear() for key in RECIPES.MINERALS: GameState.captain.minerals[key] = 5 GameState.captain.minerals[missing] = 0 var before := GameState.captain.minerals.duplicate() var stock_before := inventory.get_crafted_stock(id) assert(not inventory.craft(id)) assert(GameState.captain.minerals == before) assert(inventory.get_crafted_stock(id) == stock_before) for key in RECIPES.MINERALS: GameState.captain.minerals[key] = 5 var stock_before := inventory.get_crafted_stock(id) assert(inventory.craft(id)) assert(inventory.get_crafted_stock(id) == stock_before + int(RECIPES.DATA[id]["amount"])) for key in RECIPES.MINERALS: assert(GameState.captain.minerals[key] == 5 - int(cost.get(key, 0))) assert(inventory.get_cargo_used() == ShipInventory.CARGO_SIZE) assert(GameState.captain.credits == 500) assert(not inventory.craft("unknown")) # Sulfur is obtainable from an asteroid and uses the normal mining reward path. var asteroid := StaticBody2D.new() asteroid.set_script(preload("res://scripts/levels/exploration_poi.gd")) asteroid.set("kind", "asteroid") asteroid.set("poi_id", "crafting_sulfur_test") asteroid.set("player", ship) add_child(asteroid) asteroid.set("_mineral", "sulfur") # Isolate reward verification from the unrelated asteroid debris renderer. asteroid.set("_asteroid_sprite", null) var sulfur_before := int(GameState.captain.minerals["sulfur"]) assert(asteroid.call("claim")) assert(int(GameState.captain.minerals["sulfur"]) > sulfur_before) assert(not asteroid.call("claim")) # Exercise the actual workshop buttons and mixed-availability cost tooltip. var panel := PanelContainer.new() panel.set_script(preload("res://scripts/ui/ship_crafting_panel.gd")) add_child(panel) assert(panel.get("_resource_cards").size() == 5) assert(panel.get("_recipe_buttons").size() == 5) GameState.captain.minerals.merge({"titanium": 2, "iron": 0, "aluminium": 1}, true) GameState.captain.emit_changed() var button: Button = panel.get("_recipe_buttons")["parts"] var tooltip: PanelContainer = button.call("_make_custom_tooltip", "") var rows := tooltip.get_child(0) assert(rows.get_child(2).get_child(1).get_theme_color("font_color") == Color("85deb1")) assert(rows.get_child(3).get_child(1).get_theme_color("font_color") == Color("f08087")) tooltip.free() var parts_before := GameState.captain.parts button.pressed.emit() assert(GameState.captain.parts == parts_before) GameState.captain.minerals["iron"] = 1 GameState.captain.emit_changed() button.pressed.emit() assert(GameState.captain.parts == parts_before + 1) assert(GameState.captain.minerals["iron"] == 0) print("CRAFTING_RECIPES_TEST: PASS (all recipes, each missing ingredient, exact costs and yields, no partial charge, full cargo, sulfur mining, UI clicks, red/green tooltip)") get_tree().quit()