Initial
This commit is contained in:
parent
7a77b79dc5
commit
cdadd75ee9
104 changed files with 9416 additions and 0 deletions
257
ScarletMansion/ScarletMansion/GamePatch/Managers/AngerManager.cs
Normal file
257
ScarletMansion/ScarletMansion/GamePatch/Managers/AngerManager.cs
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using HarmonyLib;
|
||||
using Unity.Netcode;
|
||||
using ScarletMansion.GamePatch.Components;
|
||||
using DunGen;
|
||||
using Key = UnityEngine.InputSystem.Key;
|
||||
using ScarletMansion.Lights;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.HighDefinition;
|
||||
|
||||
namespace ScarletMansion.GamePatch.Managers {
|
||||
public class AngerManager : MonoBehaviour, IDungeonCompleteReceiver {
|
||||
|
||||
public static AngerManager Instance { get; private set; }
|
||||
|
||||
//public Dictionary<EnemyAI, int> angeredEnemies;
|
||||
public int level;
|
||||
public List<ScarletBedroom> bedrooms;
|
||||
public List<ScarletDoor> doors;
|
||||
public List<ScarletLight> lights;
|
||||
|
||||
//public KeyboardFloatDebug metal = new KeyboardFloatDebug("metal", 0f, 0f, 1f, 0.1f, Key.Numpad4, Key.Numpad7);
|
||||
//public KeyboardFloatDebug smooth = new KeyboardFloatDebug("smooth", 0f, 0f, 1f, 0.1f, Key.Numpad6, Key.Numpad9);
|
||||
|
||||
void Awake(){
|
||||
Instance = this;
|
||||
bedrooms = new List<ScarletBedroom>();
|
||||
doors = new List<ScarletDoor>();
|
||||
lights = new List<ScarletLight>();
|
||||
}
|
||||
/*
|
||||
void Update(){
|
||||
var enabled = 0;
|
||||
var active = 0;
|
||||
var total = 0;
|
||||
foreach(var l in lights){
|
||||
if (l.enabled) enabled++;
|
||||
if (l.gameObject.activeInHierarchy) active++;
|
||||
total++;
|
||||
}
|
||||
Plugin.logger.LogInfo($"{enabled}|{active}/{total}");
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void Update(){
|
||||
var deltaIntensity = 0;
|
||||
if (Utility.IfKeyPress(Key.Numpad7)) {
|
||||
deltaIntensity = 1;
|
||||
} else if (Utility.IfKeyPress(Key.Numpad4)) {
|
||||
deltaIntensity = -1;
|
||||
}
|
||||
|
||||
var deltaRange = 0;
|
||||
if (Utility.IfKeyPress(Key.Numpad9)) {
|
||||
deltaRange = 1;
|
||||
} else if (Utility.IfKeyPress(Key.Numpad6)) {
|
||||
deltaRange = -1;
|
||||
}
|
||||
|
||||
if (deltaIntensity != 0 || deltaRange != 0){
|
||||
var tile = Utility.GetClosestTileToPlayer();
|
||||
var lights = tile.GetComponentsInChildren<ScarletLight>();
|
||||
var localPlayer = StartOfRound.Instance.localPlayerController.transform.position;
|
||||
var closestLight = lights.OrderBy(t => Vector3.SqrMagnitude(t.transform.position - localPlayer)).FirstOrDefault();
|
||||
if (closestLight != null) {
|
||||
closestLight.light.intensity += deltaIntensity * 0.5f;
|
||||
closestLight.light.range += deltaRange * 0.25f;
|
||||
|
||||
Plugin.logger.LogInfo($"{closestLight.light.intensity}, {closestLight.light.range}");
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
public void Anger(int angerAmount = 1){
|
||||
Plugin.logger.LogInfo($"Raising anger from {level} to {level + angerAmount}");
|
||||
var manager = RoundManager.Instance;
|
||||
manager.minEnemiesToSpawn += angerAmount;
|
||||
level += angerAmount;
|
||||
}
|
||||
|
||||
public void AddBedroom(ScarletBedroom b){
|
||||
bedrooms.Add(b);
|
||||
}
|
||||
|
||||
public void AddDoor(ScarletDoor d){
|
||||
// I want to get only doors that are revelant
|
||||
foreach(var b in bedrooms){
|
||||
var dist = Vector3.SqrMagnitude(d.transform.position - b.transform.position);
|
||||
if (dist < 16f * 16f){
|
||||
doors.Add(d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ScarletBedroom GetBedroomWithPainting(Vector3 basePosition){
|
||||
ScarletBedroom target = null;
|
||||
var dist = 1f;
|
||||
|
||||
foreach(var b in bedrooms){
|
||||
var newdist = Vector3.SqrMagnitude(basePosition - b.paintingSpawnTransform.position);
|
||||
if (newdist < dist){
|
||||
target = b;
|
||||
dist = newdist;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null){
|
||||
Plugin.logger.LogError($"There is no close bedroom painting spawn at {basePosition}");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo($"Closest bedroom painting spawn {dist} away");
|
||||
return target;
|
||||
}
|
||||
|
||||
public ScarletDoor GetScarletDoor(Vector3 basePosition){
|
||||
ScarletDoor target = null;
|
||||
var dist = 1f;
|
||||
|
||||
foreach(var b in doors){
|
||||
var newdist = Vector3.SqrMagnitude(basePosition - b.transform.position);
|
||||
if (newdist < dist){
|
||||
target = b;
|
||||
dist = newdist;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == null){
|
||||
Plugin.logger.LogError($"There is no close door spawn at {basePosition}");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Plugin.logger.LogInfo($"Closest door spawn {dist} away");
|
||||
return target;
|
||||
}
|
||||
|
||||
public void AddLight(ScarletLight light){
|
||||
lights.Add(light);
|
||||
}
|
||||
|
||||
public ItemReference[] CreateAngerLoot(int count, System.Random sysRandom){
|
||||
var roundManager = RoundManager.Instance;
|
||||
if (!roundManager.IsServer) return null;
|
||||
|
||||
//Plugin.logger.LogInfo($"Creating {count} bonus items");
|
||||
if (count == 0) return new ItemReference[0];
|
||||
|
||||
var list = new List<int>();
|
||||
var scrap = Utility.GetDungeonItems();
|
||||
foreach(var e in scrap){
|
||||
list.Add(e.rarity);
|
||||
}
|
||||
|
||||
var bonusItems = new ItemReference[count];
|
||||
for(var i = 0; i < bonusItems.Length; ++i){
|
||||
var index = roundManager.GetRandomWeightedIndexList(list, sysRandom);
|
||||
var item = scrap[index].spawnableItem;
|
||||
var cost = (int)(sysRandom.Next(item.minValue + 25, item.maxValue + 35) * roundManager.scrapValueMultiplier);
|
||||
|
||||
var itemRef = new ItemReference(item, index, cost);
|
||||
bonusItems[i] = itemRef;
|
||||
|
||||
//Plugin.logger.LogInfo($"Created bonus item of {itemRef}");
|
||||
}
|
||||
|
||||
return bonusItems;
|
||||
}
|
||||
|
||||
public void SpawnAngerLoot(ItemReference[] loot, Transform[] spawnTransforms){
|
||||
var roundManager = RoundManager.Instance;
|
||||
|
||||
if (loot == null) {
|
||||
Plugin.logger.LogError($"Anger loot is empty. SPOOOKY");
|
||||
return;
|
||||
}
|
||||
|
||||
for(var i = 0; i < loot.Length; ++i){
|
||||
var item = loot[i];
|
||||
var pos = spawnTransforms[i].position;
|
||||
ScarletNetworkParams callParams = new ScarletNetworkParams() { scrapValue = item.value };
|
||||
ScarletNetworkManager.Instance.CreateScrapItemServerRpc(item.itemId, pos, callParams);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDungeonComplete(Dungeon dungeon) {
|
||||
Anger(PluginConfig.Instance.minIndoorEnemySpawnCountValue);
|
||||
}
|
||||
|
||||
public void TriggerAngerLightBrief(float duration){
|
||||
foreach(var s in lights){
|
||||
s.BeginAngry(duration, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerAngerLightForever(){
|
||||
foreach(var s in lights){
|
||||
s.BeginAngry(0f, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void Anger(){
|
||||
level += 1;
|
||||
var manager = RoundManager.Instance;
|
||||
|
||||
var enemies = manager.SpawnedEnemies;
|
||||
foreach(var e in enemies){
|
||||
// only inside
|
||||
if (e.enemyType.isDaytimeEnemy || e.isOutside) continue;
|
||||
|
||||
if (!angeredEnemies.ContainsKey(e))
|
||||
angeredEnemies.Add(e, 0);
|
||||
}
|
||||
|
||||
foreach(var e in angeredEnemies.Keys){
|
||||
AngerEnemy(e, level - angeredEnemies[e]);
|
||||
angeredEnemies[e] = level;
|
||||
}
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void AngerEnemyClientRpc(NetworkBehaviourReference enemyRef, int levelOffset){
|
||||
|
||||
if (enemyRef.TryGet<EnemyAI>(out var enemy)){
|
||||
if (levelOffset < 1) return;
|
||||
|
||||
var type = enemy.GetType();
|
||||
if (type == typeof(BlobAI)){
|
||||
Plugin.logger.LogInfo("Can't anger blob yet");
|
||||
}
|
||||
|
||||
else {
|
||||
Plugin.logger.LogInfo($"Angering {type} is not yet supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Remove(EnemyAI enemy){
|
||||
angeredEnemies.Remove(enemy);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using DunGen;
|
||||
using ScarletMansion.DunGenPatch.Doorways;
|
||||
|
||||
namespace ScarletMansion.GamePatch.Managers {
|
||||
public class DoorwayManager : MonoBehaviour {
|
||||
|
||||
public static DoorwayManager Instance { get; private set; }
|
||||
public static ActionList onMainEntranceTeleportSpawnedEvent = new ActionList("onMainEntranceTeleportSpawned");
|
||||
|
||||
public List<DoorwayCleanup> doorwayCleanup;
|
||||
|
||||
public void Awake(){
|
||||
Instance = this;
|
||||
doorwayCleanup = new List<DoorwayCleanup>();
|
||||
}
|
||||
|
||||
public void AddDoorwayCleanup(DoorwayCleanup dw){
|
||||
doorwayCleanup.Add(dw);
|
||||
}
|
||||
|
||||
public static void onMainEntranceTeleportSpawnedFunction(){
|
||||
if (Instance && DunGenPatch.Patch.active) {
|
||||
var doorwayCleanups = Instance.doorwayCleanup;
|
||||
foreach(var d in doorwayCleanups){
|
||||
d.Cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using DunGen;
|
||||
|
||||
namespace ScarletMansion {
|
||||
|
||||
public class KnightSpawnManager : MonoBehaviour, IDungeonCompleteReceiver {
|
||||
|
||||
public static KnightSpawnManager Instance { get; private set; }
|
||||
|
||||
public List<KnightSpawnPoint> spawnPoints;
|
||||
public List<KnightSpawnPoint> unusedSpawnPoints;
|
||||
|
||||
public int lastKnightSeenPlayer = -1;
|
||||
public bool disableNextKnightSpecialSpawn;
|
||||
|
||||
void Awake(){
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public void OnDungeonComplete(Dungeon dungeon) {
|
||||
// IDK KNOW IF I CAN TRUST THIS TO BE THE SAME FOR ALL CLIENTS
|
||||
// but probably
|
||||
var points = dungeon.GetComponentsInChildren<KnightSpawnPoint>();
|
||||
spawnPoints = points.ToList();
|
||||
for(var i = 0; i < spawnPoints.Count; ++i){
|
||||
spawnPoints[i].index = i;
|
||||
}
|
||||
|
||||
unusedSpawnPoints = points.ToList();
|
||||
Plugin.logger.LogInfo($"Found {spawnPoints.Count} spawn points for the knight");
|
||||
}
|
||||
|
||||
public int GetSpawnPointIndex(){
|
||||
if (disableNextKnightSpecialSpawn) {
|
||||
disableNextKnightSpecialSpawn = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unusedSpawnPoints.Count == 0) return -1;
|
||||
|
||||
// cause it would be funny
|
||||
if (lastKnightSeenPlayer >= 0){
|
||||
var tempitem = spawnPoints[lastKnightSeenPlayer];
|
||||
if (tempitem.gameObject.activeInHierarchy){
|
||||
Plugin.logger.LogInfo($"Using the last knight {tempitem.index} that saw a player");
|
||||
unusedSpawnPoints.Remove(tempitem);
|
||||
lastKnightSeenPlayer = -1;
|
||||
return tempitem.index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var index = UnityEngine.Random.Range(0, unusedSpawnPoints.Count);
|
||||
var item = unusedSpawnPoints[index];
|
||||
unusedSpawnPoints.RemoveAt(index);
|
||||
|
||||
return item.index;
|
||||
}
|
||||
|
||||
public Transform GetSpawnPointTransform(int index){
|
||||
return spawnPoints[index].transform;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
/*
|
||||
|
||||
namespace ScarletMansion {
|
||||
public static class ScarletLightingManager {
|
||||
|
||||
public static ScarletLighting[] lights;
|
||||
|
||||
public static void Init(){
|
||||
lights = UnityEngine.Object.FindObjectsOfType<ScarletLighting>();
|
||||
}
|
||||
|
||||
public static void Clean(){
|
||||
lights = null;
|
||||
}
|
||||
|
||||
public static void UpdateLights(float modifier){
|
||||
if (lights == null) return;
|
||||
|
||||
try {
|
||||
foreach(var l in lights){
|
||||
l.UpdateLight(modifier);
|
||||
}
|
||||
} catch (Exception e){
|
||||
Plugin.logger.LogError("UpdateLights found a weird error, we just aborting");
|
||||
Plugin.logger.LogError(e.ToString());
|
||||
lights = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisableLights(){
|
||||
if (lights == null) return;
|
||||
|
||||
try {
|
||||
foreach(var l in lights){
|
||||
l.DisableLights();
|
||||
}
|
||||
} catch (Exception e){
|
||||
Plugin.logger.LogError("DisableLights found a weird error, we just aborting");
|
||||
Plugin.logger.LogError(e.ToString());
|
||||
lights = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
@ -0,0 +1,409 @@
|
|||
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 GameNetcodeStuff;
|
||||
using ScarletMansion.GamePatch.Items;
|
||||
using ScarletMansion.GamePatch;
|
||||
|
||||
namespace ScarletMansion {
|
||||
|
||||
public struct ScarletNetworkParams : INetworkSerializeByMemcpy {
|
||||
public int scrapValue;
|
||||
public int specialValue;
|
||||
}
|
||||
|
||||
public class ItemReference {
|
||||
public Item item;
|
||||
public int itemId;
|
||||
public int value;
|
||||
|
||||
public ItemReference(Item item, int itemId, int value){
|
||||
this.item = item;
|
||||
this.itemId = itemId;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
var itemString = item ? item.name : "NULL";
|
||||
return $"{itemString}:{itemId} ({value})";
|
||||
}
|
||||
}
|
||||
|
||||
public class EnemyReference {
|
||||
public EnemyType enemy;
|
||||
public int index;
|
||||
|
||||
public EnemyReference(EnemyType enemy, int index){
|
||||
this.enemy = enemy;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
var enemyString = enemy ? enemy.name : "NULL";
|
||||
return $"{enemyString}:{index}";
|
||||
}
|
||||
}
|
||||
|
||||
public class EnemyReferenceSpawnLogic : EnemyReference {
|
||||
public enum SpawnLogic { None, Special };
|
||||
public SpawnLogic logic;
|
||||
|
||||
public EnemyReferenceSpawnLogic(EnemyType enemy, int index, SpawnLogic logic) : base(enemy, index) {
|
||||
this.logic = logic;
|
||||
}
|
||||
|
||||
public void ApplySpawnLogic(){
|
||||
if (logic == SpawnLogic.None) return;
|
||||
|
||||
var enemyName = enemy.name.ToLowerInvariant();
|
||||
if (enemyName == "knight")
|
||||
KnightSpawnManager.Instance.disableNextKnightSpecialSpawn = true;
|
||||
else if (enemyName == "jester")
|
||||
JesterAIPatch.active = true;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
var b = base.ToString();
|
||||
return $"{b} [{logic.ToString()}]";
|
||||
}
|
||||
}
|
||||
|
||||
public class ScarletNetworkManager : NetworkBehaviour {
|
||||
|
||||
public static ScarletNetworkManager Instance { get; private set; }
|
||||
|
||||
void Awake(){
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void DestroyPlayerItemInSlotServerRpc(NetworkBehaviourReference playerRef, int itemSlot, ServerRpcParams callParams = default(ServerRpcParams)){
|
||||
if (playerRef.TryGet<PlayerControllerB>(out var player)){
|
||||
Plugin.logger.LogInfo($"P{player.OwnerClientId}, S{callParams.Receive.SenderClientId}");
|
||||
|
||||
DestroyPlayerItemInSlotClientRpc(playerRef, itemSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin.logger.LogError($"Error trying to get player script (SERVERRPC)");
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void DestroyPlayerItemInSlotClientRpc(NetworkBehaviourReference playerRef, int itemSlot){
|
||||
if (playerRef.TryGet<PlayerControllerB>(out var player) && !player.IsOwner){
|
||||
player.DestroyPlayerItemInSlot_SDM(itemSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player == null)
|
||||
Plugin.logger.LogError($"Error trying to get player script (CLIENTRPC)");
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void CreateItemServerRpc(int itemId, Vector3 position, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
CreateItem(itemId, false, position, null, callParams);
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void CreateItemServerRpc(int itemId, Vector3 position, NetworkBehaviourReference playerRef, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
playerRef.TryGet<PlayerControllerB>(out var player);
|
||||
CreateItem(itemId, false, position, player, callParams);
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void CreateScrapItemServerRpc(int itemId, Vector3 position, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
CreateItem(itemId, true, position, null, callParams);
|
||||
}
|
||||
|
||||
[ServerRpc(RequireOwnership = false)]
|
||||
public void CreateScrapItemServerRpc(int itemId, Vector3 position, NetworkBehaviourReference playerRef, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
playerRef.TryGet<PlayerControllerB>(out var player);
|
||||
CreateItem(itemId, true, position, player, callParams);
|
||||
}
|
||||
|
||||
private void CreateItem(int itemId, bool fromScrapArray, Vector3 position, PlayerControllerB player, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
GameObject prefab;
|
||||
if (fromScrapArray) {
|
||||
prefab = Utility.GetDungeonItems()[itemId].spawnableItem.spawnPrefab;
|
||||
} else {
|
||||
prefab = StartOfRound.Instance.allItemsList.itemsList[itemId].spawnPrefab;
|
||||
}
|
||||
var comp = CreateGrabbableObject(prefab, player, position);
|
||||
|
||||
StartCoroutine(WaitForEndOfFrameToUpdateItemInitialProperities(comp));
|
||||
UpdateItemFallingProperites(comp, position);
|
||||
UpdateItemElevator(comp, player);
|
||||
|
||||
var scarletItem = comp as IScarletItem;
|
||||
if (scarletItem != null) scarletItem.UpdateSpecialProperties(callParams.specialValue);
|
||||
|
||||
var scrapValue = callParams.scrapValue;
|
||||
if (scrapValue > 0) {
|
||||
UpdateItemValueProperties(comp, scrapValue);
|
||||
}
|
||||
|
||||
comp.NetworkObject.Spawn(false);
|
||||
|
||||
if (player == null) CreateItemClientRpc(comp, position, callParams);
|
||||
else CreateItemClientRpc(comp, position, player, callParams);
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void CreateItemClientRpc(NetworkBehaviourReference itemRef, Vector3 position, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
if (IsServer) return;
|
||||
StartCoroutine(WaitForItem(itemRef, (c) => CreateItem(c, position, null, callParams)));
|
||||
}
|
||||
|
||||
[ClientRpc]
|
||||
public void CreateItemClientRpc(NetworkBehaviourReference itemRef, Vector3 position, NetworkBehaviourReference playerRef, ScarletNetworkParams callParams = default(ScarletNetworkParams)){
|
||||
if (IsServer) return;
|
||||
StartCoroutine(WaitForItemAndPlayer(itemRef, playerRef, (c, p) => CreateItem(c, position, p, callParams)));
|
||||
}
|
||||
|
||||
private IEnumerator WaitForItem(NetworkBehaviourReference itemRef, Action<GrabbableObject> action){
|
||||
var t = Time.realtimeSinceStartup + 8f;
|
||||
|
||||
GrabbableObject comp;
|
||||
while(!itemRef.TryGet(out comp)){
|
||||
yield return null;
|
||||
|
||||
if (Time.realtimeSinceStartup > t) {
|
||||
Plugin.logger.LogError("Failed to find network object (ITEM)");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
yield return new WaitForEndOfFrame();
|
||||
action.Invoke(comp);
|
||||
}
|
||||
|
||||
private IEnumerator WaitForItemAndPlayer(NetworkBehaviourReference itemRef, NetworkBehaviourReference playerRef, Action<GrabbableObject, PlayerControllerB> action){
|
||||
var t = Time.realtimeSinceStartup + 8f;
|
||||
|
||||
GrabbableObject comp;
|
||||
while(!itemRef.TryGet(out comp)){
|
||||
yield return null;
|
||||
|
||||
if (Time.realtimeSinceStartup > t) {
|
||||
Plugin.logger.LogError("Failed to find network object (ITEM)");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerControllerB player;
|
||||
while(!playerRef.TryGet(out player)){
|
||||
yield return null;
|
||||
|
||||
if (Time.realtimeSinceStartup > t) {
|
||||
Plugin.logger.LogError("Failed to find network object (PLAYER)");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
yield return new WaitForEndOfFrame();
|
||||
action.Invoke(comp, player);
|
||||
}
|
||||
|
||||
private void CreateItem(GrabbableObject item, Vector3 position, PlayerControllerB player, ScarletNetworkParams callParams = default(ScarletNetworkParams)) {
|
||||
UpdateItemFallingProperites(item, position);
|
||||
UpdateItemElevator(item, player);
|
||||
|
||||
var scarletItem = item as IScarletItem;
|
||||
if (scarletItem != null) scarletItem.UpdateSpecialProperties(callParams.specialValue);
|
||||
|
||||
var scrapValue = callParams.scrapValue;
|
||||
if (scrapValue > 0) {
|
||||
UpdateItemValueProperties(item, scrapValue);
|
||||
}
|
||||
}
|
||||
|
||||
private GrabbableObject CreateGrabbableObject(GameObject prefab, PlayerControllerB player, Vector3 position) {
|
||||
var parent = GetItemSpawnTransform(player);
|
||||
var gameObject = GameObject.Instantiate(prefab, position, Quaternion.identity, parent);
|
||||
return gameObject.GetComponent<GrabbableObject>();
|
||||
}
|
||||
|
||||
private Transform GetItemSpawnTransform(PlayerControllerB player) {
|
||||
if (((player != null && player.isInElevator) || StartOfRound.Instance.inShipPhase) && RoundManager.Instance.spawnedScrapContainer != null) {
|
||||
return RoundManager.Instance.spawnedScrapContainer;
|
||||
}
|
||||
return StartOfRound.Instance.elevatorTransform;
|
||||
}
|
||||
|
||||
private IEnumerator WaitForEndOfFrameToUpdateItemInitialProperities(GrabbableObject comp) {
|
||||
yield return new WaitForEndOfFrame();
|
||||
UpdateItemInitialProperites(comp);
|
||||
}
|
||||
|
||||
private void UpdateItemInitialProperites(GrabbableObject comp) {
|
||||
comp.reachedFloorTarget = false;
|
||||
comp.hasHitGround = false;
|
||||
comp.fallTime = 0f;
|
||||
}
|
||||
|
||||
private void UpdateItemFallingProperites(GrabbableObject comp, Vector3 position) {
|
||||
comp.startFallingPosition = position;
|
||||
comp.targetFloorPosition = comp.GetItemFloorPosition(position);
|
||||
}
|
||||
|
||||
private void UpdateItemValueProperties(GrabbableObject comp, int value) {
|
||||
comp.SetScrapValue(value);
|
||||
RoundManager.Instance.totalScrapValueInLevel += value;
|
||||
}
|
||||
|
||||
private void UpdateItemElevator(GrabbableObject comp, PlayerControllerB player){
|
||||
if (player != null && player.isInHangarShipRoom) {
|
||||
player.SetItemInElevator(true, true, comp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ScarletNetworkManagerUtility {
|
||||
|
||||
public static int GetFlashlightId(FlashlightItem flashlightItem){
|
||||
var flashlight = Assets.GetFlashlight(flashlightItem.itemProperties);
|
||||
if (flashlight != null) return flashlight.itemId;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool CreateFlashlight(PlayerControllerB player, FlashlightItem flashLight, FlandreCrystal crystal){
|
||||
var color = crystal.colorIndex;
|
||||
var position = crystal.transform.position + Vector3.up * 0.25f;
|
||||
var id = GetFlashlightId(flashLight);
|
||||
var scrapValue = crystal.scrapValue;
|
||||
var flashlightValue = scrapValue;
|
||||
var nextCrystal = crystal.targetTransformation;
|
||||
|
||||
if (nextCrystal) {
|
||||
flashlightValue = Mathf.RoundToInt(flashlightValue * 0.5f);
|
||||
}
|
||||
|
||||
if (id == -1) {
|
||||
var flashString = flashLight ? flashLight.itemProperties.itemName : "NULL";
|
||||
Plugin.logger.LogError($"Failed to find a corresponding flashlight for {flashString}");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.DestroyPlayerItemAndSync_SDM(flashLight);
|
||||
player.DestroyPlayerItemAndSync_SDM(crystal);
|
||||
|
||||
ScarletNetworkParams callParams = new ScarletNetworkParams() { scrapValue = flashlightValue, specialValue = color};
|
||||
ScarletNetworkManager.Instance.CreateItemServerRpc(id, position, player, callParams);
|
||||
|
||||
if (nextCrystal) {
|
||||
var brokenCrystal = Assets.GetGlobalItem(nextCrystal);
|
||||
if (brokenCrystal == null) {
|
||||
Plugin.logger.LogError($"Failed to find a corresponding global item for {nextCrystal.itemName}");
|
||||
return true;
|
||||
}
|
||||
|
||||
var brokenCrystalId= brokenCrystal.itemId;
|
||||
if (brokenCrystalId == -1) {
|
||||
Plugin.logger.LogError($"Failed to find a corresponding id for {nextCrystal.itemName}");
|
||||
return true;
|
||||
}
|
||||
|
||||
var colorLength = FlandreCrystal.colorVariants.Length;
|
||||
var nextScrapColorValue = scrapValue % colorLength;
|
||||
var nextScrapValue = flashlightValue - (flashlightValue % colorLength) + nextScrapColorValue;
|
||||
ScarletNetworkParams nextCallParams = new ScarletNetworkParams() { scrapValue = nextScrapValue};
|
||||
ScarletNetworkManager.Instance.CreateItemServerRpc(brokenCrystalId, position, player, nextCallParams);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void DestroyPlayerItemAndSync_SDM(this PlayerControllerB player, GrabbableObject obj){
|
||||
if (!player.IsOwner) return;
|
||||
|
||||
var itemSlots = player.ItemSlots;
|
||||
for(var i = 0; i < itemSlots.Length; ++i){
|
||||
if (itemSlots[i] == obj) {
|
||||
DestroyPlayerItemInSlotAndSync_SDM(player, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var grabObjString = obj ? obj.itemProperties.itemName : "NULL";
|
||||
Plugin.logger.LogError($"Player {player.playerUsername}:{player.actualClientId} tried to destroy item {grabObjString} which is empty or not owned by player");
|
||||
}
|
||||
|
||||
public static void DestroyPlayerItemInSlotAndSync_SDM(this PlayerControllerB player, int itemSlot){
|
||||
if (!player.IsOwner) return;
|
||||
|
||||
var itemSlots = player.ItemSlots;
|
||||
if (itemSlot >= itemSlots.Length || itemSlots[itemSlot] == null) {
|
||||
Plugin.logger.LogError($"Player {player.playerUsername}:{player.actualClientId} tried to destroy item in slot {itemSlot} which is empty or overflowed");
|
||||
return;
|
||||
}
|
||||
|
||||
player.timeSinceSwitchingSlots = 0f;
|
||||
player.DestroyPlayerItemInSlot_SDM(itemSlot);
|
||||
ScarletNetworkManager.Instance.DestroyPlayerItemInSlotServerRpc(player, itemSlot);
|
||||
}
|
||||
|
||||
public static void DestroyPlayerItemInSlot_SDM(this PlayerControllerB player, int itemSlot){
|
||||
// base game does this
|
||||
// better safe and slow then sorry
|
||||
if (GameNetworkManager.Instance.localPlayerController == null || NetworkManager.Singleton == null || NetworkManager.Singleton.ShutdownInProgress) return;
|
||||
|
||||
Plugin.logger.LogInfo($"Destroying player {player.playerUsername}:{player.actualClientId}'s item in slot {itemSlot}");
|
||||
|
||||
var heldObj = player.currentlyHeldObjectServer;
|
||||
var heldObjString = heldObj ? heldObj.itemProperties.itemName : "NULL";
|
||||
var grabObj = player.ItemSlots[itemSlot];
|
||||
var grabObjString = grabObj ? grabObj.itemProperties.itemName : "NULL";
|
||||
Plugin.logger.LogInfo($"Held item {player.currentItemSlot}:{heldObjString}");
|
||||
Plugin.logger.LogInfo($"Target item {itemSlot}:{grabObjString}");
|
||||
|
||||
// fix weight and values
|
||||
player.carryWeight -= Mathf.Clamp(grabObj.itemProperties.weight - 1f, 0f, 10f);
|
||||
RoundManager.Instance.totalScrapValueInLevel -= grabObj.scrapValue;
|
||||
|
||||
// destroy radar
|
||||
if (grabObj.radarIcon) {
|
||||
GameObject.Destroy(grabObj.radarIcon.gameObject);
|
||||
}
|
||||
|
||||
// fix character animations and UI
|
||||
// if target item is the same as held item
|
||||
if (player.isHoldingObject) {
|
||||
if (player.currentItemSlot == itemSlot) {
|
||||
player.isHoldingObject = false;
|
||||
player.twoHanded = false;
|
||||
if (player.IsOwner) {
|
||||
player.playerBodyAnimator.SetBool("cancelHolding", true);
|
||||
player.playerBodyAnimator.SetTrigger("Throw");
|
||||
HUDManager.Instance.holdingTwoHandedItem.enabled = false;
|
||||
HUDManager.Instance.ClearControlTips();
|
||||
player.activatingItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (heldObj != null && heldObj == grabObj) {
|
||||
if (player.IsOwner) {
|
||||
player.SetSpecialGrabAnimationBool(false, heldObj);
|
||||
}
|
||||
player.currentlyHeldObjectServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// no matter what, we need these to be called
|
||||
if (player.IsOwner) {
|
||||
HUDManager.Instance.itemSlotIcons[itemSlot].enabled = false;
|
||||
grabObj.DiscardItemOnClient();
|
||||
}
|
||||
|
||||
player.ItemSlots[itemSlot] = null;
|
||||
|
||||
if (player.IsServer) grabObj.NetworkObject.Despawn(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue