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 cycleTargets = new List(); private BullseyeSearch bullseyeSearch = new BullseyeSearch(); private bool isLocalPlayerDamaged; private void Awake() { teamFilter = GetComponent(); ownership = GetComponent(); } 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(); 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 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()); } }