|
|
@@ -13,33 +13,33 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
[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)
|
|
|
@@ -53,7 +53,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
void Start()
|
|
|
{
|
|
|
// Find required components
|
|
|
@@ -61,30 +61,30 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
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>
|
|
|
@@ -96,18 +96,18 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
{
|
|
|
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)
|
|
|
@@ -116,14 +116,14 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
Debug.Log("EventMarkerVisualizer: Could not find valid position for event marker");
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Create the marker
|
|
|
- GameObject markerObject = CreateMarkerObject(markerPosition);
|
|
|
+ GameObject markerObject = CreateMarkerObject(markerPosition, travelEvent);
|
|
|
if (markerObject == null)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Create event marker data
|
|
|
EventMarker marker = new EventMarker
|
|
|
{
|
|
|
@@ -133,18 +133,18 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
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>
|
|
|
@@ -153,29 +153,29 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
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>
|
|
|
@@ -186,7 +186,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
RemoveMarker(marker);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private Vector2Int GetTeamPosition()
|
|
|
{
|
|
|
if (teamPlacement != null)
|
|
|
@@ -195,7 +195,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
}
|
|
|
return Vector2Int.zero;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private float GetTeamPerceptionRange()
|
|
|
{
|
|
|
if (perceptionVisualizer != null)
|
|
|
@@ -206,16 +206,16 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
}
|
|
|
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)
|
|
|
@@ -227,16 +227,16 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
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)
|
|
|
{
|
|
|
@@ -246,7 +246,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
return configuredCharacters;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Fall back to GameStateManager
|
|
|
if (gameStateManager != null && gameStateManager.savedTeam != null)
|
|
|
{
|
|
|
@@ -256,13 +256,13 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
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++)
|
|
|
@@ -279,39 +279,39 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
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
|
|
|
@@ -319,20 +319,20 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
{
|
|
|
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)
|
|
|
+
|
|
|
+ private GameObject CreateMarkerObject(Vector2Int position, TravelEvent travelEvent)
|
|
|
{
|
|
|
GameObject markerObject;
|
|
|
-
|
|
|
+
|
|
|
if (eventMarkerPrefab != null)
|
|
|
{
|
|
|
markerObject = Instantiate(eventMarkerPrefab);
|
|
|
@@ -342,7 +342,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
// 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)
|
|
|
@@ -350,22 +350,39 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
DestroyImmediate(collider);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Position the marker
|
|
|
Vector3 worldPosition = GetWorldPosition(position);
|
|
|
markerObject.transform.position = worldPosition;
|
|
|
-
|
|
|
+
|
|
|
// Apply material and color
|
|
|
ApplyMarkerMaterial(markerObject);
|
|
|
-
|
|
|
+
|
|
|
+ // Add tooltip component for hover information using reflection (compilation-safe)
|
|
|
+ var tooltipType = System.Type.GetType("EventMarkerTooltip");
|
|
|
+ if (tooltipType != null)
|
|
|
+ {
|
|
|
+ var tooltip = markerObject.AddComponent(tooltipType) as MonoBehaviour;
|
|
|
+ if (tooltip != null)
|
|
|
+ {
|
|
|
+ // Use reflection to call Initialize method
|
|
|
+ var initMethod = tooltipType.GetMethod("Initialize");
|
|
|
+ initMethod?.Invoke(tooltip, new object[] { travelEvent });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (showDebugInfo)
|
|
|
+ {
|
|
|
+ Debug.Log("EventMarkerTooltip component not found - tooltips will not be available");
|
|
|
+ }
|
|
|
+
|
|
|
// 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
|
|
|
@@ -374,19 +391,19 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
{
|
|
|
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;
|
|
|
@@ -399,39 +416,39 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
{
|
|
|
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 ||
|
|
|
+ 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)
|
|
|
@@ -440,19 +457,19 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
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>
|
|
|
@@ -460,7 +477,7 @@ public class EventMarkerVisualizer : MonoBehaviour
|
|
|
{
|
|
|
return activeMarkers.Count(m => m.isActive);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Debug method to show all active markers
|
|
|
/// </summary>
|