141 lines
4.0 KiB
C#
141 lines
4.0 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
|
|
namespace RoR2;
|
|
|
|
[RequireComponent(typeof(CombatSquad))]
|
|
public class ScriptedCombatEncounter : MonoBehaviour
|
|
{
|
|
[Serializable]
|
|
public struct SpawnInfo
|
|
{
|
|
public SpawnCard spawnCard;
|
|
|
|
public Transform explicitSpawnPosition;
|
|
|
|
[Tooltip("The chance that this spawn card will be culled, removing it from the list. A value of 0 means it is guaranteed.")]
|
|
[Range(0f, 100f)]
|
|
public float cullChance;
|
|
}
|
|
|
|
public ulong seed;
|
|
|
|
public bool randomizeSeed;
|
|
|
|
public TeamIndex teamIndex;
|
|
|
|
public SpawnInfo[] spawns;
|
|
|
|
public bool spawnOnStart;
|
|
|
|
public bool grantUniqueBonusScaling = true;
|
|
|
|
private Xoroshiro128Plus rng;
|
|
|
|
public CombatSquad combatSquad { get; private set; }
|
|
|
|
public bool hasSpawnedServer { get; private set; }
|
|
|
|
public event Action<ScriptedCombatEncounter> onBeginEncounter;
|
|
|
|
private void Awake()
|
|
{
|
|
combatSquad = GetComponent<CombatSquad>();
|
|
hasSpawnedServer = false;
|
|
if (NetworkServer.active)
|
|
{
|
|
rng = new Xoroshiro128Plus(randomizeSeed ? Run.instance.stageRng.nextUlong : seed);
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (NetworkServer.active && spawnOnStart)
|
|
{
|
|
BeginEncounter();
|
|
}
|
|
}
|
|
|
|
private void Spawn(ref SpawnInfo spawnInfo)
|
|
{
|
|
Vector3 position = base.transform.position;
|
|
DirectorPlacementRule directorPlacementRule = new DirectorPlacementRule
|
|
{
|
|
placementMode = DirectorPlacementRule.PlacementMode.NearestNode,
|
|
minDistance = 0f,
|
|
maxDistance = 1000f,
|
|
position = position
|
|
};
|
|
if ((bool)spawnInfo.explicitSpawnPosition)
|
|
{
|
|
directorPlacementRule.placementMode = DirectorPlacementRule.PlacementMode.Direct;
|
|
directorPlacementRule.spawnOnTarget = spawnInfo.explicitSpawnPosition;
|
|
}
|
|
DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(spawnInfo.spawnCard, directorPlacementRule, rng);
|
|
directorSpawnRequest.ignoreTeamMemberLimit = true;
|
|
directorSpawnRequest.teamIndexOverride = teamIndex;
|
|
directorSpawnRequest.onSpawnedServer = (Action<SpawnCard.SpawnResult>)Delegate.Combine(directorSpawnRequest.onSpawnedServer, new Action<SpawnCard.SpawnResult>(HandleSpawn));
|
|
DirectorCore.instance.TrySpawnObject(directorSpawnRequest);
|
|
void HandleSpawn(SpawnCard.SpawnResult spawnResult)
|
|
{
|
|
GameObject spawnedInstance = spawnResult.spawnedInstance;
|
|
if ((bool)spawnedInstance)
|
|
{
|
|
hasSpawnedServer = true;
|
|
CharacterMaster component = spawnedInstance.GetComponent<CharacterMaster>();
|
|
if (grantUniqueBonusScaling)
|
|
{
|
|
float num = 1f;
|
|
float num2 = 1f;
|
|
num += Run.instance.difficultyCoefficient / 2.5f;
|
|
num2 += Run.instance.difficultyCoefficient / 30f;
|
|
int num3 = Mathf.Max(1, Run.instance.livingPlayerCount);
|
|
num *= Mathf.Pow(num3, 0.5f);
|
|
Debug.LogFormat("Scripted Combat Encounter: currentBoostHpCoefficient={0}, currentBoostDamageCoefficient={1}", num, num2);
|
|
component.inventory.GiveItem(RoR2Content.Items.BoostHp, Mathf.RoundToInt((num - 1f) * 10f));
|
|
component.inventory.GiveItem(RoR2Content.Items.BoostDamage, Mathf.RoundToInt((num2 - 1f) * 10f));
|
|
}
|
|
if (RunArtifactManager.instance.IsArtifactEnabled(RoR2Content.Artifacts.eliteOnlyArtifactDef))
|
|
{
|
|
EliteDef[] array = new EliteDef[4]
|
|
{
|
|
RoR2Content.Elites.Fire,
|
|
RoR2Content.Elites.Lightning,
|
|
RoR2Content.Elites.Ice,
|
|
DLC1Content.Elites.Earth
|
|
};
|
|
int num4 = rng.RangeInt(0, array.Length);
|
|
EquipmentIndex equipmentIndex = array[num4]?.eliteEquipmentDef?.equipmentIndex ?? EquipmentIndex.None;
|
|
if (equipmentIndex != EquipmentIndex.None)
|
|
{
|
|
component.inventory.SetEquipmentIndex(equipmentIndex);
|
|
}
|
|
}
|
|
combatSquad.AddMember(component);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogFormat("No spawned master from combat group!");
|
|
}
|
|
}
|
|
}
|
|
|
|
public void BeginEncounter()
|
|
{
|
|
if (hasSpawnedServer || !NetworkServer.active)
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < spawns.Length; i++)
|
|
{
|
|
ref SpawnInfo reference = ref spawns[i];
|
|
if (!(rng.nextNormalizedFloat * 100f < reference.cullChance))
|
|
{
|
|
Spawn(ref reference);
|
|
}
|
|
}
|
|
this.onBeginEncounter?.Invoke(this);
|
|
}
|
|
}
|