194 lines
5.3 KiB
C#
194 lines
5.3 KiB
C#
|
using System.Collections.Generic;
|
||
|
using RoR2.Audio;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Networking;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
[RequireComponent(typeof(TeamFilter))]
|
||
|
[RequireComponent(typeof(GenericOwnership))]
|
||
|
public class GrandParentSunController : MonoBehaviour
|
||
|
{
|
||
|
private TeamFilter teamFilter;
|
||
|
|
||
|
private GenericOwnership ownership;
|
||
|
|
||
|
public BuffDef buffDef;
|
||
|
|
||
|
[Min(0.001f)]
|
||
|
public float cycleInterval = 1f;
|
||
|
|
||
|
[Min(0.001f)]
|
||
|
public float nearBuffDuration = 1f;
|
||
|
|
||
|
[Min(0.001f)]
|
||
|
public float maxDistance = 1f;
|
||
|
|
||
|
public int minimumStacksBeforeApplyingBurns = 4;
|
||
|
|
||
|
public float burnDuration = 5f;
|
||
|
|
||
|
public GameObject buffApplyEffect;
|
||
|
|
||
|
[SerializeField]
|
||
|
private LoopSoundDef activeLoopDef;
|
||
|
|
||
|
[SerializeField]
|
||
|
private LoopSoundDef damageLoopDef;
|
||
|
|
||
|
[SerializeField]
|
||
|
private string stopSoundName;
|
||
|
|
||
|
private Run.FixedTimeStamp previousCycle = Run.FixedTimeStamp.negativeInfinity;
|
||
|
|
||
|
private int cycleIndex;
|
||
|
|
||
|
private List<HurtBox> cycleTargets = new List<HurtBox>();
|
||
|
|
||
|
private BullseyeSearch bullseyeSearch = new BullseyeSearch();
|
||
|
|
||
|
private bool isLocalPlayerDamaged;
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
teamFilter = GetComponent<TeamFilter>();
|
||
|
ownership = GetComponent<GenericOwnership>();
|
||
|
}
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
if ((bool)activeLoopDef)
|
||
|
{
|
||
|
Util.PlaySound(activeLoopDef.startSoundName, base.gameObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnDestroy()
|
||
|
{
|
||
|
if ((bool)activeLoopDef)
|
||
|
{
|
||
|
Util.PlaySound(activeLoopDef.stopSoundName, base.gameObject);
|
||
|
}
|
||
|
if ((bool)damageLoopDef)
|
||
|
{
|
||
|
Util.PlaySound(damageLoopDef.stopSoundName, base.gameObject);
|
||
|
}
|
||
|
if (stopSoundName != null)
|
||
|
{
|
||
|
Util.PlaySound(stopSoundName, base.gameObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void FixedUpdate()
|
||
|
{
|
||
|
if (NetworkServer.active)
|
||
|
{
|
||
|
ServerFixedUpdate();
|
||
|
}
|
||
|
if (!damageLoopDef)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
bool flag = isLocalPlayerDamaged;
|
||
|
isLocalPlayerDamaged = false;
|
||
|
foreach (HurtBox cycleTarget in cycleTargets)
|
||
|
{
|
||
|
CharacterBody characterBody = null;
|
||
|
if ((bool)cycleTarget && (bool)cycleTarget.healthComponent)
|
||
|
{
|
||
|
characterBody = cycleTarget.healthComponent.body;
|
||
|
}
|
||
|
if ((bool)characterBody && (characterBody.bodyFlags & CharacterBody.BodyFlags.OverheatImmune) != 0 && characterBody.hasEffectiveAuthority)
|
||
|
{
|
||
|
Vector3 position = base.transform.position;
|
||
|
Vector3 corePosition = characterBody.corePosition;
|
||
|
if (!Physics.Linecast(position, corePosition, out var _, LayerIndex.world.mask, QueryTriggerInteraction.Ignore))
|
||
|
{
|
||
|
isLocalPlayerDamaged = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (isLocalPlayerDamaged && !flag)
|
||
|
{
|
||
|
Util.PlaySound(damageLoopDef.startSoundName, base.gameObject);
|
||
|
}
|
||
|
else if (!isLocalPlayerDamaged && flag)
|
||
|
{
|
||
|
Util.PlaySound(damageLoopDef.stopSoundName, base.gameObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ServerFixedUpdate()
|
||
|
{
|
||
|
float num = Mathf.Clamp01(previousCycle.timeSince / cycleInterval);
|
||
|
int num2 = ((num == 1f) ? cycleTargets.Count : Mathf.FloorToInt((float)cycleTargets.Count * num));
|
||
|
Vector3 position = base.transform.position;
|
||
|
while (cycleIndex < num2)
|
||
|
{
|
||
|
HurtBox hurtBox = cycleTargets[cycleIndex];
|
||
|
if ((bool)hurtBox && (bool)hurtBox.healthComponent)
|
||
|
{
|
||
|
CharacterBody body = hurtBox.healthComponent.body;
|
||
|
if ((body.bodyFlags & CharacterBody.BodyFlags.OverheatImmune) == 0)
|
||
|
{
|
||
|
Vector3 corePosition = body.corePosition;
|
||
|
Ray ray = new Ray(position, corePosition - position);
|
||
|
if (!Physics.Linecast(position, corePosition, out var hitInfo, LayerIndex.world.mask, QueryTriggerInteraction.Ignore))
|
||
|
{
|
||
|
float num3 = Mathf.Max(1f, hitInfo.distance);
|
||
|
body.AddTimedBuff(buffDef, nearBuffDuration / num3);
|
||
|
if ((bool)buffApplyEffect)
|
||
|
{
|
||
|
EffectData effectData = new EffectData
|
||
|
{
|
||
|
origin = corePosition,
|
||
|
rotation = Util.QuaternionSafeLookRotation(-ray.direction),
|
||
|
scale = body.bestFitRadius
|
||
|
};
|
||
|
effectData.SetHurtBoxReference(hurtBox);
|
||
|
EffectManager.SpawnEffect(buffApplyEffect, effectData, transmit: true);
|
||
|
}
|
||
|
int num4 = body.GetBuffCount(buffDef) - minimumStacksBeforeApplyingBurns;
|
||
|
if (num4 > 0)
|
||
|
{
|
||
|
InflictDotInfo dotInfo = default(InflictDotInfo);
|
||
|
dotInfo.dotIndex = DotController.DotIndex.Burn;
|
||
|
dotInfo.attackerObject = ownership.ownerObject;
|
||
|
dotInfo.victimObject = body.gameObject;
|
||
|
dotInfo.damageMultiplier = 1f;
|
||
|
CharacterBody characterBody = ownership?.ownerObject?.GetComponent<CharacterBody>();
|
||
|
if ((bool)characterBody && (bool)characterBody.inventory)
|
||
|
{
|
||
|
dotInfo.totalDamage = 0.5f * characterBody.damage * burnDuration * (float)num4;
|
||
|
StrengthenBurnUtils.CheckDotForUpgrade(characterBody.inventory, ref dotInfo);
|
||
|
}
|
||
|
DotController.InflictDot(ref dotInfo);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
cycleIndex++;
|
||
|
}
|
||
|
if (previousCycle.timeSince >= cycleInterval)
|
||
|
{
|
||
|
previousCycle = Run.FixedTimeStamp.now;
|
||
|
cycleIndex = 0;
|
||
|
cycleTargets.Clear();
|
||
|
SearchForTargets(cycleTargets);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SearchForTargets(List<HurtBox> dest)
|
||
|
{
|
||
|
bullseyeSearch.searchOrigin = base.transform.position;
|
||
|
bullseyeSearch.minAngleFilter = 0f;
|
||
|
bullseyeSearch.maxAngleFilter = 180f;
|
||
|
bullseyeSearch.maxDistanceFilter = maxDistance;
|
||
|
bullseyeSearch.filterByDistinctEntity = true;
|
||
|
bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance;
|
||
|
bullseyeSearch.viewer = null;
|
||
|
bullseyeSearch.RefreshCandidates();
|
||
|
dest.AddRange(bullseyeSearch.GetResults());
|
||
|
}
|
||
|
}
|