Add map loading logic and spawn rate control
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
namespace Zennysoft.Ma.Adapter;
|
||||
public enum Floor
|
||||
{
|
||||
Overworld,
|
||||
Altar,
|
||||
BossFloorA,
|
||||
BossFloorB,
|
||||
GoddessOfGuidanceFloor,
|
||||
VoidRoom,
|
||||
FinalFloor,
|
||||
Floor01,
|
||||
Floor02,
|
||||
Floor03,
|
||||
Floor04,
|
||||
Floor05,
|
||||
}
|
||||
@@ -17,6 +17,4 @@ public partial record PlayerData
|
||||
[Meta, Id("map_data")]
|
||||
public partial record MapData
|
||||
{
|
||||
[Save("floor_list")]
|
||||
public required Dictionary<Floor, string> FloorScenes { get; init; }
|
||||
}
|
||||
|
||||
@@ -28,4 +28,8 @@
|
||||
<ProjectReference Include="..\Zennysoft.Game.Godot.Implementation\Zennysoft.Game.Implementation.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Map\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using System.Linq;
|
||||
using Zennysoft.Game.Ma;
|
||||
|
||||
[Tool]
|
||||
public partial class DungeonFloorLayout : LayoutType
|
||||
{
|
||||
[Export]
|
||||
public DungeonFloorSetType SetType
|
||||
{
|
||||
get => _setType;
|
||||
set
|
||||
{
|
||||
_setType = value;
|
||||
LayoutWithSpawnRate = [];
|
||||
NotifyPropertyListChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[ExportToolButton("Populate Map Data")]
|
||||
public Callable PopulateMapList => Callable.From(() => PopulateDictionary(SetType));
|
||||
|
||||
[Export]
|
||||
public Dictionary<string, float> LayoutWithSpawnRate { get; private set; }
|
||||
|
||||
[Export]
|
||||
public Dictionary<EnemyType, float> EnemySpawnRates { get; set; } = default!;
|
||||
|
||||
private string _floorPath = "res://src/map/dungeon/floors/";
|
||||
private DungeonFloorSetType _setType;
|
||||
|
||||
private void PopulateDictionary(DungeonFloorSetType setType)
|
||||
{
|
||||
var floorPath = _floorPath;
|
||||
var floorType = string.Empty;
|
||||
if (setType == DungeonFloorSetType.SetA)
|
||||
floorType = "SetAFloors";
|
||||
else if (setType == DungeonFloorSetType.SetB)
|
||||
floorType = "SetBFloors";
|
||||
|
||||
var pathToScenes = $"{floorPath}/{floorType}";
|
||||
|
||||
var files = DirAccess.GetFilesAt(pathToScenes).Where(x => x.EndsWith(".tscn"));
|
||||
|
||||
var newMaps = new Dictionary<string, float>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (LayoutWithSpawnRate.ContainsKey($"{floorType}/{file}"))
|
||||
{
|
||||
var spawnRate = LayoutWithSpawnRate.TryGetValue($"{floorType}/{file}", out var currentSpawnRate);
|
||||
newMaps.Add($"{floorType}/{file}", currentSpawnRate);
|
||||
}
|
||||
else
|
||||
newMaps.Add($"{floorType}/{file}", 1.0f);
|
||||
}
|
||||
|
||||
LayoutWithSpawnRate = newMaps;
|
||||
|
||||
NotifyPropertyListChanged();
|
||||
}
|
||||
|
||||
public enum DungeonFloorSetType
|
||||
{
|
||||
SetA,
|
||||
SetB
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://ci7o3nn4mdo8o
|
||||
@@ -0,0 +1,22 @@
|
||||
#if TOOLS
|
||||
using Godot;
|
||||
using Zennysoft.Game.Ma;
|
||||
|
||||
[Tool]
|
||||
public partial class DungeonFloorLayoutNode : EditorPlugin
|
||||
{
|
||||
public override void _EnterTree()
|
||||
{
|
||||
// Initialization of the plugin goes here.
|
||||
var script = GD.Load<Script>("res://addons/dungeon_floor_layout/DungeonFloorLayout.cs");
|
||||
var texture = GD.Load<Texture2D>("res://addons/dungeon_floor_layout/icon_door.png");
|
||||
AddCustomType(nameof(DungeonFloorLayout), nameof(LayoutType), script, texture);
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// Clean-up of the plugin goes here.
|
||||
RemoveCustomType(nameof(DungeonFloorLayout));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
uid://f87ejxatyy2n
|
||||
BIN
Zennysoft.Game.Ma/addons/dungeon_floor_layout/icon_door.png
Normal file
BIN
Zennysoft.Game.Ma/addons/dungeon_floor_layout/icon_door.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 161 B |
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cgd2d4fusp4pg"
|
||||
path="res://.godot/imported/icon_door.png-437da3e7d1cb55961e6afceef56e9ea2.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/dungeon_floor_layout/icon_door.png"
|
||||
dest_files=["res://.godot/imported/icon_door.png-437da3e7d1cb55961e6afceef56e9ea2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
7
Zennysoft.Game.Ma/addons/dungeon_floor_layout/plugin.cfg
Normal file
7
Zennysoft.Game.Ma/addons/dungeon_floor_layout/plugin.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Dungeon Floor Layout"
|
||||
description=""
|
||||
author="Zenny"
|
||||
version=""
|
||||
script="DungeonFloorLayoutNode.cs"
|
||||
@@ -0,0 +1,25 @@
|
||||
using Godot;
|
||||
using Zennysoft.Game.Ma;
|
||||
|
||||
[Tool]
|
||||
public partial class SpecialFloorLayout : LayoutType
|
||||
{
|
||||
[Export]
|
||||
public SpecialFloorType FloorName { get; set; }
|
||||
|
||||
public override void _EnterTree()
|
||||
{
|
||||
base._EnterTree();
|
||||
}
|
||||
|
||||
public enum SpecialFloorType
|
||||
{
|
||||
Overworld,
|
||||
Altar,
|
||||
BossFloorA,
|
||||
BossFloorB,
|
||||
GoddessOfGuidanceFloor,
|
||||
TrueGoddessOfGuidanceFloor,
|
||||
FinalFloor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://cabvj6s31iucg
|
||||
@@ -0,0 +1,23 @@
|
||||
#if TOOLS
|
||||
using Godot;
|
||||
using System;
|
||||
using Zennysoft.Game.Ma;
|
||||
|
||||
[Tool]
|
||||
public partial class SpecialFloorLayoutNode : EditorPlugin
|
||||
{
|
||||
public override void _EnterTree()
|
||||
{
|
||||
// Initialization of the plugin goes here.
|
||||
var script = GD.Load<Script>("res://addons/special_floor_layout_node/SpecialFloorLayout.cs");
|
||||
var texture = GD.Load<Texture2D>("res://addons/special_floor_layout_node/icon_door.png");
|
||||
AddCustomType(nameof(SpecialFloorLayout), nameof(LayoutType), script, texture);
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// Clean-up of the plugin goes here.
|
||||
RemoveCustomType(nameof(SpecialFloorLayout));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
uid://uy8mygg0jtd8
|
||||
BIN
Zennysoft.Game.Ma/addons/special_floor_layout_node/icon_door.png
Normal file
BIN
Zennysoft.Game.Ma/addons/special_floor_layout_node/icon_door.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 161 B |
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://pxevsja7e3s0"
|
||||
path="res://.godot/imported/icon_door.png-d7e4ac87b8cdfac1c9f03b9aff4c7e79.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/special_floor_layout_node/icon_door.png"
|
||||
dest_files=["res://.godot/imported/icon_door.png-d7e4ac87b8cdfac1c9f03b9aff4c7e79.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Special Floor Layout Node"
|
||||
description=""
|
||||
author="Zenny"
|
||||
version=""
|
||||
script="SpecialFloorLayoutNode.cs"
|
||||
@@ -41,7 +41,7 @@ project/assembly_name="Ma"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg")
|
||||
enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg", "res://addons/dungeon_floor_layout/plugin.cfg", "res://addons/special_floor_layout_node/plugin.cfg")
|
||||
|
||||
[file_customization]
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public partial class EnemyDatabase : Node
|
||||
{
|
||||
[Export]
|
||||
public PackedScene[] EnemyList;
|
||||
|
||||
[Export]
|
||||
public float[] SpawnRate;
|
||||
}
|
||||
21
Zennysoft.Game.Ma/src/enemy/EnemyType.cs
Normal file
21
Zennysoft.Game.Ma/src/enemy/EnemyType.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public enum EnemyType
|
||||
{
|
||||
Sproingy,
|
||||
Michael,
|
||||
FilthEater,
|
||||
Sara,
|
||||
Ballos,
|
||||
Chariot,
|
||||
Chinthe,
|
||||
AmbassadorGreen,
|
||||
AmbassadorRed,
|
||||
AmbassadorSteel,
|
||||
AgniDemon,
|
||||
AqueousDemon,
|
||||
EdenPillar,
|
||||
Palan,
|
||||
ShieldOfHeaven,
|
||||
GoldSproingy
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/enemy/EnemyType.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/enemy/EnemyType.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bwqjmol68w6pr
|
||||
56
Zennysoft.Game.Ma/src/enemy/EnemyTypeToEnemyConverter.cs
Normal file
56
Zennysoft.Game.Ma/src/enemy/EnemyTypeToEnemyConverter.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public static class EnemyTypeToEnemyConverter
|
||||
{
|
||||
private static readonly string _folderPath = "res://src/enemy/enemy_types";
|
||||
|
||||
public static Enemy Convert(EnemyType enemyType)
|
||||
{
|
||||
switch (enemyType)
|
||||
{
|
||||
case EnemyType.Sproingy:
|
||||
return InstantiateFromPath(@$"{_folderPath}/01. sproingy/Sproingy.tscn");
|
||||
case EnemyType.Michael:
|
||||
return InstantiateFromPath(@$"{_folderPath}/02. michael/Michael.tscn");
|
||||
case EnemyType.FilthEater:
|
||||
return InstantiateFromPath(@$"{_folderPath}/03. filth_eater/FilthEater.tscn");
|
||||
case EnemyType.Sara:
|
||||
return InstantiateFromPath(@$"{_folderPath}/04. sara/Sara.tscn");
|
||||
case EnemyType.Ballos:
|
||||
return InstantiateFromPath(@$"{_folderPath}/05. ballos/Ballos.tscn");
|
||||
case EnemyType.Chariot:
|
||||
return InstantiateFromPath(@$"{_folderPath}/06. chariot/Chariot.tscn");
|
||||
case EnemyType.Chinthe:
|
||||
return InstantiateFromPath(@$"{_folderPath}/07. chinthe/Chinthe.tscn");
|
||||
case EnemyType.AmbassadorGreen:
|
||||
return InstantiateFromPath(@$"{_folderPath}/08a. Ambassador/Ambassador.tscn");
|
||||
case EnemyType.AmbassadorRed:
|
||||
return InstantiateFromPath(@$"{_folderPath}/08b. Ambassador (red)/AmbassadorRed.tscn");
|
||||
case EnemyType.AmbassadorSteel:
|
||||
return InstantiateFromPath(@$"{_folderPath}/08c. Ambassador (steel)/AmbassadorSteel.tscn");
|
||||
case EnemyType.AgniDemon:
|
||||
return InstantiateFromPath(@$"{_folderPath}/09. Agni/AgniDemon.tscn");
|
||||
case EnemyType.AqueousDemon:
|
||||
return InstantiateFromPath(@$"{_folderPath}/9b. Aqueos Demon/AqueosDemon.tscn");
|
||||
case EnemyType.EdenPillar:
|
||||
return InstantiateFromPath(@$"{_folderPath}/10. Eden Pillar/Eden Pillar.tscn");
|
||||
case EnemyType.Palan:
|
||||
return InstantiateFromPath(@$"{_folderPath}/11. Palan/Palan.tscn");
|
||||
case EnemyType.ShieldOfHeaven:
|
||||
return InstantiateFromPath(@$"{_folderPath}/12. Shield of Heaven/ShieldModelView.tscn");
|
||||
case EnemyType.GoldSproingy:
|
||||
return InstantiateFromPath(@$"{_folderPath}/13. gold sproingy/GoldSproingy.tscn");
|
||||
default:
|
||||
throw new NotImplementedException("Not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private static Enemy InstantiateFromPath(string scenePath)
|
||||
{
|
||||
var enemyScene = GD.Load<PackedScene>(scenePath);
|
||||
return enemyScene.Instantiate<Enemy>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://ctspbxmdle4vt
|
||||
@@ -17,6 +17,8 @@ public partial class Game : Node3D, IGame
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
IGame IProvide<IGame>.Value() => this;
|
||||
|
||||
IGameRepo IProvide<IGameRepo>.Value() => GameRepo;
|
||||
|
||||
IPlayer IProvide<IPlayer>.Value() => _player;
|
||||
@@ -97,7 +99,6 @@ public partial class Game : Node3D, IGame
|
||||
},
|
||||
MapData = new MapData()
|
||||
{
|
||||
FloorScenes = []
|
||||
},
|
||||
RescuedItems = new RescuedItemDatabase()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ using Godot;
|
||||
using System.Threading.Tasks;
|
||||
using Zennysoft.Ma.Adapter;
|
||||
|
||||
public interface IGame : IProvide<IGameRepo>, IProvide<IPlayer>, IProvide<IMap>, IProvide<ISaveChunk<GameData>>, INode3D
|
||||
public interface IGame : IProvide<IGame>, IProvide<IGameRepo>, IProvide<IPlayer>, IProvide<IMap>, IProvide<ISaveChunk<GameData>>, INode3D
|
||||
{
|
||||
void LoadExistingGame();
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ public interface IMap : INode3D, IProvide<ISaveChunk<MapInfo>>
|
||||
|
||||
Task LoadFloor(string sceneName);
|
||||
|
||||
ImmutableDictionary<Floor, string> FloorScenes { get; }
|
||||
|
||||
IDungeonFloor CurrentFloor { get; }
|
||||
|
||||
Transform3D GetPlayerSpawnPosition();
|
||||
|
||||
49
Zennysoft.Game.Ma/src/map/LayoutToScenePathConverter.cs
Normal file
49
Zennysoft.Game.Ma/src/map/LayoutToScenePathConverter.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using static SpecialFloorLayout;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public static class LayoutToScenePathConverter
|
||||
{
|
||||
private static readonly string _folderPath = "res://src/map/dungeon/floors";
|
||||
|
||||
public static string Convert(LayoutType layoutType)
|
||||
{
|
||||
if (layoutType is SpecialFloorLayout specialFloor)
|
||||
{
|
||||
var path = $"{_folderPath}/Special Floors/";
|
||||
var files = DirAccess.GetFilesAt(path);
|
||||
switch (specialFloor.FloorName)
|
||||
{
|
||||
case SpecialFloorType.Overworld:
|
||||
return path + files.Single(x => x.Contains("Overworld.tscn"));
|
||||
case SpecialFloorType.Altar:
|
||||
return path + files.Single(x => x.Contains("Altar.tscn"));
|
||||
case SpecialFloorType.BossFloorA:
|
||||
return path + files.Single(x => x.Contains("Boss Floor A.tscn"));
|
||||
case SpecialFloorType.BossFloorB:
|
||||
return path + files.Single(x => x.Contains("Boss Floor B.tscn"));
|
||||
case SpecialFloorType.GoddessOfGuidanceFloor:
|
||||
return path + files.Single(x => x.Contains("Goddess of Guidance's Room.tscn"));
|
||||
case SpecialFloorType.TrueGoddessOfGuidanceFloor:
|
||||
return path + files.Single(x => x.Contains("Goddess of Guidance's Room - True Form.tscn"));
|
||||
case SpecialFloorType.FinalFloor:
|
||||
return path + files.Single(x => x.Contains("Final Floor.tscn"));
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
else if (layoutType is DungeonFloorLayout dungeonFloor)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var index = (int)rng.RandWeighted([.. dungeonFloor.LayoutWithSpawnRate.Values]);
|
||||
var result = dungeonFloor.LayoutWithSpawnRate.ElementAt(index);
|
||||
return _folderPath + "/" + result.Key;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://d0yn4yu7264c8
|
||||
7
Zennysoft.Game.Ma/src/map/LayoutType.cs
Normal file
7
Zennysoft.Game.Ma/src/map/LayoutType.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using Godot;
|
||||
|
||||
namespace Zennysoft.Game.Ma;
|
||||
|
||||
public abstract partial class LayoutType : Node
|
||||
{
|
||||
}
|
||||
1
Zennysoft.Game.Ma/src/map/LayoutType.cs.uid
Normal file
1
Zennysoft.Game.Ma/src/map/LayoutType.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://csb6g5a657010
|
||||
@@ -36,9 +36,7 @@ public partial class Map : Node3D, IMap
|
||||
#endregion
|
||||
|
||||
[Export]
|
||||
private Array<Floor> Floors { get; set; } = default!;
|
||||
|
||||
public ImmutableDictionary<Floor, string> FloorScenes { get; private set; }
|
||||
private Array<LayoutType> Floors { get; set; } = default!;
|
||||
|
||||
public IDungeonFloor CurrentFloor { get; private set; }
|
||||
|
||||
@@ -57,14 +55,6 @@ public partial class Map : Node3D, IMap
|
||||
|
||||
public void InitializeMapData()
|
||||
{
|
||||
FloorScenes = ImmutableDictionary<Floor, string>.Empty
|
||||
.Add(Floor.Overworld, _floorFilePath + "Special Floors/Overworld.tscn")
|
||||
.Add(Floor.Altar, _floorFilePath + "Special Floors/Altar.tscn")
|
||||
.Add(Floor.BossFloorA, _floorFilePath + "Special Floors/15. Boss Floor A.tscn")
|
||||
.Add(Floor.BossFloorB, _floorFilePath + "Special Floors/34. Boss Floor B.tscn")
|
||||
.Add(Floor.GoddessOfGuidanceFloor, _floorFilePath + "Special Floors/35. Goddess of Guidance's Room.tscn")
|
||||
.Add(Floor.VoidRoom, _floorFilePath + "Set B/30. Void Room.tscn")
|
||||
.Add(Floor.FinalFloor, _floorFilePath + "Special Floors/36. Final Floor.tscn");
|
||||
CurrentFloorNumber.OnNext(0);
|
||||
}
|
||||
|
||||
@@ -79,9 +69,11 @@ public partial class Map : Node3D, IMap
|
||||
|
||||
public async Task LoadFloor()
|
||||
{
|
||||
GetMapFiles();
|
||||
FloorScenes.TryGetValue(Floors.First(), out var sceneToLoad);
|
||||
var floor = GetChildren().OfType<LayoutType>().ElementAt(CurrentFloorNumber.Value);
|
||||
var sceneToLoad = LayoutToScenePathConverter.Convert(floor);
|
||||
await LoadFloor(sceneToLoad);
|
||||
if (CurrentFloor is DungeonFloor dungeonFloor && floor is DungeonFloorLayout dungeonFloorLayout)
|
||||
dungeonFloor.SpawnEnemies(dungeonFloorLayout.EnemySpawnRates);
|
||||
}
|
||||
|
||||
public async Task LoadFloor(string sceneName)
|
||||
@@ -125,10 +117,4 @@ public partial class Map : Node3D, IMap
|
||||
var transform = GetPlayerSpawnPosition();
|
||||
Player.TeleportPlayer(transform);
|
||||
}
|
||||
|
||||
private string[] GetMapFiles()
|
||||
{
|
||||
var folderLocation = _floorFilePath + "Floor" + CurrentFloorNumber.Value.ToString("D2");
|
||||
return DirAccess.GetFilesAt(folderLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://by67pn7fdsg1m"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://by67pn7fdsg1m"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://14e8mu48ed4" path="res://src/map/Map.cs" id="1_bw70o"]
|
||||
[ext_resource type="Script" uid="uid://cabvj6s31iucg" path="res://addons/special_floor_layout_node/SpecialFloorLayout.cs" id="2_00xd7"]
|
||||
[ext_resource type="Script" uid="uid://ci7o3nn4mdo8o" path="res://addons/dungeon_floor_layout/DungeonFloorLayout.cs" id="3_v14r0"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_00xd7"]
|
||||
length = 0.001
|
||||
@@ -54,9 +56,9 @@ _data = {
|
||||
&"fade_out": SubResource("Animation_v14r0")
|
||||
}
|
||||
|
||||
[node name="Map" type="Node3D"]
|
||||
[node name="Map" type="Node3D" node_paths=PackedStringArray("Floors")]
|
||||
script = ExtResource("1_bw70o")
|
||||
Floors = Array[int]([3, 2, 0, 4, 1, 5, 6])
|
||||
Floors = [3, 2, 0, 4, 1, 5, 6]
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
anchors_preset = 15
|
||||
@@ -71,3 +73,28 @@ unique_name_in_owner = true
|
||||
libraries = {
|
||||
&"": SubResource("AnimationLibrary_00xd7")
|
||||
}
|
||||
|
||||
[node name="Overworld (Add SpecialFloorLayout node for special floors and pick the FloorName from the list)" type="Node" parent="."]
|
||||
script = ExtResource("2_00xd7")
|
||||
metadata/_custom_type_script = "uid://cabvj6s31iucg"
|
||||
|
||||
[node name="Altar (Arrange order of nodes to change default load order)" type="Node" parent="."]
|
||||
script = ExtResource("2_00xd7")
|
||||
FloorName = 1
|
||||
metadata/_custom_type_script = "uid://cabvj6s31iucg"
|
||||
|
||||
[node name="Floor01 (Press Populate Map Data Button to load floor from SetAFloors folder)" type="Node" parent="."]
|
||||
script = ExtResource("3_v14r0")
|
||||
LayoutWithSpawnRate = Dictionary[String, float]({})
|
||||
EnemySpawnRates = {
|
||||
0: 1.0
|
||||
}
|
||||
metadata/_custom_type_script = "uid://ci7o3nn4mdo8o"
|
||||
|
||||
[node name="Floor02 (Add DungeonFloorLayout node for regular dungeon floors)" type="Node" parent="."]
|
||||
script = ExtResource("3_v14r0")
|
||||
LayoutWithSpawnRate = Dictionary[String, float]({})
|
||||
EnemySpawnRates = {
|
||||
0: 1.0
|
||||
}
|
||||
metadata/_custom_type_script = "uid://ci7o3nn4mdo8o"
|
||||
|
||||
@@ -12,8 +12,6 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Node] public EnemyDatabase EnemyDatabase { get; set; } = default!;
|
||||
|
||||
private Transform3D _playerSpawnPoint;
|
||||
|
||||
public ImmutableList<IDungeonRoom> Rooms { get; private set; }
|
||||
@@ -25,12 +23,16 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
|
||||
Rooms = [];
|
||||
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
|
||||
_playerSpawnPoint = RandomizePlayerSpawnPoint();
|
||||
var monsterRooms = Rooms.OfType<MonsterRoom>();
|
||||
foreach (var room in monsterRooms)
|
||||
room.SpawnEnemies(EnemyDatabase);
|
||||
}
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint() => new Transform3D(_playerSpawnPoint.Basis, new Vector3(_playerSpawnPoint.Origin.X, -1.75f, _playerSpawnPoint.Origin.Z));
|
||||
public void SpawnEnemies(Godot.Collections.Dictionary<EnemyType, float> enemyInfo)
|
||||
{
|
||||
var monsterRooms = Rooms.OfType<MonsterRoom>();
|
||||
foreach (var room in monsterRooms)
|
||||
room.SpawnEnemies(enemyInfo);
|
||||
}
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint() => new Transform3D(_playerSpawnPoint.Basis, new Vector3(_playerSpawnPoint.Origin.X, 0f, _playerSpawnPoint.Origin.Z));
|
||||
|
||||
private Transform3D RandomizePlayerSpawnPoint()
|
||||
{
|
||||
|
||||
@@ -11,8 +11,6 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||
|
||||
[Node] private MeshInstance3D _minimap { get; set; } = default!;
|
||||
|
||||
public bool IsPlayerInRoom => _isPlayerInRoom;
|
||||
@@ -30,8 +28,8 @@ public abstract partial class DungeonRoom : Node3D, IDungeonRoom
|
||||
public void Setup()
|
||||
{
|
||||
_enemiesInRoom = [];
|
||||
_room.BodyEntered += Room_BodyEntered;
|
||||
_room.BodyExited += Room_BodyExited;
|
||||
//_room.BodyEntered += Room_BodyEntered;
|
||||
//_room.BodyExited += Room_BodyExited;
|
||||
}
|
||||
|
||||
private void Room_BodyExited(Node3D body)
|
||||
|
||||
@@ -14,6 +14,8 @@ public partial class ExitRoom : DungeonRoom
|
||||
|
||||
[Node] private Area3D _exit { get; set; } = default!;
|
||||
|
||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_exit.AreaEntered += Exit_AreaEntered;
|
||||
|
||||
@@ -5,8 +5,6 @@ using System.Collections.Immutable;
|
||||
namespace Zennysoft.Game.Ma;
|
||||
public interface IDungeonRoom : INode3D
|
||||
{
|
||||
Marker3D PlayerSpawn { get; }
|
||||
|
||||
bool IsPlayerInRoom { get; }
|
||||
|
||||
bool PlayerDiscoveredRoom { get; }
|
||||
|
||||
@@ -15,6 +15,8 @@ public partial class MonsterRoom : DungeonRoom
|
||||
|
||||
[Node] public Node3D EnemySpawnPoints { get; set; } = default!;
|
||||
|
||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||
|
||||
[Node] public ItemDatabase ItemDatabase { get; set; } = default!;
|
||||
|
||||
public override void _Ready()
|
||||
@@ -22,7 +24,7 @@ public partial class MonsterRoom : DungeonRoom
|
||||
SpawnItems();
|
||||
}
|
||||
|
||||
public void SpawnEnemies(EnemyDatabase enemyDatabase)
|
||||
public void SpawnEnemies(Godot.Collections.Dictionary<EnemyType, float> enemyInfo)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
@@ -35,15 +37,19 @@ public partial class MonsterRoom : DungeonRoom
|
||||
break;
|
||||
numberOfEnemiesToSpawn--;
|
||||
|
||||
var enemy = enemyDatabase.EnemyList[rng.RandWeighted(enemyDatabase.SpawnRate)];
|
||||
var instantiatedEnemy = enemy.Instantiate<Enemy>();
|
||||
instantiatedEnemy.Position = new Vector3(spawnPoint.Position.X, 0, spawnPoint.Position.Z);
|
||||
var index = rng.RandWeighted([.. enemyInfo.Values]);
|
||||
var selectedEnemy = enemyInfo.ElementAt((int)index);
|
||||
var instantiatedEnemy = EnemyTypeToEnemyConverter.Convert(selectedEnemy.Key);
|
||||
instantiatedEnemy.Position = new Vector3(spawnPoint.Position.X, 1.75f, spawnPoint.Position.Z);
|
||||
AddChild(instantiatedEnemy);
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnItems()
|
||||
{
|
||||
if (ItemSpawnPoints == null)
|
||||
return;
|
||||
|
||||
var itemSpawnPoints = ItemSpawnPoints.GetChildren();
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="MapInfo" load_steps=2 format=3 uid="uid://c0764jocyuon4"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bb4a0ijn0q2ou" path="res://src/map/MapInfo.cs" id="1_hrh8w"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_hrh8w")
|
||||
MapNameAndOdds = Dictionary[String, float]({})
|
||||
metadata/_custom_type_script = "uid://bb4a0ijn0q2ou"
|
||||
@@ -1,10 +1,9 @@
|
||||
[gd_scene load_steps=16 format=3 uid="uid://dpec2lbt83dhe"]
|
||||
[gd_scene load_steps=15 format=3 uid="uid://dpec2lbt83dhe"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dhollu4j3pynq" path="res://src/map/dungeon/code/MonsterRoom.cs" id="1_312b8"]
|
||||
[ext_resource type="PackedScene" uid="uid://bvpwkx6ag1yf4" path="res://src/map/dungeon/models/Area 1/Antechamber/A1-Antechamber.glb" id="2_kycn2"]
|
||||
[ext_resource type="Texture2D" uid="uid://ncu0fsnqyede" path="res://src/minimap/textures/Room Maps/mi_antechamber.png" id="6_0ndak"]
|
||||
[ext_resource type="PackedScene" uid="uid://twrj4wixcbu7" path="res://src/items/ItemDatabase.tscn" id="17_25wvm"]
|
||||
[ext_resource type="Texture2D" uid="uid://bkvegamuqdsdd" path="res://src/map/dungeon/corridors/Corridor A/CORRIDOR test_FLOOR1.jpg" id="17_jig7d"]
|
||||
[ext_resource type="Texture2D" uid="uid://del2dfj3etokd" path="res://src/map/assets/Blocked Door A1 .png" id="20_le1vp"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_phhs1"]
|
||||
@@ -21,10 +20,8 @@ albedo_texture = ExtResource("20_le1vp")
|
||||
texture_filter = 0
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_b605t"]
|
||||
albedo_texture = ExtResource("17_jig7d")
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_cnaww"]
|
||||
albedo_texture = ExtResource("17_jig7d")
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_e81mq"]
|
||||
size = Vector3(20, 8, 16)
|
||||
@@ -169,7 +166,8 @@ shape = SubResource("BoxShape3D_e81mq")
|
||||
[node name="Minimap" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.61193, 0.859072, 0)
|
||||
|
||||
[node name="mi_antechamber" type="MeshInstance3D" parent="Minimap"]
|
||||
[node name="Minimap" type="MeshInstance3D" parent="Minimap"]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.983959, 0)
|
||||
layers = 2
|
||||
mesh = SubResource("PlaneMesh_7ppra")
|
||||
|
||||
@@ -111,3 +111,8 @@ popup/item_13/text = "Shield of Heaven"
|
||||
popup/item_13/id = 13
|
||||
popup/item_14/text = "Gold Sproingy"
|
||||
popup/item_14/id = 14
|
||||
|
||||
[node name="LoadNextFloorButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Load Next Floor"
|
||||
|
||||
@@ -23,6 +23,8 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
|
||||
[Node] public OptionButton SpawnEnemyDropDown { get; set; } = default!;
|
||||
|
||||
[Node] public Button LoadNextFloorButton { get; set; } = default!;
|
||||
|
||||
private readonly string _floorFilePath = @"res://src/map/dungeon/floors/";
|
||||
private readonly string _enemyFilePath = @"res://src/enemy/enemy_types";
|
||||
|
||||
@@ -33,6 +35,8 @@ public partial class PauseDebugMenu : Control, IDebugMenu
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
LoadNextFloorButton.Pressed += LoadNextFloorButton_Pressed;
|
||||
|
||||
_itemDatabase = new ItemDatabase();
|
||||
_spawnableItems = _itemDatabase.Items;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user