|
@@ -0,0 +1,493 @@
|
|
|
|
|
+using UnityEngine;
|
|
|
|
|
+using System.Collections.Generic;
|
|
|
|
|
+using System.Linq;
|
|
|
|
|
+
|
|
|
|
|
+/// <summary>
|
|
|
|
|
+/// Manages spottable event markers that appear as red dots within the team's perception range
|
|
|
|
|
+/// </summary>
|
|
|
|
|
+public class EventMarkerVisualizer : MonoBehaviour
|
|
|
|
|
+{
|
|
|
|
|
+ [Header("Event Marker Settings")]
|
|
|
|
|
+ [SerializeField] private GameObject eventMarkerPrefab;
|
|
|
|
|
+ [SerializeField] private Material eventMarkerMaterial;
|
|
|
|
|
+ [SerializeField] private Color eventMarkerColor = Color.red;
|
|
|
|
|
+ [SerializeField] private float markerSize = 0.8f;
|
|
|
|
|
+ [SerializeField] private float markerHeight = 0.6f;
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Spawn Settings")]
|
|
|
|
|
+ [SerializeField] private int maxActiveMarkers = 5;
|
|
|
|
|
+ [SerializeField] private float minDistanceFromTeam = 2f;
|
|
|
|
|
+ [SerializeField] private float maxDistanceFromTeam = 8f;
|
|
|
|
|
+ [SerializeField] private float markerLifetime = 30f; // Markers disappear after 30 seconds if not approached
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Visual Effects")]
|
|
|
|
|
+ [SerializeField] private bool enablePulsing = true;
|
|
|
|
|
+ [SerializeField] private float pulseSpeed = 2f;
|
|
|
|
|
+ [SerializeField] private float pulseIntensity = 0.3f;
|
|
|
|
|
+
|
|
|
|
|
+ [Header("Debug")]
|
|
|
|
|
+ [SerializeField] private bool showDebugInfo = false;
|
|
|
|
|
+
|
|
|
|
|
+ // Component references
|
|
|
|
|
+ private TeamPerceptionVisualizer perceptionVisualizer;
|
|
|
|
|
+ private SimpleTeamPlacement teamPlacement;
|
|
|
|
|
+ private TravelEventSystem eventSystem;
|
|
|
|
|
+ private MapMaker2 mapMaker;
|
|
|
|
|
+
|
|
|
|
|
+ // Active markers tracking
|
|
|
|
|
+ private List<EventMarker> activeMarkers = new List<EventMarker>();
|
|
|
|
|
+ private List<Vector2Int> occupiedPositions = new List<Vector2Int>();
|
|
|
|
|
+
|
|
|
|
|
+ public static EventMarkerVisualizer Instance { get; private set; }
|
|
|
|
|
+
|
|
|
|
|
+ void Awake()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Instance == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Instance = this;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.LogWarning("Multiple EventMarkerVisualizer instances found. Destroying this one.");
|
|
|
|
|
+ Destroy(gameObject);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void Start()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Find required components
|
|
|
|
|
+ perceptionVisualizer = FindFirstObjectByType<TeamPerceptionVisualizer>();
|
|
|
|
|
+ teamPlacement = FindFirstObjectByType<SimpleTeamPlacement>();
|
|
|
|
|
+ eventSystem = FindFirstObjectByType<TravelEventSystem>();
|
|
|
|
|
+ mapMaker = FindFirstObjectByType<MapMaker2>();
|
|
|
|
|
+
|
|
|
|
|
+ if (perceptionVisualizer == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.LogError("EventMarkerVisualizer: TeamPerceptionVisualizer not found!");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (teamPlacement == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.LogError("EventMarkerVisualizer: SimpleTeamPlacement not found!");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void Update()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Clean up expired markers
|
|
|
|
|
+ CleanupExpiredMarkers();
|
|
|
|
|
+
|
|
|
|
|
+ // Update marker visuals (pulsing effect)
|
|
|
|
|
+ if (enablePulsing)
|
|
|
|
|
+ {
|
|
|
|
|
+ UpdateMarkerPulsing();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Attempts to spawn a spottable event marker within perception range
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="travelEvent">The event to create a marker for</param>
|
|
|
|
|
+ /// <returns>True if marker was successfully spawned</returns>
|
|
|
|
|
+ public bool TrySpawnEventMarker(TravelEvent travelEvent)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (travelEvent == null || activeMarkers.Count >= maxActiveMarkers)
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Get team position and perception range
|
|
|
|
|
+ Vector2Int teamPosition = GetTeamPosition();
|
|
|
|
|
+ float perceptionRange = GetTeamPerceptionRange();
|
|
|
|
|
+
|
|
|
|
|
+ if (perceptionRange <= 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (showDebugInfo)
|
|
|
|
|
+ Debug.Log("EventMarkerVisualizer: No perception range, cannot spawn marker");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Find a valid position within perception range
|
|
|
|
|
+ Vector2Int markerPosition = FindValidMarkerPosition(teamPosition, perceptionRange);
|
|
|
|
|
+ if (markerPosition == Vector2Int.zero)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (showDebugInfo)
|
|
|
|
|
+ Debug.Log("EventMarkerVisualizer: Could not find valid position for event marker");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create the marker
|
|
|
|
|
+ GameObject markerObject = CreateMarkerObject(markerPosition);
|
|
|
|
|
+ if (markerObject == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create event marker data
|
|
|
|
|
+ EventMarker marker = new EventMarker
|
|
|
|
|
+ {
|
|
|
|
|
+ gameObject = markerObject,
|
|
|
|
|
+ travelEvent = travelEvent,
|
|
|
|
|
+ position = markerPosition,
|
|
|
|
|
+ spawnTime = Time.time,
|
|
|
|
|
+ isActive = true
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ activeMarkers.Add(marker);
|
|
|
|
|
+ occupiedPositions.Add(markerPosition);
|
|
|
|
|
+
|
|
|
|
|
+ if (showDebugInfo)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"EventMarkerVisualizer: Spawned marker for '{travelEvent.eventName}' at {markerPosition}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Checks if the team is close enough to trigger an event marker
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ /// <param name="teamPosition">Current team position</param>
|
|
|
|
|
+ /// <returns>The event to trigger, or null if none</returns>
|
|
|
|
|
+ public TravelEvent CheckForMarkerTrigger(Vector2Int teamPosition)
|
|
|
|
|
+ {
|
|
|
|
|
+ float triggerDistance = 1.5f; // Distance to trigger event
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var marker in activeMarkers.ToList())
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!marker.isActive) continue;
|
|
|
|
|
+
|
|
|
|
|
+ float distance = Vector2Int.Distance(teamPosition, marker.position);
|
|
|
|
|
+ if (distance <= triggerDistance)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Remove the marker and return the event
|
|
|
|
|
+ RemoveMarker(marker);
|
|
|
|
|
+
|
|
|
|
|
+ if (showDebugInfo)
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"EventMarkerVisualizer: Team triggered event '{marker.travelEvent.eventName}' at {marker.position}");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return marker.travelEvent;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Removes all active event markers
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ public void ClearAllMarkers()
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach (var marker in activeMarkers.ToList())
|
|
|
|
|
+ {
|
|
|
|
|
+ RemoveMarker(marker);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Vector2Int GetTeamPosition()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (teamPlacement != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ return teamPlacement.GetCurrentTeamPosition();
|
|
|
|
|
+ }
|
|
|
|
|
+ return Vector2Int.zero;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private float GetTeamPerceptionRange()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (perceptionVisualizer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Access the perception range from the visualizer
|
|
|
|
|
+ // We need to get the team's highest perception and apply the multiplier
|
|
|
|
|
+ return GetHighestTeamPerception() * 1.0f; // Use same multiplier as perception visualizer
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0f;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private int GetHighestTeamPerception()
|
|
|
|
|
+ {
|
|
|
|
|
+ // This mirrors the logic from TeamPerceptionVisualizer
|
|
|
|
|
+ int maxPerception = 0;
|
|
|
|
|
+ List<TeamCharacter> teamMembers = GetCurrentTeamMembers();
|
|
|
|
|
+
|
|
|
|
|
+ if (teamMembers == null || teamMembers.Count == 0)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ foreach (TeamCharacter character in teamMembers)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (character != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ int characterPerception = character.FinalPerception;
|
|
|
|
|
+ if (characterPerception > maxPerception)
|
|
|
|
|
+ {
|
|
|
|
|
+ maxPerception = characterPerception;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return maxPerception;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<TeamCharacter> GetCurrentTeamMembers()
|
|
|
|
|
+ {
|
|
|
|
|
+ // Use the same logic as TeamPerceptionVisualizer
|
|
|
|
|
+ var teamSelectScript = FindFirstObjectByType<MainTeamSelectScript>();
|
|
|
|
|
+ var gameStateManager = FindFirstObjectByType<GameStateManager>();
|
|
|
|
|
+
|
|
|
|
|
+ // Try to get team from MainTeamSelectScript first
|
|
|
|
|
+ if (teamSelectScript != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ var configuredCharacters = teamSelectScript.GetConfiguredCharacters();
|
|
|
|
|
+ if (configuredCharacters != null && configuredCharacters.Count > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return configuredCharacters;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Fall back to GameStateManager
|
|
|
|
|
+ if (gameStateManager != null && gameStateManager.savedTeam != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ var savedTeamList = new List<TeamCharacter>();
|
|
|
|
|
+ foreach (var character in gameStateManager.savedTeam)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (character != null)
|
|
|
|
|
+ savedTeamList.Add(character);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (savedTeamList.Count > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return savedTeamList;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Final fallback: Load from PlayerPrefs
|
|
|
|
|
+ var playerPrefTeam = new List<TeamCharacter>();
|
|
|
|
|
+ for (int i = 0; i < 4; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ string prefix = $"Character{i}_";
|
|
|
|
|
+ if (PlayerPrefs.HasKey(prefix + "Exists") && PlayerPrefs.GetInt(prefix + "Exists") == 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ var character = new TeamCharacter();
|
|
|
|
|
+ character.name = PlayerPrefs.GetString(prefix + "Name", "");
|
|
|
|
|
+ character.isMale = PlayerPrefs.GetInt(prefix + "IsMale", 1) == 1;
|
|
|
|
|
+ character.strength = PlayerPrefs.GetInt(prefix + "Strength", 10);
|
|
|
|
|
+ character.dexterity = PlayerPrefs.GetInt(prefix + "Dexterity", 10);
|
|
|
|
|
+ character.constitution = PlayerPrefs.GetInt(prefix + "Constitution", 10);
|
|
|
|
|
+ character.wisdom = PlayerPrefs.GetInt(prefix + "Wisdom", 10);
|
|
|
|
|
+ character.perception = PlayerPrefs.GetInt(prefix + "Perception", 10);
|
|
|
|
|
+ character.gold = PlayerPrefs.GetInt(prefix + "Gold", 25);
|
|
|
|
|
+
|
|
|
|
|
+ playerPrefTeam.Add(character);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return playerPrefTeam.Count > 0 ? playerPrefTeam : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Vector2Int FindValidMarkerPosition(Vector2Int teamPosition, float perceptionRange)
|
|
|
|
|
+ {
|
|
|
|
|
+ int maxAttempts = 20;
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < maxAttempts; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Generate random position within perception range
|
|
|
|
|
+ float angle = Random.Range(0f, 360f) * Mathf.Deg2Rad;
|
|
|
|
|
+ float distance = Random.Range(minDistanceFromTeam, Mathf.Min(maxDistanceFromTeam, perceptionRange));
|
|
|
|
|
+
|
|
|
|
|
+ Vector2Int candidatePosition = new Vector2Int(
|
|
|
|
|
+ teamPosition.x + Mathf.RoundToInt(Mathf.Cos(angle) * distance),
|
|
|
|
|
+ teamPosition.y + Mathf.RoundToInt(Mathf.Sin(angle) * distance)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // Check if position is valid
|
|
|
|
|
+ if (IsValidMarkerPosition(candidatePosition))
|
|
|
|
|
+ {
|
|
|
|
|
+ return candidatePosition;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return Vector2Int.zero; // Failed to find valid position
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private bool IsValidMarkerPosition(Vector2Int position)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Check if position is already occupied
|
|
|
|
|
+ if (occupiedPositions.Contains(position))
|
|
|
|
|
+ {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check if position is valid on the map
|
|
|
|
|
+ if (mapMaker != null && mapMaker.GetMapData() != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ return mapMaker.GetMapData().IsValidPosition(position.x, position.y);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true; // Default to valid if no map check available
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private GameObject CreateMarkerObject(Vector2Int position)
|
|
|
|
|
+ {
|
|
|
|
|
+ GameObject markerObject;
|
|
|
|
|
+
|
|
|
|
|
+ if (eventMarkerPrefab != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ markerObject = Instantiate(eventMarkerPrefab);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create simple sphere marker
|
|
|
|
|
+ markerObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
|
|
|
+ markerObject.transform.localScale = Vector3.one * markerSize;
|
|
|
|
|
+
|
|
|
|
|
+ // Remove collider to avoid interference
|
|
|
|
|
+ var collider = markerObject.GetComponent<Collider>();
|
|
|
|
|
+ if (collider != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(collider);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Position the marker
|
|
|
|
|
+ Vector3 worldPosition = GetWorldPosition(position);
|
|
|
|
|
+ markerObject.transform.position = worldPosition;
|
|
|
|
|
+
|
|
|
|
|
+ // Apply material and color
|
|
|
|
|
+ ApplyMarkerMaterial(markerObject);
|
|
|
|
|
+
|
|
|
|
|
+ // Set name and tag
|
|
|
|
|
+ markerObject.name = "EventMarker";
|
|
|
|
|
+ // Use default "Untagged" tag to avoid tag definition errors
|
|
|
|
|
+ markerObject.tag = "Untagged";
|
|
|
|
|
+
|
|
|
|
|
+ return markerObject;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Vector3 GetWorldPosition(Vector2Int mapPosition)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Convert map coordinates to world position
|
|
|
|
|
+ float tileSize = 1f;
|
|
|
|
|
+ if (mapMaker?.mapVisualizer != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ tileSize = mapMaker.mapVisualizer.tileSize;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new Vector3(
|
|
|
|
|
+ mapPosition.x * tileSize,
|
|
|
|
|
+ markerHeight,
|
|
|
|
|
+ mapPosition.y * tileSize
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void ApplyMarkerMaterial(GameObject markerObject)
|
|
|
|
|
+ {
|
|
|
|
|
+ Renderer renderer = markerObject.GetComponent<Renderer>();
|
|
|
|
|
+ if (renderer == null) return;
|
|
|
|
|
+
|
|
|
|
|
+ if (eventMarkerMaterial != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ renderer.material = eventMarkerMaterial;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create a simple red material
|
|
|
|
|
+ Material material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
|
|
|
|
|
+ if (material.shader == null)
|
|
|
|
|
+ {
|
|
|
|
|
+ material = new Material(Shader.Find("Standard"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ material.color = eventMarkerColor;
|
|
|
|
|
+
|
|
|
|
|
+ // Add emission for visibility
|
|
|
|
|
+ if (material.HasProperty("_EmissionColor"))
|
|
|
|
|
+ {
|
|
|
|
|
+ material.EnableKeyword("_EMISSION");
|
|
|
|
|
+ material.SetColor("_EmissionColor", eventMarkerColor * 0.5f);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ renderer.material = material;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void CleanupExpiredMarkers()
|
|
|
|
|
+ {
|
|
|
|
|
+ var markersToRemove = activeMarkers.Where(m =>
|
|
|
|
|
+ !m.isActive ||
|
|
|
|
|
+ m.gameObject == null ||
|
|
|
|
|
+ (Time.time - m.spawnTime) > markerLifetime
|
|
|
|
|
+ ).ToList();
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var marker in markersToRemove)
|
|
|
|
|
+ {
|
|
|
|
|
+ RemoveMarker(marker);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void UpdateMarkerPulsing()
|
|
|
|
|
+ {
|
|
|
|
|
+ float pulseValue = (Mathf.Sin(Time.time * pulseSpeed) + 1f) * 0.5f; // 0 to 1
|
|
|
|
|
+ float scale = 1f + (pulseValue * pulseIntensity);
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var marker in activeMarkers)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (marker.isActive && marker.gameObject != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ marker.gameObject.transform.localScale = Vector3.one * (markerSize * scale);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void RemoveMarker(EventMarker marker)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (marker.gameObject != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ DestroyImmediate(marker.gameObject);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ activeMarkers.Remove(marker);
|
|
|
|
|
+ occupiedPositions.Remove(marker.position);
|
|
|
|
|
+ marker.isActive = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Gets the number of currently active event markers
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ public int GetActiveMarkerCount()
|
|
|
|
|
+ {
|
|
|
|
|
+ return activeMarkers.Count(m => m.isActive);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Debug method to show all active markers
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ [ContextMenu("Show Active Markers")]
|
|
|
|
|
+ public void ShowActiveMarkers()
|
|
|
|
|
+ {
|
|
|
|
|
+ Debug.Log($"=== Active Event Markers ({activeMarkers.Count}) ===");
|
|
|
|
|
+ foreach (var marker in activeMarkers)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (marker.isActive)
|
|
|
|
|
+ {
|
|
|
|
|
+ float age = Time.time - marker.spawnTime;
|
|
|
|
|
+ Debug.Log($"- {marker.travelEvent.eventName} at {marker.position} (age: {age:F1}s)");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/// <summary>
|
|
|
|
|
+/// Data structure for tracking active event markers
|
|
|
|
|
+/// </summary>
|
|
|
|
|
+[System.Serializable]
|
|
|
|
|
+public class EventMarker
|
|
|
|
|
+{
|
|
|
|
|
+ public GameObject gameObject;
|
|
|
|
|
+ public TravelEvent travelEvent;
|
|
|
|
|
+ public Vector2Int position;
|
|
|
|
|
+ public float spawnTime;
|
|
|
|
|
+ public bool isActive;
|
|
|
|
|
+}
|