You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
12 KiB
C#
405 lines
12 KiB
C#
3 months ago
|
using Cinemachine;
|
||
|
using D2D.Core;
|
||
|
using D2D.Utilities;
|
||
|
using SRF;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using UnityEngine;
|
||
|
|
||
|
using static D2D.Utilities.CommonGameplayFacade;
|
||
|
|
||
|
public class SquadComponent : GameStateMachineUser
|
||
|
{
|
||
|
[Header("Squad Settings")]
|
||
|
[SerializeField] private List<SquadMember> squadMembers;
|
||
|
[SerializeField] private float _speed = 5f;
|
||
|
[SerializeField] private float _formationRadius = 1.5f;
|
||
|
|
||
|
[Header("Camera Settings")]
|
||
|
[SerializeField] private CinemachineTargetGroup cinemachineTargetGroup;
|
||
|
|
||
|
private Joystick _joystick;
|
||
|
private FormationComponent _formation;
|
||
|
|
||
|
private SquadMember openSquadMember;
|
||
|
|
||
|
private float temporaryFireRateIncrease;
|
||
|
private float temporaryFirePowerIncrease;
|
||
|
|
||
|
private float currentSpeed;
|
||
|
public SquadMember LastSquadMember => squadMembers[squadMembers.Count - 1];
|
||
|
|
||
|
public Vector3 SpawnPosition => squadMembers.Count > 0 ? squadMembers[squadMembers.Count - 1].transform.position - Vector3.back : _formation.transform.position;
|
||
|
|
||
|
public float TemporaryFireRateIncrease => temporaryFireRateIncrease / 100;
|
||
|
public float TemporaryFirePowerIncrease => temporaryFirePowerIncrease / 100;
|
||
|
|
||
|
private const float CinemachineMemberRadius = 5f;
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
_squad = this;
|
||
|
|
||
|
_formation = FindObjectOfType<SquadFormation>().Get<FormationComponent>();
|
||
|
cinemachineTargetGroup = FindObjectOfType<CinemachineTargetGroup>();
|
||
|
|
||
|
squadMembers = GetComponentsInChildren<SquadMember>().ToList();
|
||
|
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
member.Init();
|
||
|
member.animancer.Layers[0].Play(member.animations.Idle);
|
||
|
member.health.Died += () => MemberDie(member);
|
||
|
}
|
||
|
|
||
|
_stateMachine.On<WinState>(SqaudIdle);
|
||
|
var squadMembersCount = squadMembers.Count;
|
||
|
|
||
|
_formation.RecreateFormation(Vector3.zero, squadMembersCount <= 4 ? _formationRadius - .3f : _formationRadius, squadMembersCount - 1);
|
||
|
SetMembersToCinemachineGroup();
|
||
|
|
||
|
_gameData.SetProjectilePrefab(_gameData.pistolProjectile);
|
||
|
_gameData.SetSideProjectiles(0);
|
||
|
|
||
|
currentSpeed = _speed;
|
||
|
}
|
||
|
private void Update()
|
||
|
{
|
||
|
if (!_stateMachine.Last.Is<RunningState>())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Movement();
|
||
|
Shoot();
|
||
|
}
|
||
|
#region States
|
||
|
protected override void OnGameRun()
|
||
|
{
|
||
|
_joystick = FindObjectOfType<Joystick>();
|
||
|
}
|
||
|
protected override void OnGameWin()
|
||
|
{
|
||
|
base.OnGameWin();
|
||
|
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
member.SetDanceAnimation(member.animations.DanceAnimations.Random());
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Squad Members Control
|
||
|
public void AddMember(SquadMember member)
|
||
|
{
|
||
|
if (member != null && !squadMembers.Contains(member))
|
||
|
{
|
||
|
member.Init();
|
||
|
squadMembers.Add(member);
|
||
|
|
||
|
var squadMembersCount = squadMembers.Count;
|
||
|
_formation.RecreateFormation(squadMembers[0].transform.position, squadMembersCount <= 4 ? _formationRadius - .3f : _formationRadius, squadMembersCount - 1);
|
||
|
member.health.Died += () => MemberDie(member);
|
||
|
SetMembersToCinemachineGroup();
|
||
|
PunchScaleSquad();
|
||
|
}
|
||
|
|
||
|
CheckForEvolves(member);
|
||
|
OrderMembers();
|
||
|
}
|
||
|
private void CheckForEvolves(SquadMember newMember)
|
||
|
{
|
||
|
var exceptNewMemberList = new List<SquadMember>(squadMembers);
|
||
|
exceptNewMemberList.Remove(newMember);
|
||
|
|
||
|
if (exceptNewMemberList.Count > 0 && exceptNewMemberList.Any(x => x.EvolveLevel == newMember.EvolveLevel))
|
||
|
{
|
||
|
newMember.Evolve(exceptNewMemberList.First(x => x.EvolveLevel == newMember.EvolveLevel));
|
||
|
}
|
||
|
}
|
||
|
private void PunchScaleSquad()
|
||
|
{
|
||
|
for (int i = squadMembers.Count - 1; i >= 0; i--)
|
||
|
{
|
||
|
squadMembers[i].PunchScaleWithDelay(_gameData.punchDelay * i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SpawnLvlUpVFX()
|
||
|
{
|
||
|
var vfx = Instantiate(_gameData.levelUpVFX, squadMembers[0].transform.position + Vector3.up / 5f, Quaternion.LookRotation(Vector3.up));
|
||
|
Destroy(vfx, 2f);
|
||
|
}
|
||
|
|
||
|
private void SpawnLvlUpVFXColored(Color color)
|
||
|
{
|
||
|
var vfx = Instantiate(_gameData.levelUpVFX, squadMembers[0].transform.position + Vector3.up / 5f, Quaternion.LookRotation(Vector3.up));
|
||
|
|
||
|
var particleSystems = vfx.ChildrenGets<ParticleSystem>();
|
||
|
|
||
|
Gradient grad = new Gradient();
|
||
|
grad.SetKeys(new GradientColorKey[] { new GradientColorKey(color, 0.0f), new GradientColorKey(color, 1.0f) }, new GradientAlphaKey[] { new GradientAlphaKey(1.0f, 0.0f), new GradientAlphaKey(0.0f, 1.0f) });
|
||
|
|
||
|
foreach (var system in particleSystems)
|
||
|
{
|
||
|
var co = system.colorOverLifetime;
|
||
|
co.color = grad;
|
||
|
}
|
||
|
|
||
|
Destroy(vfx, 2f);
|
||
|
}
|
||
|
|
||
|
private void OrderMembers()
|
||
|
{
|
||
|
squadMembers = squadMembers.OrderByDescending(x => x.EvolveLevel).ToList();
|
||
|
}
|
||
|
public void EvolveMembers(SquadMember flyingMember, SquadMember staticMember = null)
|
||
|
{
|
||
|
if (flyingMember.NextEvolution == null)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var flyingMemberPos = flyingMember.transform.position;
|
||
|
Vector3 staticMemberPos = Vector3.zero;
|
||
|
|
||
|
if (squadMembers.Contains(flyingMember))
|
||
|
{
|
||
|
squadMembers.Remove(flyingMember);
|
||
|
Destroy(flyingMember.gameObject);
|
||
|
}
|
||
|
|
||
|
if (staticMember != null && squadMembers.Contains(staticMember))
|
||
|
{
|
||
|
staticMemberPos = staticMember.transform.position;
|
||
|
|
||
|
squadMembers.Remove(staticMember);
|
||
|
Destroy(staticMember.gameObject);
|
||
|
}
|
||
|
|
||
|
Vector3 newPos = staticMember == null ? flyingMemberPos : staticMemberPos;
|
||
|
|
||
|
var newMember = Instantiate(flyingMember.NextEvolution.gameObject,
|
||
|
newPos,
|
||
|
Quaternion.identity, _squad.transform).Get<SquadMember>();
|
||
|
|
||
|
newMember.animancer.Play(newMember.animations.Idle);
|
||
|
AddMember(newMember);
|
||
|
|
||
|
var squadMembersCount = squadMembers.Count;
|
||
|
|
||
|
_formation.RecreateFormation(Vector3.zero, squadMembersCount <= 4 ? _formationRadius - .3f : _formationRadius, squadMembersCount - 1);
|
||
|
SetMembersToCinemachineGroup();
|
||
|
OrderMembers();
|
||
|
|
||
|
SpawnLvlUpVFXColored(flyingMember.NextEvolution.memberColor);
|
||
|
}
|
||
|
private void MemberDie(SquadMember member)
|
||
|
{
|
||
|
if (squadMembers.Contains(member))
|
||
|
{
|
||
|
squadMembers.Remove(member);
|
||
|
|
||
|
if (squadMembers.Count <= 0)
|
||
|
{
|
||
|
_stateMachine.Push(new LoseState());
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var squadMembersCount = squadMembers.Count;
|
||
|
_formation.RecreateFormation(Vector3.zero, squadMembersCount <= 4 ? _formationRadius - .3f : _formationRadius, squadMembersCount - 1);
|
||
|
SetMembersToCinemachineGroup();
|
||
|
}
|
||
|
|
||
|
OrderMembers();
|
||
|
}
|
||
|
private void SetMembersToCinemachineGroup()
|
||
|
{
|
||
|
/*foreach (var oldTarget in cinemachineTargetGroup.m_Targets)
|
||
|
{
|
||
|
cinemachineTargetGroup.RemoveMember(oldTarget.target);
|
||
|
}
|
||
|
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
cinemachineTargetGroup.AddMember(member.transform, 1, CinemachineMemberRadius + squadMembers.Count / 2);
|
||
|
}*/
|
||
|
}
|
||
|
private void SqaudIdle()
|
||
|
{
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.animations.Idle);
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Upgrades
|
||
|
public void IncreaseFireRate(float value)
|
||
|
{
|
||
|
temporaryFireRateIncrease += value;
|
||
|
PunchScaleSquad();
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
public void IncreaseSpeed()
|
||
|
{
|
||
|
currentSpeed *= _gameData.speedIncreasePercent;
|
||
|
PunchScaleSquad();
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
public void IncreaseFirePower(float value)
|
||
|
{
|
||
|
temporaryFirePowerIncrease += value;
|
||
|
PunchScaleSquad();
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
public void SetLaserProjectile()
|
||
|
{
|
||
|
_gameData.SetProjectilePrefab(_gameData.laserProjectile);
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
public void HealSquad(float value)
|
||
|
{
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
member.health.Heal(member.health.MaxPoints * (value / 100));
|
||
|
}
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
public void DoubleEveryMember()
|
||
|
{
|
||
|
var squadMembersCopy = new List<SquadMember>(squadMembers);
|
||
|
|
||
|
foreach (var member in squadMembersCopy)
|
||
|
{
|
||
|
EvolveMembers(member);
|
||
|
}
|
||
|
|
||
|
SpawnLvlUpVFX();
|
||
|
}
|
||
|
#endregion
|
||
|
private void Shoot()
|
||
|
{
|
||
|
foreach (var member in squadMembers)
|
||
|
{
|
||
|
if (member.IsEvolving)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
member.currentTarget = member.overLapEnemy.NearestTouchedOfType<EnemyComponent>(member.transform);
|
||
|
|
||
|
if (member.currentTarget != null)
|
||
|
{
|
||
|
var newTargetPos = member.currentTarget.transform.position;
|
||
|
newTargetPos.y = member.transform.position.y;
|
||
|
member.targetVector = newTargetPos;
|
||
|
|
||
|
member.Shoot(member.currentTarget.transform);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
private void Movement()
|
||
|
{
|
||
|
var swift = new Vector3(_joystick.Horizontal, 0, _joystick.Vertical).normalized * currentSpeed;
|
||
|
|
||
|
if (swift.magnitude < .1f)
|
||
|
{
|
||
|
int index = -1;
|
||
|
|
||
|
for (int i = 0; i < squadMembers.Count; i++)
|
||
|
{
|
||
|
SquadMember member = squadMembers[i];
|
||
|
|
||
|
index++;
|
||
|
|
||
|
if (member.IsEvolving)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (index == 0)
|
||
|
{
|
||
|
member.navMesh.ResetPath();
|
||
|
member.SetIdleAnimation();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Transform targetPoint = index == 0 ? _formation.FormationPoints[index] : squadMembers[i - 1].transform;
|
||
|
|
||
|
if (Vector3.Distance(targetPoint.position, member.navMesh.transform.position) > member.navMesh.stoppingDistance)
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.runForward, .4f).Speed = .8f;
|
||
|
member.navMesh.updateRotation = true;
|
||
|
member.navMesh.SetDestination(targetPoint.position);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.animations.Idle, .4f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int memberIndex = -1;
|
||
|
|
||
|
for (int i = 0; i < squadMembers.Count; i++)
|
||
|
{
|
||
|
SquadMember member = squadMembers[i];
|
||
|
memberIndex++;
|
||
|
|
||
|
if (member.IsEvolving)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
member.navMesh.isStopped = false;
|
||
|
|
||
|
Transform targetPoint = memberIndex == 0 ? _formation.FormationPoints[memberIndex] : squadMembers[i - 1].transform;
|
||
|
|
||
|
if (memberIndex == 0)
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.runForward, .4f);
|
||
|
|
||
|
member.navMesh.Move(swift * Time.deltaTime);
|
||
|
member.navMesh.ResetPath();
|
||
|
_formation.transform.position = member.transform.position;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
member.navMesh.SetDestination(targetPoint.position);
|
||
|
member.navMesh.updateRotation = false;
|
||
|
|
||
|
member.navMesh.speed = currentSpeed;
|
||
|
|
||
|
if (Vector3.Distance(targetPoint.position, member.navMesh.transform.position) <= member.navMesh.stoppingDistance)
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.animations.Idle, .4f);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
member.animancer.Layers[0].Play(member.runForward, .4f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (member.currentTarget == null)
|
||
|
{
|
||
|
member.targetVector = member.transform.position + swift;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
private void SetNotBlockedMember()
|
||
|
{
|
||
|
if (openSquadMember == null || openSquadMember.overLapObstacle.HasTouch)
|
||
|
{
|
||
|
openSquadMember = squadMembers.DefaultIfEmpty(squadMembers[0]).FirstOrDefault(x => !x.overLapObstacle.HasTouch);
|
||
|
}
|
||
|
}
|
||
|
}
|