252 lines
6.3 KiB
C#
252 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using RoR2.Projectile;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace RoR2;
|
|
|
|
public class SoulSpiralProjectile : MonoBehaviour
|
|
{
|
|
public static List<SoulSpiralProjectile> unassignedSoulSpirals = new List<SoulSpiralProjectile>();
|
|
|
|
[SerializeField]
|
|
[Header("Basic setup")]
|
|
public Vector3 offset;
|
|
|
|
[SerializeField]
|
|
public float initialDegreesFromOwnerForward;
|
|
|
|
[SerializeField]
|
|
public float degreesPerSecond;
|
|
|
|
[SerializeField]
|
|
public float radius;
|
|
|
|
[SerializeField]
|
|
public Vector3 planeNormal = Vector3.up;
|
|
|
|
[SerializeField]
|
|
public int hitStackPerBuff = 1;
|
|
|
|
[SerializeField]
|
|
[Tooltip("How much from 'baseline' can we move up or down during our sine wave")]
|
|
public float verticalSineWaveOffset = 0.25f;
|
|
|
|
[SerializeField]
|
|
public float sineWavesPerSecond = 1.5f;
|
|
|
|
[Space(20f)]
|
|
[Header("Easing speeds")]
|
|
[Tooltip("How long it takes the projectile to ease into its orbit from starting position.")]
|
|
[SerializeField]
|
|
public float easeInDuration;
|
|
|
|
[Tooltip("How long it takes the projectile to transition from base speed to boosted speed")]
|
|
[SerializeField]
|
|
public float boostEaseDuration;
|
|
|
|
[SerializeField]
|
|
[Space(20f)]
|
|
[Header("Boost variables")]
|
|
[Tooltip("On the last hit, the projectile does more damage.")]
|
|
public float lastHitDamageMultiplier;
|
|
|
|
[SerializeField]
|
|
[Tooltip("How long will the spiral spin after being boosted")]
|
|
public float boostDuration;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Coefficient for calculating Speed boost - multiplied against the # of boosts we have.")]
|
|
public float speedBoostCoefficient;
|
|
|
|
[Tooltip("How much should baseDamage be multipled by, if the speed is 100% faster than base.")]
|
|
[SerializeField]
|
|
public float damageMultiplier;
|
|
|
|
[Tooltip("Triggered when the orbs are 'boosted'.")]
|
|
[SerializeField]
|
|
private UnityEvent OnOrbBoost;
|
|
|
|
private SeekerSoulSpiralManager spiralManager;
|
|
|
|
[HideInInspector]
|
|
public ProjectileController projectileController;
|
|
|
|
[HideInInspector]
|
|
public ProjectileDamage projectileDamage;
|
|
|
|
[HideInInspector]
|
|
public ProjectileOverlapLimitHits projectileOverlapLimitHits;
|
|
|
|
private SoulSpiralGhost _soulSpiralGhost;
|
|
|
|
private Rigidbody rigidBody;
|
|
|
|
private Transform ownerTransform;
|
|
|
|
private float initialStartTimeStamp;
|
|
|
|
private Vector3 initialRadialDirection;
|
|
|
|
private float prevDamage;
|
|
|
|
private float baseDamage;
|
|
|
|
private int baseHitLimit;
|
|
|
|
private const float twoPi = MathF.PI * 2f;
|
|
|
|
private SoulSpiralGhost soulSpiralGhost
|
|
{
|
|
get
|
|
{
|
|
if (_soulSpiralGhost == null)
|
|
{
|
|
if (projectileController == null || projectileController.ghost == null)
|
|
{
|
|
return null;
|
|
}
|
|
_soulSpiralGhost = projectileController.ghost.GetComponent<SoulSpiralGhost>();
|
|
}
|
|
return _soulSpiralGhost;
|
|
}
|
|
set
|
|
{
|
|
_soulSpiralGhost = value;
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
unassignedSoulSpirals.Add(this);
|
|
spiralManager = null;
|
|
projectileController = projectileController ?? GetComponent<ProjectileController>();
|
|
rigidBody = rigidBody ?? GetComponent<Rigidbody>();
|
|
projectileDamage = projectileDamage ?? GetComponent<ProjectileDamage>();
|
|
projectileOverlapLimitHits = projectileOverlapLimitHits ?? GetComponent<ProjectileOverlapLimitHits>();
|
|
baseHitLimit = (projectileOverlapLimitHits ? projectileOverlapLimitHits.hitLimit : 3);
|
|
if (sineWavesPerSecond < 0f)
|
|
{
|
|
sineWavesPerSecond = Mathf.Abs(sineWavesPerSecond);
|
|
}
|
|
if (sineWavesPerSecond == 0f)
|
|
{
|
|
sineWavesPerSecond = 1f;
|
|
}
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (unassignedSoulSpirals.Contains(this))
|
|
{
|
|
unassignedSoulSpirals.Remove(this);
|
|
}
|
|
}
|
|
|
|
public void AssignSpiralOwner(SeekerSoulSpiralManager _spiralManager)
|
|
{
|
|
spiralManager = _spiralManager;
|
|
if (unassignedSoulSpirals.Contains(this))
|
|
{
|
|
unassignedSoulSpirals.Remove(this);
|
|
}
|
|
ownerTransform = _spiralManager.seekerBody.transform;
|
|
SetDefaultVariables();
|
|
}
|
|
|
|
private void SetDefaultVariables()
|
|
{
|
|
if (hitStackPerBuff < 1)
|
|
{
|
|
hitStackPerBuff = 1;
|
|
}
|
|
projectileOverlapLimitHits.hitLimit = baseHitLimit + spiralManager.seekerBody.GetBuffCount(DLC2Content.Buffs.ChakraBuff.buffIndex) * hitStackPerBuff;
|
|
initialStartTimeStamp = Time.fixedTime;
|
|
initialRadialDirection = Quaternion.AngleAxis(initialDegreesFromOwnerForward, planeNormal) * ownerTransform.forward;
|
|
baseDamage = projectileDamage.damage;
|
|
soulSpiralGhost = projectileController.ghost?.GetComponent<SoulSpiralGhost>();
|
|
}
|
|
|
|
public void OnLastHit()
|
|
{
|
|
soulSpiralGhost?.OnLastHit();
|
|
}
|
|
|
|
public void Boost()
|
|
{
|
|
soulSpiralGhost?.Boost();
|
|
}
|
|
|
|
public void EndBoost()
|
|
{
|
|
soulSpiralGhost?.EndBoost();
|
|
}
|
|
|
|
public void UpdateProjectile(float currentTime, float degreesRotated, float damageMultiplier, bool doBoost = false, bool doEndBoost = false)
|
|
{
|
|
if (!(ownerTransform == null))
|
|
{
|
|
if (doBoost)
|
|
{
|
|
OnOrbBoost?.Invoke();
|
|
soulSpiralGhost?.Boost();
|
|
}
|
|
if (doEndBoost)
|
|
{
|
|
soulSpiralGhost?.EndBoost();
|
|
}
|
|
Vector3 vector = ownerTransform.position + offset + Quaternion.AngleAxis(degreesRotated, planeNormal) * initialRadialDirection * radius;
|
|
float num = verticalSineWaveOffset;
|
|
float num2 = (degreesRotated + initialDegreesFromOwnerForward) / degreesPerSecond;
|
|
float num3 = Mathf.Cos(MathF.PI * 2f * num2 * sineWavesPerSecond);
|
|
vector.y += num3 * num;
|
|
if (currentTime - initialStartTimeStamp <= easeInDuration)
|
|
{
|
|
float num4 = currentTime - initialStartTimeStamp;
|
|
vector = Vector3.Lerp(base.transform.position, vector, num4 / easeInDuration);
|
|
}
|
|
if ((bool)rigidBody)
|
|
{
|
|
rigidBody.MovePosition(vector);
|
|
}
|
|
else
|
|
{
|
|
base.transform.position = vector;
|
|
}
|
|
float num5 = baseDamage * damageMultiplier;
|
|
if (projectileOverlapLimitHits.IsLastHit())
|
|
{
|
|
num5 *= lastHitDamageMultiplier;
|
|
}
|
|
if (num5 != prevDamage)
|
|
{
|
|
projectileDamage.damage = num5;
|
|
prevDamage = num5;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetInitialDegreesFromOwnerForward(float degrees, int positionIndex)
|
|
{
|
|
initialDegreesFromOwnerForward = degrees;
|
|
if ((bool)ownerTransform)
|
|
{
|
|
initialRadialDirection = Quaternion.AngleAxis(initialDegreesFromOwnerForward, planeNormal) * ownerTransform.forward;
|
|
}
|
|
}
|
|
|
|
public void DestroySpiral()
|
|
{
|
|
EffectManagerHelper component = GetComponent<EffectManagerHelper>();
|
|
if ((bool)component && component.OwningPool != null)
|
|
{
|
|
component.OwningPool.ReturnObject(component);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Object.Destroy(base.gameObject);
|
|
}
|
|
}
|
|
}
|