103 lines
4.1 KiB
GDScript
103 lines
4.1 KiB
GDScript
extends Node2D
|
|
|
|
const CATALOG := preload("res://scripts/captain/captain_skills.gd")
|
|
const GENERATOR := preload("res://scripts/items/item_generator.gd")
|
|
const EXPLORATION := preload("res://scripts/levels/exploration_generator.gd")
|
|
const PLAYER := preload("res://scenes/game/player_ship.tscn")
|
|
const DEFINITION := preload("res://resources/items/plasma_cannon.tres")
|
|
var ship: CharacterBody2D
|
|
|
|
func snapshot() -> Dictionary:
|
|
var container := Node2D.new()
|
|
add_child(container)
|
|
EXPLORATION.spawn(container, {"planets": []}, ship)
|
|
var result := {}
|
|
for poi in container.get_children():
|
|
result[poi.get("poi_id")] = {"kind": poi.get("kind"), "position": poi.position, "reward_seed": poi.get("reward_seed")}
|
|
container.free()
|
|
return result
|
|
|
|
func count_kind(data: Dictionary, kind: String) -> int:
|
|
var count := 0
|
|
for poi in data.values():
|
|
if poi["kind"] == kind:
|
|
count += 1
|
|
return count
|
|
|
|
func _ready() -> void:
|
|
GameState.start_new_run()
|
|
ship = PLAYER.instantiate() as CharacterBody2D
|
|
ship.name = "PlayerShip"
|
|
add_child(ship)
|
|
ship.set_physics_process(false)
|
|
ship.get_node("WeaponController").set_physics_process(false)
|
|
assert(CATALOG.IDS.has("lucky") and CATALOG.IDS.has("explorer"))
|
|
for id in ["lucky", "explorer"]:
|
|
assert(not CATALOG.DATA[id]["active"])
|
|
assert(CATALOG.icon(id) != null)
|
|
assert(not CATALOG.description(id, 3).is_empty())
|
|
# Every roll threshold is exact, with 0% baseline and a hard level cap.
|
|
for rank in range(4):
|
|
GameState.captain.skills["lucky"] = rank
|
|
var chance: float = [0.0, 0.05, 0.1, 0.25][rank]
|
|
assert(is_equal_approx(GameState.captain.get_skill_bonus("lucky"), chance))
|
|
for roll in 1000:
|
|
assert(GameState.captain.roll_loot_level(10, float(roll) / 1000.0) == (11 if float(roll) / 1000.0 < chance else 10))
|
|
assert(GameState.captain.roll_loot_level(1000, 0.0) == 1000)
|
|
assert(GameState.captain.roll_loot_level(0, 0.99) == 1)
|
|
# Exercise actual drops, including stat scaling and the normal level generator.
|
|
seed(888)
|
|
var upgrades := 0
|
|
for index in 2000:
|
|
var item := GENERATOR.generate_loot(10, 0, DEFINITION)
|
|
assert(item.item_level in [10, 11])
|
|
if item.item_level == 11:
|
|
upgrades += 1
|
|
assert(upgrades == 0 if rank == 0 else absf(float(upgrades) / 2000.0 - chance) < 0.04)
|
|
assert(GENERATOR.generate_for_definition(DEFINITION, 10).item_level == 10)
|
|
# Both new skills participate in the normal level-up offer and training path.
|
|
for id in ["lucky", "explorer"]:
|
|
var captain := CaptainProgress.new()
|
|
for skill in CATALOG.IDS:
|
|
captain.skills[skill] = 3
|
|
captain.skills[id] = 2
|
|
captain.learning_points = 1
|
|
captain.prepare_skill_offers()
|
|
assert(captain.skill_offers == [id])
|
|
assert(captain.train_skill(id))
|
|
assert(captain.get_skill_rank(id) == 3)
|
|
# Each rank adds exactly 1/3/6 wrecks and leaves every base POI intact.
|
|
var baseline := {}
|
|
for rank in range(4):
|
|
GameState.start_new_run()
|
|
GameState.system_seed = 222
|
|
GameState.captain.skills["explorer"] = rank
|
|
var current := snapshot()
|
|
if rank == 0:
|
|
baseline = current
|
|
var bonus: int = [0, 1, 3, 6][rank]
|
|
assert(count_kind(current, "wreck") == count_kind(baseline, "wreck") + bonus)
|
|
assert(count_kind(current, "asteroid") == count_kind(baseline, "asteroid"))
|
|
for id in baseline:
|
|
assert(current[id] == baseline[id])
|
|
GameState.start_new_run()
|
|
GameState.system_seed = 222
|
|
var before := snapshot()
|
|
GameState.captain.skills["explorer"] = 3
|
|
GameState.captain.emit_changed()
|
|
assert(snapshot() == before) # Reloading the current board does not add wrecks.
|
|
GameState.system_seed = 333
|
|
var next_board := snapshot()
|
|
var rng := RandomNumberGenerator.new()
|
|
rng.seed = 333 ^ 0x504f49
|
|
assert(count_kind(next_board, "wreck") == rng.randi_range(2, 4) + 6)
|
|
GameState.explored_pois["333:1000"] = true
|
|
var reloaded := snapshot()
|
|
assert(not reloaded.has("333:1000"))
|
|
assert(reloaded.size() == next_board.size() - 1)
|
|
assert(GameState.exploration_wreck_bonuses[333] == 6)
|
|
GameState.start_new_run()
|
|
assert(GameState.exploration_wreck_bonuses.is_empty())
|
|
print("LUCKY_EXPLORER_TEST: PASS (0/5/10/25% luck, thresholds, 8000 drops, level cap/scaling, skill offers/training, +1/3/6 wrecks, stable base POIs, next-board application, reload/claimed-wreck persistence)")
|
|
get_tree().quit()
|