| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEngine;
- namespace MazeGen
- {
- /// <summary>
- /// Monster size for combat positioning. Determines grid footprint and spatial presence.
- /// Small: 4 creatures fit in 1 grid square (fractionally tracked)
- /// Medium: 1 creature = 1 grid square
- /// Large: 1 creature = 4x4 grid squares
- /// </summary>
- public enum MonsterSize
- {
- Small, // 4 per square
- Medium, // 1 per square (1x1)
- Large // 4x4 squares per creature
- }
- /// <summary>
- /// Defines a loot entry with an item and its min/max drop count.
- /// E.g., a Goblin might drop 0-2 Health Potions.
- /// </summary>
- [System.Serializable]
- public class LootEntry
- {
- public Item Item;
- [Tooltip("Minimum number of this item to drop (0 means it might not drop at all)")]
- public int MinCount = 0;
- [Tooltip("Maximum number of this item to drop")]
- public int MaxCount = 1;
- public LootEntry() { }
- public LootEntry(Item item, int minCount, int maxCount)
- {
- Item = item;
- MinCount = minCount;
- MaxCount = maxCount;
- }
- }
- /// <summary>
- /// A ScriptableObject that defines a monster template (stats, appearance, loot).
- /// Monsters are instantiated from this template when they spawn in a room.
- /// </summary>
- public class Monster : ScriptableObject
- {
- [SerializeField] private string _monsterName = "Goblin";
- [SerializeField] private Color _color = Color.green;
- [SerializeField] private CharacterStats _baseStats = new CharacterStats();
- [SerializeField] private MonsterSize _size = MonsterSize.Medium;
- // Optional starting equipment
- [SerializeField] private Weapon _startingWeapon;
- [SerializeField] private Armor _startingArmor;
- // Loot table: what items might this monster drop with min/max counts
- [SerializeField] private LootEntry[] _lootTable;
- // Loot options
- [SerializeField] private bool _includeStartingWeaponAsLoot = false;
- [SerializeField] private bool _includeStartingArmorAsLoot = false;
- [SerializeField] [Range(0f, 1f)] private float _lootDropChance = 1.0f; // Chance to drop any loot at all
- public string MonsterName => _monsterName;
- public Color Color => _color;
- public CharacterStats BaseStats => _baseStats;
- public MonsterSize Size => _size;
- public Weapon StartingWeapon => _startingWeapon;
- public Armor StartingArmor => _startingArmor;
- public LootEntry[] LootTable => _lootTable;
- public bool IncludeStartingWeaponAsLoot => _includeStartingWeaponAsLoot;
- public bool IncludeStartingArmorAsLoot => _includeStartingArmorAsLoot;
- public float LootDropChance => _lootDropChance;
- /// <summary>Build the final loot pool for this monster instance based on min/max ranges.</summary>
- public List<Item> GenerateLootPool()
- {
- var pool = new List<Item>();
- // Determine if this monster drops any loot at all
- if (Random.value > _lootDropChance)
- return pool; // Return empty pool (no loot)
- // Add items from the loot table based on min/max rolls
- if (_lootTable != null)
- {
- foreach (var entry in _lootTable)
- {
- if (entry?.Item == null) continue;
- int count = Random.Range(entry.MinCount, entry.MaxCount + 1);
- for (int i = 0; i < count; i++)
- {
- pool.Add(entry.Item);
- }
- }
- }
- // Optionally add starting equipment
- if (_includeStartingWeaponAsLoot && _startingWeapon != null)
- {
- pool.Add(_startingWeapon);
- }
- if (_includeStartingArmorAsLoot && _startingArmor != null)
- {
- pool.Add(_startingArmor);
- }
- return pool;
- }
- /// <summary>Create a fresh character sheet for a monster instance (with a copy of stats).</summary>
- public CharacterSheet CreateCharacterSheet()
- {
- // Pass null GameObject (Monster is a ScriptableObject, not a MonoBehaviour)
- // CharacterSheet will use a default name instead
- var sheet = new CharacterSheet(null, _baseStats.Clone());
- // Override with the monster template's name
- sheet.Name = _monsterName;
- if (_startingWeapon != null)
- sheet.EquipWeapon(_startingWeapon);
- if (_startingArmor != null)
- sheet.EquipArmor(_startingArmor);
- return sheet;
- }
- #if UNITY_EDITOR
- private void OnValidate()
- {
- if (_baseStats == null)
- _baseStats = new CharacterStats();
- }
- #endif
- }
- }
|