using UnityEngine; namespace DepthsOfGreed.HandbookUI { public enum HandbookTowerCategory { Munition, Energie, Spezial } public enum BuildMenuGroup { Physisch, Energie, Anlagen, Einsaetze } [CreateAssetMenu(menuName = "Depths of Greed/Handbuch/Turmtyp", fileName = "NeuerTurmtyp")] public sealed class HandbookTowerEntry : ScriptableObject { [Header("Name und Kategorie")] [Tooltip("Stabile ID für die Gameplay-Anbindung. Nach Zuordnung nicht ändern.")] public string id; public string displayName; [InspectorName("Waffentechnik / Basisfarbe")] public HandbookTowerCategory category; [InspectorName("Buchkategorie")] public BuildMenuGroup menuGroup; public BuildUse use; [Header("Kaufpreis")] [Tooltip("Energie-Kaufpreis. 0 wird in der Preisanzeige ausgeblendet.")] [Min(0)] public int energyCost; [Tooltip("Gedärme-Kaufpreis. 0 wird in der Preisanzeige ausgeblendet. Beide Ressourcen können gemeinsam erforderlich sein.")] [Min(0)] public int entrailsCost; [Header("Texte im Handbuch")] public string summary; [TextArea(3, 8)] public string description; [Header("Grafiken und Prefabs")] [Tooltip("Bild im Bau-, Index- und Upgrademenü.")] public Sprite icon; [Tooltip("Grafik, die während der Platzierung dem Mauszeiger folgt.")] public Sprite previewSprite; [Tooltip("Grafik des unbeweglichen Unterteils. Wird vom Platzierungsprototyp genutzt.")] public Sprite baseSprite; [Tooltip("Vorbereitetes Unterteil als GameObject. Noch nicht vom Platzierungsprototyp verwendet.")] public GameObject basePrefab; [Tooltip("Vollständiges Objekt für die spätere Gameplay-Anbindung.")] public GameObject gameplayPrefab; [Header("Platzierung und Platzbedarf")] public BuildRegion region; public BaseShape baseShape; [Tooltip("Kreis, der die gesamte Basis umschließt. Muss vollständig in die Baufläche passen.")] [Min(0.001f)] public float baseRadius = 0.36f; public Vector2 baseSize = new Vector2(0.5f, 0.5f); [Tooltip("Abstandskreis: darf andere Abstandskreise nicht überlappen.")] [Min(0.001f)] public float placementRadius = 0.6f; public bool allowPlayerRotation; public bool blocksMovement, requirePathValidation; [Header("Mengenlimits und Einsatzdauer")] public bool countsTowardWallLimit = true; [Tooltip("0 = kein zusätzliches Limit für diesen Typ.")] [Min(0)] public int maxPerType; [Min(0)] public float deploymentCooldown, lifetimeSeconds; [Min(0)] public int contactUses; [Header("Kampf, Verbrauch und Sonderfunktion")] public CombatDefinition combat = new CombatDefinition(); [Header("Kellerversorgung und Turmmagazin")] public TowerSupplyDefinition supply = new TowerSupplyDefinition(); [Header("Angreifbarkeit und Haltbarkeit")] public bool targetableByEnemies, destroyableByDamage; [Min(0)] public float maxHealth; public bool removeOnFloorLoss = true; [Header("Verbesserungen")] public bool upgradeable = true; public UpgradeDefinition[] upgrades = new UpgradeDefinition[0]; [Header("Vorläufige Werte und Designnotizen")] public bool provisional = true; [HideInInspector] public int dataVersion; public float sourceCostRating; public int sourceBalanceScore; [TextArea(3, 12)] public string designNotes; public CombatDefinition CreateCombatSnapshot(int level) { var result = JsonUtility.FromJson(JsonUtility.ToJson(combat)); for (int i = 0; i < Mathf.Min(Mathf.Max(0, level), upgrades.Length); i++) { var u = upgrades[i]; result.damagePerHit *= u.damageMultiplier; result.continuousDamagePerSecond *= u.damageMultiplier; result.attacksPerSecond *= u.fireRateMultiplier; result.range *= u.rangeMultiplier; result.effectStrength *= u.effectMultiplier; result.knockbackDistance *= u.effectMultiplier; result.energyGeneratedPerSecond *= u.effectMultiplier; result.energyCapacityBonus *= u.effectMultiplier; result.repairHealthPerSecond *= u.effectMultiplier; result.corpsesCollectedPerSecond *= u.effectMultiplier; result.slowFraction = Mathf.Clamp01(result.slowFraction * u.effectMultiplier); } return result; } private void OnValidate() { baseRadius = Mathf.Max(0.001f, baseRadius); placementRadius = Mathf.Max(baseRadius, placementRadius); energyCost = Mathf.Max(0, energyCost); entrailsCost = Mathf.Max(0, entrailsCost); baseSize = new Vector2(Mathf.Max(0.01f, baseSize.x), Mathf.Max(0.01f, baseSize.y)); if (use == BuildUse.Ability) countsTowardWallLimit = false; if (category == HandbookTowerCategory.Munition) menuGroup = BuildMenuGroup.Physisch; else if (category == HandbookTowerCategory.Energie) menuGroup = BuildMenuGroup.Energie; else if ((int)menuGroup < 2) menuGroup = use == BuildUse.Structure ? BuildMenuGroup.Anlagen : BuildMenuGroup.Einsaetze; } } }