godot-genre-simulation
Expert blueprint for simulation and tycoon games (SimCity, RollerCoaster Tycoon, Factorio, Two Point Hospital) covering economy management, time progression, interconnected systems, NPC simulation, and feedback loops. Use when building management sims, tycoon games, city builders, or resource optimization games. Keywords tycoon, economy system, resource management, time scale, feedback loop, progression unlock, simulation tick.
What this skill does
# Genre: Simulation / Tycoon
Optimization, systems mastery, and satisfying feedback loops define management games.
## NEVER Do (Expert Anti-Patterns)
### Simulation & Economy
- NEVER use floating-point for primary currency; strictly use **Integer Cents** (or fixed-point math) to prevent accumulated precision errors in financial models.
- NEVER process 1000+ entities individually in `_process()`; strictly use a **Tick Manager** to batch updates or process entities in rotating pools.
- NEVER rely on linear cost scaling; strictly use **Exponential Growth** (`Base * pow(1.15, Level)`) to maintain challenge and strategic tension.
- NEVER hide critical metrics from the player; strictly provide **Detailed Breakdowns** (Income vs. Expense) so players can make optimization-based decisions.
- NEVER allow infinite resource stacking; strictly enforce **Logistical Caps** (warehouses/silos) to create meaningful space-management gameplay loops.
- NEVER let the early game become a "Waiting Simulator"; strictly **Front-Load Decisions** and quick early wins to build player momentum.
- NEVER modify a shared Resource directly; strictly use **`duplicate()`** to avoid unintentionally updating every building of that type.
- NEVER tie simulation logic to the visual framerate; strictly use **`_physics_process()`** or delta accumulators for deterministic simulation results.
### Performance & Threading
- NEVER update UI labels every frame; strictly use **Event-Driven Signals** to refresh UI ONLY when the underlying data changes.
- NEVER run heavy economic loops synchronously; strictly use **WorkerThreadPool** to offload complex calculations and prevent UI stutters.
- NEVER store massive resource data as Nodes; strictly use **`RefCounted`** or **Data Resources** to avoid the memory/CPU overhead of the SceneTree.
- NEVER ignore **`OS.low_processor_usage_mode`**; strictly enable it for stationary management screens to save massive CPU/Battery life.
- NEVER manipulate the SceneTree from background threads; strictly use **`call_deferred()`** for thread-safe UI updates.
- NEVER parse large JSON save files on the main thread; strictly use **Threaded Serialization** or optimized binary `.res` formats.
- NEVER use standard equality (==) for needs; strictly use **`is_equal_approx()`** to prevent floating-point jitter failures in logic gates.
---
## ๐ Expert Components (scripts/)
### Original Expert Patterns
- [sim_tick_manager.gd](scripts/sim_tick_manager.gd) - Variable-speed tick system decoupling simulation from rendering.
- [tycoon_economy.gd](scripts/tycoon_economy.gd) - Multi-resource economic engine with integer-precision currency.
### Modular Components
- [simulation_patterns.gd](scripts/simulation_patterns.gd) - Reusable patterns: AStarGrid2D logistics and low-processor modes.
---
## Economy Design
The heart of any tycoon game is its economy. Key principle: **multiple interconnected resources that force trade-offs**.
### Multi-Resource System
```gdscript
class_name TycoonEconomy
extends Node
signal resource_changed(resource_type: String, amount: float)
signal went_bankrupt
var resources: Dictionary = {
"money": 10000.0,
"reputation": 50.0, # 0-100
"workers": 0,
"materials": 100.0,
"energy": 100.0
}
var resource_caps: Dictionary = {
"reputation": 100.0,
"workers": 50,
"energy": 1000.0
}
func modify_resource(type: String, amount: float) -> bool:
if amount < 0 and resources[type] + amount < 0:
if type == "money":
went_bankrupt.emit()
return false # Can't go negative
resources[type] = clamp(
resources[type] + amount,
0,
resource_caps.get(type, INF)
)
resource_changed.emit(type, resources[type])
return true
```
### Income/Expense Tracking
```gdscript
class_name FinancialTracker
extends Node
var income_sources: Dictionary = {} # source_name: amount_per_tick
var expense_sources: Dictionary = {}
signal financial_update(profit: float, income: float, expenses: float)
func calculate_tick() -> float:
var total_income := 0.0
var total_expenses := 0.0
for source in income_sources.values():
total_income += source
for source in expense_sources.values():
total_expenses += source
var profit := total_income - total_expenses
financial_update.emit(profit, total_income, total_expenses)
return profit
```
---
## Time System
Simulation games need controllable time:
```gdscript
class_name SimulationTime
extends Node
signal time_tick(delta_game_hours: float)
signal day_changed(day: int)
signal speed_changed(new_speed: int)
enum Speed { PAUSED, NORMAL, FAST, ULTRA }
@export var seconds_per_game_hour := 30.0 # Real seconds
var current_speed := Speed.NORMAL
var speed_multipliers := {
Speed.PAUSED: 0.0,
Speed.NORMAL: 1.0,
Speed.FAST: 3.0,
Speed.ULTRA: 10.0
}
var current_hour := 8.0 # Start at 8 AM
var current_day := 1
func _process(delta: float) -> void:
if current_speed == Speed.PAUSED:
return
var game_delta := (delta / seconds_per_game_hour) * speed_multipliers[current_speed]
current_hour += game_delta
if current_hour >= 24.0:
current_hour -= 24.0
current_day += 1
day_changed.emit(current_day)
time_tick.emit(game_delta)
func set_speed(speed: Speed) -> void:
current_speed = speed
speed_changed.emit(speed)
```
---
## Entity Management
### Workers/NPCs
```gdscript
class_name Worker
extends Node
enum State { IDLE, WORKING, RESTING, COMMUTING }
@export var wage_per_hour: float = 10.0
@export var skill_level: float = 1.0 # Productivity multiplier
@export var morale: float = 80.0 # 0-100
var current_state := State.IDLE
var assigned_workstation: Workstation
func update(game_hours: float) -> void:
match current_state:
State.WORKING:
if assigned_workstation:
var productivity := skill_level * (morale / 100.0)
assigned_workstation.work(game_hours * productivity)
morale -= game_hours * 0.5 # Working tires workers
State.RESTING:
morale = min(100.0, morale + game_hours * 2.0)
func calculate_hourly_cost() -> float:
return wage_per_hour
```
### Buildings/Facilities
```gdscript
class_name Facility
extends Node3D
@export var build_cost: Dictionary # resource_type: amount
@export var operating_cost_per_hour: float = 5.0
@export var capacity: int = 5
@export var output_per_hour: Dictionary # resource_type: amount
var assigned_workers: Array[Worker] = []
var is_operational := true
var efficiency := 1.0
func calculate_output(game_hours: float) -> Dictionary:
if not is_operational or assigned_workers.is_empty():
return {}
var worker_efficiency := 0.0
for worker in assigned_workers:
worker_efficiency += worker.skill_level * (worker.morale / 100.0)
worker_efficiency /= capacity # Normalize to 0-1
var result := {}
for resource in output_per_hour:
result[resource] = output_per_hour[resource] * game_hours * worker_efficiency * efficiency
return result
```
---
## Customer/Demand System
```gdscript
class_name CustomerSimulation
extends Node
@export var base_customers_per_hour := 10.0
@export var demand_curve: Curve # Hour of day vs demand multiplier
var customer_queue: Array[Customer] = []
func generate_customers(game_hour: float, delta_hours: float) -> void:
var demand_mult := demand_curve.sample(game_hour / 24.0)
var reputation_mult := Economy.resources["reputation"] / 50.0 # 100 rep = 2x customers
var customers_to_spawn := base_customers_per_hour * delta_hours * demand_mult * reputation_mult
for i in int(customers_to_spawn):
spawn_customer()
func spawn_customer() -> void:
var customer := Customer.new()
customer.patience = randf_range(30.0, 120.0) # Seconds before leaving
customer.spending_budget = randf_range(Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.