Skip to content

Commit

Permalink
Merge pull request #430 from probablykory/dungeons
Browse files Browse the repository at this point in the history
DungeonManager
  • Loading branch information
MSchmoecker committed Sep 27, 2024
2 parents b24d5b8 + b8cf2b2 commit bfc6206
Show file tree
Hide file tree
Showing 99 changed files with 32,202 additions and 0 deletions.
98 changes: 98 additions & 0 deletions JotunnLib/Configs/RoomConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using Jotunn.Entities;
using UnityEngine;

namespace Jotunn.Configs
{
/// <summary>
/// Configuration class for adding custom rooms.<br />
/// Use this in a constructor of <see cref="CustomRoom"/>
/// </summary>
public class RoomConfig
{
/// <summary>
/// Theme name of this room. If adding a room to a vanilla dungeon, use nameof(Room.Theme.value)
/// </summary>
public string ThemeName { get; set; }

/// <summary>
/// If set to false, room will not be added to <see cref="DungeonGenerator.m_availableRooms"/>, thus
/// won't be used during generation.
/// </summary>
public bool? Enabled { get; set; }

/// <summary>
/// Flag indicating if this room is a dungeon entrance.
/// </summary>
public bool? Entrance { get; set; }

/// <summary>
/// Flag indicating if this room is an endcap.
/// </summary>
public bool? Endcap { get; set; }

/// <summary>
/// Flag indicating if this room is a divider.
/// </summary>
public bool? Divider { get; set; }

/// <summary>
/// A rank value to prioritize this endcap over others during generation.
/// </summary>
public int? EndcapPrio { get; set; }

/// <summary>
/// Exclude this room if the adjoining connection's <see cref="RoomConnection.m_placeOrder"/> is less than this value.
/// </summary>
public int? MinPlaceOrder { get; set; }

/// <summary>
/// A weight value used to sort available rooms during some modes of generation. Defaults to 1f.
/// </summary>
public float? Weight { get; set; }

/// <summary>
/// Flag to orient this room towards the center. Used only for generating camps (draugr/fuling villages).
/// </summary>
public bool? FaceCenter { get; set; }

/// <summary>
/// Flag to ensure this room is only placed around the perimeter of a camp. Used only for generating camps (draugr/fuling villages).
/// </summary>
public bool? Perimeter { get; set; }

/// <summary>
/// Create a config with a theme name.
/// </summary>
/// <param name="themeName"></param>
public RoomConfig(string themeName)
{
ThemeName = themeName;
}

/// <summary>
/// Create a new <see cref="RoomConfig"/>
/// </summary>
public RoomConfig() { }

/// <summary>
/// Converts the RoomConfig to a Valheim style <see cref="Room"/>.
/// </summary>
public Room Apply(Room room)
{
// Ensure Room values are overwritten only when a value's present.
if (Enabled != null) room.m_enabled = Enabled.Value;
if (Entrance != null) room.m_entrance = Entrance.Value;
if (Endcap != null) room.m_endCap = Endcap.Value;
if (Divider != null) room.m_divider = Divider.Value;
if (EndcapPrio != null) room.m_endCapPrio = EndcapPrio.Value;
if (MinPlaceOrder != null) room.m_minPlaceOrder = MinPlaceOrder.Value;
if (Weight != null) room.m_weight = Weight.Value;
if (FaceCenter != null) room.m_faceCenter = FaceCenter.Value;
if (Perimeter != null) room.m_perimeter = Perimeter.Value;
if (Perimeter != null) room.m_perimeter = Perimeter.Value;

return room;
}
}
}
156 changes: 156 additions & 0 deletions JotunnLib/Entities/CustomRoom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System;
using System.Reflection;
using Jotunn.Configs;
using Jotunn.Managers;
using SoftReferenceableAssets;
using UnityEngine;

