Redid vent code to work better and like work in general. Knight animation now pauses for a second. Knights no longer trigger the default scarlet vent animation. Revenants now spawn at a vent if no knights exist.
234 lines
8.1 KiB
C#
234 lines
8.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using Unity.Netcode;
|
|
using DunGen;
|
|
using ScarletMansion.Lights;
|
|
using ScarletMansion.GamePatch.Managers;
|
|
using GameNetcodeStuff;
|
|
using ScarletMansion.Configs;
|
|
|
|
namespace ScarletMansion.GamePatch.Components {
|
|
public class ScarletBedroom : MonoBehaviour, IDungeonCompleteReceiver {
|
|
|
|
public const string ENEMY_SPAWN_LIST_DEFAULT = "knight@s1,crawler,nutcracker,springman,maskedplayerenemy,jester@s1,butler";
|
|
public static readonly string[] ENEMY_EVIL_LIST = new string[] { "knight", "crawler", "nutcracker", "springman" ,"maskedplayerenemy" ,"jester", "butler" };
|
|
|
|
public static ActionList onBedroomEndEvent = new ActionList("onBedroomEnd");
|
|
|
|
[Header("References")]
|
|
public ScarletVentVisuals vent;
|
|
public Transform paintingSpawnTransform;
|
|
public AudioSource screamAudioSource;
|
|
public Transform[] itemSpawns;
|
|
|
|
private Light[] lights;
|
|
private Doorway[] doorways;
|
|
private ItemReference[] bonusItems;
|
|
private EnemyReferenceSpawnLogic bonusEnemy;
|
|
|
|
const float spawnTime = 10f;
|
|
const float cloudTime = 7f;
|
|
|
|
public void Anger(Transform target){
|
|
AngerManager.Instance.Anger();
|
|
StartCoroutine(PlayAudio());
|
|
StartCoroutine(IncreaseVentAudio());
|
|
StartCoroutine(LockDoorAndSpawnEnemy(target));
|
|
|
|
foreach(var l in lights){
|
|
StartCoroutine(FlickerLight(l));
|
|
}
|
|
}
|
|
|
|
public IEnumerator PlayAudio(){
|
|
yield return new WaitForSeconds(UnityEngine.Random.Range(0.75f, 1f));
|
|
screamAudioSource.Play();
|
|
AngerManager.Instance.TriggerAngerLightBrief(6f);
|
|
|
|
var local = StartOfRound.Instance.localPlayerController;
|
|
var dist = Vector3.SqrMagnitude(local.transform.position - transform.position);
|
|
if (dist < 12f * 12f)
|
|
local.JumpToFearLevel(0.75f);
|
|
else if (dist < 24f * 24f)
|
|
local.JumpToFearLevel(0.5f);
|
|
else if (dist < 32f * 32f)
|
|
local.JumpToFearLevel(0.25f);
|
|
}
|
|
|
|
public IEnumerator LockDoorAndSpawnEnemy(Transform target){
|
|
var roundmanager = RoundManager.Instance;
|
|
var doors = new List<ScarletDoor>();
|
|
|
|
// lock doors
|
|
if (roundmanager.IsServer){
|
|
foreach(var d in doorways){
|
|
var result = ScarletGenericManager.Instance.GetScarletDoor(d.transform.position);
|
|
if (result) doors.Add(result);
|
|
}
|
|
|
|
foreach(var d in doors){
|
|
d.LockDoorClientRpc();
|
|
}
|
|
}
|
|
|
|
yield return new WaitForSeconds(spawnTime);
|
|
|
|
SpawnRandomEnemy(target);
|
|
SpawnLoot();
|
|
|
|
onBedroomEndEvent.Call();
|
|
|
|
// stop volume stuff
|
|
vent.StopSpawnParticles();
|
|
vent.StopLightningParticles();
|
|
ScarletNetworkManager.Instance.CreateSpawnAudioPrefabLocal(target.transform.position);
|
|
|
|
// unlock doors
|
|
if (roundmanager.IsServer){
|
|
foreach(var d in doors){
|
|
d.UnlockDoorClientRpc();
|
|
}
|
|
}
|
|
}
|
|
|
|
public IEnumerator IncreaseVentAudio(){
|
|
yield return new WaitForSeconds(3f);
|
|
|
|
vent.StartSpawnParticles();
|
|
var t = 0f;
|
|
while (t < cloudTime){
|
|
t += Time.deltaTime;
|
|
vent.SetVolumeLazy(t / cloudTime);
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
public IEnumerator FlickerLight(Light light){
|
|
// gives time for player to react to their environment
|
|
yield return new WaitForSeconds(UnityEngine.Random.Range(1f, 1.5f));
|
|
|
|
// scarlet lights flicker
|
|
var scarletLight = light.GetComponent<ScarletLight>();
|
|
if (scarletLight != null){
|
|
scarletLight.SetFlickeringState(ScarletLight.FlickeringState.Heavy);
|
|
}
|
|
// normal lights are candles, so just turn them off
|
|
else {
|
|
yield return new WaitForSeconds(UnityEngine.Random.Range(3f, 5f));
|
|
light.enabled = false;
|
|
}
|
|
}
|
|
|
|
private static List<EnemyReferenceSpawnLogic> spawnableEnemiesTrueList;
|
|
|
|
public static void CreateRandomEnemyList(List<SpawnableEnemyWithRarity> enemies){
|
|
var lower = ConfigMain.Instance.paintingEnemyListValue.ToLowerInvariant();
|
|
if (lower == "default"){
|
|
lower = ENEMY_SPAWN_LIST_DEFAULT;
|
|
}
|
|
|
|
spawnableEnemiesTrueList = new List<EnemyReferenceSpawnLogic>();
|
|
var entries = Utility.ParseString(lower, new string[] {","}, new string[] {"@"} );
|
|
for(var i = 0; i < enemies.Count; ++i){
|
|
var enemyType = enemies[i].enemyType;
|
|
var enemyName = enemyType.name.ToLowerInvariant();
|
|
var enemyDisplayName = enemyType.enemyName.ToLowerInvariant();
|
|
|
|
var link = entries.FirstOrDefault(e => e.main == enemyName || e.main == enemyDisplayName);
|
|
if (link != null){
|
|
EnemyReferenceSpawnLogic.SpawnLogic spawnValue;
|
|
var spawnTag = link.GetParameter("s");
|
|
if (spawnTag != null) spawnValue = (EnemyReferenceSpawnLogic.SpawnLogic)Utility.TryParseInt(spawnTag.Substring(1), 0);
|
|
else spawnValue = 0;
|
|
|
|
var reference = new EnemyReferenceSpawnLogic(enemyType, i, spawnValue);
|
|
spawnableEnemiesTrueList.Add(reference);
|
|
Plugin.logger.LogDebug($"Added {reference.ToString()} to bedroom event");
|
|
}
|
|
}
|
|
}
|
|
|
|
public EnemyReferenceSpawnLogic GetRandomEnemy(System.Random sysRandom){
|
|
var roundManager = RoundManager.Instance;
|
|
if (!roundManager.IsServer) return null;
|
|
if (!ConfigMain.Instance.paintingSpawnEnemyValue) return null;
|
|
|
|
if (spawnableEnemiesTrueList == null || spawnableEnemiesTrueList.Count == 0){
|
|
Plugin.logger.LogError($"Could not select enemy to spawn in bedroom. Empty enemy list?");
|
|
return null;
|
|
}
|
|
|
|
var index = sysRandom.Next(spawnableEnemiesTrueList.Count);
|
|
var enemy = spawnableEnemiesTrueList[index];
|
|
Plugin.logger.LogDebug($"Selected enemy to spawn {enemy.ToString()}");
|
|
return enemy;
|
|
}
|
|
|
|
public void SpawnRandomEnemy(Transform target, int overrideIndex = -1){
|
|
var roundmanager = RoundManager.Instance;
|
|
if (!roundmanager.IsHost) return;
|
|
if (bonusEnemy == null) return;
|
|
|
|
try {
|
|
var enemy = bonusEnemy.enemy;
|
|
|
|
if (bonusEnemy.index > -1){
|
|
var pos = vent.transform.position;
|
|
var dir = target.transform.position - pos;
|
|
dir.y = 0f;
|
|
var rot = Quaternion.LookRotation(dir);
|
|
var y = rot.eulerAngles.y;
|
|
|
|
bonusEnemy.ApplySpawnLogic();
|
|
|
|
roundmanager.currentEnemyPower += enemy.PowerLevel;
|
|
var spawnedEnemy = ScarletNetworkManagerUtility.CreateEnemyWithRef(bonusEnemy, pos, y);
|
|
|
|
ScarletNetworkManager.Instance.RequestEvilSkinApply(spawnedEnemy, enemy.name.ToLowerInvariant());
|
|
}
|
|
} catch (Exception e) {
|
|
var enemyString = bonusEnemy != null ? bonusEnemy.ToString() : "NULL";
|
|
Plugin.logger.LogError($"Failed to spawn enemy for bedroom event, the smelly culprit is {enemyString}");
|
|
Plugin.logger.LogError(e.ToString());
|
|
}
|
|
|
|
}
|
|
|
|
public void SpawnLoot(){
|
|
var roundmanager = RoundManager.Instance;
|
|
if (!roundmanager.IsServer) return;
|
|
|
|
try {
|
|
AngerManager.SpawnAngerLoot(bonusItems, itemSpawns);
|
|
} catch (Exception e) {
|
|
var itemStrings = string.Join("\n", bonusItems.Select(i => i != null ? i.ToString() : "NULL"));
|
|
Plugin.logger.LogError($"Failed to spawn items for bedroom event, the smelly culprits are {itemStrings}");
|
|
Plugin.logger.LogError(e.ToString());
|
|
}
|
|
}
|
|
|
|
public void OnDungeonComplete(Dungeon dungeon) {
|
|
ScarletGenericManager.Instance.AddBedroom(this);
|
|
ScarletGenericManager.Instance.AddRoomOfInterest(transform);
|
|
|
|
var parent = GetComponentInParent<Tile>();
|
|
lights = parent.GetComponentsInChildren<Light>();
|
|
doorways = parent.UsedDoorways.ToArray();
|
|
|
|
var sysRandom = DunGenPatch.Patch.CreateSystemRandom();
|
|
|
|
Utility.Shuffle(sysRandom, itemSpawns);
|
|
var count = sysRandom.Next(Plugin.CurrentConfigDungeon.GetPaintingExtraLoot.min, Plugin.CurrentConfigDungeon.GetPaintingExtraLoot.max + 1);
|
|
|
|
bonusItems = AngerManager.CreateAngerLoot(count, sysRandom);
|
|
bonusEnemy = GetRandomEnemy(sysRandom);
|
|
}
|
|
|
|
}
|
|
}
|