220 lines
5.8 KiB
C#
220 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace RoR2.Orbs;
|
|
|
|
public class LightningOrb : Orb
|
|
{
|
|
public enum LightningType
|
|
{
|
|
Ukulele,
|
|
Tesla,
|
|
BFG,
|
|
TreePoisonDart,
|
|
HuntressGlaive,
|
|
Loader,
|
|
RazorWire,
|
|
CrocoDisease,
|
|
MageLightning,
|
|
AntlerShield,
|
|
BeadDamage,
|
|
Count
|
|
}
|
|
|
|
public float speed = 100f;
|
|
|
|
public float damageValue;
|
|
|
|
public GameObject attacker;
|
|
|
|
public GameObject inflictor;
|
|
|
|
public int bouncesRemaining;
|
|
|
|
public List<HealthComponent> bouncedObjects;
|
|
|
|
public TeamIndex teamIndex;
|
|
|
|
public bool isCrit;
|
|
|
|
public ProcChainMask procChainMask;
|
|
|
|
public float procCoefficient = 1f;
|
|
|
|
public DamageColorIndex damageColorIndex;
|
|
|
|
public float range = 20f;
|
|
|
|
public float damageCoefficientPerBounce = 1f;
|
|
|
|
public int targetsToFindPerBounce = 1;
|
|
|
|
public DamageTypeCombo damageType = DamageType.Generic;
|
|
|
|
private bool canBounceOnSameTarget;
|
|
|
|
private bool failedToKill;
|
|
|
|
public LightningType lightningType;
|
|
|
|
private BullseyeSearch search;
|
|
|
|
public static event Action<LightningOrb> onLightningOrbKilledOnAllBounces;
|
|
|
|
public override void Begin()
|
|
{
|
|
base.duration = 0.1f;
|
|
string path = null;
|
|
switch (lightningType)
|
|
{
|
|
case LightningType.Ukulele:
|
|
path = "Prefabs/Effects/OrbEffects/LightningOrbEffect";
|
|
break;
|
|
case LightningType.Tesla:
|
|
path = "Prefabs/Effects/OrbEffects/TeslaOrbEffect";
|
|
break;
|
|
case LightningType.BFG:
|
|
path = "Prefabs/Effects/OrbEffects/BeamSphereOrbEffect";
|
|
base.duration = 0.4f;
|
|
break;
|
|
case LightningType.HuntressGlaive:
|
|
path = "Prefabs/Effects/OrbEffects/HuntressGlaiveOrbEffect";
|
|
base.duration = base.distanceToTarget / speed;
|
|
canBounceOnSameTarget = true;
|
|
break;
|
|
case LightningType.TreePoisonDart:
|
|
path = "Prefabs/Effects/OrbEffects/TreePoisonDartOrbEffect";
|
|
speed = 40f;
|
|
base.duration = base.distanceToTarget / speed;
|
|
break;
|
|
case LightningType.Loader:
|
|
path = "Prefabs/Effects/OrbEffects/LoaderLightningOrbEffect";
|
|
break;
|
|
case LightningType.RazorWire:
|
|
path = "Prefabs/Effects/OrbEffects/RazorwireOrbEffect";
|
|
base.duration = 0.2f;
|
|
break;
|
|
case LightningType.CrocoDisease:
|
|
path = "Prefabs/Effects/OrbEffects/CrocoDiseaseOrbEffect";
|
|
base.duration = 0.6f;
|
|
targetsToFindPerBounce = 2;
|
|
break;
|
|
case LightningType.MageLightning:
|
|
path = "Prefabs/Effects/OrbEffects/MageLightningOrbEffect";
|
|
base.duration = 0.1f;
|
|
break;
|
|
case LightningType.AntlerShield:
|
|
path = "Prefabs/Effects/OrbEffects/NegateAttackOrbEffect";
|
|
base.duration = 0.2f;
|
|
break;
|
|
case LightningType.BeadDamage:
|
|
path = "Prefabs/Effects/OrbEffects/BeadDamageOrbEffect";
|
|
base.duration = 0.2f;
|
|
break;
|
|
}
|
|
EffectData effectData = new EffectData
|
|
{
|
|
origin = origin,
|
|
genericFloat = base.duration
|
|
};
|
|
effectData.SetHurtBoxReference(target);
|
|
EffectManager.SpawnEffect(OrbStorageUtility.Get(path), effectData, transmit: true);
|
|
}
|
|
|
|
public override void OnArrival()
|
|
{
|
|
if (!target)
|
|
{
|
|
return;
|
|
}
|
|
HealthComponent healthComponent = target.healthComponent;
|
|
if ((bool)healthComponent)
|
|
{
|
|
DamageInfo damageInfo = new DamageInfo();
|
|
damageInfo.damage = damageValue;
|
|
damageInfo.attacker = attacker;
|
|
damageInfo.inflictor = inflictor;
|
|
damageInfo.force = Vector3.zero;
|
|
damageInfo.crit = isCrit;
|
|
damageInfo.procChainMask = procChainMask;
|
|
damageInfo.procCoefficient = procCoefficient;
|
|
damageInfo.position = target.transform.position;
|
|
damageInfo.damageColorIndex = damageColorIndex;
|
|
damageInfo.damageType = damageType;
|
|
healthComponent.TakeDamage(damageInfo);
|
|
GlobalEventManager.instance.OnHitEnemy(damageInfo, healthComponent.gameObject);
|
|
GlobalEventManager.instance.OnHitAll(damageInfo, healthComponent.gameObject);
|
|
}
|
|
failedToKill |= !healthComponent || healthComponent.alive;
|
|
if (bouncesRemaining > 0)
|
|
{
|
|
for (int i = 0; i < targetsToFindPerBounce; i++)
|
|
{
|
|
if (bouncedObjects != null)
|
|
{
|
|
if (canBounceOnSameTarget)
|
|
{
|
|
bouncedObjects.Clear();
|
|
}
|
|
bouncedObjects.Add(target.healthComponent);
|
|
}
|
|
HurtBox hurtBox = PickNextTarget(target.transform.position);
|
|
if ((bool)hurtBox)
|
|
{
|
|
LightningOrb lightningOrb = new LightningOrb();
|
|
lightningOrb.search = search;
|
|
lightningOrb.origin = target.transform.position;
|
|
lightningOrb.target = hurtBox;
|
|
lightningOrb.attacker = attacker;
|
|
lightningOrb.inflictor = inflictor;
|
|
lightningOrb.teamIndex = teamIndex;
|
|
lightningOrb.damageValue = damageValue * damageCoefficientPerBounce;
|
|
lightningOrb.bouncesRemaining = bouncesRemaining - 1;
|
|
lightningOrb.isCrit = isCrit;
|
|
lightningOrb.bouncedObjects = bouncedObjects;
|
|
lightningOrb.lightningType = lightningType;
|
|
lightningOrb.procChainMask = procChainMask;
|
|
lightningOrb.procCoefficient = procCoefficient;
|
|
lightningOrb.damageColorIndex = damageColorIndex;
|
|
lightningOrb.damageCoefficientPerBounce = damageCoefficientPerBounce;
|
|
lightningOrb.speed = speed;
|
|
lightningOrb.range = range;
|
|
lightningOrb.damageType = damageType;
|
|
lightningOrb.failedToKill = failedToKill;
|
|
OrbManager.instance.AddOrb(lightningOrb);
|
|
}
|
|
}
|
|
}
|
|
else if (!failedToKill)
|
|
{
|
|
LightningOrb.onLightningOrbKilledOnAllBounces?.Invoke(this);
|
|
}
|
|
}
|
|
|
|
public HurtBox PickNextTarget(Vector3 position)
|
|
{
|
|
if (search == null)
|
|
{
|
|
search = new BullseyeSearch();
|
|
}
|
|
search.searchOrigin = position;
|
|
search.searchDirection = Vector3.zero;
|
|
search.teamMaskFilter = TeamMask.allButNeutral;
|
|
search.teamMaskFilter.RemoveTeam(teamIndex);
|
|
search.filterByLoS = false;
|
|
search.sortMode = BullseyeSearch.SortMode.Distance;
|
|
search.maxDistanceFilter = range;
|
|
search.RefreshCandidates();
|
|
HurtBox hurtBox = (from v in search.GetResults()
|
|
where !bouncedObjects.Contains(v.healthComponent)
|
|
select v).FirstOrDefault();
|
|
if ((bool)hurtBox)
|
|
{
|
|
bouncedObjects.Add(hurtBox.healthComponent);
|
|
}
|
|
return hurtBox;
|
|
}
|
|
}
|