Compare commits
2 Commits
8e90447486
...
a3963fe36e
| Author | SHA1 | Date | |
|---|---|---|---|
| a3963fe36e | |||
| f4a6efe74f |
@ -7,6 +7,7 @@ const BALANCE := preload("res://scripts/captain/captain_balance.gd")
|
||||
@export var experience: int = 0
|
||||
@export var credits: int = 0
|
||||
@export var parts: float = 0.0
|
||||
@export var minerals: Dictionary = {"titanium": 0, "iron": 0, "aluminium": 0}
|
||||
@export var learning_points: int = 0
|
||||
@export var skills: Dictionary = {
|
||||
"piloting": 0, "gunner": 0, "mechanic": 0, "sharp_eye": 0,
|
||||
|
||||
@ -36,6 +36,7 @@ func _ready() -> void:
|
||||
camera.limit_bottom = int(WORLD_SIZE.y * 0.5)
|
||||
_spawn_celestial_bodies()
|
||||
_spawn_enemies()
|
||||
preload("res://scripts/levels/exploration_generator.gd").spawn(self, system_data, player)
|
||||
var marker := Control.new()
|
||||
marker.set_script(PLANET_MARKER)
|
||||
marker.name = "ProtectedPlanetMarker"
|
||||
|
||||
@ -7,6 +7,7 @@ var selected_ship_path: String = ""
|
||||
var restart_inventory: Dictionary = {}
|
||||
var system_level: int = 1
|
||||
var system_seed: int = 0
|
||||
var explored_pois: Dictionary = {}
|
||||
|
||||
func create_system_seed() -> int:
|
||||
var rng := RandomNumberGenerator.new()
|
||||
@ -18,6 +19,7 @@ func start_new_run() -> void:
|
||||
system_level = 1
|
||||
system_seed = create_system_seed()
|
||||
restart_inventory.clear()
|
||||
explored_pois.clear()
|
||||
|
||||
func _ready() -> void:
|
||||
var game_window := get_tree().root
|
||||
|
||||
@ -47,7 +47,11 @@ func can_combine(other: ItemAffixDefinition) -> bool:
|
||||
)
|
||||
|
||||
func roll_value(level: int) -> float:
|
||||
var bounds := get_value_range(level)
|
||||
return randf_range(bounds.x, bounds.y)
|
||||
|
||||
func get_value_range(level: int) -> Vector2:
|
||||
var progression := float(clampi(level, 1, 1000) - 1) / 999.0
|
||||
var lower := lerpf(minimum_value_level_1, minimum_value_level_1000, progression)
|
||||
var upper := lerpf(maximum_value_level_1, maximum_value_level_1000, progression)
|
||||
return randf_range(minf(lower, upper), maxf(lower, upper))
|
||||
return Vector2(minf(lower, upper), maxf(lower, upper))
|
||||
|
||||
@ -5,6 +5,18 @@ class_name ItemStatModifier
|
||||
@export var value: float = 0.0
|
||||
@export var affix: ItemAffixDefinition
|
||||
|
||||
# Fixed-value affixes and legacy modifiers have no roll quality to highlight.
|
||||
func get_roll_quality(level: int) -> int:
|
||||
if affix == null:
|
||||
return 0
|
||||
var bounds := affix.get_value_range(level)
|
||||
if is_equal_approx(bounds.x, bounds.y):
|
||||
return 0
|
||||
var fraction := clampf((value - bounds.x) / (bounds.y - bounds.x), 0.0, 1.0)
|
||||
if fraction >= 0.9 - 0.000001:
|
||||
return 2
|
||||
return 1 if fraction >= 0.75 - 0.000001 else 0
|
||||
|
||||
func get_display_text() -> String:
|
||||
var label := affix.display_name if affix else ItemInstance.stat_name(stat_key)
|
||||
var suffix := affix.unit if affix else ("%" if stat_key.ends_with("_percent") else "/s")
|
||||
|
||||
@ -8,7 +8,7 @@ const CARGO_SIZE := 20
|
||||
const WEAPON_SLOT_COUNT := 3
|
||||
const MISSILE_SLOT := 2
|
||||
const STARTING_MISSILE_AMMUNITION := 2
|
||||
const MISSILE_CRAFT_PARTS_COST := 50.0
|
||||
const MISSILE_CRAFT_PARTS_COST := 20.0
|
||||
const MISSILE_BUY_BASE_COST := 10
|
||||
const MISSILE_DEFINITIONS := [preload("res://resources/items/missile_launcher.tres"), preload("res://resources/items/unguided_missile.tres")]
|
||||
const MODULE_SLOT_COUNT := 6
|
||||
|
||||
@ -31,7 +31,7 @@ func _ready() -> void:
|
||||
_label = Label.new()
|
||||
_label.light_mask = 4
|
||||
_label.position = Vector2(-160, radius + 14)
|
||||
_label.size = Vector2(320, 54)
|
||||
_label.size = Vector2(320, 80)
|
||||
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_label.add_theme_font_size_override("font_size", 14)
|
||||
_update_label()
|
||||
|
||||
54
scripts/levels/exploration_generator.gd
Normal file
54
scripts/levels/exploration_generator.gd
Normal file
@ -0,0 +1,54 @@
|
||||
extends RefCounted
|
||||
|
||||
const POI := preload("res://scripts/levels/exploration_poi.gd")
|
||||
|
||||
static func spawn(game: Node2D, data: Dictionary, player: CharacterBody2D) -> void:
|
||||
var rng := RandomNumberGenerator.new()
|
||||
rng.seed = GameState.system_seed ^ 0x504f49
|
||||
var occupied: Array[Vector2] = []
|
||||
var wreck_count := rng.randi_range(2, 4)
|
||||
for index in wreck_count + rng.randi_range(6, 10):
|
||||
var kind := "wreck" if index < wreck_count else "asteroid"
|
||||
var candidate := Vector2.ZERO
|
||||
var found := false
|
||||
for attempt in 200:
|
||||
candidate = Vector2(rng.randf_range(-2300, 2300), rng.randf_range(-1500, 1500))
|
||||
if candidate.length() < 650 or candidate.distance_to(player.position) < 450:
|
||||
continue
|
||||
var clear := true
|
||||
for planet in data["planets"]:
|
||||
if candidate.distance_to(planet["position"]) < float(planet["radius"]) + 220:
|
||||
clear = false
|
||||
for point in occupied:
|
||||
if candidate.distance_to(point) < 180:
|
||||
clear = false
|
||||
if clear:
|
||||
found = true
|
||||
break
|
||||
if found:
|
||||
occupied.append(candidate)
|
||||
_add(game, player, kind, candidate, index, rng.randi())
|
||||
# Rare per system, at most one ruin on an uninhabited planet.
|
||||
if rng.randf() < 0.08:
|
||||
var candidates: Array[int] = []
|
||||
for index in data["planets"].size():
|
||||
if not data["planets"][index]["protected"]:
|
||||
candidates.append(index)
|
||||
if not candidates.is_empty():
|
||||
var index := candidates[rng.randi_range(0, candidates.size() - 1)]
|
||||
var planet := game.get_node("CelestialBodies/Planet%d" % (index + 1))
|
||||
_add(game, player, "ruin", planet.position, 100, rng.randi(), float(planet.get("radius")) + 100.0)
|
||||
|
||||
static func _add(game: Node2D, player: CharacterBody2D, kind: String, position: Vector2, index: int, reward_seed: int, approach_radius: float = 115.0) -> void:
|
||||
var id := "%d:%d" % [GameState.system_seed, index]
|
||||
if GameState.explored_pois.has(id):
|
||||
return
|
||||
var poi := StaticBody2D.new()
|
||||
poi.set_script(POI)
|
||||
poi.set("kind", kind)
|
||||
poi.set("poi_id", id)
|
||||
poi.set("reward_seed", reward_seed)
|
||||
poi.set("player", player)
|
||||
poi.set("approach_radius", approach_radius)
|
||||
poi.position = position
|
||||
game.add_child(poi)
|
||||
1
scripts/levels/exploration_generator.gd.uid
Normal file
1
scripts/levels/exploration_generator.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cx2fohii03ed6
|
||||
188
scripts/levels/exploration_poi.gd
Normal file
188
scripts/levels/exploration_poi.gd
Normal file
@ -0,0 +1,188 @@
|
||||
extends StaticBody2D
|
||||
|
||||
const GENERATOR := preload("res://scripts/items/item_generator.gd")
|
||||
const LOOT := preload("res://scripts/items/loot_pickup.gd")
|
||||
var kind := "wreck"
|
||||
var poi_id := ""
|
||||
var reward_seed := 1
|
||||
var player: CharacterBody2D
|
||||
var approach_radius := 115.0
|
||||
var hull := 20.0
|
||||
var _claimed := false
|
||||
var _module_left_outside := false
|
||||
var _label: Label
|
||||
var _rng := RandomNumberGenerator.new()
|
||||
var _mineral := "iron"
|
||||
var _points := PackedVector2Array()
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("exploration_pois")
|
||||
_rng.seed = reward_seed
|
||||
_mineral = ["iron", "aluminium", "titanium"][_rng.randi_range(0, 2)]
|
||||
hull = 20.0 * reward_scale()
|
||||
collision_layer = 4 if kind == "asteroid" else 0
|
||||
collision_mask = 0
|
||||
if kind == "asteroid":
|
||||
var shape := CollisionShape2D.new()
|
||||
var circle := CircleShape2D.new()
|
||||
circle.radius = 30
|
||||
shape.shape = circle
|
||||
add_child(shape)
|
||||
for index in 10:
|
||||
_points.append(Vector2.RIGHT.rotated(TAU * index / 10) * _rng.randf_range(23, 35))
|
||||
_label = Label.new()
|
||||
_label.light_mask = 4
|
||||
_label.position = Vector2(-160, 40)
|
||||
_label.size = Vector2(320, 70)
|
||||
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_label.add_theme_font_size_override("font_size", 12)
|
||||
if kind == "ruin":
|
||||
z_index = 20
|
||||
_label.position = Vector2(-40, -35)
|
||||
_label.size = Vector2(80, 70)
|
||||
_label.add_theme_font_size_override("font_size", 52)
|
||||
_label.add_theme_color_override("font_color", Color("ffd166"))
|
||||
_label.add_theme_color_override("font_outline_color", Color("151625"))
|
||||
_label.add_theme_constant_override("outline_size", 8)
|
||||
add_child(_label)
|
||||
_update_label(false)
|
||||
queue_redraw()
|
||||
|
||||
func reward_scale() -> float:
|
||||
return 1.0 + 0.05 * (clampi(GameState.system_level, 1, 1000) - 1)
|
||||
|
||||
func _draw() -> void:
|
||||
if kind == "asteroid":
|
||||
draw_colored_polygon(_points, Color("655e56"))
|
||||
var outline := _points.duplicate()
|
||||
outline.append(_points[0])
|
||||
draw_polyline(outline, Color("a39a88"), 2, true)
|
||||
draw_circle(Vector2(-8, -5), 7, Color("49443f"))
|
||||
elif kind == "wreck":
|
||||
draw_colored_polygon(PackedVector2Array([Vector2(-38, 20), Vector2(-16, -30), Vector2(7, -12), Vector2(22, 27), Vector2(-5, 14)]), Color("626b78"))
|
||||
draw_line(Vector2(-12, -20), Vector2(4, 15), Color("df9c67"), 3, true)
|
||||
draw_colored_polygon(PackedVector2Array([Vector2(28, -16), Vector2(42, -5), Vector2(29, 8)]), Color("434e60"))
|
||||
|
||||
func _update_label(near: bool) -> void:
|
||||
if kind == "ruin":
|
||||
_label.text = "?"
|
||||
elif kind == "asteroid":
|
||||
_label.text = "Asteroida · %s\nHP: %.0f" % [{"iron": "Żelazo", "aluminium": "Aluminium", "titanium": "Tytan"}[_mineral], hull]
|
||||
else:
|
||||
_label.text = ("Wrak statku" if kind == "wreck" else "Antyczne znalezisko") + ("\n[E] Przeszukaj" if near else "\nPodleć, aby przeszukać")
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if _claimed or not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
||||
return
|
||||
var near := global_position.distance_to(player.global_position) <= approach_radius
|
||||
_update_label(near)
|
||||
if near and (kind == "ruin" or (kind == "wreck" and Input.is_physical_key_pressed(KEY_E))):
|
||||
claim()
|
||||
|
||||
func take_weapon_hit(amount: float, _critical: bool = false) -> void:
|
||||
take_damage(amount)
|
||||
|
||||
func take_damage(amount: float) -> void:
|
||||
if kind != "asteroid" or _claimed:
|
||||
return
|
||||
hull -= maxf(0, amount)
|
||||
if hull <= 0:
|
||||
claim()
|
||||
else:
|
||||
_update_label(false)
|
||||
|
||||
func claim() -> bool:
|
||||
if _claimed or not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
||||
return false
|
||||
_claimed = true
|
||||
GameState.explored_pois[poi_id] = true
|
||||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||||
var summary := ""
|
||||
var scale := reward_scale()
|
||||
if kind == "asteroid":
|
||||
var amount := maxi(1, roundi(_rng.randi_range(1, 3) * scale))
|
||||
GameState.captain.minerals[_mineral] = int(GameState.captain.minerals.get(_mineral, 0)) + amount
|
||||
summary = "+%d %s" % [amount, {"iron": "żelaza", "aluminium": "aluminium", "titanium": "tytanu"}[_mineral]]
|
||||
elif kind == "ruin":
|
||||
var xp := roundi(_rng.randi_range(10, 20) * scale)
|
||||
GameState.captain.add_rewards(xp, 0)
|
||||
var module := _drop_module(true)
|
||||
summary = "%d XP oraz %s (poziom %d)" % [xp, module.definition.display_name, module.item_level]
|
||||
_show_discovery(summary)
|
||||
else:
|
||||
match _rng.randi_range(0, 3):
|
||||
0:
|
||||
var amount := roundi(_rng.randi_range(3, 8) * scale)
|
||||
GameState.captain.parts += amount
|
||||
summary = "+%d części" % amount
|
||||
1:
|
||||
_drop_module(false)
|
||||
summary = "Znaleziono moduł"
|
||||
2:
|
||||
var amount := maxi(1, roundi(scale))
|
||||
inventory.missile_ammunition += amount
|
||||
summary = "+%d rakiet" % amount
|
||||
3:
|
||||
var amount := roundi(_rng.randi_range(5, 15) * scale)
|
||||
inventory.ammunition += amount
|
||||
summary = "+%d amunicji" % amount
|
||||
inventory.ammunition_changed.emit()
|
||||
GameState.captain.emit_changed()
|
||||
if kind != "ruin":
|
||||
var popup := preload("res://scenes/game/damage_popup.tscn").instantiate() as Label
|
||||
popup.text = summary
|
||||
popup.set("text_color", Color("c9e8ff"))
|
||||
popup.position = position + Vector2(-80, -65)
|
||||
get_parent().add_child.call_deferred(popup)
|
||||
set_physics_process(false)
|
||||
queue_free()
|
||||
return true
|
||||
|
||||
func _show_discovery(reward: String) -> void:
|
||||
var layer := CanvasLayer.new()
|
||||
layer.layer = 30
|
||||
layer.name = "AncientDiscoveryMessage"
|
||||
get_parent().add_child(layer)
|
||||
var panel := PanelContainer.new()
|
||||
panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
layer.add_child(panel)
|
||||
panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER_TOP)
|
||||
panel.offset_left = -300
|
||||
panel.offset_right = 300
|
||||
panel.offset_top = 70
|
||||
var label := Label.new()
|
||||
label.custom_minimum_size = Vector2(600, 95)
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
label.add_theme_font_size_override("font_size", 18)
|
||||
label.add_theme_color_override("font_color", Color("ffd166"))
|
||||
label.text = "Znalazłeś ślady starożytnej upadłej cywilizacji!\nZdobyłeś: " + reward
|
||||
if _module_left_outside:
|
||||
label.text += "\nMagazyn pełny — moduł czeka obok planety."
|
||||
panel.add_child(label)
|
||||
var tween := layer.create_tween()
|
||||
tween.tween_interval(7.0)
|
||||
tween.tween_property(panel, "modulate:a", 0.0, 0.5)
|
||||
tween.tween_callback(layer.queue_free)
|
||||
|
||||
func _drop_module(ancient: bool) -> ItemInstance:
|
||||
var definitions: Array[ItemDefinition] = []
|
||||
for definition in GENERATOR.DEFINITIONS:
|
||||
if definition.category != ItemDefinition.Category.WEAPON:
|
||||
definitions.append(definition)
|
||||
var item := GENERATOR.generate_for_definition(definitions[_rng.randi_range(0, definitions.size() - 1)], mini(1000, GameState.system_level + (1 if ancient else 0)), 2 if ancient else 0)
|
||||
if ancient:
|
||||
for modifier in item.additional_modifiers:
|
||||
var bounds := modifier.affix.get_value_range(item.item_level)
|
||||
modifier.value = lerpf(bounds.x, bounds.y, _rng.randf_range(0.9, 1.0))
|
||||
if player.get_node("ShipInventory").add_item(item):
|
||||
return item
|
||||
_module_left_outside = true
|
||||
var loot := Node2D.new()
|
||||
loot.set_script(LOOT)
|
||||
loot.set("item", item)
|
||||
loot.position = position + Vector2(0, 70)
|
||||
get_parent().add_child.call_deferred(loot)
|
||||
return item
|
||||
1
scripts/levels/exploration_poi.gd.uid
Normal file
1
scripts/levels/exploration_poi.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dmmyfie4rijcn
|
||||
@ -124,16 +124,30 @@ func _make_custom_tooltip(for_text: String) -> Object:
|
||||
background.set_border_width_all(1)
|
||||
background.set_content_margin_all(12)
|
||||
panel.add_theme_stylebox_override("panel", background)
|
||||
var label := Label.new()
|
||||
label.text = for_text
|
||||
var label := RichTextLabel.new()
|
||||
label.fit_content = true
|
||||
label.scroll_active = false
|
||||
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
label.custom_minimum_size.x = 330
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
label.add_theme_font_size_override("font_size", 13)
|
||||
label.add_theme_font_size_override("normal_font_size", 13)
|
||||
var item := _inventory.get_item(slot_kind, slot_index)
|
||||
if item:
|
||||
background.bg_color = item.get_background_color()
|
||||
background.border_color = item.get_type_color()
|
||||
label.add_theme_color_override("font_color", Color("f1f4f8"))
|
||||
label.add_theme_color_override("default_color", Color("f1f4f8"))
|
||||
for line in for_text.split("\n"):
|
||||
var quality := 0
|
||||
if item:
|
||||
for modifier in item.additional_modifiers:
|
||||
if modifier != null and line == modifier.get_display_text():
|
||||
quality = modifier.get_roll_quality(item.item_level)
|
||||
break
|
||||
if quality > 0:
|
||||
label.push_color(Color("ffd166") if quality == 2 else Color("79e6a0"))
|
||||
label.add_text(("★ " if quality == 2 else "") + line + "\n")
|
||||
if quality > 0:
|
||||
label.pop()
|
||||
panel.add_child(label)
|
||||
return panel
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ var _inventory: ShipInventory
|
||||
var _drawer_open := false
|
||||
var _slide_tween: Tween
|
||||
var _missile_button: Button
|
||||
var _minerals_label: Label
|
||||
var drawer_width := 780.0
|
||||
|
||||
func _ready() -> void:
|
||||
@ -29,6 +30,10 @@ func _ready() -> void:
|
||||
_missile_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
_missile_button.pressed.connect(func() -> void: _inventory.craft_missile())
|
||||
missile_row.add_child(_missile_button)
|
||||
_minerals_label = Label.new()
|
||||
_minerals_label.add_theme_font_size_override("font_size", 12)
|
||||
$Contents.add_child(_minerals_label)
|
||||
$Contents.move_child(_minerals_label, $Contents/CargoGrid.get_index())
|
||||
_inventory = get_tree().get_first_node_in_group("ship_inventory") as ShipInventory
|
||||
if _inventory:
|
||||
_inventory.inventory_changed.connect(_refresh_title)
|
||||
@ -42,6 +47,7 @@ func _ready() -> void:
|
||||
_refresh_title()
|
||||
|
||||
func _refresh_title() -> void:
|
||||
_minerals_label.text = "SUROWCE · Tytan: %d · Żelazo: %d · Aluminium: %d" % [GameState.captain.minerals.get("titanium", 0), GameState.captain.minerals.get("iron", 0), GameState.captain.minerals.get("aluminium", 0)]
|
||||
craft_button.disabled = _inventory == null or not _inventory.can_craft_ammunition()
|
||||
_missile_button.disabled = _inventory == null or not _inventory.can_craft_missile()
|
||||
if _inventory:
|
||||
|
||||
@ -47,9 +47,9 @@ func _ready() -> void:
|
||||
weapons.set("missile_cooldown_remaining", 0.0)
|
||||
assert(not weapons.call("try_fire_missile"))
|
||||
assert(inventory.weapon_slots[2] == missile and ship.get("energy") == energy_before)
|
||||
GameState.captain.parts = 49.0
|
||||
GameState.captain.parts = 19.0
|
||||
assert(not inventory.craft_missile())
|
||||
GameState.captain.parts = 50.0
|
||||
GameState.captain.parts = 20.0
|
||||
assert(inventory.craft_missile() and GameState.captain.parts == 0.0)
|
||||
var unguided := ItemInstance.new()
|
||||
unguided.definition = ShipInventory.MISSILE_DEFINITIONS[1]
|
||||
@ -86,7 +86,7 @@ func _ready() -> void:
|
||||
if inventory.cargo[index] == null:
|
||||
inventory.cargo[index] = missile
|
||||
var ammo_before := inventory.missile_ammunition
|
||||
assert(inventory.craft_missile() and GameState.captain.parts == 50.0)
|
||||
assert(inventory.craft_missile() and GameState.captain.parts == 80.0)
|
||||
assert(inventory.buy_missile() and GameState.captain.credits == 70)
|
||||
assert(inventory.missile_ammunition == ammo_before + 2)
|
||||
addon.value = 100.0
|
||||
|
||||
72
tests/levels/exploration_test.gd
Normal file
72
tests/levels/exploration_test.gd
Normal file
@ -0,0 +1,72 @@
|
||||
extends Node2D
|
||||
const POI = preload("res://scripts/levels/exploration_poi.gd")
|
||||
func _ready() -> void:
|
||||
GameState.start_new_run()
|
||||
var ship = preload("res://scenes/game/player_ship.tscn").instantiate()
|
||||
ship.name = "PlayerShip"
|
||||
add_child(ship)
|
||||
ship.set_physics_process(false)
|
||||
ship.get_node("WeaponController").set_physics_process(false)
|
||||
var inv = ship.get_node("ShipInventory")
|
||||
for kind in ["wreck", "asteroid", "ruin"]:
|
||||
for index in 12:
|
||||
var poi = StaticBody2D.new()
|
||||
poi.set_script(POI)
|
||||
poi.kind = kind
|
||||
poi.player = ship
|
||||
poi.reward_seed = index + 1
|
||||
poi.poi_id = kind + str(index)
|
||||
add_child(poi)
|
||||
if kind == "asteroid":
|
||||
poi.take_weapon_hit(poi.hull - 1)
|
||||
assert(not poi._claimed and is_equal_approx(poi.hull, 1))
|
||||
poi.take_weapon_hit(1)
|
||||
assert(poi._claimed)
|
||||
else:
|
||||
assert(poi.claim())
|
||||
assert(not poi.claim())
|
||||
await get_tree().process_frame
|
||||
assert(GameState.captain.parts > 0)
|
||||
assert(inv.ammunition > 50 and inv.missile_ammunition > 2)
|
||||
assert(GameState.captain.minerals.iron + GameState.captain.minerals.titanium + GameState.captain.minerals.aluminium > 0)
|
||||
var ancient = 0
|
||||
var modules: Array = inv.cargo.filter(func(item): return item != null)
|
||||
for loot in get_tree().get_nodes_in_group("loot"):
|
||||
modules.append(loot.item)
|
||||
for item in modules:
|
||||
if item.item_level == 2:
|
||||
ancient += 1
|
||||
assert(item.get_addon_count() >= 4)
|
||||
for modifier in item.additional_modifiers:
|
||||
var bounds = modifier.affix.get_value_range(2)
|
||||
assert(modifier.value >= lerpf(bounds.x, bounds.y, 0.9) - 0.00001)
|
||||
assert(ancient == 12)
|
||||
var discovery = StaticBody2D.new()
|
||||
discovery.set_script(POI)
|
||||
discovery.kind = "ruin"
|
||||
discovery.player = ship
|
||||
discovery.poi_id = "auto-discovery"
|
||||
discovery.position = Vector2(1000, 0)
|
||||
discovery.approach_radius = 200
|
||||
add_child(discovery)
|
||||
assert(discovery._label.text == "?")
|
||||
discovery._physics_process(0)
|
||||
assert(not discovery._claimed)
|
||||
ship.position = Vector2(810, 0)
|
||||
discovery._physics_process(0)
|
||||
assert(discovery._claimed and GameState.explored_pois.has("auto-discovery"))
|
||||
assert(not discovery.claim())
|
||||
var data = preload("res://scripts/levels/system_generator.gd").generate(1, 1234)
|
||||
var bodies = Node2D.new()
|
||||
bodies.name = "CelestialBodies"
|
||||
add_child(bodies)
|
||||
preload("res://scripts/levels/exploration_generator.gd").spawn(self, data, ship)
|
||||
var generated = get_tree().get_nodes_in_group("exploration_pois").filter(func(p): return not p.is_queued_for_deletion())
|
||||
assert(generated.size() >= 8 and generated.size() <= 14)
|
||||
var probe = generated[0]
|
||||
assert(probe.reward_scale() == 1.0)
|
||||
GameState.system_level = 10
|
||||
assert(is_equal_approx(probe.reward_scale(), 1.45))
|
||||
GameState.system_level = 1
|
||||
print("EXPLORATION_TEST: PASS rewards, duplicate prevention, minerals, ancient level+1 and high addons, generation")
|
||||
get_tree().quit()
|
||||
1
tests/levels/exploration_test.gd.uid
Normal file
1
tests/levels/exploration_test.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bwrnlc3vjc2ty
|
||||
5
tests/levels/exploration_test.tscn
Normal file
5
tests/levels/exploration_test.tscn
Normal file
@ -0,0 +1,5 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
[ext_resource type="Script" path="res://tests/levels/exploration_test.gd" id="1"]
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user