190 lines
9.2 KiB
GDScript
190 lines
9.2 KiB
GDScript
extends Node2D
|
|
const GENERATOR_ATLAS_PATH := preload("res://scripts/planets/surface_details.gd").ATLAS_PATH
|
|
const BUILDING_SCALE := preload("res://scripts/planets/surface_scenery.gd").BUILDING_SCALE
|
|
const GENERATOR := preload("res://scripts/planets/surface_generator.gd")
|
|
var data: Dictionary
|
|
var terrain: ImageTexture
|
|
var tree_canopy: Node2D
|
|
var _nature: Array[AtlasTexture] = []
|
|
var _tree: Texture2D
|
|
var _poi_sprites: Dictionary = {}
|
|
var _poi_labels: Dictionary = {}
|
|
var _event_nodes: Array[Dictionary] = []
|
|
|
|
func _ready() -> void:
|
|
texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
|
terrain = GENERATOR.terrain_texture(data)
|
|
var ground := Sprite2D.new()
|
|
ground.name = "Terrain"
|
|
ground.texture = data.height_texture
|
|
ground.scale = Vector2.ONE * GENERATOR.WORLD_SIZE / ground.texture.get_width()
|
|
ground.z_index = -5
|
|
var material := ShaderMaterial.new()
|
|
material.shader = preload("res://resources/effects/planet_terrain.gdshader")
|
|
material.set_shader_parameter("height_map",data.height_texture)
|
|
material.set_shader_parameter("grass_detail",preload("res://assets/planets/grass.png"))
|
|
for kind in ["soil","rock","sand","moss"]:
|
|
material.set_shader_parameter(kind+"_detail",load("res://assets/planets/terrain/%s.png" % kind))
|
|
material.set_shader_parameter("biome_kind",int(data.landscape.index))
|
|
for key in ["low","high","sand","rock"]:
|
|
material.set_shader_parameter(key+"_color",data.landscape[key])
|
|
material.set_shader_parameter("climate",float(data.profile.temperature))
|
|
material.set_shader_parameter("seed_offset",float(posmod(int(data.seed),10000)))
|
|
ground.material = material
|
|
add_child(ground)
|
|
var atlas: Texture2D = load(GENERATOR_ATLAS_PATH)
|
|
var atlas_scale := Vector2(atlas.get_size()) / 1280.0
|
|
# The painted sheet has uneven transparent gutters; avoid clipping canopies.
|
|
var rows := [Vector2(0,360), Vector2(360,280), Vector2(640,310), Vector2(950,330)]
|
|
for index in 16:
|
|
var tile := AtlasTexture.new()
|
|
tile.atlas = atlas
|
|
var band: Vector2 = rows[index / 4]
|
|
var region := Rect2(float(index % 4)*320.0, band.x, 320.0, band.y)
|
|
if index == 12:
|
|
region = Rect2(0,950,365,330)
|
|
elif index == 13:
|
|
region = Rect2(370,950,270,330)
|
|
tile.region = Rect2(region.position*atlas_scale, region.size*atlas_scale)
|
|
tile.filter_clip = true
|
|
_nature.append(tile)
|
|
_tree = load("res://assets/planets/tree.png")
|
|
var mountains := Node2D.new()
|
|
mountains.name = "Mountains"
|
|
mountains.set_script(preload("res://scripts/planets/surface_mountains.gd"))
|
|
mountains.data = data
|
|
mountains.z_index = -1
|
|
add_child(mountains)
|
|
tree_canopy = Node2D.new()
|
|
tree_canopy.set_script(preload("res://scripts/planets/surface_tree_canopy.gd"))
|
|
tree_canopy.world = self
|
|
add_child(tree_canopy)
|
|
for poi in data.pois:
|
|
var sprite := Sprite2D.new()
|
|
if poi.kind in ["deposit", "deep_deposit"]:
|
|
sprite.set_script(preload("res://scripts/planets/surface_deposit.gd"))
|
|
sprite.configure(data,poi)
|
|
else:
|
|
if poi.kind == "cave":
|
|
sprite.set_script(preload("res://scripts/planets/surface_cave.gd"))
|
|
sprite.configure(data,poi)
|
|
else:
|
|
var textures := {"ruins":"ruins", "warehouse":"props/warehouse", "village":"landmarks/abandoned_hamlet", "crew":"props/engineer_camp", "hermit":"props/hermit_cartographer", "time_engineer":"props/time_engineer"}
|
|
sprite.texture = load("res://assets/planets/%s.png" % textures[poi.kind])
|
|
sprite.position = poi.position
|
|
if sprite.texture != null and poi.kind != "cave":
|
|
sprite.scale = Vector2.ONE * 125.0*BUILDING_SCALE / maxf(sprite.texture.get_width(), sprite.texture.get_height())
|
|
sprite.z_index = 10
|
|
if poi.kind == "crew" and sprite.texture != null:
|
|
sprite.scale = Vector2.ONE * 170.0 / maxf(sprite.texture.get_width(),sprite.texture.get_height())
|
|
add_child(sprite)
|
|
_poi_sprites[poi.id] = sprite
|
|
var label := Label.new()
|
|
label.position = poi.position + Vector2(-120, 46)
|
|
label.size.x = 240
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
label.add_theme_font_size_override("font_size", 13)
|
|
label.add_theme_color_override("font_color", Color("f0d5a1"))
|
|
label.add_theme_color_override("font_shadow_color", Color("061310"))
|
|
label.add_theme_constant_override("shadow_outline_size", 5)
|
|
label.z_index = 15
|
|
add_child(label)
|
|
_poi_labels[poi.id] = label
|
|
for landmark in data.get("landmarks", []):
|
|
var prop := Sprite2D.new()
|
|
prop.name = str(landmark.kind).to_pascal_case()
|
|
prop.texture = load("res://assets/planets/landmarks/%s.png" % landmark.kind)
|
|
prop.position = landmark.position
|
|
prop.rotation = landmark.rotation
|
|
prop.scale = Vector2.ONE * float(landmark.size) / maxf(prop.texture.get_width(), prop.texture.get_height())
|
|
prop.z_index = -2
|
|
add_child(prop)
|
|
for structure in data.structures:
|
|
var prop := Sprite2D.new()
|
|
prop.name = str(structure.kind).to_pascal_case()
|
|
prop.texture = load("res://assets/planets/props/%s.png" % structure.kind)
|
|
prop.position = structure.position
|
|
prop.rotation = structure.rotation
|
|
prop.scale = Vector2.ONE * float(structure.size) / maxf(prop.texture.get_width(),prop.texture.get_height())
|
|
prop.z_index = 4
|
|
add_child(prop)
|
|
for index in data.events.size():
|
|
var event: Dictionary = data.events[index]
|
|
var marker := Label.new()
|
|
marker.name = "EventMarker%d" % index
|
|
marker.text = "?"
|
|
marker.position = event.position+Vector2(-22,-28)
|
|
marker.size = Vector2(44,55)
|
|
marker.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
marker.add_theme_font_size_override("font_size",40)
|
|
marker.add_theme_color_override("font_color",Color("f8d685"))
|
|
marker.add_theme_color_override("font_outline_color",Color("17211b"))
|
|
marker.add_theme_constant_override("outline_size",7)
|
|
marker.z_index = 25
|
|
add_child(marker)
|
|
_event_nodes.append({"marker":marker})
|
|
|
|
refresh_pois(Vector2.ZERO)
|
|
|
|
func refresh_pois(lander_position: Vector2) -> void:
|
|
for index in data.events.size():
|
|
var event: Dictionary = data.events[index]
|
|
if lander_position.distance_to(event.position) < 600:
|
|
event.discovered = true
|
|
var nodes: Dictionary = _event_nodes[index]
|
|
nodes.marker.visible = not event.complete
|
|
|
|
for poi in data.pois:
|
|
if lander_position.distance_to(poi.position) < 650:
|
|
poi.discovered = true
|
|
var sprite: Sprite2D = _poi_sprites[poi.id]
|
|
sprite.visible = bool(poi.discovered)
|
|
sprite.modulate = Color(0.5, 0.55, 0.5) if poi.complete else Color.WHITE
|
|
var label: Label = _poi_labels[poi.id]
|
|
label.visible = bool(poi.discovered)
|
|
if poi.kind == "deep_deposit":
|
|
var built: bool = GameState.captain.expedition.mining_stations.has(str(data.profile.id))
|
|
if built and not bool(sprite.get_meta("outpost", false)):
|
|
sprite.texture = load("res://assets/planets/props/deuterium_outpost.png")
|
|
sprite.material = null
|
|
sprite.rotation = 0
|
|
sprite.scale = Vector2.ONE * 185.0 / maxf(sprite.texture.get_width(), sprite.texture.get_height())
|
|
sprite.set_meta("outpost", true)
|
|
var network := preload("res://scripts/planets/mining_network.gd")
|
|
var richness: int = network.station_richness(GameState.captain.expedition.mining_stations[str(data.profile.id)]) if built else network.deposit_richness(data.profile, int(data.profile.get("system_level", GameState.system_level)))
|
|
label.text = ("%s · %d/100" % ["Placówka górnicza" if built else "Głębokie złoże deuteru", richness])
|
|
if lander_position.distance_to(poi.position) <= 150: label.text += "\n[F] Placówka" if built else "\n[F] Buduj"
|
|
continue
|
|
if poi.kind == "time_engineer":
|
|
label.text = "Inżynier chronalny" + ("\n[F] Maksymalizuj addon" if lander_position.distance_to(poi.position) <= 150 else "")
|
|
continue
|
|
if poi.kind == "hermit":
|
|
var progress: Resource = GameState.captain.expedition
|
|
var map := preload("res://scripts/planets/distant_expeditions.gd").visit_offer(progress, data.profile, int(data.profile.get("system_level", GameState.system_level)))
|
|
var owned: bool = progress.hermit_purchases.has(str(map.id))
|
|
label.text = "Pustelnik / Kartograf" + (" · mapa kupiona" if owned else ("\n[F] Kup mapę" if lander_position.distance_to(poi.position) <= 150 else ""))
|
|
continue
|
|
if poi.kind == "crew":
|
|
label.text = "Obóz specjalisty" + (" · zatrudniono" if poi.complete else ("\n[F] Porozmawiaj" if lander_position.distance_to(poi.position) <= 150 else ""))
|
|
continue
|
|
var title: String = preload("res://scripts/planets/poi_rules.gd").NAMES[poi.kind]
|
|
label.text = title + ((" · zatrudniono" if poi.kind == "crew" else " · zbadano") if poi.complete else ("\n[F] Zbadaj" if lander_position.distance_to(poi.position) <= 150 else ""))
|
|
|
|
func _draw() -> void:
|
|
if terrain == null:
|
|
return
|
|
for detail in data.get("details", []):
|
|
var shade := float(detail.shade)
|
|
_draw_prop(_nature[int(detail.variant)], detail.position, detail.size, detail.rotation, Color(shade,shade,shade))
|
|
for rock in data.rocks:
|
|
_draw_prop(_nature[int(rock.get("variant",4))],rock.position,rock.size,rock.rotation,Color.WHITE)
|
|
# Small landing beacon.
|
|
draw_circle(Vector2.ZERO, 50, Color(0.5, 0.85, 0.8, 0.12))
|
|
draw_arc(Vector2.ZERO, 48, 0, TAU, 48, Color("8cd9c2"), 2, true)
|
|
|
|
func _draw_prop(texture: Texture2D, point: Vector2, width: float, angle: float, color: Color) -> void:
|
|
draw_set_transform(point, angle)
|
|
var size := Vector2(width, width*float(texture.get_height())/float(texture.get_width()))
|
|
draw_texture_rect(texture, Rect2(-size*0.5, size), false, color)
|
|
draw_set_transform(Vector2.ZERO)
|