547 lines
22 KiB
GDScript
547 lines
22 KiB
GDScript
class_name Tile
|
||
extends Resource
|
||
## Single hex tile data. Holds terrain, overlays, ownership, and per-player visibility.
|
||
## Resource class (not Node) — lightweight, serializable, no scene tree dependency.
|
||
|
||
const ImprovementScript: GDScript = preload("res://engine/src/entities/improvement.gd")
|
||
|
||
var biome_id: String = "" # biome classification result
|
||
var substrate_id: String = "" # geological substrate from elevation
|
||
var water_body_id: int = -1 # water body index (-1 if land)
|
||
var water_body_type: String = "" # pond/river/lake/large_lake/ocean
|
||
var depth_from_coast: int = -1 # BFS distance from land (-1 if land)
|
||
var soil_type: String = "" # rocky/sandy/clay/loam/peat/volcanic_ash/permafrost
|
||
var is_river_mouth: bool = false # true if water tile adjacent to both river and ocean
|
||
var has_cave: bool = false # true if cave system present (mountain/highland with geology marker)
|
||
|
||
## Axial coordinates (q, r) — primary position key
|
||
var position: Vector2i = Vector2i.ZERO
|
||
|
||
## Overlay resource ID from resources.json (e.g. "mithril_vein"), empty if none
|
||
var resource_id: String = ""
|
||
|
||
## Tile improvement type (e.g. "farm", "mine", "road"), empty if none
|
||
var improvement: String = ""
|
||
|
||
## Owning player index, -1 = unclaimed
|
||
var owner: int = -1
|
||
|
||
## Lair type ID from wilds.json (e.g. "beast_den"), empty if no lair
|
||
var lair_type: String = ""
|
||
|
||
## Per-player visibility state: player_index → int
|
||
## 0 = unexplored, 1 = fog of war (previously seen), 2 = currently visible
|
||
var visibility: Dictionary = {}
|
||
|
||
## Render metadata — populated by MapGenerator, used by tileset renderer
|
||
## Texture variant selector (deterministic from position + seed)
|
||
var variation_index: int = 0
|
||
## Raw noise values [0,1] for gradient coloring in the renderer
|
||
var elevation: float = 0.0
|
||
var moisture: float = 0.0
|
||
var temperature: float = 0.0
|
||
## Hex edge indices (0-5) that have rivers flowing along them
|
||
var river_edges: Array[int] = []
|
||
## River flow per edge: edge_index → accumulation value (0.0 = no river, <0 = frozen)
|
||
var river_flow: Dictionary = {}
|
||
## Total upstream drainage accumulation at this tile
|
||
var flow_accumulation: float = 0.0
|
||
## Lake group ID, -1 = not part of a lake
|
||
var lake_id: int = -1
|
||
## River source type: "", "snowmelt", "spring", "hot_spring", "glacial"
|
||
var river_source_type: String = ""
|
||
## True if this land tile is adjacent to water (for beach/shore transitions)
|
||
var is_coastal: bool = false
|
||
|
||
## Tile quality tier: 1=nascent, 2=standard, 3=mature
|
||
var quality: int = 2
|
||
## Ticks accumulated toward the next quality change
|
||
var quality_progress: int = 0
|
||
## Wind speed at this tile [0,1]
|
||
var wind_speed: float = 0.5
|
||
## Wind direction as hex edge index (0=E, 1=NE, 2=NW, 3=W, 4=SW, 5=SE)
|
||
var wind_direction: int = 0
|
||
## Cultural pressure accumulated from enemy cities (for ownership flip).
|
||
## Resets to 0 after a flip. Not bounded — flip_threshold determines ownership change.
|
||
var culture_pressure: float = 0.0
|
||
## Per-turn heat forcing from active spells (transient, not saved)
|
||
var magic_heat_delta: float = 0.0
|
||
## Per-turn moisture forcing from active spells (transient, not saved)
|
||
var magic_moisture_delta: float = 0.0
|
||
## City mitigation: aerosol cooling/drying scaled down by this fraction [0, 1].
|
||
## Written each turn by economy.gd from protection building effects. Not saved.
|
||
var aerosol_mitigation: float = 0.0
|
||
## Ley line mana density [0,1]. 0.0 = dead zone, 1.0 = nexus.
|
||
var mana_density: float = 0.0
|
||
## Number of ley line edges passing through or adjacent to this tile.
|
||
var ley_line_count: int = 0
|
||
## Dominant school of ley lines at this tile ("" = none/neutral).
|
||
var ley_school: String = ""
|
||
## True when a Death-school spell has corrupted this ley segment.
|
||
var ley_corrupted: bool = false
|
||
## Residue school left by a spell cast on this tile ("" = none).
|
||
var ley_residue_school: String = ""
|
||
## Residue strength [0,1] — decays each turn.
|
||
var ley_residue_strength: float = 0.0
|
||
## Turns remaining for residue decay. 0 = no residue.
|
||
var ley_residue_turns: int = 0
|
||
|
||
## Fish stock for marine resource tiles [0, 100]. -1 = not a marine resource tile.
|
||
## 0 with resource_id == "" = permanently dead (exhausted or reef-killed).
|
||
var fish_stock: int = -1
|
||
## Coral reef health [0.0, 1.0]. Only meaningful when resource_id == "coral_reef".
|
||
var reef_health: float = 1.0
|
||
## Active marine bloom turns remaining (iron seeding or spell effect). 0 = no bloom.
|
||
var marine_bloom_turns: int = 0
|
||
## Corrupted marine creature occupying this tile ("" = none, e.g. "wraith_eel").
|
||
var marine_creature: String = ""
|
||
|
||
## -- Flora fields (Layer 3) --
|
||
## Tree canopy density [0-1]. Drives biome classification, shade, lumber yield.
|
||
var canopy_cover: float = 0.0
|
||
## Ground-level vegetation [0-1]. Drives food yield, movement cost, habitat quality.
|
||
var undergrowth: float = 0.0
|
||
## Mycorrhizal network [0-1]. Drives ecosystem resilience, regrowth speed.
|
||
var fungi_network: float = 0.0
|
||
|
||
## -- Flora tracking --
|
||
## Consecutive turns with moisture < desertification_threshold.
|
||
var drought_counter: int = 0
|
||
## Turns at high canopy toward succession.
|
||
var succession_progress: int = 0
|
||
## Regrowth stage: -1=none, 0=barren, 1=scrub, 2=young_forest, 3=forest.
|
||
var regrowth_stage: int = -1
|
||
## Turns spent in current regrowth stage.
|
||
var regrowth_turns: int = 0
|
||
|
||
## -- Fauna tracking --
|
||
## Per-turn computed habitat suitability [0-1]. NOT serialized (recalculated each turn).
|
||
var habitat_suitability: float = 0.0
|
||
## Consecutive turns with habitat_suitability < abandon_threshold.
|
||
var habitat_low_turns: int = 0
|
||
## Landmark name set when tile crosses Q4 quality threshold.
|
||
var landmark_name: String = ""
|
||
|
||
## Ground loot: items dropped on this tile from dead units.
|
||
## Array of { "item_id": String, "charges_remaining": int, "turns_remaining": int }
|
||
var ground_items: Array = []
|
||
|
||
## Ley anchor strength injected by a geological ecological event [0.0, 5.0].
|
||
## 0.0 = no anchor present.
|
||
var wonder_anchor_strength: float = 0.0
|
||
## LEGACY single school — kept for anchor_decay compat during transition.
|
||
var wonder_anchor_school: String = ""
|
||
## Multi-school affinities for ley resonance network (e.g. ["death", "chaos"]).
|
||
var wonder_anchor_schools: Array[String] = []
|
||
## Wonder tier 1-5 — aligned with 5 eras. Separate from terrain quality (1-3).
|
||
## Tier = strength for ley resonance calculations.
|
||
var wonder_tier: int = 0
|
||
|
||
## Stratospheric sulfate aerosol [0, 1]. Injected by volcanic/impact events.
|
||
## Applied each turn to magic_heat_delta (cooling) and magic_moisture_delta (drying).
|
||
## Spreads downwind and decays per turn. Persistent — saved to disk.
|
||
var sulfate_aerosol: float = 0.0
|
||
|
||
## Accumulated solar forcing from solar cycle events [−1, 1].
|
||
## Positive = solar maximum (warming), negative = solar minimum (cooling).
|
||
## Written by _process_solar, read by climate.gd each turn. Persistent — saved to disk.
|
||
var solar_forcing: float = 0.0
|
||
|
||
## Accumulated glacial forcing from glacial/ice events [−1, 1].
|
||
## Positive = warm runaway melt, negative = glacial advance.
|
||
## Written by _process_glacial, read by climate.gd each turn. Persistent — saved to disk.
|
||
var glacial_forcing: float = 0.0
|
||
|
||
## Barometric pressure (hPa). Sea level baseline ~1013.
|
||
var pressure: float = 1013.0
|
||
## Atmospheric water vapor [0,1] — persistent, saved to disk
|
||
var humidity: float = 0.5
|
||
## Derived: humidity / saturation_capacity(temperature) — recalculated each turn, not saved
|
||
var relative_humidity: float = 0.5
|
||
## Temperature at which condensation occurs [0,1 scale] — recalculated each turn, not saved
|
||
var dew_point: float = 0.4
|
||
## Convective Available Potential Energy [0,1 normalized] — recalculated each turn, not saved
|
||
## Real scale: 0=0 J/kg, 1.0=5000+ J/kg
|
||
var cape: float = 0.0
|
||
## Dynamic deviation from baseline pressure (-50 to +50 hPa) — persistent, saved to disk
|
||
var pressure_anomaly: float = 0.0
|
||
|
||
|
||
func _init(
|
||
p_position: Vector2i = Vector2i.ZERO,
|
||
p_biome_id: String = "",
|
||
) -> void:
|
||
position = p_position
|
||
biome_id = p_biome_id
|
||
|
||
|
||
func get_movement_cost() -> int:
|
||
## Look up movement cost from terrain data via DataLoader.
|
||
## Roads reduce cost by 1 (minimum 1).
|
||
var terrain: Dictionary = DataLoader.get_terrain(biome_id)
|
||
var base: int = terrain.get("movement_cost", 1) if not terrain.is_empty() else 1
|
||
if improvement != "":
|
||
var modifier: int = int(ImprovementScript.get_movement_cost_modifier(improvement))
|
||
base = maxi(1, base + modifier)
|
||
return base
|
||
|
||
|
||
func get_defense_bonus() -> int:
|
||
## Look up defense bonus from terrain data via DataLoader.
|
||
var terrain: Dictionary = DataLoader.get_terrain(biome_id)
|
||
if terrain.is_empty():
|
||
return 0
|
||
return terrain.get("defense_bonus", 0)
|
||
|
||
|
||
func get_yields(for_player: int = -1) -> Dictionary:
|
||
## Return terrain yields factoring quality tier and resource bonuses.
|
||
## Pass for_player to exclude tech-gated resources the player hasn't discovered.
|
||
return get_quality_yields(for_player)
|
||
|
||
|
||
func get_quality_yields(for_player: int = -1) -> Dictionary:
|
||
## Return base terrain yields modified by quality tier (1–5), plus resource bonuses.
|
||
## Q1 (Degraded): base - 2 (min 0) for food/production/trade; no mana.
|
||
## Q2 (Sparse): base - 1 (min 0) for food/production/trade; 0.5× mana.
|
||
## Q3 (Healthy): base yields; 1× mana. ← baseline
|
||
## Q4 (Thriving): base + quality_bonuses × 1; 1.5× mana.
|
||
## Q5 (Pristine): base + quality_bonuses × 2; 2× mana.
|
||
## culture is never penalized, only boosted at Q4/Q5.
|
||
## When for_player >= 0, tech-gated resources are excluded if player lacks the tech.
|
||
## mana: Dictionary[String, float] keyed by school name.
|
||
var terrain: Dictionary = DataLoader.get_terrain(biome_id)
|
||
var food: int = terrain.get("food", 0)
|
||
var production: int = terrain.get("production", 0)
|
||
var trade: int = terrain.get("trade", 0)
|
||
var culture: int = terrain.get("culture", 0)
|
||
|
||
if quality < 3:
|
||
var penalty: int = 3 - quality # Q1 → 2, Q2 → 1
|
||
food = maxi(0, food - penalty)
|
||
production = maxi(0, production - penalty)
|
||
trade = maxi(0, trade - penalty)
|
||
elif quality > 3:
|
||
var bonus_scale: int = quality - 3 # Q4 → 1, Q5 → 2
|
||
var bonuses: Dictionary = terrain.get("quality_bonuses", {})
|
||
food += bonuses.get("food", 0) * bonus_scale
|
||
production += bonuses.get("production", 0) * bonus_scale
|
||
trade += bonuses.get("trade", 0) * bonus_scale
|
||
culture += bonuses.get("culture", 0) * bonus_scale
|
||
|
||
# Mana from terrain: major + minor schools
|
||
var mana: Dictionary = {}
|
||
var mana_scale: float = (quality - 1) * 0.5 # Q1=0, Q2=0.5, Q3=1.0, Q4=1.5, Q5=2.0
|
||
var mana_major: Variant = terrain.get("mana_major", null)
|
||
if mana_major is Dictionary and mana_major.get("school", "") != "":
|
||
var school: String = mana_major["school"]
|
||
var amount: float = float(mana_major.get("amount", 0)) * mana_scale
|
||
if amount > 0.0:
|
||
if school == "all":
|
||
for s: String in ["life", "death", "chaos", "nature", "aether"]:
|
||
mana[s] = mana.get(s, 0.0) + amount
|
||
else:
|
||
mana[school] = mana.get(school, 0.0) + amount
|
||
var mana_minor: Variant = terrain.get("mana_minor", [])
|
||
if mana_minor is Array:
|
||
for entry: Variant in mana_minor:
|
||
if not entry is Dictionary:
|
||
continue
|
||
var school: String = entry.get("school", "")
|
||
if school == "":
|
||
continue
|
||
var amount: float = float(entry.get("amount", 0)) * mana_scale
|
||
if amount > 0.0:
|
||
mana[school] = mana.get(school, 0.0) + amount
|
||
|
||
if resource_id != "":
|
||
var include_resource: bool = for_player < 0 or is_resource_visible_to(for_player)
|
||
if include_resource:
|
||
var res: Dictionary = DataLoader.get_resource(resource_id)
|
||
food += res.get("food_bonus", 0)
|
||
production += res.get("production_bonus", 0)
|
||
trade += res.get("trade_bonus", 0)
|
||
culture += res.get("culture_bonus", 0)
|
||
# Resource mana bonuses
|
||
var res_mana: Variant = res.get("mana_bonus", null)
|
||
if res_mana is Dictionary:
|
||
for school: String in res_mana:
|
||
mana[school] = mana.get(school, 0.0) + float(res_mana[school])
|
||
|
||
if improvement != "":
|
||
var imp_yields: Dictionary = ImprovementScript.get_yield_bonus(improvement)
|
||
food += imp_yields.get("food", 0)
|
||
production += imp_yields.get("production", 0)
|
||
trade += imp_yields.get("gold", 0)
|
||
|
||
# Scale mana output by ley-line mana density field.
|
||
# Dead zones (density == 0.0) mean the ley field has not been computed yet — pass through.
|
||
# Dense zones (density == 1.0) double mana via 2x multiplier.
|
||
# density 0.05 = fringe (5%), 0.2 = 2-hex from edge, 0.4 = adjacent, 0.7 = edge, 1.0 = nexus
|
||
if mana_density > 0.0 and not mana.is_empty():
|
||
var density_mult: float = mana_density * 2.0 # 0.05→0.1, 0.4→0.8, 0.7→1.4, 1.0→2.0
|
||
for school: String in mana:
|
||
mana[school] = mana[school] * density_mult
|
||
|
||
# Active marine bloom grants +2 food to this tile
|
||
if marine_bloom_turns > 0:
|
||
food += 2
|
||
|
||
return {
|
||
"food": food, "production": production, "trade": trade,
|
||
"culture": culture, "mana": mana,
|
||
}
|
||
|
||
|
||
func is_resource_visible_to(player_index: int) -> bool:
|
||
## Check if this tile's resource is visible to the given player.
|
||
## Resources without revealed_by_tech are always visible.
|
||
## FORCE_UNLIMITED_RESEARCH debug flag reveals all resources.
|
||
if resource_id == "":
|
||
return false
|
||
if EnvConfig.get_bool("FORCE_UNLIMITED_RESEARCH"):
|
||
return true
|
||
var res_data: Dictionary = DataLoader.get_resource(resource_id)
|
||
var required_tech: String = res_data.get("revealed_by_tech", "")
|
||
if required_tech == "":
|
||
return true
|
||
var player: Variant = GameState.get_player(player_index)
|
||
if player == null:
|
||
return false
|
||
return player.has_tech(required_tech)
|
||
|
||
|
||
func get_quality_defense() -> int:
|
||
## Return defense bonus scaled by quality tier (1–5).
|
||
## Q1: 0%, Q2: 50%, Q3: 100% (base), Q4: 150%, Q5: 200%.
|
||
var base: int = get_defense_bonus()
|
||
match quality:
|
||
1: return 0
|
||
2: return base / 2
|
||
4: return base + base / 2
|
||
5: return base * 2
|
||
_: return base # Q3 = base
|
||
|
||
|
||
func get_terrain_flags() -> Array:
|
||
## Return terrain flags (e.g. ["water", "naval_only"]).
|
||
var terrain: Dictionary = DataLoader.get_terrain(biome_id)
|
||
return terrain.get("flags", [])
|
||
|
||
|
||
func is_water() -> bool:
|
||
return "water" in get_terrain_flags()
|
||
|
||
|
||
func is_natural_wonder() -> bool:
|
||
return "natural_wonder" in get_terrain_flags()
|
||
|
||
|
||
func is_land() -> bool:
|
||
return not is_water()
|
||
|
||
|
||
func has_flag(flag: String) -> bool:
|
||
return flag in get_terrain_flags()
|
||
|
||
|
||
func get_visibility(player_index: int) -> int:
|
||
## Return visibility state for a player. 0 = unexplored (default).
|
||
return visibility.get(player_index, 0)
|
||
|
||
|
||
func set_visibility(player_index: int, state: int) -> void:
|
||
visibility[player_index] = state
|
||
|
||
|
||
func to_dict() -> Dictionary:
|
||
## Serialize tile state for save files.
|
||
var data: Dictionary = {
|
||
"position": [position.x, position.y],
|
||
"biome_id": biome_id,
|
||
}
|
||
if substrate_id != "":
|
||
data["substrate_id"] = substrate_id
|
||
if water_body_id != -1:
|
||
data["water_body_id"] = water_body_id
|
||
if water_body_type != "":
|
||
data["water_body_type"] = water_body_type
|
||
if depth_from_coast != -1:
|
||
data["depth_from_coast"] = depth_from_coast
|
||
if soil_type != "":
|
||
data["soil_type"] = soil_type
|
||
if is_river_mouth:
|
||
data["is_river_mouth"] = true
|
||
if has_cave:
|
||
data["has_cave"] = true
|
||
if resource_id != "":
|
||
data["resource_id"] = resource_id
|
||
if improvement != "":
|
||
data["improvement"] = improvement
|
||
if owner != -1:
|
||
data["owner"] = owner
|
||
if lair_type != "":
|
||
data["lair_type"] = lair_type
|
||
if not visibility.is_empty():
|
||
data["visibility"] = visibility
|
||
if variation_index != 0:
|
||
data["variation_index"] = variation_index
|
||
if elevation != 0.0:
|
||
data["elevation"] = elevation
|
||
if moisture != 0.0:
|
||
data["moisture"] = moisture
|
||
if temperature != 0.0:
|
||
data["temperature"] = temperature
|
||
if not river_edges.is_empty():
|
||
data["river_edges"] = river_edges
|
||
if not river_flow.is_empty():
|
||
data["river_flow"] = river_flow
|
||
if flow_accumulation != 0.0:
|
||
data["flow_accumulation"] = flow_accumulation
|
||
if lake_id != -1:
|
||
data["lake_id"] = lake_id
|
||
if river_source_type != "":
|
||
data["river_source_type"] = river_source_type
|
||
if is_coastal:
|
||
data["is_coastal"] = true
|
||
if quality != 2:
|
||
data["quality"] = quality
|
||
if quality_progress != 0:
|
||
data["quality_progress"] = quality_progress
|
||
if wind_speed != 0.5:
|
||
data["wind_speed"] = wind_speed
|
||
if culture_pressure != 0.0:
|
||
data["culture_pressure"] = culture_pressure
|
||
# magic_heat_delta and magic_moisture_delta are per-turn transients — not saved
|
||
# relative_humidity, dew_point, cape are recalculated each turn — not saved
|
||
# ley fields
|
||
if mana_density != 0.0:
|
||
data["mana_density"] = mana_density
|
||
if ley_line_count != 0:
|
||
data["ley_line_count"] = ley_line_count
|
||
if ley_school != "":
|
||
data["ley_school"] = ley_school
|
||
if ley_corrupted:
|
||
data["ley_corrupted"] = true
|
||
if ley_residue_school != "":
|
||
data["ley_residue_school"] = ley_residue_school
|
||
if ley_residue_strength != 0.0:
|
||
data["ley_residue_strength"] = ley_residue_strength
|
||
if ley_residue_turns != 0:
|
||
data["ley_residue_turns"] = ley_residue_turns
|
||
if humidity != 0.5:
|
||
data["humidity"] = humidity
|
||
if pressure_anomaly != 0.0:
|
||
data["pressure_anomaly"] = pressure_anomaly
|
||
if fish_stock != -1:
|
||
data["fish_stock"] = fish_stock
|
||
if reef_health != 1.0:
|
||
data["reef_health"] = reef_health
|
||
# marine_bloom_turns is transient (spell effect) — not saved
|
||
if marine_creature != "":
|
||
data["marine_creature"] = marine_creature
|
||
# Flora fields
|
||
if canopy_cover != 0.0:
|
||
data["canopy_cover"] = canopy_cover
|
||
if undergrowth != 0.0:
|
||
data["undergrowth"] = undergrowth
|
||
if fungi_network != 0.0:
|
||
data["fungi_network"] = fungi_network
|
||
if drought_counter != 0:
|
||
data["drought_counter"] = drought_counter
|
||
if succession_progress != 0:
|
||
data["succession_progress"] = succession_progress
|
||
if regrowth_stage != -1:
|
||
data["regrowth_stage"] = regrowth_stage
|
||
if regrowth_turns != 0:
|
||
data["regrowth_turns"] = regrowth_turns
|
||
# Fauna tracking (habitat_suitability is NOT serialized — recalculated per turn)
|
||
if habitat_low_turns != 0:
|
||
data["habitat_low_turns"] = habitat_low_turns
|
||
if landmark_name != "":
|
||
data["landmark_name"] = landmark_name
|
||
if not ground_items.is_empty():
|
||
data["ground_items"] = ground_items.duplicate(true)
|
||
if wonder_anchor_strength != 0.0:
|
||
data["wonder_anchor_strength"] = wonder_anchor_strength
|
||
if wonder_anchor_school != "":
|
||
data["wonder_anchor_school"] = wonder_anchor_school
|
||
if not wonder_anchor_schools.is_empty():
|
||
data["wonder_anchor_schools"] = wonder_anchor_schools.duplicate()
|
||
if wonder_tier != 0:
|
||
data["wonder_tier"] = wonder_tier
|
||
if sulfate_aerosol != 0.0:
|
||
data["sulfate_aerosol"] = sulfate_aerosol
|
||
if solar_forcing != 0.0:
|
||
data["solar_forcing"] = solar_forcing
|
||
if glacial_forcing != 0.0:
|
||
data["glacial_forcing"] = glacial_forcing
|
||
return data
|
||
|
||
|
||
static func from_dict(data: Dictionary) -> Resource: # Tile
|
||
## Deserialize tile state from save files.
|
||
var pos_arr: Array = data.get("position", [0, 0])
|
||
var pos: Vector2i = Vector2i(pos_arr[0], pos_arr[1])
|
||
var SelfScript: GDScript = load("res://engine/src/map/tile.gd")
|
||
var tile: Resource = SelfScript.new(pos, data.get("biome_id", ""))
|
||
tile.substrate_id = data.get("substrate_id", "")
|
||
tile.water_body_id = data.get("water_body_id", -1)
|
||
tile.water_body_type = data.get("water_body_type", "")
|
||
tile.depth_from_coast = data.get("depth_from_coast", -1)
|
||
tile.soil_type = data.get("soil_type", "")
|
||
tile.is_river_mouth = data.get("is_river_mouth", false)
|
||
tile.has_cave = data.get("has_cave", false)
|
||
tile.resource_id = data.get("resource_id", "")
|
||
tile.improvement = data.get("improvement", "")
|
||
tile.owner = data.get("owner", -1)
|
||
tile.lair_type = data.get("lair_type", "")
|
||
tile.visibility = data.get("visibility", {})
|
||
tile.variation_index = data.get("variation_index", 0)
|
||
tile.elevation = data.get("elevation", 0.0)
|
||
tile.moisture = data.get("moisture", 0.0)
|
||
tile.temperature = data.get("temperature", 0.0)
|
||
var edges: Array = data.get("river_edges", [])
|
||
for edge: Variant in edges:
|
||
tile.river_edges.append(int(edge))
|
||
tile.river_flow = data.get("river_flow", {})
|
||
tile.flow_accumulation = data.get("flow_accumulation", 0.0)
|
||
tile.lake_id = data.get("lake_id", -1)
|
||
tile.river_source_type = data.get("river_source_type", "")
|
||
tile.is_coastal = data.get("is_coastal", false)
|
||
tile.quality = data.get("quality", 2)
|
||
tile.quality_progress = data.get("quality_progress", 0)
|
||
tile.wind_speed = data.get("wind_speed", 0.5)
|
||
tile.culture_pressure = data.get("culture_pressure", 0.0)
|
||
tile.mana_density = data.get("mana_density", 0.0)
|
||
tile.ley_line_count = data.get("ley_line_count", 0)
|
||
tile.ley_school = data.get("ley_school", "")
|
||
tile.ley_corrupted = data.get("ley_corrupted", false)
|
||
tile.ley_residue_school = data.get("ley_residue_school", "")
|
||
tile.ley_residue_strength = data.get("ley_residue_strength", 0.0)
|
||
tile.ley_residue_turns = data.get("ley_residue_turns", 0)
|
||
tile.humidity = data.get("humidity", 0.5)
|
||
tile.pressure_anomaly = data.get("pressure_anomaly", 0.0)
|
||
tile.fish_stock = data.get("fish_stock", -1)
|
||
tile.reef_health = data.get("reef_health", 1.0)
|
||
tile.marine_creature = data.get("marine_creature", "")
|
||
tile.canopy_cover = data.get("canopy_cover", 0.0)
|
||
tile.undergrowth = data.get("undergrowth", 0.0)
|
||
tile.fungi_network = data.get("fungi_network", 0.0)
|
||
tile.drought_counter = data.get("drought_counter", 0)
|
||
tile.succession_progress = data.get("succession_progress", 0)
|
||
tile.regrowth_stage = data.get("regrowth_stage", -1)
|
||
tile.regrowth_turns = data.get("regrowth_turns", 0)
|
||
tile.habitat_low_turns = data.get("habitat_low_turns", 0)
|
||
tile.landmark_name = data.get("landmark_name", "")
|
||
tile.ground_items = data.get("ground_items", [])
|
||
tile.wonder_anchor_strength = data.get("wonder_anchor_strength", 0.0)
|
||
tile.wonder_anchor_school = data.get("wonder_anchor_school", "")
|
||
var schools_raw: Array = data.get("wonder_anchor_schools", [])
|
||
for s: Variant in schools_raw:
|
||
tile.wonder_anchor_schools.append(str(s))
|
||
tile.wonder_tier = data.get("wonder_tier", 0)
|
||
tile.sulfate_aerosol = data.get("sulfate_aerosol", 0.0)
|
||
tile.solar_forcing = data.get("solar_forcing", 0.0)
|
||
tile.glacial_forcing = data.get("glacial_forcing", 0.0)
|
||
return tile
|