Server-authoritative Godot 4.6 strategy game. Includes the headless WebSocket game server, the browser client, and Nix packaging (server and web-export derivations plus a NixOS module) for deployment.
75 lines
2.7 KiB
GDScript
75 lines
2.7 KiB
GDScript
class_name ProtoBuilding
|
|
|
|
extends Resource
|
|
|
|
## Template for a city building. Concrete instances live under
|
|
## res://data/buildings and are edited in the inspector.
|
|
##
|
|
## Unlike Civilisation's one-off buildings, these can be levelled up and down.
|
|
## The build cost and the upkeep grow exponentially with the level (alpha^level)
|
|
## while the effects grow linearly or sublinear (see BuildingEffect), so pushing
|
|
## a building too high yields diminishing returns for an accelerating bill.
|
|
##
|
|
## The build cost is based on the owner's GDP: a flat base_cost plus a fraction
|
|
## of GDP, both multiplied by cost_alpha^level, so it stays meaningful as the
|
|
## economy grows.
|
|
|
|
## Effect stat keys consumed by GameState.
|
|
const EFFECT_GDP := "gdp"
|
|
const EFFECT_RESEARCH := "research"
|
|
const EFFECT_CULTURE := "culture"
|
|
const EFFECT_BUDGET_INCOME := "budget_income"
|
|
|
|
@export var name : String
|
|
@export_multiline var description : String
|
|
|
|
## Levels the building can reach; 0 means "not built".
|
|
@export var max_level : int = 10
|
|
|
|
## Flat part of the build cost, in budget currency.
|
|
@export var base_cost : float = 0.0
|
|
## Fraction of the owner's GDP added to the build cost.
|
|
@export var cost_gdp_fraction : float = 0.0
|
|
## Exponential cost growth per level (alpha in alpha^level).
|
|
@export_range(1.0, 5.0) var cost_alpha : float = 1.5
|
|
|
|
## Flat part of the hourly upkeep, in budget currency.
|
|
@export var base_upkeep : float = 0.0
|
|
## Fraction of the owner's GDP charged as hourly upkeep.
|
|
@export var upkeep_gdp_fraction : float = 0.0
|
|
## Exponential upkeep growth per level (alpha in alpha^level).
|
|
@export_range(1.0, 5.0) var upkeep_alpha : float = 1.5
|
|
|
|
## Fraction of the removed level's build cost refunded when downgrading.
|
|
@export_range(0.0, 1.0) var refund_fraction : float = 0.5
|
|
|
|
@export var effects : Array[BuildingEffect] = []
|
|
|
|
|
|
## Budget cost to raise the building from `level` to `level + 1`.
|
|
func build_cost(gdp: float, level: int) -> float:
|
|
return (base_cost + cost_gdp_fraction * maxf(gdp, 0.0)) * pow(cost_alpha, float(maxi(level, 0)))
|
|
|
|
|
|
## Budget refunded when lowering the building from `level` to `level - 1`.
|
|
func refund(gdp: float, level: int) -> float:
|
|
return build_cost(gdp, level - 1) * refund_fraction
|
|
|
|
|
|
## Budget upkeep per game hour while the building sits at `level`.
|
|
func upkeep(gdp: float, level: int) -> float:
|
|
if level <= 0:
|
|
return 0.0
|
|
var base := base_upkeep + upkeep_gdp_fraction * maxf(gdp, 0.0)
|
|
return base * pow(upkeep_alpha, float(level))
|
|
|
|
|
|
## Total contribution to `stat` at `level`, summed over every effect that feeds
|
|
## it. Returns 0.0 for an unknown stat or an unbuilt building.
|
|
func effect_value(stat: String, level: int) -> float:
|
|
var total := 0.0
|
|
for effect in effects:
|
|
if effect.stat == stat:
|
|
total += effect.value_at(level)
|
|
return total
|