extends RefCounted const E = preload("res://world/owniverse/math/exact.gd") const GREEN = "#40cc40" const RED = "#ff6060" const GREY = "#888888" const Parameters = preload("res://world/owniverse/world_parameters.gd") static func number(value, digits: int = 0) -> String: if not E.finite(value): return "—" return E.grouped(value, digits, false) static func colored(text: String, color: String) -> String: return E.add(E.add(E.add(E.add("[color=", color), "]"), text), "[/color]") static func matches(world, id: String) -> Array: var result: Array = [] for key in world.catalog.entities: var entity = world.catalog.entities[key] if ((E.eq(key, id) or E.eq(entity.count_as, id)) or E.eq(entity.group_as, id)): if (not world.catalog.is_group(key)): result.append(key) return result static func quantities(world, id: String) -> Dictionary: var free: Variant = 0 var total: Variant = 0 var physical: Dictionary = world.ledger.physical_amounts(world.state) for key in matches(world, id): free = E.add(free, world.state.amount.get(key, 0)) total = E.add(total, physical.get(key, 0)) if E.eq(id, "SMBH"): free = world.state.amount.get(id, 0) total = free return {"free": free, "total": total} static func costs(world, global: Node, id: String) -> String: if (not world.catalog.entities.has(id)): return "" var lines: PackedStringArray = [] for requirements in [world.catalog.entities[id].cost, world.catalog.entities[id].bind]: for resource in requirements: var required: Variant = requirements[resource] if E.lt(required, 0): continue var available: Variant = E.floor_value(world.ledger.available(world.state, resource)) var name: String = str(global.get_template(resource, "Entity", "Name").get("text", resource)) lines.append(colored(E.add(E.add(E.add(E.add(E.add(name, ": "), number(required)), " ("), number(available)), ")"), (GREEN if E.ge(available, required) else RED))) return "\n".join(lines) static func variables(world, global: Node, id: String, rate: Variant = 0.0) -> Dictionary: var counts: Dictionary = quantities(world, id) var show_total: bool = false for key in matches(world, id): show_total = (show_total or E.eq(world.catalog.entities[key].group_as, "Planet")) var amount: String = (number((counts.total if show_total else counts.free)) if world.catalog.entities.has(id) else "—") if ((not show_total) and E.gt(counts.total, counts.free)): amount = E.add(amount, E.add(" ", colored(E.add(E.add("(", number(counts.total)), ")"), GREY))) if E.ne(rate, 0): amount = E.add(amount, E.add(" | ", colored(E.add((("−" if E.lt(rate, 0) else "+")), number(E.absolute(rate), 1)), (RED if E.lt(rate, 0) else GREEN)))) var physical: Dictionary = world.ledger.physical_amounts(world.state) var voids: Variant = 0 for key in physical: voids = E.add(voids, E.multiply(physical[key], world.catalog.entities[key].voids)) var he: Variant = world.state.amount.get("He", 0) var h: Variant = world.state.amount.get("H", 0) var mixture: String = "—" if E.gt(E.add(he, h), 0): mixture = E.add(E.add(E.add(E.add("He: ", number(E.mul_div(100, he, (E.add(he, h))), 2)), "% / H: "), number(E.mul_div(100, h, (E.add(he, h))), 2)), "%") var environment: Dictionary = world.environment.stellar_environment(world.state) return {"amount": amount, "colored costs": costs(world, global, id), "lifespan": (number(world.catalog.entities[id].lifespan) if world.catalog.entities.has(id) else "—"), "voids": number(voids), "he / h": E.add("\n", mixture), "metallicity": E.add(number(E.multiply(environment.metallicity, 100), 2), "%"), "энергия": number(world.state.energy), "плотность": number(environment.density, 6), "лет в секунду": number(world.state.speed_in_year), "amount1": "—", "amount2": "—", "amount3": "—", "amount4": "—"} static func render(world, global: Node, id: String, category: String = "Entity", rate: Variant = 0.0) -> String: var values: Dictionary = variables(world, global, id, rate) if E.eq(category, "Indicator"): if E.eq(id, "Density"): id = Parameters.density_display(world.environment.stellar_environment(world.state).density).mode var scales: Dictionary = {"Burnability": "Bur", "Explosiveness": "Exp", "Aggression": "Agg"} if scales.has(id): var level: Variant = Parameters.value(world.state, scales[id]) values.amount = number(level, (1 if E.ne(level, E.floor_value(level)) else 0)) values.scale = global.render_template(global.get_template(E.add("Scale", str(clampi(E.integer(E.round_value(level)), 1, 19))), "Indicator", "Scale"), {}) if E.eq(id, "Trends"): for trend in Parameters.TRENDS: values[trend.to_lower()] = E.add(number(E.multiply(world.state.get("trends", {}).get(trend, 0), 100), 2), "%") if E.eq(id, "Energy"): values["энергия"] = E.add(E.add(E.add(number(world.state.energy), " ("), number(E.multiply(E.clamp_value(E.divide(world.state.energy, Parameters.INITIAL_ENERGY), 0, 1), 100), 2)), "%)") var title: String = global.render_template(global.get_template(id, category, "Name"), values) var body: String = global.render_template(global.get_template(id, category, "Description"), values) return E.add(E.add(E.add("[b]", ((title if E.ne(title, "") else id))), "[/b]\n"), body)