r2mods/ilspy_dump/ror2_csproj/RoR2/BulletAttack.cs

1054 lines
30 KiB
C#
Raw Normal View History

2024-10-04 07:26:37 +00:00
using System;
using System.Collections.Generic;
using Grumpy;
using RoR2.Networking;
using UnityEngine;
using UnityEngine.Networking;
namespace RoR2;
public class BulletAttack
{
public enum FalloffModel
{
None,
DefaultBullet,
Buckshot
}
public delegate bool HitCallback(BulletAttack bulletAttack, ref BulletHit hitInfo);
public delegate void ModifyOutgoingDamageCallback(BulletAttack bulletAttack, ref BulletHit hitInfo, DamageInfo damageInfo);
public delegate bool FilterCallback(BulletAttack bulletAttack, ref BulletHit hitInfo);
public class BulletHit
{
public Vector3 direction;
public Vector3 point;
public Vector3 surfaceNormal;
public float distance;
public Collider collider;
public HurtBox hitHurtBox;
public GameObject entityObject;
public HurtBox.DamageModifier damageModifier;
public bool isSniperHit;
public HurtBox hurtBox;
public void Reset()
{
direction = Vector3.zero;
point = Vector3.zero;
surfaceNormal = Vector3.zero;
distance = 0f;
collider = null;
entityObject = null;
damageModifier = HurtBox.DamageModifier.Normal;
isSniperHit = false;
hurtBox = null;
}
}
public class BulletHitPool : GenericPool<BulletHit>
{
protected override BulletHit CreateNewObject(bool inPoolEntry = true)
{
return new BulletHit();
}
public void ReturnAllInUse()
{
if (_InUse != null)
{
for (int num = _InUse.Count - 1; num >= 0; num--)
{
ReturnObject(_InUse[num]);
}
}
}
}
private static GameObject sniperTargetHitEffect;
public GameObject owner;
public GameObject weapon;
public float damage = 1f;
public bool isCrit;
public float force = 1f;
public ProcChainMask procChainMask;
public float procCoefficient = 1f;
public DamageTypeCombo damageType = DamageType.Generic;
public DamageColorIndex damageColorIndex;
public bool sniper;
public FalloffModel falloffModel = FalloffModel.DefaultBullet;
public GameObject tracerEffectPrefab;
public GameObject hitEffectPrefab;
public string muzzleName = "";
public bool HitEffectNormal = true;
public Vector3 origin;
private Vector3 _aimVector;
private float _maxDistance = 200f;
public float radius;
public uint bulletCount = 1u;
public float minSpread;
public float maxSpread;
public float spreadPitchScale = 1f;
public float spreadYawScale = 1f;
public QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.Ignore;
private static readonly LayerMask defaultHitMask = (int)LayerIndex.world.mask | (int)LayerIndex.entityPrecise.mask;
public LayerMask hitMask = defaultHitMask;
private static readonly LayerMask defaultStopperMask = defaultHitMask;
public LayerMask stopperMask = defaultStopperMask;
public bool smartCollision;
public bool cheapMultiBullet;
public float multiBulletOdds = 0.4f;
public bool allowTrajectoryAimAssist = true;
public float trajectoryAimAssistMultiplier = 1f;
public HitCallback hitCallback;
protected DamageInfo _dmgInfo;
public static readonly HitCallback defaultHitCallback = DefaultHitCallbackImplementation;
public ModifyOutgoingDamageCallback modifyOutgoingDamageCallback;
private static NetworkWriter messageWriter = new NetworkWriter();
public FilterCallback filterCallback;
public static readonly FilterCallback defaultFilterCallback = DefaultFilterCallbackImplementation;
protected static BulletHitPool __BulletHitPool = null;
protected static List<BulletHit> _BulletHits = new List<BulletHit>();
protected static List<GameObject> _IgnoreList = new List<GameObject>();
protected static HashSet<GameObject> _EncounteredEntityObjects = new HashSet<GameObject>();
protected static bool _UsePools = true;
protected static EffectData _effectData = null;
public Vector3 aimVector
{
get
{
return _aimVector;
}
set
{
_aimVector = value;
_aimVector.Normalize();
}
}
public float maxDistance
{
get
{
return _maxDistance;
}
set
{
if (!float.IsInfinity(value) && !float.IsNaN(value))
{
_maxDistance = value;
return;
}
Debug.LogFormat("BulletAttack.maxDistance was assigned a value other than a finite number. value={0}", value);
}
}
[Obsolete("Use .defaultHitCallback instead.", false)]
public static HitCallback DefaultHitCallback => defaultHitCallback;
[Obsolete("Use .defaultFilterCallback instead.", false)]
public static FilterCallback DefaultFilterCallback => defaultFilterCallback;
protected static BulletHitPool _BulletHitPool
{
get
{
if (__BulletHitPool == null)
{
__BulletHitPool = new BulletHitPool();
__BulletHitPool.AlwaysGrowable = true;
__BulletHitPool.Initialize(20, 10);
}
return __BulletHitPool;
}
}
public static bool UsePools => _UsePools;
public BulletAttack()
{
filterCallback = defaultFilterCallback;
hitCallback = defaultHitCallback;
}
[InitDuringStartup]
private static void Init()
{
LegacyResourcesAPI.LoadAsyncCallback("Prefabs/Effects/ImpactEffects/SniperTargetHitEffect", delegate(GameObject operationResult)
{
sniperTargetHitEffect = operationResult;
});
}
public void Reset()
{
owner = null;
weapon = null;
damage = 1f;
isCrit = false;
force = 1f;
procChainMask.mask = 0u;
procCoefficient = 1f;
damageType = DamageType.Generic;
damageColorIndex = DamageColorIndex.Default;
sniper = false;
falloffModel = FalloffModel.DefaultBullet;
tracerEffectPrefab = null;
hitEffectPrefab = null;
muzzleName = "";
HitEffectNormal = true;
origin = Vector3.zero;
_aimVector = Vector3.zero;
_maxDistance = 200f;
radius = 0f;
bulletCount = 1u;
minSpread = 0f;
maxSpread = 0f;
spreadPitchScale = 1f;
spreadYawScale = 1f;
queryTriggerInteraction = QueryTriggerInteraction.Ignore;
hitMask = defaultHitMask;
stopperMask = defaultStopperMask;
smartCollision = false;
cheapMultiBullet = false;
filterCallback = defaultFilterCallback;
hitCallback = defaultHitCallback;
}
private static void PlayHitEffect(BulletAttack bulletAttack, ref BulletHit hitInfo)
{
if ((bool)bulletAttack.hitEffectPrefab)
{
EffectManager.SimpleImpactEffect(bulletAttack.hitEffectPrefab, hitInfo.point, bulletAttack.HitEffectNormal ? hitInfo.surfaceNormal : (-hitInfo.direction), transmit: true);
}
if (hitInfo.isSniperHit && (object)sniperTargetHitEffect != null)
{
EffectData effectData = new EffectData
{
origin = hitInfo.point,
rotation = Quaternion.LookRotation(-hitInfo.direction)
};
effectData.SetHurtBoxReference(hitInfo.hitHurtBox);
EffectManager.SpawnEffect(sniperTargetHitEffect, effectData, transmit: true);
}
if ((bool)hitInfo.collider)
{
SurfaceDef objectSurfaceDef = SurfaceDefProvider.GetObjectSurfaceDef(hitInfo.collider, hitInfo.point);
if ((bool)objectSurfaceDef && (bool)objectSurfaceDef.impactEffectPrefab)
{
EffectData effectData2 = new EffectData
{
origin = hitInfo.point,
rotation = Quaternion.LookRotation(hitInfo.surfaceNormal),
color = objectSurfaceDef.approximateColor,
surfaceDefIndex = objectSurfaceDef.surfaceDefIndex
};
EffectManager.SpawnEffect(objectSurfaceDef.impactEffectPrefab, effectData2, transmit: true);
}
}
}
private static bool DefaultHitCallbackImplementation(BulletAttack bulletAttack, ref BulletHit hitInfo)
{
bool result = false;
if ((bool)hitInfo.collider)
{
result = ((1 << hitInfo.collider.gameObject.layer) & (int)bulletAttack.stopperMask) == 0;
}
PlayHitEffect(bulletAttack, ref hitInfo);
GameObject entityObject = hitInfo.entityObject;
if ((bool)entityObject)
{
float num = CalcFalloffFactor(bulletAttack.falloffModel, hitInfo.distance);
DamageInfo damageInfo = new DamageInfo();
damageInfo.damage = bulletAttack.damage * num;
damageInfo.crit = bulletAttack.isCrit;
damageInfo.attacker = bulletAttack.owner;
damageInfo.inflictor = bulletAttack.weapon;
damageInfo.position = hitInfo.point;
damageInfo.force = hitInfo.direction * (bulletAttack.force * num);
damageInfo.procChainMask = bulletAttack.procChainMask;
damageInfo.procCoefficient = bulletAttack.procCoefficient;
damageInfo.damageType = bulletAttack.damageType;
damageInfo.damageColorIndex = bulletAttack.damageColorIndex;
damageInfo.ModifyDamageInfo(hitInfo.damageModifier);
if (hitInfo.isSniperHit)
{
damageInfo.crit = true;
damageInfo.damageColorIndex = DamageColorIndex.Sniper;
}
bulletAttack.modifyOutgoingDamageCallback?.Invoke(bulletAttack, ref hitInfo, damageInfo);
TeamIndex attackerTeamIndex = TeamIndex.None;
if ((bool)bulletAttack.owner)
{
TeamComponent component = bulletAttack.owner.GetComponent<TeamComponent>();
if ((bool)component)
{
attackerTeamIndex = component.teamIndex;
}
}
HealthComponent healthComponent = null;
if ((bool)hitInfo.hitHurtBox)
{
healthComponent = hitInfo.hitHurtBox.healthComponent;
}
bool flag = (bool)healthComponent && FriendlyFireManager.ShouldDirectHitProceed(healthComponent, attackerTeamIndex);
if (NetworkServer.active)
{
if (flag)
{
healthComponent.TakeDamage(damageInfo);
GlobalEventManager.instance.OnHitEnemy(damageInfo, hitInfo.entityObject);
}
GlobalEventManager.instance.OnHitAll(damageInfo, hitInfo.entityObject);
}
else if (ClientScene.ready)
{
messageWriter.StartMessage(53);
int currentLogLevel = LogFilter.currentLogLevel;
LogFilter.currentLogLevel = 4;
messageWriter.Write(entityObject);
LogFilter.currentLogLevel = currentLogLevel;
messageWriter.Write(damageInfo);
messageWriter.Write(flag);
messageWriter.FinishMessage();
ClientScene.readyConnection.SendWriter(messageWriter, QosChannelIndex.defaultReliable.intVal);
}
}
return result;
}
private static float CalcFalloffFactor(FalloffModel falloffModel, float distance)
{
return falloffModel switch
{
FalloffModel.DefaultBullet => 0.5f + Mathf.Clamp01(Mathf.InverseLerp(60f, 25f, distance)) * 0.5f,
FalloffModel.Buckshot => 0.25f + Mathf.Clamp01(Mathf.InverseLerp(25f, 7f, distance)) * 0.75f,
_ => 1f,
};
}
private static bool DefaultFilterCallbackImplementation(BulletAttack bulletAttack, ref BulletHit hitInfo)
{
HurtBox component = hitInfo.collider.GetComponent<HurtBox>();
if ((bool)component && (bool)component.healthComponent && component.healthComponent.gameObject == bulletAttack.weapon)
{
return false;
}
return hitInfo.entityObject != bulletAttack.weapon;
}
private void InitBulletHitFromOriginHit(ref BulletHit bulletHit, Vector3 direction, Collider hitCollider)
{
bulletHit.direction = direction;
bulletHit.point = origin;
bulletHit.surfaceNormal = -direction;
bulletHit.distance = 0f;
bulletHit.collider = hitCollider;
HurtBox component = bulletHit.collider.GetComponent<HurtBox>();
bulletHit.hitHurtBox = component;
bulletHit.entityObject = (((bool)component && (bool)component.healthComponent) ? component.healthComponent.gameObject : bulletHit.collider.gameObject);
bulletHit.damageModifier = (component ? component.damageModifier : HurtBox.DamageModifier.Normal);
}
private void InitBulletHitFromRaycastHit(ref BulletHit bulletHit, Vector3 origin, Vector3 direction, ref RaycastHit raycastHit)
{
bulletHit.direction = direction;
bulletHit.surfaceNormal = raycastHit.normal;
bulletHit.distance = raycastHit.distance;
bulletHit.collider = raycastHit.collider;
bulletHit.point = ((bulletHit.distance == 0f) ? origin : raycastHit.point);
HurtBox component = bulletHit.collider.GetComponent<HurtBox>();
bulletHit.hitHurtBox = component;
bulletHit.entityObject = (((bool)component && (bool)component.healthComponent) ? component.healthComponent.gameObject : bulletHit.collider.gameObject);
bulletHit.damageModifier = (component ? component.damageModifier : HurtBox.DamageModifier.Normal);
}
private bool ProcessHit(ref BulletHit hitInfo)
{
if (!filterCallback(this, ref hitInfo))
{
return true;
}
if (sniper)
{
hitInfo.isSniperHit = IsSniperTargetHit(in hitInfo);
}
return hitCallback(this, ref hitInfo);
}
private static bool IsSniperTargetHit(in BulletHit hitInfo)
{
if ((bool)hitInfo.hitHurtBox && (bool)hitInfo.hitHurtBox.hurtBoxGroup)
{
HurtBox[] hurtBoxes = hitInfo.hitHurtBox.hurtBoxGroup.hurtBoxes;
foreach (HurtBox hurtBox in hurtBoxes)
{
if ((bool)hurtBox && hurtBox.isSniperTarget && Vector3.ProjectOnPlane(hitInfo.point - hurtBox.transform.position, hitInfo.direction).sqrMagnitude <= HurtBox.sniperTargetRadiusSqr)
{
return true;
}
}
}
return false;
}
private GameObject ProcessHitList(List<BulletHit> hits, ref Vector3 endPosition, List<GameObject> ignoreList)
{
int count = hits.Count;
int[] array = new int[count];
for (int i = 0; i < count; i++)
{
array[i] = i;
}
for (int j = 0; j < count; j++)
{
float distance = maxDistance;
int num = j;
for (int k = j; k < count; k++)
{
int index = array[k];
if (hits[index].distance < distance)
{
distance = hits[index].distance;
num = k;
}
}
GameObject entityObject = hits[array[num]].entityObject;
if (!ignoreList.Contains(entityObject))
{
ignoreList.Add(entityObject);
BulletHit hitInfo = hits[array[num]];
if (!ProcessHit(ref hitInfo))
{
endPosition = hits[array[num]].point;
return entityObject;
}
}
array[num] = array[j];
}
return null;
}
private static GameObject LookUpColliderEntityObject(Collider collider)
{
HurtBox component = collider.GetComponent<HurtBox>();
if (!component || !component.healthComponent)
{
return collider.gameObject;
}
return component.healthComponent.gameObject;
}
private static Collider[] PhysicsOverlapPoint(Vector3 point, int layerMask = -1, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.Ignore)
{
return Physics.OverlapBox(point, Vector3.zero, Quaternion.identity, layerMask, queryTriggerInteraction);
}
public void Fire()
{
if (allowTrajectoryAimAssist)
{
aimVector = TrajectoryAimAssist.ApplyTrajectoryAimAssist(aimVector, origin, maxDistance, owner, weapon, trajectoryAimAssistMultiplier);
}
Vector3[] array = new Vector3[bulletCount];
Vector3 up = Vector3.up;
Vector3 axis = Vector3.Cross(up, aimVector);
for (int i = 0; i < bulletCount; i++)
{
float x = UnityEngine.Random.Range(minSpread, maxSpread);
float z = UnityEngine.Random.Range(0f, 360f);
Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward);
float y = vector.y;
vector.y = 0f;
float angle = (Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f) * spreadYawScale;
float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f * spreadPitchScale;
array[i] = Quaternion.AngleAxis(angle, up) * (Quaternion.AngleAxis(angle2, axis) * aimVector);
}
int muzzleIndex = -1;
if (!weapon)
{
weapon = owner;
}
if ((bool)weapon)
{
ModelLocator component = weapon.GetComponent<ModelLocator>();
if ((bool)component && (bool)component.modelTransform)
{
ChildLocator component2 = component.modelTransform.GetComponent<ChildLocator>();
if ((bool)component2)
{
muzzleIndex = component2.FindChildIndex(muzzleName);
}
}
}
Vector3 axis2 = Vector3.Cross(Vector3.up, aimVector);
Vector3 forward = Vector3.forward;
if (cheapMultiBullet)
{
float x2 = UnityEngine.Random.Range(minSpread, maxSpread);
float z2 = UnityEngine.Random.Range(0f, 360f);
Vector3 vector2 = Quaternion.Euler(0f, 0f, z2) * (Quaternion.Euler(x2, 0f, 0f) * Vector3.forward);
float y2 = vector2.y;
vector2.y = 0f;
float angle3 = (Mathf.Atan2(vector2.z, vector2.x) * 57.29578f - 90f) * spreadYawScale;
float angle4 = Mathf.Atan2(y2, vector2.magnitude) * 57.29578f * spreadPitchScale;
forward = Quaternion.AngleAxis(angle3, Vector3.up) * (Quaternion.AngleAxis(angle4, axis2) * aimVector);
FireMulti(forward, muzzleIndex);
return;
}
for (int j = 0; j < bulletCount; j++)
{
float x3 = UnityEngine.Random.Range(minSpread, maxSpread);
float z3 = UnityEngine.Random.Range(0f, 360f);
Vector3 vector3 = Quaternion.Euler(0f, 0f, z3) * (Quaternion.Euler(x3, 0f, 0f) * Vector3.forward);
float y3 = vector3.y;
vector3.y = 0f;
float angle5 = (Mathf.Atan2(vector3.z, vector3.x) * 57.29578f - 90f) * spreadYawScale;
float angle6 = Mathf.Atan2(y3, vector3.magnitude) * 57.29578f * spreadPitchScale;
forward = Quaternion.AngleAxis(angle5, Vector3.up) * (Quaternion.AngleAxis(angle6, axis2) * aimVector);
FireSingle(forward, muzzleIndex);
}
}
public Vector3 Fire_ReturnHit()
{
int muzzleIndex = -1;
_ = origin;
if (!weapon)
{
weapon = owner;
}
if ((bool)weapon)
{
ModelLocator component = weapon.GetComponent<ModelLocator>();
if ((bool)component && (bool)component.modelTransform)
{
ChildLocator component2 = component.modelTransform.GetComponent<ChildLocator>();
if ((bool)component2)
{
muzzleIndex = component2.FindChildIndex(muzzleName);
}
}
}
Vector3 axis = Vector3.Cross(Vector3.up, aimVector);
Vector3 forward = Vector3.forward;
Vector3 result = Vector3.zero;
for (int i = 0; i < bulletCount; i++)
{
float x = UnityEngine.Random.Range(minSpread, maxSpread);
float z = UnityEngine.Random.Range(0f, 360f);
Vector3 vector = Quaternion.Euler(0f, 0f, z) * (Quaternion.Euler(x, 0f, 0f) * Vector3.forward);
float y = vector.y;
vector.y = 0f;
float angle = (Mathf.Atan2(vector.z, vector.x) * 57.29578f - 90f) * spreadYawScale;
float angle2 = Mathf.Atan2(y, vector.magnitude) * 57.29578f * spreadPitchScale;
forward = Quaternion.AngleAxis(angle, Vector3.up) * (Quaternion.AngleAxis(angle2, axis) * aimVector);
result = FireSingle_ReturnHit(forward, muzzleIndex);
}
return result;
}
public static void TogglePooling()
{
_UsePools = !_UsePools;
Debug.LogFormat("BulletAttack pooling {0}", _UsePools ? "ENABLED" : "DISABLED");
}
public static void DumpPools()
{
Debug.LogFormat("BulletAttack Pool: Pooled {0}, InUse {1}", _BulletHitPool.PoolCount(), _BulletHitPool.InUseCount());
}
protected static BulletHit GetBulletHit()
{
BulletHit @object = _BulletHitPool.GetObject();
@object.Reset();
return @object;
}
private void FireSingle(Vector3 normal, int muzzleIndex)
{
if (_UsePools)
{
float distance = maxDistance;
Vector3 endPosition = origin + normal * maxDistance;
_BulletHits.Clear();
bool num = radius == 0f || smartCollision;
bool flag = radius != 0f;
if (smartCollision)
{
_EncounteredEntityObjects.Clear();
}
if (num)
{
int num2 = 0;
num2 = HGPhysics.RaycastAll(out var hits, origin, normal, distance, hitMask, queryTriggerInteraction);
for (int i = 0; i < num2; i++)
{
BulletHit bulletHit = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit, origin, normal, ref hits[i]);
_BulletHits.Add(bulletHit);
if (smartCollision)
{
_EncounteredEntityObjects.Add(bulletHit.entityObject);
}
if (bulletHit.distance < distance)
{
distance = bulletHit.distance;
}
}
HGPhysics.ReturnResults(hits);
}
if (flag)
{
LayerMask layerMask = hitMask;
if (smartCollision)
{
layerMask = (int)layerMask & ~(int)LayerIndex.world.mask;
}
int num3 = 0;
num3 = HGPhysics.SphereCastAll(out var hits2, origin, radius, normal, distance, layerMask, queryTriggerInteraction);
for (int j = 0; j < num3; j++)
{
BulletHit bulletHit2 = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit2, origin, normal, ref hits2[j]);
if (!smartCollision || !_EncounteredEntityObjects.Contains(bulletHit2.entityObject))
{
_BulletHits.Add(bulletHit2);
}
}
HGPhysics.ReturnResults(hits2);
}
_IgnoreList.Clear();
ProcessHitList(_BulletHits, ref endPosition, _IgnoreList);
if ((bool)tracerEffectPrefab)
{
if (_effectData == null)
{
_effectData = new EffectData();
}
_effectData.Reset();
_effectData.origin = endPosition;
_effectData.start = origin;
_effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, _effectData, transmit: true);
}
_BulletHitPool.ReturnAllInUse();
_EncounteredEntityObjects.Clear();
return;
}
float distance2 = maxDistance;
Vector3 endPosition2 = origin + normal * maxDistance;
List<BulletHit> list = new List<BulletHit>();
bool num4 = radius == 0f || smartCollision;
bool flag2 = radius != 0f;
HashSet<GameObject> hashSet = null;
if (smartCollision)
{
hashSet = new HashSet<GameObject>();
}
if (num4)
{
int num5 = 0;
num5 = HGPhysics.RaycastAll(out var hits3, origin, normal, distance2, hitMask, queryTriggerInteraction);
for (int k = 0; k < num5; k++)
{
BulletHit bulletHit3 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit3, origin, normal, ref hits3[k]);
list.Add(bulletHit3);
if (smartCollision)
{
hashSet.Add(bulletHit3.entityObject);
}
if (bulletHit3.distance < distance2)
{
distance2 = bulletHit3.distance;
}
}
HGPhysics.ReturnResults(hits3);
}
if (flag2)
{
LayerMask layerMask2 = hitMask;
if (smartCollision)
{
layerMask2 = (int)layerMask2 & ~(int)LayerIndex.world.mask;
}
int num6 = 0;
num6 = HGPhysics.SphereCastAll(out var hits4, origin, radius, normal, distance2, layerMask2, queryTriggerInteraction);
for (int l = 0; l < num6; l++)
{
BulletHit bulletHit4 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit4, origin, normal, ref hits4[l]);
if (!smartCollision || !hashSet.Contains(bulletHit4.entityObject))
{
list.Add(bulletHit4);
}
}
HGPhysics.ReturnResults(hits4);
}
ProcessHitList(list, ref endPosition2, new List<GameObject>());
if ((bool)tracerEffectPrefab)
{
EffectData effectData = new EffectData
{
origin = endPosition2,
start = origin
};
effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true);
}
}
private void FireMulti(Vector3 normal, int muzzleIndex)
{
if (_UsePools)
{
float distance = maxDistance;
Vector3 endPosition = origin + normal * maxDistance;
_BulletHits.Clear();
bool num = radius == 0f || smartCollision;
bool flag = radius != 0f;
if (smartCollision)
{
_EncounteredEntityObjects.Clear();
}
if (num)
{
int num2 = 0;
num2 = HGPhysics.RaycastAll(out var hits, origin, normal, distance, hitMask, queryTriggerInteraction);
for (int i = 0; i < num2; i++)
{
BulletHit bulletHit = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit, origin, normal, ref hits[i]);
_BulletHits.Add(bulletHit);
if (smartCollision)
{
_EncounteredEntityObjects.Add(bulletHit.entityObject);
}
if (bulletHit.distance < distance)
{
distance = bulletHit.distance;
}
}
HGPhysics.ReturnResults(hits);
}
if (flag)
{
LayerMask layerMask = hitMask;
if (smartCollision)
{
layerMask = (int)layerMask & ~(int)LayerIndex.world.mask;
}
int num3 = 0;
num3 = HGPhysics.SphereCastAll(out var hits2, origin, radius, normal, distance, layerMask, queryTriggerInteraction);
for (int j = 0; j < num3; j++)
{
BulletHit bulletHit2 = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit2, origin, normal, ref hits2[j]);
if (!smartCollision || !_EncounteredEntityObjects.Contains(bulletHit2.entityObject))
{
_BulletHits.Add(bulletHit2);
}
}
HGPhysics.ReturnResults(hits2);
}
_IgnoreList.Clear();
ProcessHitList(_BulletHits, ref endPosition, _IgnoreList);
if ((bool)tracerEffectPrefab)
{
if (_effectData == null)
{
_effectData = new EffectData();
}
_effectData.Reset();
_effectData.origin = endPosition;
_effectData.start = origin;
_effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, _effectData, transmit: true);
}
_BulletHitPool.ReturnAllInUse();
_EncounteredEntityObjects.Clear();
return;
}
float distance2 = maxDistance;
Vector3 endPosition2 = origin + normal * maxDistance;
List<BulletHit> list = new List<BulletHit>();
bool num4 = radius == 0f || smartCollision;
bool flag2 = radius != 0f;
HashSet<GameObject> hashSet = null;
if (smartCollision)
{
hashSet = new HashSet<GameObject>();
}
if (num4)
{
int num5 = 0;
num5 = HGPhysics.RaycastAll(out var hits3, origin, normal, distance2, hitMask, queryTriggerInteraction);
for (int k = 0; k < num5; k++)
{
BulletHit bulletHit3 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit3, origin, normal, ref hits3[k]);
list.Add(bulletHit3);
if (smartCollision)
{
hashSet.Add(bulletHit3.entityObject);
}
if (bulletHit3.distance < distance2)
{
distance2 = bulletHit3.distance;
}
}
HGPhysics.ReturnResults(hits3);
}
if (flag2)
{
LayerMask layerMask2 = hitMask;
if (smartCollision)
{
layerMask2 = (int)layerMask2 & ~(int)LayerIndex.world.mask;
}
int num6 = 0;
num6 = HGPhysics.SphereCastAll(out var hits4, origin, radius, normal, distance2, layerMask2, queryTriggerInteraction);
for (int l = 0; l < num6; l++)
{
BulletHit bulletHit4 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit4, origin, normal, ref hits4[l]);
if (!smartCollision || !hashSet.Contains(bulletHit4.entityObject))
{
list.Add(bulletHit4);
}
}
HGPhysics.ReturnResults(hits4);
}
ProcessHitList(list, ref endPosition2, new List<GameObject>());
if ((bool)tracerEffectPrefab)
{
EffectData effectData = new EffectData
{
origin = endPosition2,
start = origin
};
effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true);
}
}
private Vector3 FireSingle_ReturnHit(Vector3 normal, int muzzleIndex)
{
Vector3 endPosition;
if (_UsePools)
{
float distance = maxDistance;
endPosition = origin + normal * maxDistance;
_BulletHits.Clear();
bool num = radius == 0f || smartCollision;
bool flag = radius != 0f;
if (smartCollision)
{
_EncounteredEntityObjects.Clear();
}
if (num)
{
int num2 = 0;
num2 = HGPhysics.RaycastAll(out var hits, origin, normal, distance, hitMask, queryTriggerInteraction);
for (int i = 0; i < num2; i++)
{
BulletHit bulletHit = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit, origin, normal, ref hits[i]);
_BulletHits.Add(bulletHit);
if (smartCollision)
{
_EncounteredEntityObjects.Add(bulletHit.entityObject);
}
if (bulletHit.distance < distance)
{
distance = bulletHit.distance;
}
}
HGPhysics.ReturnResults(hits);
}
if (flag)
{
LayerMask layerMask = hitMask;
if (smartCollision)
{
layerMask = (int)layerMask & ~(int)LayerIndex.world.mask;
}
int num3 = 0;
num3 = HGPhysics.SphereCastAll(out var hits2, origin, radius, normal, distance, layerMask, queryTriggerInteraction);
for (int j = 0; j < num3; j++)
{
BulletHit bulletHit2 = GetBulletHit();
InitBulletHitFromRaycastHit(ref bulletHit2, origin, normal, ref hits2[j]);
if (!smartCollision || !_EncounteredEntityObjects.Contains(bulletHit2.entityObject))
{
_BulletHits.Add(bulletHit2);
}
}
HGPhysics.ReturnResults(hits2);
}
_IgnoreList.Clear();
ProcessHitList(_BulletHits, ref endPosition, _IgnoreList);
if ((bool)tracerEffectPrefab)
{
if (_effectData == null)
{
_effectData = new EffectData();
}
_effectData.Reset();
_effectData.origin = endPosition;
_effectData.start = origin;
_effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, _effectData, transmit: true);
}
_BulletHitPool.ReturnAllInUse();
_EncounteredEntityObjects.Clear();
}
else
{
float distance2 = maxDistance;
endPosition = origin + normal * maxDistance;
List<BulletHit> list = new List<BulletHit>();
bool num4 = radius == 0f || smartCollision;
bool flag2 = radius != 0f;
HashSet<GameObject> hashSet = null;
if (smartCollision)
{
hashSet = new HashSet<GameObject>();
}
if (num4)
{
int num5 = 0;
num5 = HGPhysics.RaycastAll(out var hits3, origin, normal, distance2, hitMask, queryTriggerInteraction);
for (int k = 0; k < num5; k++)
{
BulletHit bulletHit3 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit3, origin, normal, ref hits3[k]);
list.Add(bulletHit3);
if (smartCollision)
{
hashSet.Add(bulletHit3.entityObject);
}
if (bulletHit3.distance < distance2)
{
distance2 = bulletHit3.distance;
}
}
HGPhysics.ReturnResults(hits3);
}
if (flag2)
{
LayerMask layerMask2 = hitMask;
if (smartCollision)
{
layerMask2 = (int)layerMask2 & ~(int)LayerIndex.world.mask;
}
int num6 = 0;
num6 = HGPhysics.SphereCastAll(out var hits4, origin, radius, normal, distance2, layerMask2, queryTriggerInteraction);
for (int l = 0; l < num6; l++)
{
BulletHit bulletHit4 = new BulletHit();
InitBulletHitFromRaycastHit(ref bulletHit4, origin, normal, ref hits4[l]);
if (!smartCollision || !hashSet.Contains(bulletHit4.entityObject))
{
list.Add(bulletHit4);
}
}
HGPhysics.ReturnResults(hits4);
}
ProcessHitList(list, ref endPosition, new List<GameObject>());
if ((bool)tracerEffectPrefab)
{
EffectData effectData = new EffectData
{
origin = endPosition,
start = origin
};
effectData.SetChildLocatorTransformReference(weapon, muzzleIndex);
EffectManager.SpawnEffect(tracerEffectPrefab, effectData, transmit: true);
}
}
return endPosition;
}
[NetworkMessageHandler(msgType = 53, server = true)]
private static void HandleBulletDamage(NetworkMessage netMsg)
{
NetworkReader reader = netMsg.reader;
GameObject gameObject = reader.ReadGameObject();
DamageInfo damageInfo = reader.ReadDamageInfo();
if (reader.ReadBoolean() && (bool)gameObject)
{
HealthComponent component = gameObject.GetComponent<HealthComponent>();
if ((bool)component)
{
component.TakeDamage(damageInfo);
}
GlobalEventManager.instance.OnHitEnemy(damageInfo, gameObject);
}
GlobalEventManager.instance.OnHitAll(damageInfo, gameObject);
}
}