namespace Jotunn.Entities
{
/// <summary>
/// Main interface for adding custom dungeon rooms to the game.<br />
/// All custom rooms have to be wrapped inside this class to add it to Jötunns <see cref="DungeonManager"/>.
/// </summary>
public class CustomRoom : CustomEntity
{
/// <summary>
/// The prefab for this custom room.
/// </summary>
public GameObject Prefab { get; }

/// <summary>
/// The <see cref="global::Room"/> component for this custom room as a shortcut.
/// </summary>
public Room Room { get; }

/// <summary>
/// The name of this custom room as a shortcut.
/// </summary>
public string Name { get; }

/// <summary>
/// Indicator if references from <see cref="Entities.Mock{T}"/>s will be replaced at runtime.
/// </summary>
public bool FixReference { get; set; }

/// <summary>
/// Theme name of this room.
/// </summary>
public string ThemeName { get; set; }

/// <summary>
/// Associated <see cref="DungeonDB.RoomData"/> holding data used during generation.
/// </summary>
public DungeonDB.RoomData RoomData { get; private set; }

/// <summary>
/// Custom room from a prefab loaded from an <see cref="AssetBundle"/> with a <see cref="global::Room"/> made from a <see cref="RoomConfig"/>.<br />
/// Can fix references for <see cref="Entities.Mock{T}"/>s.
/// </summary>
/// <param name="assetBundle">A preloaded <see cref="AssetBundle"/></param>
/// <param name="assetName">Name of the prefab in the bundle.</param>
/// <param name="fixReference">If true references for <see cref="Entities.Mock{T}"/> objects get resolved at runtime by Jötunn.</param>
/// <param name="roomConfig">The config for this custom room.</param>
public CustomRoom(AssetBundle assetBundle, string assetName, bool fixReference, RoomConfig roomConfig) : base(Assembly.GetCallingAssembly())
{
Prefab = assetBundle.LoadAsset<GameObject>(assetName);
Name = Prefab.name;

ThemeName = roomConfig.ThemeName;

if (Prefab != null && Prefab.TryGetComponent<Room>(out var room))
{
var existingRoom = room;
Room = roomConfig.Apply(existingRoom);
}
else
{
var newRoom = Prefab.AddComponent<Room>();
Room = roomConfig.Apply(newRoom);
}

FixReference = fixReference;

// DungeonGenerator.PlaceRoom*() utilize soft references directly, thus registering the assets here.
RoomData = new DungeonDB.RoomData()
{
m_prefab = new SoftReference<GameObject>(AssetManager.Instance.AddAsset(Prefab)),
m_loadedRoom = Room,
m_enabled = Room.m_enabled,
m_theme = GetRoomTheme(ThemeName)
};
}

/// <summary>
/// Custom room from a prefab loaded from an <see cref="AssetBundle"/> with a <see cref="global::Room"/> made from a <see cref="RoomConfig"/>.<br />
/// Can fix references for <see cref="Entities.Mock{T}"/>s.
/// </summary>
/// <param name="prefab">The prefab for this custom room.</param>
/// <param name="fixReference">If true references for <see cref="Entities.Mock{T}"/> objects get resolved at runtime by Jötunn.</param>
/// <param name="roomConfig">The config for this custom room.</param>
public CustomRoom(GameObject prefab, bool fixReference, RoomConfig roomConfig) : base(Assembly.GetCallingAssembly())
{
Prefab = prefab;
Name = prefab.name;

ThemeName = roomConfig.ThemeName;

if (prefab != null && prefab.TryGetComponent<Room>(out var room))
{
var existingRoom = room;
Room = roomConfig.Apply(existingRoom);
}
else
{
var newRoom = prefab.AddComponent<Room>();
Room = roomConfig.Apply(newRoom);
}

FixReference = fixReference;

// DungeonGenerator.PlaceRoom*() utilize soft references directly, thus registering the assets here.
RoomData = new DungeonDB.RoomData()
{
m_prefab = new SoftReference<GameObject>(AssetManager.Instance.AddAsset(Prefab)),
m_loadedRoom = Room,
m_enabled = Room.m_enabled,
m_theme = GetRoomTheme(ThemeName)
};
}

/// <summary>
/// Helper method to determine if a prefab with a given name is a custom room created with Jötunn.
/// </summary>
/// <param name="prefabName">Name of the prefab to test.</param>
/// <returns>true if the prefab is added as a custom item to the <see cref="DungeonManager"/>.</returns>
public static bool IsCustomRoom(string prefabName)
{
return DungeonManager.Instance.Rooms.ContainsKey(prefabName);
}

/// <summary>
/// Helper method to determine if a given themeName matches any vanilla <see cref="global::Room.Theme"/> values.
/// </summary>
/// <param name="themeName">Name of the theme to test.</param>
/// <returns>true if the themeName matches a built-in value, or false.</returns>
public static bool IsVanillaTheme(string themeName)
{
return Enum.TryParse(themeName, false, out Room.Theme _);
}

/// <summary>
/// Helper method to get the <see cref="global::Room.Theme"/> value, if the given themeName matches any vanilla values.
/// </summary>
/// <param name="themeName">Name of the theme.</param>
/// <returns>The <see cref="global::Room.Theme"/> value, or Room.Theme.None if no match is found.</returns>
public static Room.Theme GetRoomTheme(string themeName)
{
if (Enum.TryParse(themeName, false, out Room.Theme theme))
{
return theme;
}

return Room.Theme.None;
}
}
}
Loading

0 comments on commit bfc6206

Please sign in to comment.