433 lines
8.8 KiB
C#
433 lines
8.8 KiB
C#
using System.Runtime.InteropServices;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.Networking;
|
|
|
|
namespace RoR2.Projectile;
|
|
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
[RequireComponent(typeof(ProjectileController))]
|
|
[DefaultExecutionOrder(-1)]
|
|
[RequireComponent(typeof(ProjectileNetworkTransform))]
|
|
public class ProjectileStickOnImpact : NetworkBehaviour, IProjectileImpactBehavior
|
|
{
|
|
public string stickSoundString;
|
|
|
|
public ParticleSystem[] stickParticleSystem;
|
|
|
|
public bool ignoreCharacters;
|
|
|
|
public bool ignoreWorld;
|
|
|
|
public bool alignNormals = true;
|
|
|
|
public UnityEvent stickEvent;
|
|
|
|
private ProjectileController projectileController;
|
|
|
|
private Rigidbody rigidbody;
|
|
|
|
private bool wasEverEnabled;
|
|
|
|
private GameObject _victim;
|
|
|
|
[SyncVar]
|
|
private GameObject syncVictim;
|
|
|
|
[SyncVar]
|
|
private sbyte hitHurtboxIndex = -1;
|
|
|
|
[SyncVar]
|
|
private Vector3 localPosition;
|
|
|
|
[SyncVar]
|
|
private Quaternion localRotation;
|
|
|
|
[SyncVar]
|
|
private bool runStickEvent;
|
|
|
|
private bool alreadyRanStickEvent;
|
|
|
|
private NetworkInstanceId ___syncVictimNetId;
|
|
|
|
public Transform stuckTransform { get; private set; }
|
|
|
|
public CharacterBody stuckBody { get; private set; }
|
|
|
|
public GameObject victim
|
|
{
|
|
get
|
|
{
|
|
return _victim;
|
|
}
|
|
private set
|
|
{
|
|
_victim = value;
|
|
NetworksyncVictim = value;
|
|
}
|
|
}
|
|
|
|
public bool stuck => hitHurtboxIndex != -1;
|
|
|
|
public GameObject NetworksyncVictim
|
|
{
|
|
get
|
|
{
|
|
return syncVictim;
|
|
}
|
|
[param: In]
|
|
set
|
|
{
|
|
SetSyncVarGameObject(value, ref syncVictim, 1u, ref ___syncVictimNetId);
|
|
}
|
|
}
|
|
|
|
public sbyte NetworkhitHurtboxIndex
|
|
{
|
|
get
|
|
{
|
|
return hitHurtboxIndex;
|
|
}
|
|
[param: In]
|
|
set
|
|
{
|
|
SetSyncVar(value, ref hitHurtboxIndex, 2u);
|
|
}
|
|
}
|
|
|
|
public Vector3 NetworklocalPosition
|
|
{
|
|
get
|
|
{
|
|
return localPosition;
|
|
}
|
|
[param: In]
|
|
set
|
|
{
|
|
SetSyncVar(value, ref localPosition, 4u);
|
|
}
|
|
}
|
|
|
|
public Quaternion NetworklocalRotation
|
|
{
|
|
get
|
|
{
|
|
return localRotation;
|
|
}
|
|
[param: In]
|
|
set
|
|
{
|
|
SetSyncVar(value, ref localRotation, 8u);
|
|
}
|
|
}
|
|
|
|
public bool NetworkrunStickEvent
|
|
{
|
|
get
|
|
{
|
|
return runStickEvent;
|
|
}
|
|
[param: In]
|
|
set
|
|
{
|
|
SetSyncVar(value, ref runStickEvent, 16u);
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
projectileController = GetComponent<ProjectileController>();
|
|
rigidbody = GetComponent<Rigidbody>();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (wasEverEnabled)
|
|
{
|
|
Collider component = GetComponent<Collider>();
|
|
component.enabled = false;
|
|
component.enabled = true;
|
|
}
|
|
wasEverEnabled = true;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (NetworkServer.active)
|
|
{
|
|
Detach();
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
public void Detach()
|
|
{
|
|
if (!NetworkServer.active)
|
|
{
|
|
Debug.LogWarning("[Server] function 'System.Void RoR2.Projectile.ProjectileStickOnImpact::Detach()' called on client");
|
|
return;
|
|
}
|
|
victim = null;
|
|
stuckTransform = null;
|
|
NetworkhitHurtboxIndex = -1;
|
|
UpdateSticking();
|
|
}
|
|
|
|
public void OnProjectileImpact(ProjectileImpactInfo impactInfo)
|
|
{
|
|
if (base.enabled)
|
|
{
|
|
TrySticking(impactInfo.collider, impactInfo.estimatedImpactNormal);
|
|
}
|
|
}
|
|
|
|
private bool TrySticking(Collider hitCollider, Vector3 impactNormal)
|
|
{
|
|
if ((bool)victim)
|
|
{
|
|
return false;
|
|
}
|
|
GameObject gameObject = null;
|
|
sbyte networkhitHurtboxIndex = -1;
|
|
HurtBox component = hitCollider.GetComponent<HurtBox>();
|
|
if ((bool)component)
|
|
{
|
|
HealthComponent healthComponent = component.healthComponent;
|
|
if ((bool)healthComponent)
|
|
{
|
|
gameObject = healthComponent.gameObject;
|
|
}
|
|
networkhitHurtboxIndex = (sbyte)component.indexInGroup;
|
|
}
|
|
if (!gameObject && !ignoreWorld)
|
|
{
|
|
gameObject = hitCollider.gameObject;
|
|
networkhitHurtboxIndex = -2;
|
|
}
|
|
if (gameObject == projectileController.owner || (ignoreCharacters && (bool)component))
|
|
{
|
|
gameObject = null;
|
|
networkhitHurtboxIndex = -1;
|
|
}
|
|
if ((bool)gameObject)
|
|
{
|
|
NetworkrunStickEvent = true;
|
|
ParticleSystem[] array = stickParticleSystem;
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i].Play();
|
|
}
|
|
if (stickSoundString.Length > 0)
|
|
{
|
|
Util.PlaySound(stickSoundString, base.gameObject);
|
|
}
|
|
if (alignNormals && impactNormal != Vector3.zero)
|
|
{
|
|
base.transform.rotation = Util.QuaternionSafeLookRotation(impactNormal, base.transform.up);
|
|
}
|
|
Transform transform = hitCollider.transform;
|
|
NetworklocalPosition = transform.InverseTransformPoint(base.transform.position);
|
|
NetworklocalRotation = Quaternion.Inverse(transform.rotation) * base.transform.rotation;
|
|
victim = gameObject;
|
|
NetworkhitHurtboxIndex = networkhitHurtboxIndex;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
MyFixedUpdate(Time.deltaTime);
|
|
}
|
|
|
|
private void UpdateSticking()
|
|
{
|
|
bool flag = stuckTransform;
|
|
if (flag)
|
|
{
|
|
base.transform.SetPositionAndRotation(stuckTransform.TransformPoint(localPosition), alignNormals ? (stuckTransform.rotation * localRotation) : base.transform.rotation);
|
|
}
|
|
else
|
|
{
|
|
GameObject gameObject = (NetworkServer.active ? victim : syncVictim);
|
|
if ((bool)gameObject)
|
|
{
|
|
stuckTransform = gameObject.transform;
|
|
flag = true;
|
|
if (hitHurtboxIndex >= 0)
|
|
{
|
|
stuckBody = stuckTransform.GetComponent<CharacterBody>();
|
|
if ((bool)stuckBody && hitHurtboxIndex < stuckBody.hurtBoxGroup.hurtBoxes.Length && stuckBody.hurtBoxGroup.hurtBoxes[hitHurtboxIndex] != null)
|
|
{
|
|
stuckTransform = stuckBody.hurtBoxGroup.hurtBoxes[hitHurtboxIndex].transform;
|
|
}
|
|
ModelLocator component = syncVictim.GetComponent<ModelLocator>();
|
|
if ((bool)component)
|
|
{
|
|
Transform modelTransform = component.modelTransform;
|
|
if ((bool)modelTransform)
|
|
{
|
|
HurtBoxGroup component2 = modelTransform.GetComponent<HurtBoxGroup>();
|
|
if ((bool)component2)
|
|
{
|
|
HurtBox hurtBox = component2.hurtBoxes[hitHurtboxIndex];
|
|
if ((bool)hurtBox)
|
|
{
|
|
stuckTransform = hurtBox.transform;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (hitHurtboxIndex == -2 && !NetworkServer.active)
|
|
{
|
|
flag = true;
|
|
}
|
|
}
|
|
if (!NetworkServer.active)
|
|
{
|
|
return;
|
|
}
|
|
if (rigidbody.isKinematic != flag)
|
|
{
|
|
if (flag)
|
|
{
|
|
rigidbody.detectCollisions = false;
|
|
rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
|
|
rigidbody.isKinematic = true;
|
|
}
|
|
else
|
|
{
|
|
rigidbody.detectCollisions = true;
|
|
rigidbody.isKinematic = false;
|
|
rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
NetworkhitHurtboxIndex = -1;
|
|
}
|
|
}
|
|
|
|
public void MyFixedUpdate(float deltaTime)
|
|
{
|
|
UpdateSticking();
|
|
if (!alreadyRanStickEvent && runStickEvent)
|
|
{
|
|
stickEvent.Invoke();
|
|
alreadyRanStickEvent = true;
|
|
}
|
|
}
|
|
|
|
private void UNetVersion()
|
|
{
|
|
}
|
|
|
|
public override bool OnSerialize(NetworkWriter writer, bool forceAll)
|
|
{
|
|
if (forceAll)
|
|
{
|
|
writer.Write(syncVictim);
|
|
writer.WritePackedUInt32((uint)hitHurtboxIndex);
|
|
writer.Write(localPosition);
|
|
writer.Write(localRotation);
|
|
writer.Write(runStickEvent);
|
|
return true;
|
|
}
|
|
bool flag = false;
|
|
if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
flag = true;
|
|
}
|
|
writer.Write(syncVictim);
|
|
}
|
|
if ((base.syncVarDirtyBits & 2u) != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
flag = true;
|
|
}
|
|
writer.WritePackedUInt32((uint)hitHurtboxIndex);
|
|
}
|
|
if ((base.syncVarDirtyBits & 4u) != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
flag = true;
|
|
}
|
|
writer.Write(localPosition);
|
|
}
|
|
if ((base.syncVarDirtyBits & 8u) != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
flag = true;
|
|
}
|
|
writer.Write(localRotation);
|
|
}
|
|
if ((base.syncVarDirtyBits & 0x10u) != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
flag = true;
|
|
}
|
|
writer.Write(runStickEvent);
|
|
}
|
|
if (!flag)
|
|
{
|
|
writer.WritePackedUInt32(base.syncVarDirtyBits);
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|
{
|
|
if (initialState)
|
|
{
|
|
___syncVictimNetId = reader.ReadNetworkId();
|
|
hitHurtboxIndex = (sbyte)reader.ReadPackedUInt32();
|
|
localPosition = reader.ReadVector3();
|
|
localRotation = reader.ReadQuaternion();
|
|
runStickEvent = reader.ReadBoolean();
|
|
return;
|
|
}
|
|
int num = (int)reader.ReadPackedUInt32();
|
|
if (((uint)num & (true ? 1u : 0u)) != 0)
|
|
{
|
|
syncVictim = reader.ReadGameObject();
|
|
}
|
|
if (((uint)num & 2u) != 0)
|
|
{
|
|
hitHurtboxIndex = (sbyte)reader.ReadPackedUInt32();
|
|
}
|
|
if (((uint)num & 4u) != 0)
|
|
{
|
|
localPosition = reader.ReadVector3();
|
|
}
|
|
if (((uint)num & 8u) != 0)
|
|
{
|
|
localRotation = reader.ReadQuaternion();
|
|
}
|
|
if (((uint)num & 0x10u) != 0)
|
|
{
|
|
runStickEvent = reader.ReadBoolean();
|
|
}
|
|
}
|
|
|
|
public override void PreStartClient()
|
|
{
|
|
if (!___syncVictimNetId.IsEmpty())
|
|
{
|
|
NetworksyncVictim = ClientScene.FindLocalObject(___syncVictimNetId);
|
|
}
|
|
}
|
|
}
|