diff --git a/game/addons/world_generator/resources/world_gen_base_resource.gd b/game/addons/world_generator/resources/world_gen_base_resource.gd index 612fd7ad..ccc34e1f 100644 --- a/game/addons/world_generator/resources/world_gen_base_resource.gd +++ b/game/addons/world_generator/resources/world_gen_base_resource.gd @@ -27,6 +27,31 @@ func create_content(item_name : String = "") -> void: func remove_content_entry(entry : WorldGenBaseResource) -> void: pass +func get_content_with_name(name : String) -> WorldGenBaseResource: + if resource_name == name: + return self + + for c in get_content(): + if c: + var cc = c.get_content_with_name(name) + if cc: + return cc + + return null + +func get_all_contents_with_name(name : String) -> Array: + var arr : Array = Array() + + if resource_name == name: + arr.append(self) + + for c in get_content(): + if c: + var cc : Array = c.get_all_contents_with_name(name) + arr.append_array(cc) + + return arr + func duplicate_content_entry(entry : WorldGenBaseResource) -> void: var de : WorldGenBaseResource = entry.duplicate(true) de.resource_name += " (Duplicate)" @@ -43,6 +68,25 @@ func _setup_terra_library(library : TerramanLibrary, pseed : int) -> void: pass func generate_terra_chunk(chunk: TerraChunk, pseed : int, spawn_mobs: bool) -> void: + generate_terra_chunk_internal(chunk, pseed, spawn_mobs, get_rect()) + +func generate_terra_chunk_internal(chunk: TerraChunk, pseed : int, spawn_mobs: bool, world_parent_rect : Rect2) -> void: + var wcr : Rect2 = get_rect() + wcr.position += world_parent_rect.position + + var p : Vector2 = Vector2(chunk.get_position_x(), chunk.get_position_z()) + + #TODO + #if !wcr.has_point(p): + # return + + _generate_terra_chunk(chunk, spawn_mobs, spawn_mobs) + + for c in get_content(): + if c: + c.generate_terra_chunk_internal(chunk, pseed, spawn_mobs, wcr) + +func _generate_terra_chunk(chunk: TerraChunk, pseed : int, spawn_mobs: bool) -> void: pass func generate_map(pseed : int) -> Image: diff --git a/game/modules/planets/test_planet/test_world.tres b/game/modules/planets/test_planet/test_world.tres new file mode 100644 index 00000000..97e7ab97 --- /dev/null +++ b/game/modules/planets/test_planet/test_world.tres @@ -0,0 +1,39 @@ +[gd_resource type="Resource" load_steps=11 format=2] + +[ext_resource path="res://addons/world_generator/resources/world_gen_world.gd" type="Script" id=1] +[ext_resource path="res://world_generator/continents/test_continent.gd" type="Script" id=2] +[ext_resource path="res://world_generator/zones/test_zone.gd" type="Script" id=3] +[ext_resource path="res://world_generator/subzones/spawner.gd" type="Script" id=4] +[ext_resource path="res://modules/planets/test_planet/dungeons/dung_teleporter.tscn" type="PackedScene" id=5] +[ext_resource path="res://modules/planets/test_planet/biomes/simple_biome/low_poly_rpg_item_collection_3/t1.tres" type="PropData" id=6] +[ext_resource path="res://modules/planets/test_planet/biomes/simple_biome/low_poly_rpg_item_collection_3/t2.tres" type="PropData" id=7] + +[sub_resource type="Resource" id=2] +resource_name = "Spawner" +script = ExtResource( 4 ) +rect = Rect2( 55, 78, 22, 25 ) +locked = false + +[sub_resource type="Resource" id=3] +resource_name = "TestForest" +script = ExtResource( 3 ) +rect = Rect2( 39, 35, 142, 171 ) +locked = false +subzones = [ SubResource( 2 ) ] + +[sub_resource type="Resource" id=1] +resource_name = "Continent" +script = ExtResource( 2 ) +rect = Rect2( 30, 15, 434, 459 ) +locked = false +zones = [ SubResource( 3 ) ] +dungeon_teleporter = ExtResource( 5 ) +prop_tree = ExtResource( 6 ) +prop_tree2 = ExtResource( 7 ) + +[resource] +resource_name = "TestWorld" +script = ExtResource( 1 ) +rect = Rect2( -250, -250, 500, 500 ) +locked = false +continents = [ SubResource( 1 ) ] diff --git a/game/project.godot b/game/project.godot index 8b7958e5..8b316853 100644 --- a/game/project.godot +++ b/game/project.godot @@ -234,6 +234,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/world_generator/resources/subzone.gd" }, { +"base": "TerramanLevelGenerator", +"class": "TerraWorldGenerator", +"language": "GDScript", +"path": "res://scripts/world_generators/TerraWorldGenerator.gd" +}, { "base": "GameModule", "class": "UIGuiChildModule", "language": "GDScript", @@ -310,6 +315,7 @@ _global_script_class_icons={ "SpellEffectVisualBasic": "", "SpellGD": "", "SubZone": "", +"TerraWorldGenerator": "", "UIGuiChildModule": "", "UIWindowModule": "", "WorldGenBaseResource": "", diff --git a/game/scripts/world_generators/TerraWorldGenerator.gd b/game/scripts/world_generators/TerraWorldGenerator.gd new file mode 100644 index 00000000..79d2a9db --- /dev/null +++ b/game/scripts/world_generators/TerraWorldGenerator.gd @@ -0,0 +1,45 @@ +tool +extends TerramanLevelGenerator +class_name TerraWorldGenerator + +# Copyright (c) 2019-2021 Péter Magyar +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +export(int) var _level_seed : int +export(bool) var _spawn_mobs : bool +export(Resource) var world_gen_world : Resource = null + +var _world : TerraWorld +var _library : TerramanLibrary + +func setup(world : TerraWorld, level_seed : int, spawn_mobs : bool, library: TerramanLibrary) -> void: + _level_seed = level_seed + _spawn_mobs = spawn_mobs + _library = library + + if world_gen_world != null: + world_gen_world.setup_terra_library(_library, _level_seed) + _library.refresh_rects() + +func _generate_chunk(chunk : TerraChunk) -> void: + if world_gen_world == null: + return + + world_gen_world.generate_terra_chunk(chunk, _level_seed, _spawn_mobs) diff --git a/game/tw/TerraWorldBlocky.tscn b/game/tw/TerraWorldBlocky.tscn index 25264b80..dd049a50 100644 --- a/game/tw/TerraWorldBlocky.tscn +++ b/game/tw/TerraWorldBlocky.tscn @@ -1,18 +1,10 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://tw/new_terramanlibrarymergerpcm.tres" type="TerramanLibraryMergerPCM" id=1] [ext_resource path="res://tw/TerraWorldBlocky.gd" type="Script" id=2] -[ext_resource path="res://scripts/world_generators/MainTPlanetGenerator.gd" type="Script" id=3] +[ext_resource path="res://tw/world_generator.tres" type="TerramanLevelGenerator" id=3] [ext_resource path="res://scripts/settings/DirectionalLightSettings.gd" type="Script" id=4] [ext_resource path="res://test_props/MeshDataInstance.tres" type="PropData" id=5] -[ext_resource path="res://modules/planets/test_planet/DungeonPlanetData.tres" type="Planet" id=6] - -[sub_resource type="TerramanLevelGenerator" id=1] -script = ExtResource( 3 ) -_force_planet = -1 -_level_seed = 0 -_spawn_mobs = false -planet = ExtResource( 6 ) [sub_resource type="ProceduralSky" id=2] sky_top_color = Color( 0.34902, 0.643137, 0.705882, 1 ) @@ -58,7 +50,7 @@ glow_hdr_luminance_cap = 1.0 [node name="World" type="TerraWorldBlocky"] world_height = 100.0 library = ExtResource( 1 ) -level_generator = SubResource( 1 ) +level_generator = ExtResource( 3 ) voxel_scale = 3.0 build_flags = 510 num_lods = 5 diff --git a/game/tw/world_generator.tres b/game/tw/world_generator.tres new file mode 100644 index 00000000..b6acbabb --- /dev/null +++ b/game/tw/world_generator.tres @@ -0,0 +1,10 @@ +[gd_resource type="TerramanLevelGenerator" load_steps=3 format=2] + +[ext_resource path="res://scripts/world_generators/TerraWorldGenerator.gd" type="Script" id=1] +[ext_resource path="res://modules/planets/test_planet/test_world.tres" type="Resource" id=2] + +[resource] +script = ExtResource( 1 ) +_level_seed = 0 +_spawn_mobs = true +world_gen_world = ExtResource( 2 ) diff --git a/game/world_generator/continents/test_continent.gd b/game/world_generator/continents/test_continent.gd index a737283c..0e54ed34 100644 --- a/game/world_generator/continents/test_continent.gd +++ b/game/world_generator/continents/test_continent.gd @@ -1,6 +1,13 @@ tool extends Continent +export(PackedScene) var dungeon_teleporter : PackedScene +export(PropData) var prop_tree : PropData +export(PropData) var prop_tree2 : PropData + +var voxel_scale : float = 1 +var current_seed : int = 0 + func get_editor_rect_border_color() -> Color: return Color(0.8, 0.8, 0.8, 1) @@ -19,3 +26,126 @@ func get_editor_class() -> String: func get_editor_additional_text() -> String: return "TestContinent" +func _setup_terra_library(library : TerramanLibrary, pseed : int) -> void: + pass + +func _generate_terra_chunk(chunk: TerraChunk, pseed : int, spawn_mobs: bool) -> void: + voxel_scale = chunk.voxel_scale + current_seed = pseed + +# #todo generate this properly +# var entrance_position : Vector3 = Vector3(7, 5, 7) +# +# for i in range(get_building_count()): +# var d : Building = get_building(i) +# +# if d.has_method("has_entrance_position"): +# d.entrance_position.origin = entrance_position +# +# entrance_position = d.next_level_teleporter_position_data_space +# entrance_position *= voxel_scale + + var cx : int = chunk.get_position_x() + var cz : int = chunk.get_position_z() + + var chunk_seed : int = 123 + (cx * 231) + (cz * 123) + + var rng : RandomNumberGenerator = RandomNumberGenerator.new() + rng.seed = chunk_seed + + #terrarin_gen.generate_simple_terrarin(chunk, spawn_mobs) + gen_terra_chunk(chunk, rng) + + if chunk.position_x == 0 && chunk.position_z == 0: + #test + spawn_dungeon(chunk, chunk_seed, spawn_mobs) + else: + if rng.randi() % 10 == 0: + spawn_dungeon(chunk, chunk_seed, spawn_mobs) + +# for i in range(get_building_count()): +# get_building(i).generate_terra_chunk(chunk, spawn_mobs) + + if not Engine.editor_hint and spawn_mobs and rng.randi() % 4 == 0: + var level : int = 1 + + if chunk.get_voxel_world().has_method("get_mob_level"): + level = chunk.get_voxel_world().get_mob_level() + + ESS.entity_spawner.spawn_mob(0, level, \ + Vector3(chunk.position_x * chunk.size_x * chunk.voxel_scale + chunk.size_x / 2,\ + 100, \ + chunk.position_z * chunk.size_z * chunk.voxel_scale + chunk.size_z / 2)) + +func gen_terra_chunk(chunk: TerraChunk, rng : RandomNumberGenerator) -> void: + chunk.channel_ensure_allocated(TerraChunkDefault.DEFAULT_CHANNEL_TYPE, 1) + chunk.channel_ensure_allocated(TerraChunkDefault.DEFAULT_CHANNEL_ISOLEVEL, 0) + + var s : FastNoise = FastNoise.new() + s.set_noise_type(FastNoise.TYPE_SIMPLEX) + s.set_seed(current_seed) + + var sdet : FastNoise = FastNoise.new() + sdet.set_noise_type(FastNoise.TYPE_SIMPLEX) + sdet.set_seed(current_seed) + + for x in range(-chunk.margin_start, chunk.size_x + chunk.margin_end): + for z in range(-chunk.margin_start, chunk.size_x + chunk.margin_end): + var vx : int = x + (chunk.position_x * chunk.size_x) + var vz : int = z + (chunk.position_z * chunk.size_z) + + var val : float = (s.get_noise_2d(vx * 0.05, vz * 0.05) + 2) + val *= val + val *= 20.0 + val += abs(sdet.get_noise_2d(vx * 0.8, vz * 0.8)) * 20 + + chunk.set_voxel(val, x, z, TerraChunkDefault.DEFAULT_CHANNEL_ISOLEVEL) + + if val < 50: + chunk.set_voxel(2, x, z, TerraChunkDefault.DEFAULT_CHANNEL_TYPE) + elif val > 90: + chunk.set_voxel(4, x, z, TerraChunkDefault.DEFAULT_CHANNEL_TYPE) + else: + if chunk.position_x == 0 && chunk.position_z == 0: + continue + + if rng.randf() > 0.992: + var tr : Transform = Transform() + + tr = tr.rotated(Vector3(0, 1, 0), rng.randf() * PI) + tr = tr.rotated(Vector3(1, 0, 0), rng.randf() * 0.2 - 0.1) + tr = tr.rotated(Vector3(0, 0, 1), rng.randf() * 0.2 - 0.1) + tr = tr.scaled(Vector3(0.9 + rng.randf() * 0.2, 0.9 + rng.randf() * 0.2, 0.9 + rng.randf() * 0.2)) + tr.origin = Vector3((x + chunk.position_x * chunk.size_x), ((val - 2) / 255.0) * chunk.world_height, (z + chunk.position_z * chunk.size_z)) + + chunk.voxel_world.prop_add(tr, prop_tree) + +# Uncomment to test the prop texture merger system: +# if randf() > 0.5: +# chunk.voxel_world.prop_add(tr, prop_tree) +# else: +# chunk.voxel_world.prop_add(tr, prop_tree2) + + +func spawn_dungeon(chunk: TerraChunk, dungeon_seed : int, spawn_mobs : bool) -> void: + var x : float = chunk.position_x * chunk.voxel_scale * chunk.size_x + var z : float = chunk.position_z * chunk.voxel_scale * chunk.size_z + + var vh : int = chunk.get_voxel(6, 6, TerraChunkDefault.DEFAULT_CHANNEL_ISOLEVEL) + var vwh : float = chunk.get_voxel_scale() * chunk.get_world_height() * (vh / 256.0) + + var dt : Spatial = dungeon_teleporter.instance() + chunk.voxel_world.add_child(dt) + dt.owner_chunk = chunk + + var level : int = 2 + + if chunk.get_voxel_world().has_method("get_mob_level"): + level = chunk.get_voxel_world().get_mob_level() + + dt.min_level = level - 1 + dt.max_level = level + 1 + dt.dungeon_seed = dungeon_seed + dt.spawn_mobs = spawn_mobs + dt.transform = Transform(Basis().scaled(Vector3(chunk.voxel_scale, chunk.voxel_scale, chunk.voxel_scale)), Vector3(x, vwh, z)) + diff --git a/game/world_generator/subzones/spawner.gd b/game/world_generator/subzones/spawner.gd new file mode 100644 index 00000000..17157e09 --- /dev/null +++ b/game/world_generator/subzones/spawner.gd @@ -0,0 +1,20 @@ +tool +extends SubZone + +func get_editor_rect_border_color() -> Color: + return Color(0.8, 0.8, 0.8, 1) + +func get_editor_rect_color() -> Color: + return Color(0.8, 0.8, 0.8, 0.9) + +func get_editor_rect_border_size() -> int: + return 2 + +func get_editor_font_color() -> Color: + return Color(0, 0, 0, 1) + +func get_editor_class() -> String: + return "Spawner" + +func get_editor_additional_text() -> String: + return "Spawner"