Revamp map route stuff

This commit is contained in:
2026-06-11 20:53:16 -07:00
parent fc598ab48f
commit 403b136c5c
34 changed files with 731 additions and 559 deletions
@@ -13,6 +13,7 @@ public partial class GameState
public FloorExitScreen()
{
OnAttach(() => Get<IGameRepo>().Pause());
OnDetach(() => Get<IGameRepo>().Resume());
}
public Transition On(in Input.LoadNextFloor input)
@@ -11,5 +11,7 @@ public interface IDungeonFloor : INode3D
public ImmutableList<IDungeonRoom> Rooms { get; }
public IDungeonRoom GetPlayersCurrentRoom();
public bool FloorIsLoaded { get; set; }
}
@@ -35,7 +35,7 @@ public partial class FleeBehavior : Node3D, IBehavior
public void StartFlee(NavigationAgent3D navigationAgent)
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
var rooms = _game.CurrentFloor.Rooms;
var validRooms = new Godot.Collections.Array<MonsterRoom>(rooms.OfType<MonsterRoom>());
var randomRoom = validRooms.PickRandom();
+13 -33
View File
@@ -185,12 +185,10 @@ public partial class Game : Node3D, IGame
PauseContainer.AddChild((Map)_map);
}
public async void OnResolved()
public void OnResolved()
{
LoadExistingGame();
await InitializeGame();
GameState.Set(GameRepo);
GameState.Set(_player);
GameState.Set(_map);
@@ -200,13 +198,11 @@ public partial class Game : Node3D, IGame
GameState.Start();
this.Provide();
InitializeGame();
InGameUI.UseTeleportPrompt.TeleportToNextFloor += UseTeleportPrompt_TeleportToNextFloor;
InGameUI.UseTeleportPrompt.CloseTeleportPrompt += UseTeleportPrompt_CloseTeleportPrompt;
LoadNextLevel.GoToNextFloor += FloorClearMenu_GoToNextFloor;
LoadNextLevel.Exit += FloorClearMenu_Exit;
LoadNextLevel.TransitionCompleted += FloorClearMenu_TransitionCompleted;
OnLoadLevelRequest += LoadLevel;
GameRepo.CloseInventoryEvent += ExitInventoryAction;
@@ -250,12 +246,11 @@ public partial class Game : Node3D, IGame
public void LoadExistingGame() => SaveFile.Load().ContinueWith((_) => CallDeferred(nameof(FinishedLoadingSaveFile)));
public async Task InitializeGame()
public void InitializeGame()
{
_player.ResetPlayerData();
_map.InitializeMapData();
_map.LoadFloor(_map.FloorRoute.First());
_effectService = new EffectService(this, _player, _map);
await _map.LoadFloor();
}
public async Task Save() => await SaveFile.Save();
@@ -424,7 +419,6 @@ public partial class Game : Node3D, IGame
})
.Handle((in GameState.Output.LoadNextFloor _) =>
{
EmitSignal(SignalName.OnLoadLevelRequest);
var breakableItems = _player.Inventory.Items.Where(x => x.ItemTag == ItemTag.BreaksOnFloorExit).ToList();
foreach (IEquipableItem breakableItem in breakableItems)
{
@@ -433,11 +427,9 @@ public partial class Game : Node3D, IGame
_player.Inventory.Remove(breakableItem);
}
Task.Run(() => Save());
LoadNextLevel.FadeOut();
})
.Handle((in GameState.Output.ReturnToOverworld _) =>
{
LoadNextLevel.FadeOut();
Task.Run(() => Save());
InitializeGame();
})
@@ -464,13 +456,6 @@ public partial class Game : Node3D, IGame
InGameUI.InventoryMenu.SetProcessInput(false);
}
private async void LoadLevel()
{
await _map.LoadFloor();
}
private void FloorClearMenu_GoToNextFloor() => GameState.Input(new GameState.Input.LoadNextFloor());
private void DropRestorative(Vector3 vector)
{
var restorativeScene = GD.Load<PackedScene>("res://src/items/restorative/Restorative.tscn");
@@ -506,11 +491,6 @@ public partial class Game : Node3D, IGame
private void PointUpFinished() => GameState.Input(new GameState.Input.UseTeleport());
private void FloorClearMenu_TransitionCompleted()
{
GameRepo.Resume();
}
private void IsPaused_Sync(bool isPaused) => GetTree().Paused = isPaused;
private void FinishedLoadingSaveFile() => EmitSignal(SignalName.SaveFileLoaded);
@@ -924,13 +904,13 @@ public partial class Game : Node3D, IGame
private void OnFloorLoadFinished()
{
LoadNextLevel.Hide();
GameLoaded?.Invoke();
_map.FadeIn();
if (GameOverMenu.Visible)
GameOverMenu.FadeOut();
GameRepo.Resume();
_player.Activate();
_map.ShowMap();
GameState.Input(new GameState.Input.LoadNextFloor());
Resume();
}
private void RustStatusChanged(bool rustStatus)
@@ -1001,9 +981,13 @@ public partial class Game : Node3D, IGame
UnlockGalleryItem.Invoke("TrueEnd");
}
public void Pause() => GameRepo.Pause();
public void Resume() => GameRepo.Resume();
private void OnQuit() => GameExitRequested?.Invoke();
private void GameOverMenuAppeared() => _map.ClearFloor();
private void GameOverMenuAppeared() => _map.EndCurrentGame();
private void OnResume() => GameState.Input(new GameState.Input.PauseButtonPressed());
@@ -1011,11 +995,7 @@ public partial class Game : Node3D, IGame
{
InGameUI.UseTeleportPrompt.TeleportToNextFloor -= UseTeleportPrompt_TeleportToNextFloor;
InGameUI.UseTeleportPrompt.CloseTeleportPrompt -= UseTeleportPrompt_CloseTeleportPrompt;
LoadNextLevel.GoToNextFloor -= FloorClearMenu_GoToNextFloor;
LoadNextLevel.Exit -= FloorClearMenu_Exit;
LoadNextLevel.TransitionCompleted -= FloorClearMenu_TransitionCompleted;
OnLoadLevelRequest -= LoadLevel;
GameRepo.CloseInventoryEvent -= ExitInventoryAction;
+4
View File
@@ -52,6 +52,10 @@ public interface IGame : IProvide<IGame>, IProvide<IGameRepo>, IProvide<IPlayer>
public Task OnReachTrueEnd();
public void Pause();
public void Resume();
public ItemRescueMenu ItemRescueMenu { get; }
public QuestData QuestData { get; }
+6 -6
View File
@@ -22,7 +22,7 @@ public class EffectService
public void TeleportEnemiesToCurrentRoom(List<IEnemy> enemyList)
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is MonsterRoom currentMonsterRoom)
{
@@ -33,7 +33,7 @@ public class EffectService
public void KillHalfEnemiesInRoom()
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom)
return;
@@ -46,7 +46,7 @@ public class EffectService
public void TurnAllEnemiesInRoomIntoHealingItem()
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom)
return;
@@ -78,7 +78,7 @@ public class EffectService
public void HealAllEnemiesAndPlayerInRoomToFull()
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom)
return;
@@ -91,7 +91,7 @@ public class EffectService
public int AbsorbHPFromAllEnemiesInRoom()
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom)
return 0;
@@ -110,7 +110,7 @@ public class EffectService
public void DealElementalDamageToAllEnemiesInRoom(ElementType elementType)
{
var currentRoom = _map.GetPlayersCurrentRoom();
var currentRoom = _map.CurrentFloor.GetPlayersCurrentRoom();
if (currentRoom is not MonsterRoom)
return;
@@ -1,75 +0,0 @@
using Godot;
namespace Zennysoft.Game.Ma;
public partial class DungeonFloorNode : FloorNode
{
[ExportGroup("Floor Set")]
[Export]
public string FolderName { get; set; }
[Export]
public Godot.Collections.Array<float> FloorOdds { get; set; } = [];
[ExportGroup("Spawn Rates")]
[Export]
public float Sproingy { get; set; }
[Export]
public float Michael { get; set; }
[Export]
public float FilthEater { get; set; }
[Export]
public float Sara { get; set; }
[Export]
public float Ballos { get; set; }
[Export]
public float Chinthe { get; set; }
[Export]
public float GreenAmbassador { get; set; }
[Export]
public float RedAmbassador { get; set; }
[Export]
public float SteelAmbassador { get; set; }
[Export]
public float AgniDemon { get; set; }
[Export]
public float AqueosDemon { get; set; }
[Export]
public float Palan { get; set; }
[Export]
public float ShieldOfHeaven { get; set; }
[Export]
public float GoldSproingy { get; set; }
[ExportGroup("True Route Spawn Rates")]
[Export]
public float TrueSproingy { get; set; }
[Export]
public float TrueMichael { get; set; }
[Export]
public float TrueFilthEater { get; set; }
[Export]
public float TrueSara { get; set; }
[Export]
public float TrueBallos { get; set; }
[Export]
public float TrueChariot { get; set; }
[Export]
public float TrueChinthe { get; set; }
[Export]
public float TrueGreenAmbassador { get; set; }
[Export]
public float TrueRedAmbassador { get; set; }
[Export]
public float TrueSteelAmbassador { get; set; }
[Export]
public float TrueAgniDemon { get; set; }
[Export]
public float TrueAqueosDemon { get; set; }
[Export]
public float TruePalan { get; set; }
[Export]
public float TrueShieldOfHeaven { get; set; }
[Export]
public float TrueGoldSproingy { get; set; }
}
@@ -0,0 +1,13 @@
using Godot;
namespace Zennysoft.Game.Ma;
[GlobalClass]
public partial class EnemySpawnRate : Resource
{
[Export]
public EnemyType EnemyType { get; set; }
[Export]
public float SpawnRate { get; set; }
}
@@ -0,0 +1 @@
uid://bjal67ir4k11d
@@ -0,0 +1 @@
uid://0xsxfrp5akmf
@@ -1,11 +0,0 @@
using Godot;
namespace Zennysoft.Game.Ma;
[GlobalClass]
public partial class FloorResourceType : Resource
{
[Export] public string FloorDisplayName { get; set; }
[Export] public string FolderPath { get; set; }
}
@@ -0,0 +1,152 @@
using Godot;
using Godot.Collections;
using System;
using System.Linq;
namespace Zennysoft.Game.Ma;
public static class FloorScenePathConverter
{
public static string Convert(FloorScene sceneToConvert)
{
string filePath = @"res://src/map/dungeon/floors/";
switch (sceneToConvert.FloorType)
{
case FloorType.Overworld:
return filePath + @"Special Floors/Overworld.tscn";
case FloorType.Altar:
return filePath + @"Special Floors/00. Altar.tscn";
case FloorType.Floor01:
return PickRandomFromFolder(filePath + "Floor01/");
case FloorType.Floor02:
return PickRandomFromFolder(filePath + "Floor02/");
case FloorType.Floor03:
return PickRandomFromFolder(filePath + "Floor03/");
case FloorType.Floor04:
return PickRandomFromFolder(filePath + "Floor04/");
case FloorType.Floor05:
return PickRandomFromFolder(filePath + "Floor05/");
case FloorType.Floor06:
return PickRandomFromFolder(filePath + "Floor06/");
case FloorType.Floor07:
return PickRandomFromFolder(filePath + "Floor07/");
case FloorType.BossFloorA:
return filePath + "Special Floors/Floor 08 Boss Floor A.tscn";
case FloorType.Floor09:
return PickRandomFromFolder(filePath + "Floor09/");
case FloorType.Floor10:
return PickRandomFromFolder(filePath + "Floor10/");
case FloorType.Floor11:
return PickRandomFromFolder(filePath + "Floor11/");
case FloorType.Floor12:
return PickRandomFromFolder(filePath + "Floor12/");
case FloorType.Floor13:
return PickRandomFromFolder(filePath + "Floor13/");
case FloorType.Floor14:
return PickRandomFromFolder(filePath + "Floor14/");
case FloorType.Floor15:
return PickRandomFromFolder(filePath + "Floor15/");
case FloorType.BossFloorB:
return filePath + "Special Floors/Floor 16 Boss Floor B.tscn";
case FloorType.GoddessOfGuidance:
return filePath + "Special Floors/35. Goddess of Guidance's Room.tscn";
case FloorType.FinalFloor:
return filePath + "Special Floors/36. Final Floor.tscn";
case FloorType.Server:
return filePath + "Special Floors/Server.tscn";
case FloorType.Cellular:
return filePath + "Special Floors/Cellular.tscn";
case FloorType.Grassland:
return filePath + "Special Floors/Grassland.tscn";
case FloorType.Platform:
return filePath + "Special Floors/Platform.tscn";
case FloorType.River:
return filePath + "Special Floors/River.tscn";
case FloorType.BadEnd:
return filePath + "Special Floors/BAD END.tscn";
case FloorType.HeartOfAllThings:
break;
case FloorType.TrueGoddessOfGuidance:
return filePath + "Special Floors/40. Goddess of Guidance's Room - True Form.tscn";
default:
throw new NotImplementedException("Floor not added yet.");
}
return string.Empty;
}
public static string ConvertFromSpecificLayout(FloorScene sceneToConvert, string layoutSceneName)
{
string filePath = @"res://src/map/dungeon/floors/";
switch (sceneToConvert.FloorType)
{
case FloorType.Overworld:
return filePath + @"Special Floors/Overworld.tscn";
case FloorType.Altar:
return filePath + @"Special Floors/00. Altar.tscn";
case FloorType.Floor01:
return filePath + "Floor01/" + layoutSceneName;
case FloorType.Floor02:
return filePath + "Floor02/" + layoutSceneName;
case FloorType.Floor03:
return filePath + "Floor03/" + layoutSceneName;
case FloorType.Floor04:
return filePath + "Floor04/" + layoutSceneName;
case FloorType.Floor05:
return filePath + "Floor05/" + layoutSceneName;
case FloorType.Floor06:
return filePath + "Floor06/" + layoutSceneName;
case FloorType.Floor07:
return filePath + "Floor07/" + layoutSceneName;
case FloorType.BossFloorA:
return filePath + "Special Floors/Floor 08 Boss Floor A.tscn";
case FloorType.Floor09:
return filePath + "Floor09/" + layoutSceneName;
case FloorType.Floor10:
return filePath + "Floor10/" + layoutSceneName;
case FloorType.Floor11:
return filePath + "Floor11/" + layoutSceneName;
case FloorType.Floor12:
return filePath + "Floor12/" + layoutSceneName;
case FloorType.Floor13:
return filePath + "Floor13/" + layoutSceneName;
case FloorType.Floor14:
return filePath + "Floor14/" + layoutSceneName;
case FloorType.Floor15:
return filePath + "Floor15/" + layoutSceneName;
case FloorType.BossFloorB:
return filePath + "Special Floors/Floor 16 Boss Floor B.tscn";
case FloorType.GoddessOfGuidance:
return filePath + "Special Floors/35. Goddess of Guidance's Room.tscn";
case FloorType.FinalFloor:
return filePath + "Special Floors/36. Final Floor.tscn";
case FloorType.Server:
return filePath + "Special Floors/Server.tscn";
case FloorType.Cellular:
return filePath + "Special Floors/Cellular.tscn";
case FloorType.Grassland:
return filePath + "Special Floors/Grassland.tscn";
case FloorType.Platform:
return filePath + "Special Floors/Platform.tscn";
case FloorType.TrueGoddessOfGuidance:
return filePath + "Special Floors/40. Goddess of Guidance's Room - True Form.tscn";
case FloorType.River:
return filePath + "Special Floors/River.tscn";
case FloorType.BadEnd:
return filePath + "Special Floors/BAD END.tscn";
case FloorType.HeartOfAllThings:
break;
default:
throw new NotImplementedException("Floor not added yet.");
}
return string.Empty;
}
private static string PickRandomFromFolder(string folder)
{
Array<string> files = [.. DirAccess.GetFilesAt(folder).Where(x => x.EndsWith(".tscn"))];
return folder + files.PickRandom();
}
}
@@ -0,0 +1 @@
uid://bbabjp5tg27q2
+33
View File
@@ -0,0 +1,33 @@
namespace Zennysoft.Game.Ma;
public enum FloorType
{
Overworld,
Altar,
Floor01,
Floor02,
Floor03,
Floor04,
Floor05,
Floor06,
Floor07,
Floor09,
Floor10,
Floor11,
Floor12,
Floor13,
Floor14,
Floor15,
BossFloorA,
BossFloorB,
GoddessOfGuidance,
TrueGoddessOfGuidance,
Cellular,
Grassland,
Platform,
River,
Server,
FinalFloor,
BadEnd,
HeartOfAllThings
}
@@ -0,0 +1 @@
uid://bdyjlodn1pijf
+19 -20
View File
@@ -1,6 +1,7 @@
using Chickensoft.Collections;
using Chickensoft.GodotNodeInterfaces;
using Godot;
using Godot.Collections;
using System;
using System.Threading.Tasks;
@@ -8,31 +9,29 @@ namespace Zennysoft.Game.Ma;
public interface IMap : INode3D
{
void ClearFloor();
Task LoadFloor();
Task LoadFloor(string sceneName);
IDungeonFloor CurrentFloor { get; }
(Vector3 Rotation, Vector3 Position) GetPlayerSpawnPosition();
public AutoProp<FloorScene> CurrentSelectedFloor { get; }
IDungeonRoom GetPlayersCurrentRoom();
void InitializeMapData();
public void FadeIn();
public void FadeOut();
public AutoProp<int> CurrentFloorNumber { get; }
AutoProp<string> CurrentFloorDisplayString { get; }
public string NextFloorDisplayString { get; }
public Array<FloorScene> FloorRoute { get; }
public event Action<(Vector3 Rotation, Vector3 Position)> SpawnPointCreated;
public event Action FloorLoaded;
public void ShowMap();
Task LoadFloor(FloorScene floorToLoad);
Task LoadFloorByPath(string filePath);
public void AddNormalRoute();
public void AddTrueRoute();
public void AddBadEndRoute();
public void ResetToBaseRoute();
public void EndCurrentGame();
}
@@ -1,55 +0,0 @@
using Godot;
using System;
using System.Linq;
namespace Zennysoft.Game.Ma;
public static class LayoutToScenePathConverter
{
private static readonly string _folderPath = "res://src/map/dungeon/floors";
public static string Convert(FloorNode floorNode)
{
if (floorNode is DungeonFloorNode dungeonFloorNode)
return RandomDungeonFloor(dungeonFloorNode);
else if (floorNode is SpecialFloorNode specialFloorNode)
return SpawnSpecialFloor(specialFloorNode.FloorName);
throw new NotImplementedException();
}
private static string SpawnSpecialFloor(SpecialFloorType floorType)
{
var path = $"{_folderPath}/Special Floors/";
var files = DirAccess.GetFilesAt(path);
switch (floorType)
{
case SpecialFloorType.Overworld:
return path + files.Single(x => x.EndsWith("Overworld.tscn"));
case SpecialFloorType.Altar:
return path + files.Single(x => x.EndsWith("Altar.tscn"));
case SpecialFloorType.BossFloorA:
return path + files.Single(x => x.EndsWith("Boss Floor A.tscn"));
case SpecialFloorType.BossFloorB:
return path + files.Single(x => x.EndsWith("Boss Floor B.tscn"));
case SpecialFloorType.GoddessOfGuidanceFloor:
return path + files.Single(x => x.EndsWith("Goddess of Guidance's Room.tscn"));
case SpecialFloorType.TrueGoddessOfGuidanceFloor:
return path + files.Single(x => x.EndsWith("Goddess of Guidance's Room - True Form.tscn"));
case SpecialFloorType.FinalFloor:
return path + files.Single(x => x.EndsWith("Final Floor.tscn"));
default:
throw new NotImplementedException();
}
}
private static string RandomDungeonFloor(DungeonFloorNode floorNode)
{
var folderName = _folderPath + "/" + floorNode.FolderName;
var floorList = DirAccess.GetFilesAt(folderName).Where(x => x.EndsWith(".tscn"));
var rng = new RandomNumberGenerator();
rng.Randomize();
var index = (int)rng.RandWeighted([.. floorNode.FloorOdds]);
var result = floorList.ElementAt(index);
return folderName + "/" + result;
}
}
@@ -1 +0,0 @@
uid://d0yn4yu7264c8
+99 -77
View File
@@ -18,30 +18,34 @@ public partial class Map : Node3D, IMap
[Dependency]
public IGame Game => this.DependOn<IGame>();
[Node]
public Node MapOrder { get; set; } = default!;
[Node]
public AnimationPlayer AnimationPlayer { get; set; } = default!;
public IDungeonFloor CurrentFloor { get; private set; }
public AutoProp<int> CurrentFloorNumber { get; private set; } = new AutoProp<int>(0);
public AutoProp<string> CurrentFloorDisplayString { get; private set; } = new AutoProp<string>(string.Empty);
public string NextFloorDisplayString => MapOrder.GetChildren().OfType<FloorNode>().ElementAt(CurrentFloorNumber.Value + 1).DisplayedFloorNumber;
private readonly string _floorFilePath = @"res://src/map/dungeon/floors/";
public event Action<(Vector3 Rotation, Vector3 Position)> SpawnPointCreated;
[Export]
public Array<FloorResourceType> FloorOrder { get; set; } = [];
public Array<FloorScene> FloorRoute { get; private set; }
[Export] public Array<FloorScene> BaseRoute { get; set; }
[Export] public Array<FloorScene> NormalEndRoute { get; set; }
[Export] public Array<FloorScene> TrueEndRoute { get; set; }
[Export] public Array<FloorScene> BadEndRoute { get; set; }
public AutoProp<FloorScene> CurrentSelectedFloor { get; set; }
public event Action FloorLoaded;
private string _sceneName;
private string _floorToLoad;
public override void _EnterTree()
{
FloorRoute = [.. BaseRoute];
CurrentSelectedFloor = new AutoProp<FloorScene>(FloorRoute.First());
}
public void OnResolved()
{
@@ -52,47 +56,93 @@ public partial class Map : Node3D, IMap
private async void AnimationPlayer_AnimationFinished(StringName animName)
{
if (animName == "fade_out")
{
await LoadNewFloor();
FloorLoaded?.Invoke();
}
await ContinueLoadingFloor(_floorToLoad);
}
private async Task LoadNewFloor()
public void ShowMap() => FadeIn();
private void FadeIn() => AnimationPlayer.Play("fade_in");
private void FadeOut() => AnimationPlayer.Play("fade_out");
public void EndCurrentGame()
{
CleanupCurrentFloor();
ClearFloor();
FloorRoute = [.. BaseRoute];
}
public async Task LoadFloor(FloorScene floorToLoad)
{
Game.Pause();
// Clean up current floor
CleanupCurrentFloor();
// Start loading new floor
var filePath = FloorScenePathConverter.Convert(floorToLoad);
_floorToLoad = filePath;
FadeOut();
}
public async Task LoadFloorByPath(string filePath)
{
Game.Pause();
// Clean up current floor
CleanupCurrentFloor();
// Start loading new floor
_floorToLoad = filePath;
FadeOut();
}
public void AddNormalRoute()
{
FloorRoute.AddRange(NormalEndRoute);
}
public void AddTrueRoute()
{
FloorRoute.AddRange(TrueEndRoute);
}
public void AddBadEndRoute()
{
FloorRoute.AddRange(BadEndRoute);
}
public void ResetToBaseRoute()
{
FloorRoute = [.. BaseRoute];
CurrentSelectedFloor = new AutoProp<FloorScene>(FloorRoute.First());
}
private async Task ContinueLoadingFloor(string filePath)
{
SpawnPointCreated?.Invoke((Vector3.Forward, new Vector3(-999, -999, -999)));
var newFloor = await LoadNewFloor(_sceneName);
var newFloor = await LoadSceneFile(filePath);
// New floor created, remove old floor
ClearFloor();
// Setup new floor
AddChild(newFloor);
InitializeFloor(newFloor);
var floor = MapOrder.GetChildren().OfType<FloorNode>().ElementAt(CurrentFloorNumber.Value);
if (CurrentFloor is DungeonFloor dungeonFloor && floor is DungeonFloorNode dungeonFloorNode)
dungeonFloor.SpawnEnemies(dungeonFloorNode);
CurrentFloorDisplayString.OnNext(floor.DisplayedFloorNumber);
CurrentFloor = newFloor as IDungeonFloor;
CurrentFloor.InitializeDungeon();
SpawnPointCreated?.Invoke(CurrentFloor.GetPlayerSpawnPoint());
if (CurrentFloor is SpecialFloor)
Game.ShowMinimap(false);
else
Game.ShowMinimap(true);
SpawnEnemies();
CurrentFloor.FloorIsLoaded = true;
FloorLoaded?.Invoke();
}
public void FadeIn() => AnimationPlayer.Play("fade_in");
public void FadeOut() => AnimationPlayer.Play("fade_out");
public void InitializeMapData()
private void CleanupCurrentFloor()
{
CurrentFloorNumber.OnNext(-1);
var dimmableAudio = GetTree().GetNodesInGroup("DimmableAudio").OfType<IDimmableAudioStreamPlayer>();
foreach (var node in dimmableAudio)
node.FadeOut();
}
public IDungeonRoom GetPlayersCurrentRoom()
{
var rooms = CurrentFloor.Rooms;
var playersRoom = rooms.SingleOrDefault(x => x.IsPlayerInRoom);
return playersRoom;
}
public (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPosition()
{
var spawnPoint = CurrentFloor.GetPlayerSpawnPoint();
return (spawnPoint.Rotation, spawnPoint.Position);
}
public void ClearFloor()
private void ClearFloor()
{
try
{
@@ -105,35 +155,7 @@ public partial class Map : Node3D, IMap
}
}
public async Task LoadFloor()
{
var floor = MapOrder.GetChildren().OfType<FloorNode>().ElementAt(CurrentFloorNumber.Value + 1);
var sceneToLoad = LayoutToScenePathConverter.Convert(floor);
await LoadFloor(sceneToLoad);
}
public async Task LoadFloor(string sceneName)
{
CallDeferred(MethodName.FadeOut);
_sceneName = sceneName;
var dimmableAudio = GetTree().GetNodesInGroup("DimmableAudio").OfType<IDimmableAudioStreamPlayer>();
foreach (var node in dimmableAudio)
node.FadeOut();
}
private void InitializeFloor(Node newFloor)
{
CurrentFloor = (IDungeonFloor)newFloor;
SetupDungeonFloor();
CurrentFloor.FloorIsLoaded = true;
CurrentFloorNumber.OnNext(CurrentFloorNumber.Value + 1);
if (CurrentFloor is SpecialFloor)
Game.ShowMinimap(false);
else
Game.ShowMinimap(true);
}
private async Task<Node> LoadNewFloor(string sceneName)
private async Task<Node> LoadSceneFile(string sceneName)
{
var sceneLoader = new SceneLoader();
AddChild(sceneLoader);
@@ -144,10 +166,10 @@ public partial class Map : Node3D, IMap
return result;
}
private void SetupDungeonFloor()
private void SpawnEnemies()
{
CurrentFloor.InitializeDungeon();
var transform = GetPlayerSpawnPosition();
SpawnPointCreated?.Invoke(transform);
var monsterRooms = CurrentFloor.Rooms.OfType<MonsterRoom>();
foreach (var room in monsterRooms)
room.SpawnEnemies(CurrentSelectedFloor.Value.EnemySpawnTable);
}
}
+199 -178
View File
@@ -1,15 +1,202 @@
[gd_scene load_steps=10 format=3 uid="uid://by67pn7fdsg1m"]
[gd_scene load_steps=36 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://bvacb3ih0qt6u" path="res://src/map/FloorResourceType.cs" id="2_0qcd2"]
[ext_resource type="Script" uid="uid://dbe3wf3ywtjqh" path="res://src/map/DungeonFloorNode.cs" id="2_00xd7"]
[ext_resource type="Script" uid="uid://dpj4qg0ip6yui" path="res://src/map/SpecialFloorNode.cs" id="3_v14r0"]
[ext_resource type="Script" uid="uid://bnxutyeas2ymm" path="res://src/map/dungeon/floors/FloorScene.cs" id="2_0qcd2"]
[ext_resource type="Script" uid="uid://bjal67ir4k11d" path="res://src/map/EnemySpawnRate.cs" id="2_s7lwc"]
[sub_resource type="Resource" id="Resource_s7lwc"]
script = ExtResource("2_0qcd2")
FloorDisplayName = ""
FolderPath = ""
metadata/_custom_type_script = "uid://bvacb3ih0qt6u"
FloorDisplayName = "Surface"
FloorType = 0
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_1ny7u"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "Altar"
FloorType = 1
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_v14r0"]
script = ExtResource("2_s7lwc")
EnemyType = 0
SpawnRate = 0.5
metadata/_custom_type_script = "uid://bjal67ir4k11d"
[sub_resource type="Resource" id="Resource_0qcd2"]
script = ExtResource("2_s7lwc")
EnemyType = 1
SpawnRate = 0.5
metadata/_custom_type_script = "uid://bjal67ir4k11d"
[sub_resource type="Resource" id="Resource_3olkd"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "01"
FloorType = 2
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([SubResource("Resource_v14r0"), SubResource("Resource_0qcd2")])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_55rmo"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "02"
FloorType = 3
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_f6kwn"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "03"
FloorType = 4
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_ne2vg"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "04"
FloorType = 5
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_abpbr"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "05"
FloorType = 6
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_caf7v"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "06"
FloorType = 7
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_y74f3"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "07"
FloorType = 8
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_dbqu2"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "08"
FloorType = 16
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_xcm54"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "09"
FloorType = 9
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_pvu0e"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "10"
FloorType = 10
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_1de7e"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "11"
FloorType = 11
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_5suoo"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "12"
FloorType = 12
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_t2vkt"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "13"
FloorType = 13
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_hi63v"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "14"
FloorType = 14
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_httk4"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "15"
FloorType = 15
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_ro62w"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "16"
FloorType = 18
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_q7oan"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "18"
FloorType = 25
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_3vg2e"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "192"
FloorType = 24
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_tx34j"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "7776"
FloorType = 20
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_8npfy"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "11,664"
FloorType = 23
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_pids3"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "117,000,000,000"
FloorType = 21
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_u3fsa"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "5.63 × 10^7"
FloorType = 22
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_io2ww"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "∞"
FloorType = 19
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Resource" id="Resource_rb6u5"]
script = ExtResource("2_0qcd2")
FloorDisplayName = "-1"
FloorType = 26
EnemySpawnTable = Array[ExtResource("2_s7lwc")]([])
metadata/_custom_type_script = "uid://bnxutyeas2ymm"
[sub_resource type="Animation" id="Animation_00xd7"]
length = 0.001
@@ -64,8 +251,12 @@ _data = {
}
[node name="Map" type="Node3D"]
process_mode = 3
script = ExtResource("1_bw70o")
FloorOrder = Array[ExtResource("2_0qcd2")]([SubResource("Resource_s7lwc")])
BaseRoute = Array[ExtResource("2_0qcd2")]([SubResource("Resource_s7lwc"), SubResource("Resource_1ny7u"), SubResource("Resource_3olkd"), SubResource("Resource_55rmo"), SubResource("Resource_f6kwn"), SubResource("Resource_ne2vg"), SubResource("Resource_abpbr"), SubResource("Resource_caf7v"), SubResource("Resource_y74f3"), SubResource("Resource_dbqu2"), SubResource("Resource_xcm54"), SubResource("Resource_pvu0e"), SubResource("Resource_1de7e"), SubResource("Resource_5suoo"), SubResource("Resource_t2vkt"), SubResource("Resource_hi63v"), SubResource("Resource_httk4"), SubResource("Resource_ro62w")])
NormalEndRoute = Array[ExtResource("2_0qcd2")]([SubResource("Resource_q7oan")])
TrueEndRoute = Array[ExtResource("2_0qcd2")]([SubResource("Resource_3vg2e"), SubResource("Resource_tx34j"), SubResource("Resource_8npfy"), SubResource("Resource_pids3"), SubResource("Resource_u3fsa"), SubResource("Resource_io2ww")])
BadEndRoute = Array[Object]([SubResource("Resource_rb6u5")])
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
@@ -73,176 +264,6 @@ libraries = {
&"": SubResource("AnimationLibrary_00xd7")
}
[node name="MapOrder" type="Node" parent="."]
unique_name_in_owner = true
[node name="Overworld" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
DisplayedFloorNumber = "Surface"
[node name="Altar" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
FloorName = 1
DisplayedFloorNumber = "Altar"
[node name="Floor01" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor01"
FloorOdds = Array[float]([0.33, 0.33, 0.33])
Sproingy = 0.5
Michael = 0.5
DisplayedFloorNumber = "01"
[node name="Floor02" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor02"
FloorOdds = Array[float]([0.33, 0.33, 0.33])
Sproingy = 0.5
Michael = 0.5
FilthEater = 0.1
GoldSproingy = 0.05
TrueRedAmbassador = 0.3
DisplayedFloorNumber = "02"
[node name="Floor03" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor03"
FloorOdds = Array[float]([0.33, 0.33, 0.33])
Sproingy = 0.25
Michael = 0.5
FilthEater = 0.3
Sara = 0.1
GoldSproingy = 0.05
TrueRedAmbassador = 0.3
DisplayedFloorNumber = "03"
[node name="Floor04" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor04"
FloorOdds = Array[float]([0.33, 0.33, 0.33])
FilthEater = 0.5
Sara = 0.3
AgniDemon = 0.3
GoldSproingy = 0.05
DisplayedFloorNumber = "04"
[node name="Floor05" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor05"
FloorOdds = Array[float]([0.5, 0.5])
FilthEater = 0.25
Sara = 0.5
Ballos = 0.4
RedAmbassador = 0.3
AgniDemon = 0.5
GoldSproingy = 0.05
DisplayedFloorNumber = "05"
[node name="Floor06" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor06"
FloorOdds = Array[float]([0.2, 0.8, 0.5, 0.1])
Sara = 0.5
Ballos = 0.5
RedAmbassador = 0.3
AgniDemon = 0.5
GoldSproingy = 0.05
DisplayedFloorNumber = "06"
[node name="Floor07" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor07"
FloorOdds = Array[float]([0.33, 0.33, 0.33])
Sara = 0.1
Ballos = 0.5
RedAmbassador = 0.3
AgniDemon = 0.4
GoldSproingy = 0.05
DisplayedFloorNumber = "07"
[node name="Boss Floor 1" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
FloorName = 2
DisplayedFloorNumber = "08"
[node name="Floor09" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor09"
FloorOdds = Array[float]([0.5, 0.5])
Chinthe = 0.5
GreenAmbassador = 0.1
DisplayedFloorNumber = "09"
[node name="Floor10" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor10"
FloorOdds = Array[float]([0.5, 0.5])
Chinthe = 0.5
GreenAmbassador = 0.5
ShieldOfHeaven = 0.1
DisplayedFloorNumber = "10"
[node name="Floor11" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor11"
FloorOdds = Array[float]([0.5, 0.5])
Chinthe = 0.5
GreenAmbassador = 0.5
ShieldOfHeaven = 0.5
DisplayedFloorNumber = "11"
[node name="Floor12" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor12"
FloorOdds = Array[float]([0.5, 0.5])
GreenAmbassador = 0.5
SteelAmbassador = 0.05
ShieldOfHeaven = 0.5
DisplayedFloorNumber = "12"
[node name="Floor13" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor13"
FloorOdds = Array[float]([0.5, 0.5])
Sproingy = 1.0
GreenAmbassador = 0.25
SteelAmbassador = 0.05
Palan = 0.3
ShieldOfHeaven = 0.5
DisplayedFloorNumber = "13"
[node name="Floor14" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor14"
FloorOdds = Array[float]([0.5, 0.5])
SteelAmbassador = 0.05
Palan = 0.5
ShieldOfHeaven = 0.5
GoldSproingy = 0.05
DisplayedFloorNumber = "14"
[node name="Floor15" type="Node" parent="MapOrder"]
script = ExtResource("2_00xd7")
FolderName = "Floor15"
FloorOdds = Array[float]([1.0])
Sproingy = 1.0
DisplayedFloorNumber = "15"
[node name="Boss Floor 2" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
FloorName = 3
DisplayedFloorNumber = "16"
[node name="Goddess of Guidance Floor" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
FloorName = 4
DisplayedFloorNumber = "17"
[node name="Final Floor" type="Node" parent="MapOrder"]
script = ExtResource("3_v14r0")
FloorName = 6
DisplayedFloorNumber = "18"
[node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
@@ -1,9 +0,0 @@
using Godot;
namespace Zennysoft.Game.Ma;
[GlobalClass]
public partial class SpecialFloorObject : FloorResourceType
{
//[Export] public SpecialFloorType specialFloorType { get; set; }
}
@@ -30,30 +30,6 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
}
public void SpawnEnemies(DungeonFloorNode floorNode)
{
var enemyOdds = new Godot.Collections.Dictionary<EnemyType, float>
{
{ EnemyType.Sproingy, floorNode.Sproingy },
{ EnemyType.Michael, floorNode.Michael },
{ EnemyType.FilthEater, floorNode.FilthEater },
{ EnemyType.Sara, floorNode.Sara },
{ EnemyType.Ballos, floorNode.Ballos },
{ EnemyType.Chinthe, floorNode.Chinthe },
{ EnemyType.AmbassadorGreen, floorNode.GreenAmbassador },
{ EnemyType.AmbassadorRed, floorNode.RedAmbassador },
{ EnemyType.AmbassadorSteel, floorNode.SteelAmbassador },
{ EnemyType.AgniDemon, floorNode.AgniDemon },
{ EnemyType.AqueousDemon, floorNode.AqueosDemon },
{ EnemyType.Palan, floorNode.Palan },
{ EnemyType.ShieldOfHeaven, floorNode.ShieldOfHeaven },
{ EnemyType.GoldSproingy, floorNode.GoldSproingy },
};
var monsterRooms = Rooms.OfType<MonsterRoom>();
foreach (var room in monsterRooms)
room.SpawnEnemies(enemyOdds);
}
public (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint() { return (_playerSpawnPoint.Rotation, new Vector3(_playerSpawnPoint.GlobalPosition.X, 0, _playerSpawnPoint.GlobalPosition.Z)); }
@@ -80,4 +56,10 @@ public partial class DungeonFloor : Node3D, IDungeonFloor
return FindAllDungeonRooms([.. nodesToSearch.SelectMany(x => x.GetChildren())], roomsFound);
}
public IDungeonRoom GetPlayersCurrentRoom()
{
var playersRoom = Rooms.SingleOrDefault(x => x.IsPlayerInRoom);
return playersRoom;
}
}
@@ -1,6 +1,7 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Godot.Collections;
using System.Linq;
namespace Zennysoft.Game.Ma;
@@ -21,9 +22,9 @@ public partial class MonsterRoom : DungeonRoom
SpawnItems();
}
public void SpawnEnemies(Godot.Collections.Dictionary<EnemyType, float> enemyInfo)
public void SpawnEnemies(Array<EnemySpawnRate> spawnTable)
{
if (enemyInfo == null || !enemyInfo.Any(x => x.Value > 0))
if (spawnTable.Count == 0)
return;
var rng = new RandomNumberGenerator();
@@ -37,9 +38,9 @@ public partial class MonsterRoom : DungeonRoom
break;
numberOfEnemiesToSpawn--;
var index = rng.RandWeighted([.. enemyInfo.Values]);
var selectedEnemy = enemyInfo.ElementAt((int)index);
var instantiatedEnemy = EnemyTypeToEnemyConverter.Convert(selectedEnemy.Key);
var index = rng.RandWeighted([.. spawnTable.Select(x => x.SpawnRate)]);
var selectedEnemy = spawnTable.ElementAt((int)index);
var instantiatedEnemy = EnemyTypeToEnemyConverter.Convert(selectedEnemy.EnemyType);
AddChild(instantiatedEnemy);
instantiatedEnemy.GlobalPosition = new Vector3(spawnPoint.GlobalPosition.X, 0f, spawnPoint.GlobalPosition.Z);
ResetPhysicsInterpolation();
@@ -21,4 +21,6 @@ public partial class SpecialFloor : Node3D, IDungeonFloor
public bool FloorIsLoaded { get; set; }
public virtual (Vector3 Rotation, Vector3 Position) GetPlayerSpawnPoint() => (PlayerSpawnPoint.Rotation, new Vector3(PlayerSpawnPoint.Position.X, 0, PlayerSpawnPoint.Position.Z));
public IDungeonRoom GetPlayersCurrentRoom() => null;
}
@@ -0,0 +1,14 @@
using Godot;
using Godot.Collections;
namespace Zennysoft.Game.Ma;
[GlobalClass]
public partial class FloorScene : Resource
{
[Export] public string FloorDisplayName { get; set; }
[Export] public FloorType FloorType { get; set; }
[Export] public Array<EnemySpawnRate> EnemySpawnTable { get; set; } = [];
}
@@ -0,0 +1 @@
uid://bnxutyeas2ymm
+28
View File
@@ -63,6 +63,17 @@ layout_mode = 2
focus_neighbor_bottom = NodePath("../SpawnEnemyDropDown")
theme_override_styles/normal = SubResource("StyleBoxFlat_1ctjd")
[node name="Layout Select" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
layout_mode = 2
text = "Layout Select:"
label_settings = ExtResource("2_a7f7f")
[node name="LayoutSelectDropDown" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
unique_name_in_owner = true
layout_mode = 2
focus_neighbor_bottom = NodePath("../SpawnEnemyDropDown")
theme_override_styles/normal = SubResource("StyleBoxFlat_1ctjd")
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VFlowContainer"]
layout_mode = 2
text = "Spawn Item:"
@@ -167,3 +178,20 @@ text = "Rust"
unique_name_in_owner = true
layout_mode = 2
text = "Show Debug Info Overlay"
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 15
[node name="RouteSelect" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "Route Select:"
label_settings = ExtResource("2_a7f7f")
[node name="RouteSelectDropDown" type="OptionButton" parent="MarginContainer/VBoxContainer/HBoxContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/normal = SubResource("StyleBoxFlat_1ctjd")
+4 -4
View File
@@ -21,7 +21,7 @@ public partial class Minimap : Control
public void OnResolved()
{
_map.CurrentFloorDisplayString.Sync += CurrentFloorNumber_Sync;
_map.CurrentSelectedFloor.Sync += CurrentFloorNumber_Sync;
_ready = true;
}
@@ -31,13 +31,13 @@ public partial class Minimap : Control
MinimapCamera.Position = new Vector3(_player.GlobalPosition.X, MinimapCamera.Position.Y, _player.GlobalPosition.Z);
}
private void CurrentFloorNumber_Sync(string obj)
private void CurrentFloorNumber_Sync(FloorScene obj)
{
LayerNumberText.Text = obj;
LayerNumberText.Text = obj.FloorDisplayName;
}
public void OnExitTree()
{
_map.CurrentFloorDisplayString.Sync -= CurrentFloorNumber_Sync;
_map.CurrentSelectedFloor.Sync -= CurrentFloorNumber_Sync;
}
}
+2 -1
View File
@@ -42,6 +42,7 @@ orientation = 1
[node name="Minimap" type="Control"]
process_mode = 3
visible = false
light_mask = 2
visibility_layer = 2
layout_mode = 3
@@ -71,7 +72,7 @@ layout_mode = 2
transparent_bg = true
handle_input_locally = false
size = Vector2i(400, 350)
render_target_update_mode = 4
render_target_update_mode = 0
[node name="MinimapCamera" type="Camera3D" parent="CenterContainer/SubViewportContainer/SubViewport"]
unique_name_in_owner = true
@@ -5,8 +5,6 @@ namespace Zennysoft.Game.Ma;
public interface IFloorClearMenu : IControl
{
public event Action GoToNextFloor;
public event Action Exit;
public event Action TransitionCompleted;
@@ -33,8 +33,6 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
public void FadeOut() => AnimationPlayer.Play("fade_out");
public event Action GoToNextFloor;
public event Action Exit;
public event Action TransitionCompleted;
@@ -49,9 +47,10 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
AnimationPlayer.AnimationStarted += AnimationPlayer_AnimationStarted;
ContinueButton.Pressed += ContinueButton_Pressed;
ExitButton.Pressed += ExitButton_Pressed;
_map.CurrentSelectedFloor.Changed += CurrentSelectedFloor_Changed;
}
private void CurrentFloorNumber_Sync(int _) => FloorNumber.Text = _map.NextFloorDisplayString;
private void CurrentSelectedFloor_Changed(FloorScene obj) => FloorNumber.Text = obj.FloorDisplayName;
private void EquipmentComponent_EquipmentChanged(IEquipableItem obj)
{
@@ -81,22 +80,24 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
ContinueButton.FocusMode = FocusModeEnum.None;
ExitButton.FocusMode = FocusModeEnum.None;
SfxDatabase.Instance.Play(SoundEffect.SelectUI);
GoToNextFloor?.Invoke();
FadeOut();
}
private void AnimationPlayer_AnimationStarted(StringName animName)
private async void AnimationPlayer_AnimationStarted(StringName animName)
{
if (animName == "fade_in")
{
_fadingIn = true;
ContinueButton.FocusMode = FocusModeEnum.None;
ExitButton.FocusMode = FocusModeEnum.None;
_map.CurrentSelectedFloor.OnNext(_map.FloorRoute[_map.FloorRoute.IndexOf(_map.CurrentSelectedFloor.Value) + 1]);
}
if (animName == "fade_out")
{
DisableUISync();
_fadingIn = false;
ContinueButton.CallDeferred(MethodName.ReleaseFocus);
await _map.LoadFloor(_map.CurrentSelectedFloor.Value);
}
}
@@ -130,7 +131,7 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
_player.DefenseComponent.CurrentDefense.Sync += Defense_Sync;
_player.DefenseComponent.MaximumDefense.Sync += Defense_Sync;
_player.EquipmentComponent.EquipmentChanged += EquipmentComponent_EquipmentChanged;
_map.CurrentFloorNumber.Sync += CurrentFloorNumber_Sync;
_map.CurrentSelectedFloor.Changed += CurrentSelectedFloor_Changed;
}
private void DisableUISync()
@@ -147,6 +148,6 @@ public partial class LoadNextLevel : Control, IFloorClearMenu
_player.DefenseComponent.CurrentDefense.Sync -= Defense_Sync;
_player.DefenseComponent.MaximumDefense.Sync -= Defense_Sync;
_player.EquipmentComponent.EquipmentChanged -= EquipmentComponent_EquipmentChanged;
_map.CurrentFloorNumber.Sync -= CurrentFloorNumber_Sync;
_map.CurrentSelectedFloor.Changed -= CurrentSelectedFloor_Changed;
}
}
@@ -77,10 +77,22 @@ tracks/0/path = NodePath(".:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.999, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(0, 0, 0, 1), Color(0, 0, 0, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(0, 0, 0, 1)]
"update": 1,
"values": [true, false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_7x216"]
@@ -1,6 +1,9 @@
using Chickensoft.AutoInject;
using Chickensoft.Collections;
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
using Godot;
using Godot.Collections;
using System.Collections.Immutable;
using System.Linq;
using Zennysoft.Ma;
@@ -20,6 +23,9 @@ public partial class PauseDebugMenu : Control, IDebugMenu
[Dependency] private IPlayer _player => this.DependOn<IPlayer>();
[Node] public OptionButton FloorSelectDropDown { get; set; } = default!;
[Node] public OptionButton LayoutSelectDropDown { get; set; } = default!;
[Node] public OptionButton RouteSelectDropDown { get; set; } = default!;
[Node] public OptionButton SpawnItemDropDown { get; set; } = default;
@@ -74,22 +80,30 @@ public partial class PauseDebugMenu : Control, IDebugMenu
foreach (var item in _spawnableItems)
SpawnItemDropDown.AddItem(item.ItemName);
var folders = DirAccess.GetDirectoriesAt(_floorFilePath);
foreach (var folder in folders)
{
var files = DirAccess.GetFilesAt(_floorFilePath + folder).Where(x => x.EndsWith(".tscn"));
foreach (var file in files)
FloorSelectDropDown.AddItem(folder + "/" + file);
}
SigilDropDown.Select(0);
var dungeonFolders = DirAccess.GetDirectoriesAt(_floorFilePath).Except(["Special Floors"]);
foreach (var dungeonFolder in dungeonFolders)
{
var layouts = DirAccess.GetFilesAt(_floorFilePath + dungeonFolder).Where(x => x.EndsWith(".tscn"));
foreach (var layout in layouts)
LayoutSelectDropDown.AddItem(dungeonFolder + "/" + layout);
}
FloorSelectDropDown.AllowReselect = true;
LayoutSelectDropDown.AllowReselect = true;
SpawnItemDropDown.AllowReselect = true;
SpawnEnemyDropDown.AllowReselect = true;
RouteSelectDropDown.AddItem("Base");
RouteSelectDropDown.AddItem("Normal");
RouteSelectDropDown.AddItem("True");
RouteSelectDropDown.AddItem("Bad");
RouteSelectDropDown.Select(0);
RouteSelectDropDown.ItemSelected += RouteSelectDropDown_ItemSelected;
FloorSelectDropDown.ItemSelected += FloorSelectDropDown_ItemSelected;
LayoutSelectDropDown.ItemSelected += LayoutSelectDropDown_ItemSelected;
SpawnItemDropDown.ItemSelected += SpawnItemDropDown_ItemSelected;
SpawnEnemyDropDown.ItemSelected += SpawnEnemyDropDown_ItemSelected;
@@ -98,6 +112,42 @@ public partial class PauseDebugMenu : Control, IDebugMenu
DebugInfoCheckbox.Pressed += DebugInfoCheckbox_Pressed;
}
private void RouteSelectDropDown_ItemSelected(long index)
{
_map.ResetToBaseRoute();
var selectedItem = RouteSelectDropDown.GetItemText((int)index);
if (selectedItem == "Normal")
_map.AddNormalRoute();
else if (selectedItem == "True")
_map.AddTrueRoute();
else if (selectedItem == "Bad")
_map.AddBadEndRoute();
SetFloorDropdownItems();
LayoutSelectDropDown.Select(0);
FloorSelectDropDown_ItemSelected(0);
}
private void SetFloorDropdownItems()
{
FloorSelectDropDown.Clear();
foreach (var item in _map.FloorRoute)
FloorSelectDropDown.AddItem(item.FloorType.ToString());
}
private async void LayoutSelectDropDown_ItemSelected(long index)
{
var selection = LayoutSelectDropDown.GetItemText((int)index);
_map.CurrentSelectedFloor.OnNext(_map.FloorRoute.Single(x => selection.Contains(x.FloorDisplayName)));
await _map.LoadFloorByPath(_floorFilePath + selection);
}
public void OnResolved()
{
SetFloorDropdownItems();
}
private void SigilDropDown_ItemSelected(long index)
{
var sigilName = SigilDropDown.GetItemText((int)index);
@@ -128,10 +178,12 @@ public partial class PauseDebugMenu : Control, IDebugMenu
private void RustButton_Pressed() => _player.StatusEffectComponent.Rust.OnNext(true);
private void FloorSelectDropDown_ItemSelected(long index)
private async void FloorSelectDropDown_ItemSelected(long index)
{
var sceneName = FloorSelectDropDown.GetItemText((int)index);
_map.LoadFloor(_floorFilePath + "/" + sceneName);
var selection = FloorSelectDropDown.GetItemText((int)index);
var selectedFloor = _map.FloorRoute[(int)index];
_map.CurrentSelectedFloor.OnNext(selectedFloor);
await _map.LoadFloor(selectedFloor);
}
private void SpawnEnemyDropDown_ItemSelected(long index)
@@ -152,6 +204,7 @@ public partial class PauseDebugMenu : Control, IDebugMenu
private async void LoadNextFloorButton_Pressed()
{
await _map.LoadFloor();
_map.CurrentSelectedFloor.OnNext(_map.FloorRoute[_map.FloorRoute.IndexOf(_map.CurrentSelectedFloor.Value) + 1]);
await _map.LoadFloor(_map.CurrentSelectedFloor.Value);
}
}
@@ -1,5 +1,4 @@
using Godot;
using System;
using System.Linq;
namespace Zennysoft.Game.Ma;