Major Player refactor

This commit is contained in:
2025-02-07 02:29:50 -08:00
parent 0cdae88952
commit fe1a1e61ef
132 changed files with 2554 additions and 2478 deletions

View File

@@ -1,9 +1,9 @@
[gd_scene load_steps=9 format=3 uid="uid://by67pn7fdsg1m"]
[ext_resource type="Script" path="res://src/map/Map.cs" id="1_bw70o"]
[ext_resource type="Script" uid="uid://14e8mu48ed4" path="res://src/map/Map.cs" id="1_bw70o"]
[ext_resource type="PackedScene" uid="uid://dl6h1djc27ddl" path="res://src/map/overworld/Floor0.tscn" id="2_0m8h8"]
[ext_resource type="PackedScene" uid="uid://bc1sp6xwe0j65" path="res://src/map/dungeon/floors/Floor01.tscn" id="2_merfv"]
[ext_resource type="Script" path="res://src/map/dungeon/code/Floor0.cs" id="3_n0f1p"]
[ext_resource type="Script" uid="uid://c1nhqlem1ew3m" path="res://src/map/dungeon/code/Floor0.cs" id="3_n0f1p"]
[ext_resource type="PackedScene" uid="uid://g28xmp6cn16h" path="res://src/map/dungeon/floors/Floor11.tscn" id="3_niasb"]
[ext_resource type="PackedScene" uid="uid://dmiqwmivkjgmq" path="res://src/map/dungeon/floors/Floor02.tscn" id="4_8y0oy"]
[ext_resource type="PackedScene" uid="uid://bjqgl5u05ia04" path="res://src/map/dungeon/Teleport.tscn" id="5_jiohg"]

View File

@@ -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
{

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -2,6 +2,7 @@
using Chickensoft.Introspection;
using Godot;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class Floor0 : Node3D, IDungeonFloor
{

View File

@@ -0,0 +1,12 @@
using Chickensoft.GodotNodeInterfaces;
using Godot;
namespace GameJamDungeon;
public interface IDungeonFloor : INode3D
{
void InitializeDungeon();
public Transform3D GetPlayerSpawnPoint();
public Vector3 GetTeleportSpawnPoint();
}

View File

@@ -2,6 +2,7 @@ using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
namespace GameJamDungeon;
[Meta(typeof(IAutoNode))]
public partial class MinimapManager : Area3D
{

View File

@@ -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
{

View File

@@ -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

View File

@@ -1,9 +1,8 @@
[gd_scene load_steps=8 format=3 uid="uid://dl6h1djc27ddl"]
[gd_scene load_steps=7 format=3 uid="uid://dl6h1djc27ddl"]
[ext_resource type="Script" uid="uid://cuhfkyh3d7noa" path="res://src/map/dungeon/code/Overworld.cs" id="1_2ce63"]
[ext_resource type="PackedScene" uid="uid://duis2vhf5ojy3" path="res://src/item_rescue/ItemRescue.tscn" id="2_4ixnb"]
[ext_resource type="PackedScene" uid="uid://tc5kdfoggrng" path="res://src/item_rescue/RescuedItems.tscn" id="3_tbcl3"]
[ext_resource type="PackedScene" uid="uid://1fl6s352e2ej" path="res://src/items/throwable/ThrowableItem.tscn" id="4_wibf0"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pb22g"]
@@ -57,7 +56,4 @@ collision_mask = 3
[node name="CollisionShape3D" type="CollisionShape3D" parent="Spawn Rescued Items/Area3D"]
shape = SubResource("SphereShape3D_tbcl3")
[node name="ThrowableItem" parent="." instance=ExtResource("4_wibf0")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0)
[connection signal="body_entered" from="Spawn Rescued Items/Area3D" to="Rescued Items" method="OnSpawnItemsEntered"]