200 lines
8.1 KiB
C#
200 lines
8.1 KiB
C#
using DunGen;
|
|
using DunGen.Graph;
|
|
using DunGenPlus.DevTools;
|
|
using DunGenPlus.Patches;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace DunGenPlus.Generation {
|
|
internal partial class DunGenPlusGenerator {
|
|
|
|
public static void AddAdditionalTiles(DungeonGenerator gen){
|
|
if (!Properties.AdditionalTilesProperties.UseAdditionalTiles) return;
|
|
|
|
var forcedTileSetLists = Properties.AdditionalTilesProperties.AdditionalTileSets.ToList();
|
|
while(forcedTileSetLists.Count > 0){
|
|
var item = forcedTileSetLists[forcedTileSetLists.Count - 1];
|
|
|
|
// we have to check ALL tiles
|
|
var allTiles = gen.proxyDungeon.AllTiles
|
|
.Select(t => {
|
|
var depthValue = item.DepthWeightScale.Evaluate(t.Placement.NormalizedDepth);
|
|
var weight = t.Placement.IsOnMainPath ? item.MainPathWeight : item.BranchPathWeight;
|
|
return (t, depthValue * weight * gen.RandomStream.NextDouble());
|
|
})
|
|
.Where(pair => pair.Item2 > 0f)
|
|
.OrderBy(pair => pair.Item2);
|
|
|
|
// try every tile, if we somehow fail than man that sucks
|
|
foreach(var pair in allTiles){
|
|
var t = pair.t;
|
|
var sourcePlacement = t.Placement;
|
|
var sourceParameters = sourcePlacement.PlacementParameters;
|
|
|
|
var tileProxy = gen.AddTile(t, item.TileSets, sourcePlacement.NormalizedDepth, sourceParameters);
|
|
if (tileProxy == null) continue;
|
|
|
|
AddTileProxy(tileProxy, GetMainPathIndexFromTileProxy(t));
|
|
var placement = tileProxy.Placement;
|
|
var parameters = placement.PlacementParameters;
|
|
placement.BranchDepth = sourcePlacement.BranchDepth;
|
|
placement.NormalizedBranchDepth = sourcePlacement.NormalizedDepth;
|
|
parameters.Node = sourceParameters.Node;
|
|
parameters.Line = sourceParameters.Line;
|
|
|
|
Plugin.logger.LogDebug($"Forcefully added tile {tileProxy.Prefab.name}");
|
|
break;
|
|
}
|
|
|
|
forcedTileSetLists.RemoveAt(forcedTileSetLists.Count - 1);
|
|
}
|
|
|
|
Plugin.logger.LogDebug($"Forcefully added all tiles");
|
|
}
|
|
|
|
public static void RandomizeLineArchetypes(DungeonGenerator gen, bool randomizeMainPath){
|
|
if (!Properties.LineRandomizerProperties.UseLineRandomizer) return;
|
|
|
|
var flow = Instance.DungeonFlow;
|
|
var lines = flow.Lines;
|
|
var tilesetsUsed = new Dictionary<TileSet, int>();
|
|
foreach(var t in Properties.LineRandomizerProperties.TileSets){
|
|
tilesetsUsed.Add(t, 0);
|
|
}
|
|
|
|
foreach(var a in Properties.LineRandomizerProperties.Archetypes) {
|
|
var tiles = randomizeMainPath ? a.TileSets : a.BranchCapTileSets;
|
|
RandomizeArchetype(gen, tiles, tilesetsUsed);
|
|
}
|
|
}
|
|
|
|
public static void RandomizeArchetype(DungeonGenerator gen, List<TileSet> targetTileSet, Dictionary<TileSet, int> tilesetsUsed){
|
|
// get 3 random
|
|
var newTiles = Properties.LineRandomizerProperties.TileSets
|
|
.OrderBy(t => tilesetsUsed[t] + gen.RandomStream.NextDouble())
|
|
.Take(Properties.LineRandomizerProperties.TileSetsTakeCount);
|
|
|
|
var i = targetTileSet.Count - 1;
|
|
foreach(var n in newTiles){
|
|
targetTileSet[i] = n;
|
|
--i;
|
|
|
|
tilesetsUsed[n] += 1;
|
|
}
|
|
}
|
|
|
|
public static void ModifyMainBranchNodeArchetype(TilePlacementParameters parameters, GraphNode node, RandomStream randomStream){
|
|
if (!DunGenPlusGenerator.Active) return;
|
|
|
|
if (Properties.NormalNodeArchetypesProperties.AddArchetypesToNormalNodes && node.NodeType == NodeType.Normal) {
|
|
parameters.Archetype = Properties.NormalNodeArchetypesProperties.GetRandomArchetype(node.Label, randomStream);;
|
|
}
|
|
}
|
|
|
|
public static bool AllowRetryStop(bool defaultState){
|
|
return defaultState || API.IsDevDebugModeActive();
|
|
}
|
|
|
|
public static IEnumerable<DoorwayPair> GetPotentialDoorwayPairsForNonFirstTileAlternate(DoorwayPairFinder __instance){
|
|
var previousTile = __instance.PreviousTile;
|
|
var previousTileExtended = TileProxyPatch.GetTileExtenderProxy(previousTile);
|
|
|
|
var tileOrder = __instance.tileOrder;
|
|
|
|
IEnumerable<DoorwayProxy> validPrevExits;
|
|
// default base behaviour
|
|
if (!previousTileExtended.EntranceExitInterchangable){
|
|
validPrevExits = previousTile.UnusedDoorways.Intersect(previousTileExtended.Exits);
|
|
}
|
|
// interchangable behaviour
|
|
else {
|
|
// check if previous tile used a specific exit/entrance
|
|
// they used an exit as their entrance, so use entrances
|
|
if (previousTile.UsedDoorways.Intersect(previousTileExtended.Exits).Any()){
|
|
validPrevExits = previousTile.UnusedDoorways.Intersect(previousTileExtended.Entrances);
|
|
}
|
|
// they used an entrance as their entrance, so use exits
|
|
else if (previousTile.UsedDoorways.Intersect(previousTileExtended.Entrances).Any()){
|
|
validPrevExits = previousTile.UnusedDoorways.Intersect(previousTileExtended.Exits);
|
|
}
|
|
// uhh i guess it's fine?
|
|
else {
|
|
validPrevExits = new List<DoorwayProxy>();
|
|
}
|
|
}
|
|
|
|
var requiresSpecExit = validPrevExits.Any();
|
|
|
|
foreach(var previousDoor in previousTile.UnusedDoorways) {
|
|
if (previousDoor.IsDisabled) continue;
|
|
|
|
// overlapping doors aren't allowed to be potential doorway pairs since this function only finds entrance/exits
|
|
// or have fun
|
|
var isPrevOverlappingDoor = previousTileExtended.OverlappingDoorways.Contains(previousDoor);
|
|
if (isPrevOverlappingDoor) {
|
|
continue;
|
|
}
|
|
|
|
// only use allowed doorway exits
|
|
if (requiresSpecExit && !validPrevExits.Contains(previousDoor)) continue;
|
|
|
|
foreach(var tileWeight in __instance.TileWeights) {
|
|
// skip if not ever considered
|
|
if (!tileOrder.Contains(tileWeight)) continue;
|
|
|
|
var nextTile = __instance.GetTileTemplateDelegate(tileWeight.Value);
|
|
var weight = (float)(tileOrder.Count - tileOrder.IndexOf(tileWeight));
|
|
if (__instance.IsTileAllowedPredicate != null && !__instance.IsTileAllowedPredicate(previousTile, nextTile, ref weight)) continue;
|
|
|
|
var nextTileExtended = TileProxyPatch.GetTileExtenderProxy(nextTile);
|
|
foreach(var nextDoor in nextTile.Doorways) {
|
|
// check for previous and next
|
|
// i forget next which causes problems obviously
|
|
var isNextOverlappingDoor = nextTileExtended.OverlappingDoorways.Contains(nextDoor);
|
|
if (isNextOverlappingDoor) {
|
|
continue;
|
|
}
|
|
|
|
bool AllowEntranceAndExitPair(IEnumerable<DoorwayProxy> entrances, IEnumerable<DoorwayProxy> exits){
|
|
// only use allowed doorway entrances
|
|
if (entrances.Any() && !entrances.Contains(nextDoor)) return false;
|
|
// skip if desiganted as an exit
|
|
if (exits.Contains(nextDoor)) return false;
|
|
return true;
|
|
}
|
|
|
|
// normal default behaviour
|
|
if (!nextTileExtended.EntranceExitInterchangable){
|
|
if (!AllowEntranceAndExitPair(nextTileExtended.Entrances, nextTileExtended.Exits)) continue;
|
|
}
|
|
// interchangable behaviour
|
|
else {
|
|
var firstCheck = AllowEntranceAndExitPair(nextTileExtended.Entrances, nextTileExtended.Exits);
|
|
var secondCheck = AllowEntranceAndExitPair(nextTileExtended.Exits, nextTileExtended.Entrances);
|
|
if (!firstCheck && !secondCheck) continue;
|
|
}
|
|
|
|
var doorwayWeight = 0f;
|
|
if (__instance.IsValidDoorwayPairing(previousDoor, nextDoor, previousTile, nextTile, ref doorwayWeight)) {
|
|
|
|
if (__instance.IsOnMainPath){
|
|
var collection = new Collections.DoorwayPairCollection(previousTile, nextTile, previousDoor, nextDoor);
|
|
Instance.Events.OnModifyDoorwayPairWeight.Invoke(ref doorwayWeight, collection, default);
|
|
}
|
|
|
|
yield return new DoorwayPair(previousTile, previousDoor, nextTile, nextDoor, tileWeight.TileSet, weight, doorwayWeight);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|