230 lines
5.4 KiB
C#
230 lines
5.4 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using RoR2.ExpansionManagement;
|
||
|
using TMPro;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Networking;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
public class BazaarController : MonoBehaviour
|
||
|
{
|
||
|
[Serializable]
|
||
|
public struct SeerSceneOverride
|
||
|
{
|
||
|
[SerializeField]
|
||
|
public SceneDef sceneDef;
|
||
|
|
||
|
[SerializeField]
|
||
|
public ExpansionDef requiredExpasion;
|
||
|
|
||
|
[SerializeField]
|
||
|
[Range(0f, 1f)]
|
||
|
public float overrideChance;
|
||
|
|
||
|
[SerializeField]
|
||
|
public int minStagesCleared;
|
||
|
|
||
|
[SerializeField]
|
||
|
public string bannedEventFlag;
|
||
|
}
|
||
|
|
||
|
public GameObject shopkeeper;
|
||
|
|
||
|
public TextMeshPro shopkeeperChat;
|
||
|
|
||
|
public float shopkeeperTrackDistance = 250f;
|
||
|
|
||
|
public float shopkeeperTrackAngle = 120f;
|
||
|
|
||
|
[Tooltip("Any PurchaseInteraction objects here will have their activation state set based on whether or not the specified unlockable is available.")]
|
||
|
public PurchaseInteraction[] unlockableTerminals;
|
||
|
|
||
|
public SeerStationController[] seerStations;
|
||
|
|
||
|
public SeerSceneOverride[] seerSceneOverrides;
|
||
|
|
||
|
private InputBankTest shopkeeperInputBank;
|
||
|
|
||
|
private CharacterBody shopkeeperTargetBody;
|
||
|
|
||
|
private Xoroshiro128Plus rng;
|
||
|
|
||
|
public static BazaarController instance { get; private set; }
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
instance = SingletonHelper.Assign(instance, this);
|
||
|
}
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
if (NetworkServer.active)
|
||
|
{
|
||
|
OnStartServer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnStartServer()
|
||
|
{
|
||
|
rng = new Xoroshiro128Plus(Run.instance.stageRng.nextUlong);
|
||
|
SetUpSeerStations();
|
||
|
}
|
||
|
|
||
|
private void SetUpSeerStations()
|
||
|
{
|
||
|
SceneDef nextStageScene = Run.instance.nextStageScene;
|
||
|
List<SceneDef> list = new List<SceneDef>();
|
||
|
if (nextStageScene != null)
|
||
|
{
|
||
|
int stageOrder = nextStageScene.stageOrder;
|
||
|
foreach (SceneDef allSceneDef in SceneCatalog.allSceneDefs)
|
||
|
{
|
||
|
if (allSceneDef.stageOrder == stageOrder && (allSceneDef.requiredExpansion == null || Run.instance.IsExpansionEnabled(allSceneDef.requiredExpansion)) && IsUnlockedBeforeLooping(allSceneDef))
|
||
|
{
|
||
|
list.Add(allSceneDef);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
WeightedSelection<SceneDef> weightedSelection = new WeightedSelection<SceneDef>();
|
||
|
float num = 0f;
|
||
|
SeerSceneOverride[] array = seerSceneOverrides;
|
||
|
for (int i = 0; i < array.Length; i++)
|
||
|
{
|
||
|
SeerSceneOverride seerSceneOverride = array[i];
|
||
|
bool num2 = Run.instance.stageClearCount >= seerSceneOverride.minStagesCleared;
|
||
|
bool flag = seerSceneOverride.requiredExpasion == null || Run.instance.IsExpansionEnabled(seerSceneOverride.requiredExpasion);
|
||
|
bool flag2 = string.IsNullOrEmpty(seerSceneOverride.bannedEventFlag) || !Run.instance.GetEventFlag(seerSceneOverride.bannedEventFlag);
|
||
|
if (num2 && flag && flag2)
|
||
|
{
|
||
|
weightedSelection.AddChoice(seerSceneOverride.sceneDef, seerSceneOverride.overrideChance);
|
||
|
num += seerSceneOverride.overrideChance;
|
||
|
}
|
||
|
}
|
||
|
SeerStationController[] array2 = seerStations;
|
||
|
foreach (SeerStationController seerStationController in array2)
|
||
|
{
|
||
|
if (list.Count == 0)
|
||
|
{
|
||
|
seerStationController.GetComponent<PurchaseInteraction>().SetAvailable(newAvailable: false);
|
||
|
continue;
|
||
|
}
|
||
|
Util.ShuffleList(list, rng);
|
||
|
int index = list.Count - 1;
|
||
|
SceneDef sceneDef = list[index];
|
||
|
if (rng.nextNormalizedFloat < num)
|
||
|
{
|
||
|
sceneDef = weightedSelection.Evaluate(rng.nextNormalizedFloat);
|
||
|
}
|
||
|
if (IsSceneAlreadySelected(sceneDef))
|
||
|
{
|
||
|
sceneDef = list[index];
|
||
|
}
|
||
|
list.RemoveAt(index);
|
||
|
seerStationController.SetTargetScene(sceneDef);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool IsUnlockedBeforeLooping(SceneDef sceneDef)
|
||
|
{
|
||
|
if (Run.instance.stageClearCount < 4 && sceneDef.isLockedBeforeLooping)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private bool IsSceneAlreadySelected(SceneDef sceneDef)
|
||
|
{
|
||
|
for (int i = 0; i < seerStations.Length; i++)
|
||
|
{
|
||
|
if (sceneDef.sceneDefIndex == (SceneIndex)seerStations[i].ReturnTargetSceneDefIndex())
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private void OnDestroy()
|
||
|
{
|
||
|
instance = SingletonHelper.Unassign(instance, this);
|
||
|
}
|
||
|
|
||
|
public void CommentOnAnnoy()
|
||
|
{
|
||
|
int maxExclusive = 6;
|
||
|
if (Util.CheckRoll(20f))
|
||
|
{
|
||
|
Chat.SendBroadcastChat(new Chat.NpcChatMessage
|
||
|
{
|
||
|
sender = shopkeeper,
|
||
|
baseToken = "NEWT_ANNOY_" + UnityEngine.Random.Range(1, maxExclusive)
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void CommentOnEnter()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public void CommentOnLeaving()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public void CommentOnLunarPurchase()
|
||
|
{
|
||
|
int maxExclusive = 8;
|
||
|
if (Util.CheckRoll(20f))
|
||
|
{
|
||
|
Chat.SendBroadcastChat(new Chat.NpcChatMessage
|
||
|
{
|
||
|
sender = shopkeeper,
|
||
|
baseToken = "NEWT_LUNAR_PURCHASE_" + UnityEngine.Random.Range(1, maxExclusive)
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void CommentOnBlueprintPurchase()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public void CommentOnDronePurchase()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public void CommentOnUpgrade()
|
||
|
{
|
||
|
int maxExclusive = 3;
|
||
|
if (Util.CheckRoll(100f))
|
||
|
{
|
||
|
Chat.SendBroadcastChat(new Chat.NpcChatMessage
|
||
|
{
|
||
|
sender = shopkeeper,
|
||
|
baseToken = "NEWT_UPGRADE_" + UnityEngine.Random.Range(1, maxExclusive)
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Update()
|
||
|
{
|
||
|
if (!shopkeeper)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (!shopkeeperInputBank)
|
||
|
{
|
||
|
shopkeeperInputBank = shopkeeper.GetComponent<InputBankTest>();
|
||
|
return;
|
||
|
}
|
||
|
Ray aimRay = new Ray(shopkeeperInputBank.aimOrigin, shopkeeper.transform.forward);
|
||
|
shopkeeperTargetBody = Util.GetEnemyEasyTarget(shopkeeper.GetComponent<CharacterBody>(), aimRay, shopkeeperTrackDistance, shopkeeperTrackAngle);
|
||
|
if ((bool)shopkeeperTargetBody)
|
||
|
{
|
||
|
Vector3 direction = shopkeeperTargetBody.mainHurtBox.transform.position - aimRay.origin;
|
||
|
aimRay.direction = direction;
|
||
|
}
|
||
|
shopkeeperInputBank.aimDirection = aimRay.direction;
|
||
|
}
|
||
|
}
|