191 lines
8.3 KiB
GDScript3
191 lines
8.3 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Headless test: run with
|
||
|
|
# godot --headless -s res://tests/test_local_costs_use_hold.gd
|
||
|
|
# Forgejo #158: "any costs local to a building (creating a ship in the ship
|
||
|
|
# crafter, researching in the lab...) can also be paid thanks to the ship
|
||
|
|
# inventory."
|
||
|
|
#
|
||
|
|
# #12 made a building's production cost resources physically DELIVERED to it
|
||
|
|
# rather than money out of the bank, and that principle stands - the bank is
|
||
|
|
# still not raided from here. What changes is that the fleet's own hold
|
||
|
|
# counts as well, because it is the one other place resources physically
|
||
|
|
# are: a hull that flew in carrying gas can hand it over, and making the
|
||
|
|
# player park, open the transfer menu and move it across by hand was
|
||
|
|
# ceremony rather than a decision.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. a crafter with an empty stock builds out of the fleet's hold
|
||
|
|
# B. the building's OWN stock is spent first - what was hauled in goes
|
||
|
|
# before the hold the player is still flying around with
|
||
|
|
# C. a cost split across both is taken from both
|
||
|
|
# D. the bank is still not touched: banked ore alone does not start an
|
||
|
|
# order, which is the #12 rule this must not quietly undo
|
||
|
|
# E. all or nothing - an order that cannot be paid for takes nothing
|
||
|
|
# F. the same for lab research
|
||
|
|
# G. and only WHERE THE FLEET IS. A crafter across the map must not reach
|
||
|
|
# into the hold and spend ore the player withdrew to carry elsewhere -
|
||
|
|
# which is the same complaint that got automatic banking removed in #24,
|
||
|
|
# arriving from the other direction. test_manual_supply_route caught the
|
||
|
|
# first draft of this doing exactly that.
|
||
|
|
|
||
|
|
var game_state: Node
|
||
|
|
var crafter_id: int = 0
|
||
|
|
var lab_id: int = 0
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_LOCAL_COSTS_USE_HOLD: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|
||
|
|
|
||
|
|
|
||
|
|
# Emptied rather than replaced: GameState.INVENTORY is reached through the
|
||
|
|
# autoload's name, which an `extends SceneTree` script cannot compile.
|
||
|
|
func _reset() -> void:
|
||
|
|
for resource_type in game_state.resource_types():
|
||
|
|
var id: String = String(resource_type)
|
||
|
|
game_state.bank_inventory.set_amount(id, 0)
|
||
|
|
game_state.fleet_inventory.set_amount(id, 0)
|
||
|
|
game_state.building_inventory(crafter_id).set_amount(id, 0)
|
||
|
|
game_state.building_inventory(lab_id).set_amount(id, 0)
|
||
|
|
game_state.fleet_inventory.total_capacity = 500
|
||
|
|
for b in game_state.buildings:
|
||
|
|
b["orders"] = []
|
||
|
|
b["research_orders"] = []
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
# GameState is an autoload: a bare GameState.<instance member> does not
|
||
|
|
# compile in a SceneTree script, so the node is fetched by name instead.
|
||
|
|
game_state = root.get_node("GameState")
|
||
|
|
game_state.reset_new_game()
|
||
|
|
game_state.intro_active = false
|
||
|
|
game_state.reset_quests()
|
||
|
|
game_state.build_time_scale = 0.02
|
||
|
|
crafter_id = game_state.add_building(GameState.BUILDING_SHIP_CRAFTER, Vector2.ZERO)
|
||
|
|
lab_id = game_state.add_building(GameState.BUILDING_SHIP_LAB, Vector2(500.0, 0.0))
|
||
|
|
# Parked on the crafter. The hold only pays for what the fleet is
|
||
|
|
# standing at - see G below, which is the half of #158 that matters.
|
||
|
|
game_state.fleet_position = Vector2.ZERO
|
||
|
|
|
||
|
|
var cost: int = int(game_state.product_costs(GameState.VESSEL_INTERCEPTOR).get(
|
||
|
|
GameState.RESOURCE_ORE, 0))
|
||
|
|
if cost <= 1:
|
||
|
|
_fail("an interceptor costs %d ore - nothing here would be measurable" % cost)
|
||
|
|
return
|
||
|
|
|
||
|
|
# --- A. built out of the hold alone ---------------------------------
|
||
|
|
_reset()
|
||
|
|
game_state.fleet_inventory.deposit(GameState.RESOURCE_ORE, cost)
|
||
|
|
if not game_state.queue_order(crafter_id, GameState.VESSEL_INTERCEPTOR):
|
||
|
|
_fail("the order would not queue")
|
||
|
|
return
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
var order: Dictionary = game_state.order_list(crafter_id)[0]
|
||
|
|
if not bool(order.started):
|
||
|
|
_fail("a crafter with the fleet parked on it and %d ore aboard did not start" % cost)
|
||
|
|
return
|
||
|
|
if game_state.fleet_resource(GameState.RESOURCE_ORE) != 0:
|
||
|
|
_fail("the hold still holds %d after paying" \
|
||
|
|
% game_state.fleet_resource(GameState.RESOURCE_ORE))
|
||
|
|
return
|
||
|
|
print("an empty crafter built out of the fleet's hold (%d ore)" % cost)
|
||
|
|
|
||
|
|
# --- B and C. the building's own stock goes first -------------------
|
||
|
|
_reset()
|
||
|
|
for b in game_state.buildings:
|
||
|
|
b["orders"] = []
|
||
|
|
var in_building: int = cost - 1
|
||
|
|
game_state.building_inventory(crafter_id).set_amount(GameState.RESOURCE_ORE, in_building)
|
||
|
|
game_state.fleet_inventory.deposit(GameState.RESOURCE_ORE, 5)
|
||
|
|
game_state.queue_order(crafter_id, GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
if not bool(game_state.order_list(crafter_id)[0].started):
|
||
|
|
_fail("a cost split across the crafter and the hold did not start")
|
||
|
|
return
|
||
|
|
if game_state.building_resource(crafter_id, GameState.RESOURCE_ORE) != 0:
|
||
|
|
_fail("the crafter's own %d ore was not spent first - %d left" \
|
||
|
|
% [in_building, game_state.building_resource(crafter_id, GameState.RESOURCE_ORE)])
|
||
|
|
return
|
||
|
|
if game_state.fleet_resource(GameState.RESOURCE_ORE) != 4:
|
||
|
|
_fail("the hold paid %d, expected to cover the last 1" \
|
||
|
|
% (5 - game_state.fleet_resource(GameState.RESOURCE_ORE)))
|
||
|
|
return
|
||
|
|
print("stock first, then the hold: %d from the crafter and 1 from the fleet" % in_building)
|
||
|
|
|
||
|
|
# --- D. the bank is still not raided --------------------------------
|
||
|
|
_reset()
|
||
|
|
game_state.bank_inventory.set_amount(GameState.RESOURCE_ORE, 5000)
|
||
|
|
game_state.queue_order(crafter_id, GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
if bool(game_state.order_list(crafter_id)[0].started):
|
||
|
|
_fail("the order started out of the BANK - #12's rule is undone")
|
||
|
|
return
|
||
|
|
if game_state.banked_resource(GameState.RESOURCE_ORE) != 5000:
|
||
|
|
_fail("the bank was charged %d for an order that did not start" \
|
||
|
|
% (5000 - game_state.banked_resource(GameState.RESOURCE_ORE)))
|
||
|
|
return
|
||
|
|
print("banked ore alone does not start an order, and is not touched")
|
||
|
|
|
||
|
|
# --- E. all or nothing ----------------------------------------------
|
||
|
|
_reset()
|
||
|
|
game_state.fleet_inventory.deposit(GameState.RESOURCE_ORE, cost - 1)
|
||
|
|
game_state.queue_order(crafter_id, GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
if bool(game_state.order_list(crafter_id)[0].started):
|
||
|
|
_fail("an order started one ore short")
|
||
|
|
return
|
||
|
|
if game_state.fleet_resource(GameState.RESOURCE_ORE) != cost - 1:
|
||
|
|
_fail("an order that could not be paid for still took %d from the hold" \
|
||
|
|
% (cost - 1 - game_state.fleet_resource(GameState.RESOURCE_ORE)))
|
||
|
|
return
|
||
|
|
print("one short takes nothing at all")
|
||
|
|
|
||
|
|
# --- F. and the lab does the same -----------------------------------
|
||
|
|
_reset()
|
||
|
|
var upgrade: String = "int_damage"
|
||
|
|
var research: Dictionary = game_state.research_costs(upgrade)
|
||
|
|
if research.is_empty():
|
||
|
|
_fail("the upgrade %s costs nothing - F would prove nothing" % upgrade)
|
||
|
|
return
|
||
|
|
game_state.research_points = 99
|
||
|
|
game_state.fleet_position = Vector2(500.0, 0.0)
|
||
|
|
for resource_type in research:
|
||
|
|
game_state.fleet_inventory.deposit(String(resource_type), int(research[resource_type]))
|
||
|
|
if not game_state.queue_lab_research(lab_id, upgrade):
|
||
|
|
_fail("the research would not queue")
|
||
|
|
return
|
||
|
|
game_state._advance_lab_research(0.01)
|
||
|
|
if not bool(game_state.lab_research_order(lab_id).started):
|
||
|
|
_fail("research did not start from the fleet's hold")
|
||
|
|
return
|
||
|
|
for resource_type in research:
|
||
|
|
if game_state.fleet_resource(String(resource_type)) != 0:
|
||
|
|
_fail("the hold still holds %s after paying for research" % resource_type)
|
||
|
|
return
|
||
|
|
print("a lab researches out of the hold too (%s)" % str(research))
|
||
|
|
|
||
|
|
# --- G. and not from across the map ---------------------------------
|
||
|
|
_reset()
|
||
|
|
game_state.fleet_position = Vector2(9000.0, 9000.0)
|
||
|
|
game_state.fleet_inventory.deposit(GameState.RESOURCE_ORE, cost * 4)
|
||
|
|
game_state.queue_order(crafter_id, GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
if bool(game_state.order_list(crafter_id)[0].started):
|
||
|
|
_fail("a crafter on the far side of the map started out of the fleet's hold")
|
||
|
|
return
|
||
|
|
if game_state.fleet_resource(GameState.RESOURCE_ORE) != cost * 4:
|
||
|
|
_fail("a distant crafter took %d from the hold" \
|
||
|
|
% (cost * 4 - game_state.fleet_resource(GameState.RESOURCE_ORE)))
|
||
|
|
return
|
||
|
|
# ...and flying back is all it takes.
|
||
|
|
game_state.fleet_position = Vector2.ZERO
|
||
|
|
game_state._advance_production(0.01)
|
||
|
|
if not bool(game_state.order_list(crafter_id)[0].started):
|
||
|
|
_fail("the order did not start once the fleet was parked on the crafter")
|
||
|
|
return
|
||
|
|
print("out of range it takes nothing; parked on it, the same order starts")
|
||
|
|
|
||
|
|
print("TEST_LOCAL_COSTS_USE_HOLD: PASS")
|
||
|
|
quit(0)
|