Files
unity-zone-system/Runtime/ZoneResolver.cs
Sebastian Bularca 823e146df0 copy from github
2026-03-27 15:13:27 +01:00

84 lines
3.3 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Jovian.ZoneSystem {
public static class ZoneResolver {
/// <summary>
/// Resolves a list of overlapping ZoneData into a single ZoneContext.
/// Resolution rules:
/// 1. If any Override zone is present → use highest-priority Override exclusively.
/// 2. Otherwise → find highest-priority Base zone, then stack all Modifier zones
/// multiplicatively on top.
/// </summary>
public static ZoneContext Resolve(List<ZoneData> overlapping) {
if(overlapping == null || overlapping.Count == 0) {
return SafeFallback(string.Empty);
}
// ── 1. Check for Override zones ──────────────────────────────
var overrides = overlapping
.Where(z => z.role == ZoneRole.Override)
.OrderByDescending(z => z.priority)
.ToList();
if(overrides.Count > 0) {
var ov = overrides[0];
return new ZoneContext {
resolvedZoneId = ov.zoneId,
isSafe = ov.isSafeZone,
encounterTableId = ov.overrideEncounterTableId,
finalEncounterChance = ov.overrideEncounterChance,
finalDifficultyTier = ov.overrideDifficultyTier
};
}
// ── 2. Find highest-priority Base zone ───────────────────────
var baseZone = overlapping
.Where(z => z.role == ZoneRole.Base)
.OrderByDescending(z => z.priority)
.FirstOrDefault();
if(!baseZone) {
return SafeFallback(string.Empty);
}
// ── 3. Collect all Modifier zones ────────────────────────────
var modifiers = overlapping
.Where(z => z.role == ZoneRole.Modifier)
.ToList();
var chance = baseZone.baseEncounterChance;
var tierOffset = 0;
foreach(var mod in modifiers) {
// Multiplicative stacking — each modifier is independent
chance *= mod.encounterChanceMultiplier;
tierOffset += mod.difficultyTierBonus;
}
chance = Mathf.Clamp01(chance);
var rawTier = (int)baseZone.baseDifficultyTier + tierOffset;
var clampedTier = Mathf.Clamp(rawTier, (int)DifficultyTier.Safe, (int)DifficultyTier.Deadly);
return new ZoneContext {
resolvedZoneId = baseZone.zoneId,
isSafe = false,
encounterTableId = baseZone.encounterTableId,
finalEncounterChance = chance,
finalDifficultyTier = (DifficultyTier)clampedTier
};
}
private static ZoneContext SafeFallback(string name) {
return new ZoneContext {
resolvedZoneId = name,
isSafe = true,
encounterTableId = string.Empty,
finalEncounterChance = 0f,
finalDifficultyTier = DifficultyTier.Safe
};
}
}
}