r2mods/ilspy_dump/ror2_csproj/RoR2/BodySplitter.cs

174 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace RoR2;
public class BodySplitter
{
public CharacterBody body;
public float moneyMultiplier;
private int _count = 1;
public readonly MasterSummon masterSummon;
private Dictionary<CharacterBody, Vector3> spawnedBodyVelocity = new Dictionary<CharacterBody, Vector3>();
public int count
{
get
{
return _count;
}
set
{
if (value <= 0)
{
throw new ArgumentException("'value' cannot be non-positive.", "value");
}
_count = value;
}
}
public Vector3 splinterInitialVelocityLocal { get; set; } = Vector3.zero;
public float minSpawnCircleRadius { get; set; }
public BodySplitter()
{
masterSummon = new MasterSummon
{
masterPrefab = null,
ignoreTeamMemberLimit = false,
useAmbientLevel = null,
teamIndexOverride = null
};
}
public void Perform()
{
PerformInternal(masterSummon);
}
private void PerformInternal(MasterSummon masterSummon)
{
if ((object)body == null)
{
throw new InvalidOperationException("'body' is null.");
}
if (!body)
{
throw new InvalidOperationException("'body' is an invalid object.");
}
GameObject masterPrefab = masterSummon.masterPrefab;
CharacterMaster obj = masterPrefab.GetComponent<CharacterMaster>() ?? throw new InvalidOperationException("'splinterMasterPrefab' does not have a CharacterMaster component.");
if (!obj.masterIndex.isValid)
{
throw new InvalidOperationException("'splinterMasterPrefab' is not registered with MasterCatalog.");
}
if ((object)MasterCatalog.GetMasterPrefab(obj.masterIndex) != masterPrefab)
{
throw new InvalidOperationException("'splinterMasterPrefab' is not a prefab.");
}
Vector3 position = body.transform.position;
float y = Quaternion.LookRotation(body.inputBank.aimDirection).eulerAngles.y;
GameObject bodyPrefab = obj.bodyPrefab;
bodyPrefab.GetComponent<CharacterBody>();
float num = CalcBodyXZRadius(bodyPrefab);
float a = 0f;
if (count > 1)
{
a = num / Mathf.Sin(MathF.PI / (float)count);
}
a = Mathf.Max(a, minSpawnCircleRadius);
masterSummon.summonerBodyObject = body.gameObject;
masterSummon.inventoryToCopy = body.inventory;
masterSummon.loadout = (body.master ? body.master.loadout : null);
masterSummon.inventoryItemCopyFilter = CopyItemFilter;
foreach (float item in new DegreeSlices(count, 0.5f))
{
Quaternion quaternion = Quaternion.Euler(0f, y + item + 180f, 0f);
Vector3 vector = quaternion * Vector3.forward;
float num2 = a;
if (Physics.Raycast(new Ray(position, vector), out var hitInfo, a + num, LayerIndex.world.intVal, QueryTriggerInteraction.Ignore))
{
num2 = hitInfo.distance - num;
}
Vector3 position2 = position + vector * num2;
masterSummon.position = position2;
masterSummon.rotation = quaternion;
try
{
CharacterMaster characterMaster = masterSummon.Perform();
if ((bool)characterMaster)
{
CharacterBody characterBody = characterMaster.GetBody();
if ((bool)characterBody)
{
spawnedBodyVelocity.Add(characterBody, quaternion * splinterInitialVelocityLocal);
characterMaster.money = (uint)Mathf.FloorToInt((float)body.master.money * moneyMultiplier);
characterBody.characterMotor.onMotorStart += OnCharacterMotorStart;
}
}
}
catch (Exception message)
{
Debug.LogError(message);
}
}
}
private void OnCharacterMotorStart(CharacterBody characterBody)
{
if (spawnedBodyVelocity.TryGetValue(characterBody, out var value))
{
AddBodyVelocity(characterBody, value);
}
else
{
Debug.LogError("Split characterBody has not stored split velocity");
}
}
private static float CalcBodyXZRadius(GameObject bodyPrefab)
{
Collider component = bodyPrefab.GetComponent<Collider>();
if (!component)
{
return 0f;
}
Vector3 position = bodyPrefab.transform.position;
Bounds bounds = component.bounds;
Vector3 min = bounds.min;
Vector3 max = bounds.max;
return Mathf.Max(Mathf.Max(Mathf.Max(Mathf.Max(0f, position.x - min.x), position.z - min.z), max.x - position.x), max.z - position.z);
}
private static void AddBodyVelocity(CharacterBody body, Vector3 additionalVelocity)
{
IPhysMotor component = body.GetComponent<IPhysMotor>();
if (component != null)
{
PhysForceInfo physForceInfo = PhysForceInfo.Create();
physForceInfo.force = additionalVelocity;
physForceInfo.massIsOne = true;
physForceInfo.ignoreGroundStick = true;
physForceInfo.disableAirControlUntilCollision = false;
component.ApplyForceImpulse(in physForceInfo);
}
}
private static bool CopyItemFilter(ItemIndex itemIndex)
{
ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
if ((bool)itemDef)
{
return itemDef.tier == ItemTier.NoTier;
}
return false;
}
}