Files
tiny_tackle_heroes/Assets/_Project/Scripts/Constants/DefenseConstants.cs
T
2026-09-25 06:27:30 +09:00

160 lines
6.4 KiB
C#

using BumpCombat.Defense;
using UnityEngine;
namespace BumpCombat.Constants
{
[CreateAssetMenu(menuName = "BumpCombat/Constants/Defense Prototype")]
public sealed class DefenseConstants : ScriptableObject
{
[Header("Prototype economy")]
[Tooltip("Initial construction currency for the test mode.")]
[Min(0)] public int InitialConstructionCurrency = 100;
[Min(0)] public int DirectTowerCost = 30;
[Min(0)] public int SummonTowerCost = 40;
[Min(0)] public int PortalRewardCurrency = 20;
[Min(0)] public int EnemyKillCurrency = 15;
[Min(0)] public int LightningTowerCost = 35;
[Min(0)] public int ColdTowerCost = 35;
[Min(0)] public int SeismicTowerCost = 35;
[Min(0)] public int EmpoweringTowerCost = 35;
[Min(0)] public int Tier2UpgradeCost = 20;
[Min(0)] public int Tier3UpgradeCost = 30;
[Min(0)] public int Tier4UpgradeCost = 40;
[Min(0.1f)] public float BuildInteractionRadius = 1.5f;
[Header("Prototype arena")]
public Vector2 ArenaCenter = Vector2.zero;
public Vector2 ArenaPlayableHalfExtents = new(11f, 6f);
[Header("Prototype bases and routes")]
[Min(1)] public int BaseMaximumHealth = 12;
[Min(1)] public int PortalEnemyCount = 8;
[Min(0)] public int ArrivalBaseDamage = 1;
[Min(0.1f)] public float PortalSpawnInterval = 1.25f;
[Min(0.1f)] public float RouteSpeedMultiplier = 0.75f;
[Min(0f)] public float PostAttackProgressSeconds = 0.65f;
public Vector2[] PortalPositions =
{
new(-9f, 3.25f),
new(-9f, -3.25f),
};
public Vector2[] BasePositions =
{
new(9f, 0f),
new(9f, 0f),
};
[Tooltip("Build-only branches sit outside the enemy travel lanes.")]
public Vector2[] BuildPadPositions =
{
new(-3.25f, 4.9f),
new(3.25f, -4.9f),
new(-3.25f, -4.9f),
new(3.25f, 4.9f),
new(0f, 4.9f),
new(0f, -4.9f),
};
[Tooltip("Two ordered waypoints per lane, indexed by lane * 2 + waypoint.")]
public Vector2[] WaypointPositions =
{
new(-3f, 3.25f), new(3f, 3.25f),
new(-3f, -3.25f), new(3f, -3.25f),
};
[Tooltip("The tower source kind ignored by each portal's enemies.")]
public DefenseTowerKind[] PortalImmuneTowerKinds =
{
DefenseTowerKind.Direct,
DefenseTowerKind.Summon,
};
[Header("Prototype tower sight and damage")]
[Min(0.1f)] public float PlayerSightRadius = 6f;
[Range(0f, 1f)] public float OutsideSightDamageEfficiency = 0.7f;
[Min(0.1f)] public float TowerRange = 5.5f;
[Min(0.1f)] public float DirectTowerDamage = 10f;
[Min(0.05f)] public float DirectTowerAttackInterval = 0.75f;
[Min(0.1f)] public float SummonDamage = 6f;
[Min(0.05f)] public float SummonAttackInterval = 0.9f;
[Min(1)] public int SummonUnitCount = 2;
[Min(0.1f)] public float SummonAreaRadius = 2.25f;
[Min(0.1f)] public float SummonUnitMoveSpeed = 2.5f;
[Min(0.1f)] public float SummonAttackRange = 1.2f;
[Header("Six tower family comparison values")]
[Min(0.1f)] public float LightningDamage = 6f;
[Min(0.05f)] public float LightningInterval = 1.1f;
[Min(0.1f)] public float LightningRadius = 1.3f;
[Min(0.1f)] public float ColdDamage = 3f;
[Min(0.05f)] public float ColdInterval = 1.2f;
[Min(0f)] public float ColdSlowFraction = 0.35f;
[Min(0f)] public float ColdSlowSeconds = 1.5f;
[Min(0.1f)] public float SeismicDamage = 2f;
[Min(0.05f)] public float SeismicInterval = 2f;
[Min(0f)] public float SeismicStunSeconds = 0.45f;
[Min(0.1f)] public float SeismicRadius = 1.4f;
[Min(0.1f)] public float SupportRadius = 3.5f;
[Range(0f, 1f)] public float SupportRangeAlpha = 0.4f;
// Alpha bounds in the 100x100 source cells, top-left origin, by frame.
public static readonly RectInt[] SupportRangeAlphaBounds =
{
new(35, 54, 30, 15), new(34, 54, 31, 16), new(34, 54, 32, 16),
new(35, 54, 30, 15), new(34, 54, 31, 16), new(34, 54, 32, 16),
};
public Color[] SupportTierColors =
{
new(151, 169, 119, 102), new(153, 183, 108, 148),
new(158, 201, 96, 194), new(170, 218, 103, 242),
};
[Min(0f)] public float SupportDamageBonusPerTier = 0.1f;
[Min(0f)] public float SmotheringDamageBonus = 0.3f;
[Range(0.1f, 1f)] public float ImbuingAttackIntervalMultiplier = 0.75f;
[Min(0f)] public float TowerDamageBonusPerTier = 0.25f;
[Header("Prototype player recovery")]
[Min(0f)] public float PlayerReviveDelaySeconds = 5f;
[Min(0f)] public float PlayerReviveInvulnerabilitySeconds = 1f;
[Min(0.1f)] public float RewardPickupRadius = 1.35f;
public Vector2 GetPortalPosition(int lane)
{
return GetPosition(PortalPositions, lane, new Vector2(-9f, lane == 0 ? 3.25f : -3.25f));
}
public Vector2 GetBasePosition(int lane)
{
return GetPosition(BasePositions, lane, new Vector2(9f, 0f));
}
public Vector2 GetBuildPadPosition(int index)
{
return GetPosition(BuildPadPositions, index, Vector2.zero);
}
public Vector2 GetWaypointPosition(int lane, int waypointIndex)
{
int index = lane * 2 + waypointIndex;
Vector2 fallback = new(
waypointIndex == 0 ? -3f : 3f,
lane == 0 ? 3.25f : -3.25f);
return GetPosition(WaypointPositions, index, fallback);
}
public DefenseTowerKind GetPortalImmuneTowerKind(int lane)
{
if (PortalImmuneTowerKinds != null
&& lane >= 0
&& lane < PortalImmuneTowerKinds.Length)
{
return PortalImmuneTowerKinds[lane];
}
return (DefenseTowerKind)Mathf.Clamp(lane, 0, 1);
}
private static Vector2 GetPosition(Vector2[] positions, int index, Vector2 fallback)
{
return positions != null && index >= 0 && index < positions.Length
? positions[index]
: fallback;
}
}
}