Major Player refactor
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using GameJamDungeon;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class BossFloor : Node3D, IDungeonFloor
|
||||
{
|
||||
|
||||
@@ -3,67 +3,66 @@ using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using System.Linq;
|
||||
|
||||
namespace GameJamDungeon
|
||||
namespace GameJamDungeon;
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class BossRoom : Node3D, IDungeonRoom
|
||||
{
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class BossRoom : Node3D, IDungeonRoom
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
|
||||
|
||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||
|
||||
[Node] public Marker3D TeleportSpawn { get; set; } = default!;
|
||||
|
||||
[Node] public Marker3D ItemSpawnPoint { get; set; } = default!;
|
||||
|
||||
[Node] public ItemDatabase ItemDatabase { get; set; } = default!;
|
||||
|
||||
[Node] public Node3D HorseHeadStatue { get; set; } = default!;
|
||||
|
||||
[Node] public Node3D OxFaceStatue { get; set; } = default!;
|
||||
|
||||
[Node] public Boss OxFace { get; set; } = default!;
|
||||
|
||||
[Node] public Boss HorseFace { get; set; } = default!;
|
||||
|
||||
[Node] public Area3D ActivateTrap { get; set; } = default!;
|
||||
|
||||
[Node] public StaticBody3D GateCollision { get; set; } = default!;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
SpawnItems();
|
||||
ActivateTrap.BodyEntered += StartBossFight;
|
||||
OxFace.CurrentHP.Sync += BossHPUpdate;
|
||||
HorseFace.CurrentHP.Sync += BossHPUpdate;
|
||||
}
|
||||
|
||||
[Dependency] public IGameRepo GameRepo => this.DependOn<IGameRepo>();
|
||||
private void BossHPUpdate(double obj)
|
||||
{
|
||||
if (OxFace.CurrentHP.Value <= 0 && HorseFace.CurrentHP.Value <= 0)
|
||||
GateCollision.CallDeferred(MethodName.QueueFree);
|
||||
}
|
||||
|
||||
[Node] public Marker3D PlayerSpawn { get; set; } = default!;
|
||||
private void SpawnItems()
|
||||
{
|
||||
var database = ItemDatabase.Initialize().OfType<ConsumableItem>().ToArray();
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var weights = database.Select(x => x.SpawnRate).ToArray();
|
||||
var selectedItem = database[rng.RandWeighted(weights)];
|
||||
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
|
||||
duplicated.Position = ItemSpawnPoint.Position;
|
||||
AddChild(duplicated);
|
||||
}
|
||||
|
||||
[Node] public Marker3D TeleportSpawn { get; set; } = default!;
|
||||
|
||||
[Node] public Marker3D ItemSpawnPoint { get; set; } = default!;
|
||||
|
||||
[Node] public ItemDatabase ItemDatabase { get; set; } = default!;
|
||||
|
||||
[Node] public Node3D HorseHeadStatue { get; set; } = default!;
|
||||
|
||||
[Node] public Node3D OxFaceStatue { get; set; } = default!;
|
||||
|
||||
[Node] public Boss OxFace { get; set; } = default!;
|
||||
|
||||
[Node] public Boss HorseFace { get; set; } = default!;
|
||||
|
||||
[Node] public Area3D ActivateTrap { get; set; } = default!;
|
||||
|
||||
[Node] public StaticBody3D GateCollision { get; set; } = default!;
|
||||
|
||||
public void Setup()
|
||||
{
|
||||
SpawnItems();
|
||||
ActivateTrap.BodyEntered += StartBossFight;
|
||||
OxFace.CurrentHP.Sync += BossHPUpdate;
|
||||
HorseFace.CurrentHP.Sync += BossHPUpdate;
|
||||
}
|
||||
|
||||
private void BossHPUpdate(double obj)
|
||||
{
|
||||
if (OxFace.CurrentHP.Value <= 0 && HorseFace.CurrentHP.Value <= 0)
|
||||
GateCollision.CallDeferred(MethodName.QueueFree);
|
||||
}
|
||||
|
||||
private void SpawnItems()
|
||||
{
|
||||
var database = ItemDatabase.Initialize().OfType<ConsumableItem>().ToArray();
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var weights = database.Select(x => x.Info.SpawnRate).ToArray();
|
||||
var selectedItem = database[rng.RandWeighted(weights)];
|
||||
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
|
||||
duplicated.Position = ItemSpawnPoint.Position;
|
||||
AddChild(duplicated);
|
||||
}
|
||||
|
||||
private void StartBossFight(Node3D body)
|
||||
{
|
||||
OxFaceStatue.Hide();
|
||||
HorseHeadStatue.Hide();
|
||||
OxFace.Activate();
|
||||
HorseFace.Activate();
|
||||
}
|
||||
private void StartBossFight(Node3D body)
|
||||
{
|
||||
OxFaceStatue.Hide();
|
||||
HorseHeadStatue.Hide();
|
||||
OxFace.Activate();
|
||||
HorseFace.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,90 +1,83 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public interface IDungeonFloor : INode3D
|
||||
namespace GameJamDungeon
|
||||
{
|
||||
void InitializeDungeon();
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint();
|
||||
|
||||
public Vector3 GetTeleportSpawnPoint();
|
||||
}
|
||||
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class DungeonFloor : Node3D, IDungeonFloor
|
||||
{
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
[Node] public GodotObject DungeonGenerator { get; set; } = default!;
|
||||
|
||||
[Node] public NavigationRegion3D NavigationRegion3D { get; set; } = default!;
|
||||
|
||||
private Transform3D _playerSpawnPoint;
|
||||
|
||||
private Vector3 _teleportSpawnPoint;
|
||||
|
||||
internal List<IDungeonRoom> Rooms { get; private set; }
|
||||
|
||||
public void InitializeDungeon()
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class DungeonFloor : Node3D, IDungeonFloor
|
||||
{
|
||||
Rooms = new List<IDungeonRoom>();
|
||||
DungeonGenerator.Call("generate");
|
||||
NavigationRegion3D.BakeNavigationMesh();
|
||||
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
|
||||
_playerSpawnPoint = RandomizePlayerSpawnPoint();
|
||||
_teleportSpawnPoint = RandomizeTeleportSpawnPointAwayFromPosition(_playerSpawnPoint.Origin);
|
||||
}
|
||||
public override void _Notification(int what) => this.Notify(what);
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint() => _playerSpawnPoint;
|
||||
[Node] public GodotObject DungeonGenerator { get; set; } = default!;
|
||||
|
||||
public Vector3 GetTeleportSpawnPoint() => _teleportSpawnPoint;
|
||||
[Node] public NavigationRegion3D NavigationRegion3D { get; set; } = default!;
|
||||
|
||||
private Transform3D RandomizePlayerSpawnPoint()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var rngDistribution = new List<float>();
|
||||
var randomSpawnLocations = Rooms
|
||||
.Select(x => x.PlayerSpawn);
|
||||
var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations);
|
||||
var result = godotCollection.PickRandom();
|
||||
return result.GlobalTransform;
|
||||
}
|
||||
private Transform3D _playerSpawnPoint;
|
||||
|
||||
private Vector3 RandomizeTeleportSpawnPointAwayFromPosition(Vector3 target)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var rngDistribution = new List<float>();
|
||||
var roomsSortedByDistance = Rooms
|
||||
.Select(x => x.TeleportSpawn.GlobalPosition)
|
||||
.OrderByDescending(x => x.DistanceTo(target))
|
||||
.ToArray();
|
||||
var rngIndex = 1.0;
|
||||
var rngSteps = rngIndex / roomsSortedByDistance.Count();
|
||||
foreach (var room in roomsSortedByDistance)
|
||||
private Vector3 _teleportSpawnPoint;
|
||||
|
||||
internal List<IDungeonRoom> Rooms { get; private set; }
|
||||
|
||||
public void InitializeDungeon()
|
||||
{
|
||||
rngIndex -= rngSteps;
|
||||
rngDistribution.Add((float)rngIndex);
|
||||
Rooms = new List<IDungeonRoom>();
|
||||
DungeonGenerator.Call("generate");
|
||||
NavigationRegion3D.BakeNavigationMesh();
|
||||
Rooms = FindAllDungeonRooms([.. GetChildren()], Rooms);
|
||||
_playerSpawnPoint = RandomizePlayerSpawnPoint();
|
||||
_teleportSpawnPoint = RandomizeTeleportSpawnPointAwayFromPosition(_playerSpawnPoint.Origin);
|
||||
}
|
||||
|
||||
var result = roomsSortedByDistance[rng.RandWeighted([.. rngDistribution])];
|
||||
return result;
|
||||
}
|
||||
public Transform3D GetPlayerSpawnPoint() => _playerSpawnPoint;
|
||||
|
||||
private List<IDungeonRoom> FindAllDungeonRooms(List<Node> nodesToSearch, List<IDungeonRoom> roomsFound)
|
||||
{
|
||||
if (nodesToSearch.Count == 0)
|
||||
return roomsFound;
|
||||
public Vector3 GetTeleportSpawnPoint() => _teleportSpawnPoint;
|
||||
|
||||
foreach (var node in nodesToSearch)
|
||||
if (node is IDungeonRoom dungeonRoom)
|
||||
roomsFound.Add(dungeonRoom);
|
||||
private Transform3D RandomizePlayerSpawnPoint()
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var rngDistribution = new List<float>();
|
||||
var randomSpawnLocations = Rooms
|
||||
.Select(x => x.PlayerSpawn);
|
||||
var godotCollection = new Godot.Collections.Array<Marker3D>(randomSpawnLocations);
|
||||
var result = godotCollection.PickRandom();
|
||||
return result.GlobalTransform;
|
||||
}
|
||||
|
||||
return FindAllDungeonRooms(nodesToSearch.SelectMany(x => x.GetChildren()).ToList(), roomsFound);
|
||||
private Vector3 RandomizeTeleportSpawnPointAwayFromPosition(Vector3 target)
|
||||
{
|
||||
var rng = new RandomNumberGenerator();
|
||||
rng.Randomize();
|
||||
var rngDistribution = new List<float>();
|
||||
var roomsSortedByDistance = Rooms
|
||||
.Select(x => x.TeleportSpawn.GlobalPosition)
|
||||
.OrderByDescending(x => x.DistanceTo(target))
|
||||
.ToArray();
|
||||
var rngIndex = 1.0;
|
||||
var rngSteps = rngIndex / roomsSortedByDistance.Length;
|
||||
foreach (var room in roomsSortedByDistance)
|
||||
{
|
||||
rngIndex -= rngSteps;
|
||||
rngDistribution.Add((float)rngIndex);
|
||||
}
|
||||
|
||||
var result = roomsSortedByDistance[rng.RandWeighted([.. rngDistribution])];
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<IDungeonRoom> FindAllDungeonRooms(List<Node> nodesToSearch, List<IDungeonRoom> roomsFound)
|
||||
{
|
||||
if (nodesToSearch.Count == 0)
|
||||
return roomsFound;
|
||||
|
||||
foreach (var node in nodesToSearch)
|
||||
if (node is IDungeonRoom dungeonRoom)
|
||||
roomsFound.Add(dungeonRoom);
|
||||
|
||||
return FindAllDungeonRooms(nodesToSearch.SelectMany(x => x.GetChildren()).ToList(), roomsFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using GameJamDungeon;
|
||||
using Godot;
|
||||
using System.Linq;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
public interface IDungeonRoom : INode3D
|
||||
{
|
||||
public Marker3D PlayerSpawn { get; set; }
|
||||
@@ -50,7 +51,7 @@ public partial class DungeonRoom : Node3D, IDungeonRoom
|
||||
break;
|
||||
numberOfItemsToSpawn--;
|
||||
|
||||
var weights = database.Select(x => x.Info.SpawnRate).ToArray();
|
||||
var weights = database.Select(x => x.SpawnRate).ToArray();
|
||||
var selectedItem = database[rng.RandWeighted(weights)];
|
||||
var duplicated = selectedItem.Duplicate((int)DuplicateFlags.UseInstantiation) as Node3D;
|
||||
duplicated.Position = new Vector3(spawnPoint.Position.X, -1.75f, spawnPoint.Position.Z);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class Floor0 : Node3D, IDungeonFloor
|
||||
{
|
||||
|
||||
12
src/map/dungeon/code/IDungeonFloor.cs
Normal file
12
src/map/dungeon/code/IDungeonFloor.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Chickensoft.GodotNodeInterfaces;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
public interface IDungeonFloor : INode3D
|
||||
{
|
||||
void InitializeDungeon();
|
||||
|
||||
public Transform3D GetPlayerSpawnPoint();
|
||||
|
||||
public Vector3 GetTeleportSpawnPoint();
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class MinimapManager : Area3D
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Chickensoft.AutoInject;
|
||||
using Chickensoft.Introspection;
|
||||
using GameJamDungeon;
|
||||
using Godot;
|
||||
|
||||
namespace GameJamDungeon;
|
||||
[Meta(typeof(IAutoNode))]
|
||||
public partial class Overworld : Node3D, IDungeonFloor
|
||||
{
|
||||
|
||||
@@ -705,7 +705,7 @@ skeleton = NodePath("")
|
||||
|
||||
[node name="PlayerSpawn" type="Marker3D" parent="Antechamber"]
|
||||
unique_name_in_owner = true
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.61757, -2.04983, 0.580412)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.61757, -1.89174, 0.580412)
|
||||
|
||||
[node name="ItemSpawnPoints" type="Node3D" parent="Antechamber"]
|
||||
unique_name_in_owner = true
|
||||
|
||||
Reference in New Issue
Block a user