Add gas bomber skill-shot vessel
This commit is contained in:
parent
d0a9f5b971
commit
1d9afcbc2e
28 changed files with 882 additions and 85 deletions
114
GameState.gd
114
GameState.gd
|
|
@ -410,6 +410,7 @@ func building_has_capability(building: Dictionary, capability: String) -> bool:
|
|||
# but transporters themselves belong to hubs and are never production orders.
|
||||
const VESSEL_INTERCEPTOR: String = "interceptor"
|
||||
const VESSEL_SHIELD: String = "shield"
|
||||
const VESSEL_GAS_BOMBER: String = "gas_bomber"
|
||||
const VESSEL_TRANSPORTER: String = "transporter"
|
||||
|
||||
# Compatibility constants for callers and old tests. Runtime metadata is
|
||||
|
|
@ -501,8 +502,11 @@ func unlock_vessel(vessel: String) -> bool:
|
|||
var definition: Resource = vessel_definition(vessel)
|
||||
if definition == null or definition.unlock_id == "" or vessel_is_unlocked(vessel) or not has_ship_lab():
|
||||
return false
|
||||
if not spend(definition.unlock_cost):
|
||||
var costs: Dictionary = research_costs(definition.unlock_id)
|
||||
if not can_afford_resources(costs):
|
||||
return false
|
||||
for resource_type in costs:
|
||||
bank_inventory.withdraw(String(resource_type), int(costs[resource_type]))
|
||||
vessel_levels[definition.unlock_id] = 1
|
||||
vessel_upgraded.emit(definition.unlock_id)
|
||||
return true
|
||||
|
|
@ -604,8 +608,16 @@ const PRODUCT_SHIP: String = "interceptor"
|
|||
|
||||
|
||||
func product_cost(product: String) -> int:
|
||||
return int(product_costs(product).get(RESOURCE_ORE, 0))
|
||||
|
||||
|
||||
func product_costs(product: String) -> Dictionary:
|
||||
var definition: Resource = vessel_definition(product)
|
||||
return definition.build_cost if definition != null else 0
|
||||
if definition == null:
|
||||
return {}
|
||||
if not definition.build_resource_costs.is_empty():
|
||||
return definition.build_resource_costs.duplicate()
|
||||
return {RESOURCE_ORE: definition.build_cost} if definition.build_cost > 0 else {}
|
||||
|
||||
|
||||
func can_produce(type: String) -> bool:
|
||||
|
|
@ -661,34 +673,53 @@ func cancel_order(id: int, index: int) -> bool:
|
|||
return false
|
||||
var order: Dictionary = orders[index]
|
||||
if bool(order.started):
|
||||
_inventory_for_record(b).deposit(RESOURCE_ORE, product_cost(String(order.product)))
|
||||
var inventory: RefCounted = _inventory_for_record(b)
|
||||
var costs: Dictionary = product_costs(String(order.product))
|
||||
for resource_type in costs:
|
||||
inventory.deposit(String(resource_type), int(costs[resource_type]))
|
||||
orders.remove_at(index)
|
||||
return true
|
||||
|
||||
|
||||
func outstanding_cost(id: int) -> int:
|
||||
return outstanding_resource_cost(id, RESOURCE_ORE)
|
||||
|
||||
|
||||
func outstanding_costs(id: int) -> Dictionary:
|
||||
var result: Dictionary = {}
|
||||
for resource_type in resource_types():
|
||||
var need: int = outstanding_resource_cost(id, resource_type)
|
||||
if need > 0:
|
||||
result[resource_type] = need
|
||||
return result
|
||||
|
||||
|
||||
func outstanding_resource_cost(id: int, resource_type: String) -> int:
|
||||
# What this building still needs delivered to clear everything queued.
|
||||
var b: Dictionary = find_building(id)
|
||||
if b.is_empty():
|
||||
return 0
|
||||
var need: int = 0
|
||||
for o in b.get("orders", []):
|
||||
# A started build has already paid, so it is not still owed.
|
||||
if not bool(o.started):
|
||||
need += product_cost(String(o.product))
|
||||
need += int(product_costs(String(o.product)).get(resource_type, 0))
|
||||
for order in b.get("research_orders", []):
|
||||
if not bool(order.started):
|
||||
need += research_cost(String(order.id))
|
||||
return maxi(need - _inventory_for_record(b).amount(RESOURCE_ORE), 0)
|
||||
need += int(research_costs(String(order.id)).get(resource_type, 0))
|
||||
return maxi(need - _inventory_for_record(b).amount(resource_type), 0)
|
||||
|
||||
|
||||
func deposit_to_building(id: int, amount: int) -> int:
|
||||
return deposit_resource_to_building(id, RESOURCE_ORE, amount)
|
||||
|
||||
|
||||
func deposit_resource_to_building(id: int, resource_type: String, amount: int) -> int:
|
||||
if amount <= 0:
|
||||
return 0
|
||||
var b: Dictionary = find_building(id)
|
||||
if b.is_empty():
|
||||
return 0
|
||||
return _inventory_for_record(b).deposit(RESOURCE_ORE, amount)
|
||||
return _inventory_for_record(b).deposit(resource_type, amount)
|
||||
|
||||
|
||||
func queue_order(id: int, product: String = PRODUCT_SHIP) -> bool:
|
||||
|
|
@ -717,14 +748,20 @@ func _advance_production(delta: float) -> void:
|
|||
# this did before #23) leaves nothing to see or cancel.
|
||||
var order: Dictionary = orders[0]
|
||||
var product: String = String(order.product)
|
||||
var cost: int = product_cost(product)
|
||||
var costs: Dictionary = product_costs(product)
|
||||
var inventory: RefCounted = _inventory_for_record(b)
|
||||
var definition: Resource = vessel_definition(product)
|
||||
|
||||
if not bool(order.started):
|
||||
if inventory.amount(RESOURCE_ORE) < cost:
|
||||
var affordable := true
|
||||
for resource_type in costs:
|
||||
if inventory.amount(String(resource_type)) < int(costs[resource_type]):
|
||||
affordable = false
|
||||
break
|
||||
if not affordable:
|
||||
continue
|
||||
inventory.withdraw(RESOURCE_ORE, cost)
|
||||
for resource_type in costs:
|
||||
inventory.withdraw(String(resource_type), int(costs[resource_type]))
|
||||
order.started = true
|
||||
|
||||
order.elapsed = float(order.elapsed) + delta
|
||||
|
|
@ -764,8 +801,17 @@ func lab_research_order(lab_id: int) -> Dictionary:
|
|||
|
||||
|
||||
func research_cost(id: String) -> int:
|
||||
return int(research_costs(id).get(RESOURCE_ORE, 0))
|
||||
|
||||
|
||||
func research_costs(id: String) -> Dictionary:
|
||||
var unlock_definition: Resource = vessel_for_unlock(id)
|
||||
return unlock_definition.unlock_cost if unlock_definition != null else upgrade_cost(id)
|
||||
if unlock_definition != null:
|
||||
if not unlock_definition.unlock_resource_costs.is_empty():
|
||||
return unlock_definition.unlock_resource_costs.duplicate()
|
||||
return {RESOURCE_ORE: unlock_definition.unlock_cost} if unlock_definition.unlock_cost > 0 else {}
|
||||
var cost: int = upgrade_cost(id)
|
||||
return {RESOURCE_ORE: cost} if cost > 0 else {}
|
||||
|
||||
|
||||
func _advance_lab_research(delta: float) -> void:
|
||||
|
|
@ -778,12 +824,18 @@ func _advance_lab_research(delta: float) -> void:
|
|||
var order: Dictionary = orders[0]
|
||||
var id: String = String(order.id)
|
||||
var unlock_definition: Resource = vessel_for_unlock(id)
|
||||
var cost: int = research_cost(id)
|
||||
var costs: Dictionary = research_costs(id)
|
||||
var inventory: RefCounted = _inventory_for_record(lab)
|
||||
if not bool(order.started):
|
||||
if inventory.amount(RESOURCE_ORE) < cost:
|
||||
var affordable := true
|
||||
for resource_type in costs:
|
||||
if inventory.amount(String(resource_type)) < int(costs[resource_type]):
|
||||
affordable = false
|
||||
break
|
||||
if not affordable:
|
||||
continue
|
||||
inventory.withdraw(RESOURCE_ORE, cost)
|
||||
for resource_type in costs:
|
||||
inventory.withdraw(String(resource_type), int(costs[resource_type]))
|
||||
order.started = true
|
||||
order.elapsed = float(order.elapsed) + delta
|
||||
if float(order.elapsed) < lab_research_time():
|
||||
|
|
@ -1129,7 +1181,13 @@ func _dispatch_transporters() -> void:
|
|||
_begin_leg(chosen_extractor, transporter_position(chosen_extractor), extractor.position,
|
||||
TRANSPORTER_TO_EXTRACTOR)
|
||||
for b in buildings:
|
||||
if outstanding_cost(int(b.id)) <= 0:
|
||||
var needed_resource := ""
|
||||
for resource_type in resource_types():
|
||||
if outstanding_resource_cost(int(b.id), resource_type) > 0 \
|
||||
and bank_inventory.amount(resource_type) > 0:
|
||||
needed_resource = resource_type
|
||||
break
|
||||
if needed_resource == "":
|
||||
continue
|
||||
# One at a time per building: without this every idle transporter
|
||||
# would be sent after the same shortfall and they would all arrive
|
||||
|
|
@ -1149,6 +1207,7 @@ func _dispatch_transporters() -> void:
|
|||
if chosen.is_empty():
|
||||
return # every transporter is busy
|
||||
chosen.target_id = int(b.id)
|
||||
chosen.resource_type = needed_resource
|
||||
_begin_leg(chosen, transporter_position(chosen), mothership, TRANSPORTER_TO_MOTHERSHIP)
|
||||
|
||||
|
||||
|
|
@ -1175,22 +1234,24 @@ func _arrive(t: Dictionary) -> void:
|
|||
match t.state:
|
||||
TRANSPORTER_TO_MOTHERSHIP:
|
||||
var target: Dictionary = find_building(int(t.target_id))
|
||||
var want: int = outstanding_cost(int(t.target_id))
|
||||
var take: int = mini(mini(want, bank_inventory.amount(RESOURCE_ORE)), transporter_load_limit())
|
||||
var resource_type: String = String(t.get("resource_type", RESOURCE_ORE))
|
||||
var want: int = outstanding_resource_cost(int(t.target_id), resource_type)
|
||||
var take: int = mini(mini(want, bank_inventory.amount(resource_type)), transporter_load_limit())
|
||||
if take <= 0 or target.is_empty():
|
||||
# Nothing to carry, or the building is gone. Go home empty.
|
||||
t.target_id = 0
|
||||
_begin_leg(t, here, hub_pos if hub_pos != null else here, TRANSPORTER_RETURNING)
|
||||
return
|
||||
bank_inventory.withdraw(RESOURCE_ORE, take)
|
||||
bank_inventory.withdraw(resource_type, take)
|
||||
t.carrying = take
|
||||
_begin_leg(t, here, target.position, TRANSPORTER_TO_BUILDING)
|
||||
TRANSPORTER_TO_BUILDING:
|
||||
# The ore moves at exactly the moment the vessel arrives.
|
||||
if deposit_to_building(int(t.target_id), int(t.carrying)) <= 0:
|
||||
# Building demolished in transit - put the ore back rather
|
||||
# The cargo moves at exactly the moment the vessel arrives.
|
||||
var resource_type: String = String(t.get("resource_type", RESOURCE_ORE))
|
||||
if deposit_resource_to_building(int(t.target_id), resource_type, int(t.carrying)) <= 0:
|
||||
# Building demolished in transit - put the cargo back rather
|
||||
# than quietly destroying it.
|
||||
bank_inventory.deposit(RESOURCE_ORE, int(t.carrying))
|
||||
bank_inventory.deposit(resource_type, int(t.carrying))
|
||||
t.carrying = 0
|
||||
t.target_id = 0
|
||||
_begin_leg(t, here, hub_pos if hub_pos != null else here, TRANSPORTER_RETURNING)
|
||||
|
|
@ -1226,6 +1287,13 @@ func can_afford(cost: int) -> bool:
|
|||
return bank_inventory.amount(RESOURCE_ORE) >= cost
|
||||
|
||||
|
||||
func can_afford_resources(costs: Dictionary) -> bool:
|
||||
for resource_type in costs:
|
||||
if bank_inventory.amount(String(resource_type)) < int(costs[resource_type]):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
func spend(cost: int) -> bool:
|
||||
if not can_afford(cost):
|
||||
return false
|
||||
|
|
|
|||
Loading…
Reference in a new issue