using System; using System.Collections.Generic; using Core; using Godot; using Models; public partial class CampusController : Node2D { private const int GridSearchRadius = 6; private static readonly CampusTaskType[] TaskTypePool = { CampusTaskType.Experiment, CampusTaskType.Writing, CampusTaskType.Administration, CampusTaskType.Exercise, CampusTaskType.Coding, CampusTaskType.Social }; private readonly List _astarWalkableCells = new(); private readonly List _behaviorAgents = new(); private readonly CampusBehaviorWorld _behaviorWorld = new(); private readonly Dictionary _buildings = new() { { CampusLocationId.Laboratory, new CampusBuilding("Laboratory", new Rect2I(48, 72, 192, 160), new Vector2I(150, 196)) }, { CampusLocationId.Library, new CampusBuilding("Library", new Rect2I(312, 64, 256, 160), new Vector2I(440, 196)) }, { CampusLocationId.Canteen, new CampusBuilding("Canteen", new Rect2I(640, 64, 128, 96), new Vector2I(745, 166)) }, { CampusLocationId.Dormitory, new CampusBuilding("Dormitory", new Rect2I(800, 64, 96, 96), new Vector2I(848, 192)) }, { CampusLocationId.ArtificialLake, new CampusBuilding("ArtificialLake", new Rect2I(), new Vector2I(943, 179)) }, { CampusLocationId.CoffeeShop, new CampusBuilding("CoffeeShop", new Rect2I(), new Vector2I(160, 395)) }, { CampusLocationId.AdminBuilding, new CampusBuilding("AdminBuilding", new Rect2I(234, 312, 128, 96), new Vector2I(296, 452)) }, { CampusLocationId.FootballField, new CampusBuilding("FootballField", new Rect2I(568, 320, 160, 160), new Vector2I(560, 300)) } }; private readonly List _coveragePoints = new(); private readonly CampusLocationRegistry _locationRegistry = new(); private List _archetypeIds = new(); private AStarGrid2D _astarGrid; private Rid _astarMap; private int _astarMapIteration; private Rect2I _astarRegion; private CampusBehaviorConfig _behaviorConfig; private GameContentDatabase _contentDatabase; private DebugGridOverlay _debugGridOverlay; private List _disciplineIds = new(); private Control _logContainer; private RichTextLabel _logLabel; private Button _logToggle; private uint _navBakeIterationId; private Rid _navBakeMap; private bool _navBakePending; private bool _navBakeReady; private NavigationRegion2D _navigationRegion; private Random _random; private List _roleIds = new(); private bool _roundActive; private float _roundElapsed; private int _roundIndex; private bool _spawnPending = true; private Node2D _studentsRoot; private Control _taskContainer; private Button _taskToggle; private TopBar _topBar; private List _traitIds = new(); [Export] public PackedScene StudentScene { get; set; } [Export] public int StudentCount { get; set; } = 5; [Export] public float CoverageStep { get; set; } = 48.0f; [Export] public int MaxCoveragePoints { get; set; } = 200; [Export] public string BehaviorConfigPath { get; set; } = "res://resources/definitions/campus_behavior.json"; [Export] public int RandomSeed { get; set; } [Export] public int AssignedTaskChancePercent { get; set; } = 60; [Export] public float RoundDurationSeconds { get; set; } = 30.0f; [Export] public float AgentMoveSpeed { get; set; } = 180.0f; [Export] public float GridCellSize { get; set; } = 8.0f; [Export] public float GridWalkableTolerance { get; set; } = 2.0f; [Export] public bool DebugGridEnabled { get; set; } [Export] public Key DebugGridToggleKey { get; set; } = Key.G; [Export] public bool DebugLogGrid { get; set; } // Called when the node enters the scene tree for the first time. public override void _Ready() { SetProcessUnhandledInput(true); _taskContainer = GetNode("Task"); _logContainer = GetNode("Log"); // Path to buttons based on scene structure _taskToggle = GetNode