Changed title font to Montserrat Added trailer-specific camera transitions Added key to hide UI Fixed input listening while console is open Added animated zone reveal effect in galaxy map Added Ping action for sensors Added debug console commands (e.g. give command to get any item in legendary+ quality) Temporarily disabled wwise Fixed infinite loop in weapon penetration code Guided missiles now predict target position Fixed hitscan weapons Fixed invisible enemies bug Fixed various loadout generator issues (can now generate turrets!) Fixed wormhole crash when enemy is targeted Saving/loading current zone time when exiting game (planets keep their positions) Created slime simulation in test scene - WIP
312 lines
15 KiB
C#
312 lines
15 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using MessagePack;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using Unity.Mathematics;
|
|
using static Unity.Mathematics.math;
|
|
using static Unity.Mathematics.noise;
|
|
using Random = UnityEngine.Random;
|
|
using float2 = Unity.Mathematics.float2;
|
|
|
|
public class SectorMap : MonoBehaviour
|
|
{
|
|
public Camera InfluenceCamera;
|
|
public Prototype InfluenceRendererPrototype;
|
|
public MeshRenderer SectorRenderer;
|
|
public Prototype ZonePrototype;
|
|
public Prototype LinkPrototype;
|
|
public Prototype IconPrototype;
|
|
public Prototype IconBackgroundPrototype;
|
|
public Material ZonePrimaryMaterial;
|
|
public Material ZoneSecondaryMaterial;
|
|
public Material ZoneLinkMaterial;
|
|
public float MegaPrimaryBoost = .75f;
|
|
public float MegaSecondaryBoost = 2f;
|
|
public float MegaLinkBoost = 2f;
|
|
public Texture2D EntranceIcon;
|
|
public Texture2D ExitIcon;
|
|
public Texture2D BossIcon;
|
|
public Texture2D HomeIcon;
|
|
public Prototype LegendPrototype;
|
|
public float IconDistance = 1;
|
|
public float IconBackgroundSize = 3;
|
|
public float LabelDistance = .4f;
|
|
public float LinkWidth;
|
|
public float CriticalLinkWidth;
|
|
public AnimationCurve IconScaleAnimation;
|
|
|
|
private HashSet<SectorZone> _revealedZones = new HashSet<SectorZone>();
|
|
private HashSet<(SectorZone, SectorZone)> _revealedLinks = new HashSet<(SectorZone, SectorZone)>();
|
|
|
|
private Dictionary<Faction, (MeshRenderer influenceRenderer, RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)> _factionMaterials =
|
|
new Dictionary<Faction, (MeshRenderer influenceRenderer, RenderTexture influence, Material primaryMaterial, Material secondaryMaterial, Material linkMaterial)>();
|
|
|
|
private Dictionary<SectorZone, SectorZoneUI> _zoneInstances = new Dictionary<SectorZone, SectorZoneUI>();
|
|
private Queue<IEnumerable<SectorZone>> _queuedZoneReveals = new Queue<IEnumerable<SectorZone>>();
|
|
|
|
public void QueueZoneReveal(IEnumerable<SectorZone> zones)
|
|
{
|
|
_queuedZoneReveals.Enqueue(zones);
|
|
}
|
|
|
|
public void StartReveal(float linkDuration, float iconDuration)
|
|
{
|
|
if (_queuedZoneReveals.Count > 0)
|
|
{
|
|
StartCoroutine(RevealZone(_queuedZoneReveals.Dequeue(), linkDuration, iconDuration));
|
|
}
|
|
}
|
|
|
|
public IEnumerator RevealZone(IEnumerable<SectorZone> zones, float linkDuration, float iconDuration)
|
|
{
|
|
var linksToReveal = new List<(float2 start, float2 end, Transform linkInstance, bool critical)>();
|
|
var zoneTransforms = new List<Transform>();
|
|
var zoneInstanceScale = ZonePrototype.transform.localScale;
|
|
|
|
foreach (var zone in zones)
|
|
{
|
|
if (!_revealedZones.Contains(zone))
|
|
{
|
|
var zoneInstance = ZonePrototype.Instantiate<SectorZoneUI>();
|
|
_zoneInstances[zone] = zoneInstance;
|
|
var zoneInstanceTransform = zoneInstance.transform;
|
|
zoneTransforms.Add(zoneInstanceTransform);
|
|
zoneInstanceTransform.localPosition = new Vector3(zone.Position.x, zone.Position.y);
|
|
if(zone.Owner != null)
|
|
{
|
|
zoneInstance.Primary.sharedMaterial = _factionMaterials[zone.Owner].primaryMaterial;
|
|
zoneInstance.Secondary.sharedMaterial = _factionMaterials[zone.Owner].secondaryMaterial;
|
|
if(zone == ActionGameManager.CurrentSector.HomeZones[zone.Owner])
|
|
zoneInstance.Secondary.transform.localScale = Vector3.one * 4;
|
|
}
|
|
else
|
|
{
|
|
zoneInstance.Secondary.gameObject.SetActive(false);
|
|
}
|
|
|
|
var isOnCriticalPath = ActionGameManager.CurrentSector.ExitPath.Contains(zone);
|
|
foreach (var adjacentZone in zone.AdjacentZones)
|
|
{
|
|
// If the adjacent zone is in the set already revealed, then show the link
|
|
if (_revealedZones.Contains(adjacentZone) &&
|
|
!(_revealedLinks.Contains((zone, adjacentZone)) ||
|
|
_revealedLinks.Contains((adjacentZone, zone))))
|
|
{
|
|
var link = LinkPrototype.Instantiate<Transform>();
|
|
var critical = isOnCriticalPath && ActionGameManager.CurrentSector.ExitPath.Contains(adjacentZone);
|
|
linksToReveal.Add((zone.Position, adjacentZone.Position, link, critical));
|
|
if (zone.Owner != null && zone.Owner == adjacentZone.Owner)
|
|
link.GetComponent<MeshRenderer>().sharedMaterial = _factionMaterials[zone.Owner].linkMaterial;
|
|
|
|
var dir = normalize(zone.Position - adjacentZone.Position);
|
|
link.rotation = Quaternion.Euler(0,0,atan2(dir.y,dir.x) * Mathf.Rad2Deg);
|
|
|
|
placeLink(zone.Position, adjacentZone.Position, link, 0, critical);
|
|
}
|
|
}
|
|
_revealedZones.Add(zone);
|
|
|
|
// Determine center of mass for adjacent zone links, used for placement of label and icons
|
|
var linkDirection = normalize(zone.AdjacentZones
|
|
.Aggregate(float2.zero, (v, adjacentZone) => v + normalize(adjacentZone.Position - zone.Position)));
|
|
|
|
var zoneText = zoneInstance.Label;
|
|
zoneText.text = zone.Name;
|
|
var zoneTextTransform = zoneText.GetComponent<RectTransform>();
|
|
zoneTextTransform.pivot = new Vector2(sign(linkDirection.x)/2+.5f,sign(linkDirection.y)/2+.5f);
|
|
zoneTextTransform.localPosition = new Vector3(-linkDirection.x * LabelDistance, -linkDirection.y * LabelDistance, -1);
|
|
|
|
if (zone == ActionGameManager.CurrentSector.Entrance)
|
|
{
|
|
var iconInstance = IconPrototype.Instantiate<MeshRenderer>();
|
|
iconInstance.material.mainTexture = EntranceIcon;
|
|
var iconTransform = iconInstance.transform;
|
|
iconTransform.SetParent(zoneInstanceTransform);
|
|
iconTransform.localScale = Vector3.one;
|
|
iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance);
|
|
}
|
|
|
|
if (zone == ActionGameManager.CurrentSector.Exit)
|
|
{
|
|
var iconInstance = IconPrototype.Instantiate<MeshRenderer>();
|
|
iconInstance.material.mainTexture = ExitIcon;
|
|
var iconTransform = iconInstance.transform;
|
|
iconTransform.SetParent(zoneInstanceTransform);
|
|
iconTransform.localScale = Vector3.one;
|
|
iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance);
|
|
}
|
|
|
|
var homeMega = ActionGameManager.CurrentSector.HomeZones.Keys
|
|
.FirstOrDefault(m => ActionGameManager.CurrentSector.HomeZones[m] == zone);
|
|
if (homeMega != null)
|
|
{
|
|
var backgroundInstance = IconBackgroundPrototype.Instantiate<MeshRenderer>();
|
|
var iconInstance = IconPrototype.Instantiate<MeshRenderer>();
|
|
|
|
backgroundInstance.material.SetColor("_Color", homeMega.SecondaryColor.ToColor());
|
|
iconInstance.material.mainTexture = HomeIcon;
|
|
iconInstance.material.SetColor("_Color", homeMega.PrimaryColor.ToColor());
|
|
|
|
var backgroundTransform = backgroundInstance.transform;
|
|
var iconTransform = iconInstance.transform;
|
|
|
|
backgroundTransform.SetParent(zoneInstanceTransform);
|
|
iconTransform.SetParent(zoneInstanceTransform);
|
|
|
|
backgroundTransform.localScale = Vector3.one * IconBackgroundSize;
|
|
iconTransform.localScale = Vector3.one;
|
|
|
|
backgroundTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance, .5f);
|
|
iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance);
|
|
}
|
|
|
|
var bossMega = ActionGameManager.CurrentSector.BossZones.Keys
|
|
.FirstOrDefault(m => ActionGameManager.CurrentSector.BossZones[m] == zone);
|
|
if (bossMega != null)
|
|
{
|
|
var backgroundInstance = IconBackgroundPrototype.Instantiate<MeshRenderer>();
|
|
var iconInstance = IconPrototype.Instantiate<MeshRenderer>();
|
|
|
|
backgroundInstance.material.SetColor("_Color", bossMega.SecondaryColor.ToColor());
|
|
iconInstance.material.mainTexture = BossIcon;
|
|
iconInstance.material.SetColor("_Color", bossMega.PrimaryColor.ToColor());
|
|
|
|
var backgroundTransform = backgroundInstance.transform;
|
|
var iconTransform = iconInstance.transform;
|
|
|
|
backgroundTransform.SetParent(zoneInstanceTransform);
|
|
iconTransform.SetParent(zoneInstanceTransform);
|
|
|
|
backgroundTransform.localScale = Vector3.one * IconBackgroundSize;
|
|
iconTransform.localScale = Vector3.one;
|
|
|
|
if (homeMega != null)
|
|
{
|
|
backgroundTransform.localPosition = new Vector3(linkDirection.x * IconDistance, linkDirection.y * IconDistance, .5f);
|
|
iconTransform.localPosition = new Vector3(linkDirection.x * IconDistance, linkDirection.y * IconDistance);
|
|
}
|
|
else
|
|
{
|
|
backgroundTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance, .5f);
|
|
iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
foreach (var tr in zoneTransforms) tr.gameObject.SetActive(false);
|
|
|
|
// Local function for animating the placement of a link
|
|
void placeLink(float2 start, float2 end, Transform link, float t, bool critical)
|
|
{
|
|
var pos = lerp(start, end, t / 2);
|
|
link.localPosition = new Vector3(pos.x, pos.y);
|
|
|
|
var localScale = link.localScale;
|
|
localScale = new Vector3(length(start - end)*t, critical ? CriticalLinkWidth : LinkWidth, 1);
|
|
link.localScale = localScale;
|
|
}
|
|
|
|
var startTime = Time.time;
|
|
while (Time.time - startTime < linkDuration)
|
|
{
|
|
var t = (Time.time - startTime) / linkDuration;
|
|
foreach (var (start, end, link, critical) in linksToReveal) placeLink(end, start, link, t, critical);
|
|
|
|
yield return null;
|
|
}
|
|
foreach (var (start, end, link, critical) in linksToReveal) placeLink(start, end, link, 1, critical);
|
|
|
|
foreach (var tr in zoneTransforms) tr.gameObject.SetActive(true);
|
|
startTime = Time.time;
|
|
while (Time.time - startTime < iconDuration)
|
|
{
|
|
var t = (Time.time - startTime) / iconDuration;
|
|
foreach (var tr in zoneTransforms) tr.localScale = zoneInstanceScale * IconScaleAnimation.Evaluate(t);
|
|
RenderInfluence();
|
|
|
|
yield return null;
|
|
}
|
|
foreach (var tr in zoneTransforms) tr.localScale = zoneInstanceScale;
|
|
|
|
StartReveal(linkDuration, iconDuration);
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (ActionGameManager.CurrentSector == null)
|
|
{
|
|
gameObject.SetActive(false);
|
|
return;
|
|
}
|
|
foreach (var mega in ActionGameManager.CurrentSector.Factions)
|
|
{
|
|
var influenceTexture = new RenderTexture(1024, 1024, 0, RenderTextureFormat.RHalf);
|
|
var influenceRenderer = InfluenceRendererPrototype.Instantiate<MeshRenderer>();
|
|
|
|
influenceRenderer.material.mainTexture = influenceTexture;
|
|
influenceRenderer.material.SetColor("_Color1", mega.PrimaryColor.ToColor());
|
|
influenceRenderer.material.SetColor("_Color2", mega.SecondaryColor.ToColor());
|
|
influenceRenderer.material.SetFloat("_FillTilt", Random.value * PI);
|
|
|
|
var primary = Instantiate(ZonePrimaryMaterial);
|
|
primary.SetColor("_Color", (mega.PrimaryColor * MegaPrimaryBoost).ToColor());
|
|
|
|
var secondary = Instantiate(ZoneSecondaryMaterial);
|
|
secondary.SetColor("_Color", (mega.SecondaryColor * MegaSecondaryBoost).ToColor());
|
|
|
|
var link = Instantiate(ZoneLinkMaterial);
|
|
link.SetColor("_Color", (mega.PrimaryColor * MegaLinkBoost).ToColor());
|
|
|
|
_factionMaterials.Add(mega, (influenceRenderer, influenceTexture, primary, secondary, link));
|
|
|
|
var legendElement = LegendPrototype.Instantiate<LegendElement>();
|
|
legendElement.Primary.color = mega.PrimaryColor.ToColor();
|
|
legendElement.Secondary.color = mega.SecondaryColor.ToColor();
|
|
legendElement.Label.text = mega.ShortName;
|
|
}
|
|
|
|
SectorRenderer.material.SetFloat("CloudAmplitude", ActionGameManager.CurrentSector.Settings.CloudAmplitude);
|
|
SectorRenderer.material.SetFloat("CloudExponent", ActionGameManager.CurrentSector.Settings.CloudExponent);
|
|
SectorRenderer.material.SetFloat("NoisePosition", ActionGameManager.CurrentSector.Settings.NoisePosition);
|
|
SectorRenderer.material.SetFloat("NoiseAmplitude", ActionGameManager.CurrentSector.Settings.NoiseAmplitude);
|
|
SectorRenderer.material.SetFloat("NoiseOffset", ActionGameManager.CurrentSector.Settings.NoiseOffset);
|
|
SectorRenderer.material.SetFloat("NoiseGain", ActionGameManager.CurrentSector.Settings.NoiseGain);
|
|
SectorRenderer.material.SetFloat("NoiseLacunarity", ActionGameManager.CurrentSector.Settings.NoiseLacunarity);
|
|
SectorRenderer.material.SetFloat("NoiseFrequency", ActionGameManager.CurrentSector.Settings.NoiseFrequency);
|
|
}
|
|
|
|
private void RenderInfluence()
|
|
{
|
|
// Render Influence Textures
|
|
foreach (var mega in ActionGameManager.CurrentSector.Factions)
|
|
{
|
|
foreach (var zone in ActionGameManager.CurrentSector.Zones)
|
|
{
|
|
if(_zoneInstances.ContainsKey(zone))
|
|
{
|
|
var instance = _zoneInstances[zone];
|
|
var influence = 0f;
|
|
if (zone.Factions.Length > 0)
|
|
{
|
|
if (zone.Factions.Contains(mega))
|
|
{
|
|
influence = 10;
|
|
if (zone.Owner != mega)
|
|
influence *= .5f;
|
|
}
|
|
else influence = -10;
|
|
}
|
|
|
|
instance.Influence.material.SetFloat("_Depth", influence);
|
|
}
|
|
}
|
|
|
|
InfluenceCamera.targetTexture = _factionMaterials[mega].influence;
|
|
InfluenceCamera.Render();
|
|
}
|
|
}
|
|
}
|