193 lines
5.0 KiB
C#
193 lines
5.0 KiB
C#
|
using System;
|
||
|
using HG;
|
||
|
using RoR2.Audio;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Networking;
|
||
|
|
||
|
namespace RoR2.Projectile;
|
||
|
|
||
|
[RequireComponent(typeof(ProjectileController))]
|
||
|
public class ProjectileImpactExplosion : ProjectileExplosion, IProjectileImpactBehavior
|
||
|
{
|
||
|
public enum TransformSpace
|
||
|
{
|
||
|
World,
|
||
|
Local,
|
||
|
Normal
|
||
|
}
|
||
|
|
||
|
private Vector3 impactNormal = Vector3.up;
|
||
|
|
||
|
[Header("Impact & Lifetime Properties")]
|
||
|
public GameObject impactEffect;
|
||
|
|
||
|
[ShowFieldObsolete]
|
||
|
[Tooltip("This sound will not play over the network. Use lifetimeExpiredSound instead.")]
|
||
|
[HideInInspector]
|
||
|
[Obsolete("This sound will not play over the network. Use lifetimeExpiredSound instead.", false)]
|
||
|
public string lifetimeExpiredSoundString;
|
||
|
|
||
|
public NetworkSoundEventDef lifetimeExpiredSound;
|
||
|
|
||
|
public float offsetForLifetimeExpiredSound;
|
||
|
|
||
|
public bool destroyOnEnemy = true;
|
||
|
|
||
|
public bool destroyOnWorld;
|
||
|
|
||
|
public bool impactOnWorld = true;
|
||
|
|
||
|
public bool timerAfterImpact;
|
||
|
|
||
|
public float lifetime;
|
||
|
|
||
|
public float lifetimeAfterImpact;
|
||
|
|
||
|
public float lifetimeRandomOffset;
|
||
|
|
||
|
private float stopwatch;
|
||
|
|
||
|
public uint minimumPhysicsStepsToKeepAliveAfterImpact;
|
||
|
|
||
|
private float stopwatchAfterImpact;
|
||
|
|
||
|
private bool hasImpact;
|
||
|
|
||
|
private bool hasPlayedLifetimeExpiredSound;
|
||
|
|
||
|
public TransformSpace transformSpace;
|
||
|
|
||
|
public bool explodeOnLifeTimeExpiration;
|
||
|
|
||
|
protected override void Awake()
|
||
|
{
|
||
|
base.Awake();
|
||
|
lifetime += UnityEngine.Random.Range(0f, lifetimeRandomOffset);
|
||
|
}
|
||
|
|
||
|
protected void FixedUpdate()
|
||
|
{
|
||
|
stopwatch += Time.fixedDeltaTime;
|
||
|
if (!NetworkServer.active && !projectileController.isPrediction)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (explodeOnLifeTimeExpiration && alive && stopwatch >= lifetime)
|
||
|
{
|
||
|
explosionEffect = impactEffect ?? explosionEffect;
|
||
|
Detonate();
|
||
|
}
|
||
|
if (timerAfterImpact && hasImpact)
|
||
|
{
|
||
|
stopwatchAfterImpact += Time.fixedDeltaTime;
|
||
|
}
|
||
|
bool num = stopwatch >= lifetime;
|
||
|
bool flag = timerAfterImpact && stopwatchAfterImpact > lifetimeAfterImpact;
|
||
|
bool flag2 = (bool)projectileHealthComponent && !projectileHealthComponent.alive;
|
||
|
if (num || flag || flag2)
|
||
|
{
|
||
|
alive = false;
|
||
|
}
|
||
|
if (timerAfterImpact && hasImpact && minimumPhysicsStepsToKeepAliveAfterImpact != 0)
|
||
|
{
|
||
|
minimumPhysicsStepsToKeepAliveAfterImpact--;
|
||
|
alive = true;
|
||
|
}
|
||
|
if (alive && !hasPlayedLifetimeExpiredSound)
|
||
|
{
|
||
|
bool flag3 = stopwatch > lifetime - offsetForLifetimeExpiredSound;
|
||
|
if (timerAfterImpact)
|
||
|
{
|
||
|
flag3 |= stopwatchAfterImpact > lifetimeAfterImpact - offsetForLifetimeExpiredSound;
|
||
|
}
|
||
|
if (flag3)
|
||
|
{
|
||
|
hasPlayedLifetimeExpiredSound = true;
|
||
|
if (NetworkServer.active && (bool)lifetimeExpiredSound)
|
||
|
{
|
||
|
PointSoundManager.EmitSoundServer(lifetimeExpiredSound.index, base.transform.position);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!alive)
|
||
|
{
|
||
|
explosionEffect = impactEffect ?? explosionEffect;
|
||
|
Detonate();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override Quaternion GetRandomDirectionForChild()
|
||
|
{
|
||
|
Quaternion randomChildRollPitch = GetRandomChildRollPitch();
|
||
|
return transformSpace switch
|
||
|
{
|
||
|
TransformSpace.Local => base.transform.rotation * randomChildRollPitch,
|
||
|
TransformSpace.Normal => Quaternion.FromToRotation(Vector3.forward, impactNormal) * randomChildRollPitch,
|
||
|
_ => randomChildRollPitch,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
public void OnProjectileImpact(ProjectileImpactInfo impactInfo)
|
||
|
{
|
||
|
if (!alive)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
Collider collider = impactInfo.collider;
|
||
|
impactNormal = impactInfo.estimatedImpactNormal;
|
||
|
if (!collider)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
DamageInfo damageInfo = new DamageInfo();
|
||
|
if ((bool)projectileDamage)
|
||
|
{
|
||
|
damageInfo.damage = projectileDamage.damage;
|
||
|
damageInfo.crit = projectileDamage.crit;
|
||
|
damageInfo.attacker = (projectileController.owner ? projectileController.owner.gameObject : null);
|
||
|
damageInfo.inflictor = base.gameObject;
|
||
|
damageInfo.position = impactInfo.estimatedPointOfImpact;
|
||
|
damageInfo.force = projectileDamage.force * base.transform.forward;
|
||
|
damageInfo.procChainMask = projectileController.procChainMask;
|
||
|
damageInfo.procCoefficient = projectileController.procCoefficient;
|
||
|
}
|
||
|
HurtBox component = collider.GetComponent<HurtBox>();
|
||
|
if ((bool)component)
|
||
|
{
|
||
|
if (destroyOnEnemy)
|
||
|
{
|
||
|
HealthComponent healthComponent = component.healthComponent;
|
||
|
if ((bool)healthComponent)
|
||
|
{
|
||
|
if (healthComponent.gameObject == projectileController.owner || ((bool)projectileHealthComponent && healthComponent == projectileHealthComponent))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
alive = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (destroyOnWorld)
|
||
|
{
|
||
|
alive = false;
|
||
|
}
|
||
|
hasImpact = (bool)component || impactOnWorld;
|
||
|
if (NetworkServer.active && hasImpact)
|
||
|
{
|
||
|
GlobalEventManager.instance.OnHitAll(damageInfo, collider.gameObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void OnValidate()
|
||
|
{
|
||
|
if (!Application.IsPlaying(this))
|
||
|
{
|
||
|
base.OnValidate();
|
||
|
if (!string.IsNullOrEmpty(lifetimeExpiredSoundString))
|
||
|
{
|
||
|
Debug.LogWarningFormat(base.gameObject, "{0} ProjectileImpactExplosion component supplies a value in the lifetimeExpiredSoundString field. This will not play correctly over the network. Please use lifetimeExpiredSound instead.", Util.GetGameObjectHierarchyName(base.gameObject));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|