fixed multi state quantum objects appearing into states that are visible to the player

This commit is contained in:
FreezeDriedMangoes 2022-06-18 22:36:09 -04:00
parent 6b0f924143
commit 98b5840e20
2 changed files with 181 additions and 1 deletions

View File

@ -1,4 +1,5 @@
using HarmonyLib; using HarmonyLib;
using NewHorizons.Components;
using NewHorizons.External.Configs; using NewHorizons.External.Configs;
using NewHorizons.External.Modules; using NewHorizons.External.Modules;
using NewHorizons.Utility; using NewHorizons.Utility;
@ -120,7 +121,7 @@ namespace NewHorizons.Builder.Props
} }
groupRoot.SetActive(false); groupRoot.SetActive(false);
var multiState = groupRoot.AddComponent<MultiStateQuantumObject>(); var multiState = groupRoot.AddComponent<NHMultiStateQuantumObject>();
multiState._loop = quantumGroup.loop; multiState._loop = quantumGroup.loop;
multiState._sequential = quantumGroup.sequential; multiState._sequential = quantumGroup.sequential;
multiState._states = states.ToArray(); multiState._states = states.ToArray();

View File

@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
{
public class NHMultiStateQuantumObject : MultiStateQuantumObject
{
public override bool ChangeQuantumState(bool skipInstantVisibilityCheck)
{
for (int i = 0; i < _prerequisiteObjects.Length; i++)
{
if (!_prerequisiteObjects[i].HasCollapsed())
{
return false;
}
}
int stateIndex = _stateIndex;
if (_stateIndex == -1 && _initialState != -1)
{
_stateIndex = _initialState;
}
else if (_sequential)
{
_stateIndex = (_reverse ? (_stateIndex - 1) : (_stateIndex + 1));
if (_loop)
{
if (_stateIndex < 0)
{
_stateIndex = _states.Length - 1;
}
else if (_stateIndex > _states.Length - 1)
{
_stateIndex = 0;
}
}
else
{
_stateIndex = Mathf.Clamp(_stateIndex, 0, _states.Length - 1);
}
}
else
{
// TODO: perform this roll for number of states, each time adding the selected state to the end of a list and removing it from the source list
// this gets us a randomly ordered list that respects states' probability
// then we can sequentially attempt collapsing to them, checking at each state whether the new state is invalid due to the player being able to see it, according to this:
//
// if (!((!IsPlayerEntangled()) ? (CheckIllumination() ? CheckVisibilityInstantly() : CheckPointInside(Locator.GetPlayerCamera().transform.position)) : CheckIllumination()))
// {
// return true; // this is a valid state
// }
//
List<int> indices = new List<int>();
for (var i = 0; i < _states.Length; i++) if (i != stateIndex) indices.Add(i);
var previousIndex = stateIndex;
do
{
previousIndex = _stateIndex;
_stateIndex = RollState(stateIndex, indices);
if (previousIndex >= 0 && previousIndex < _states.Length) _states[previousIndex].SetVisible(visible: false);
_states[_stateIndex].SetVisible(visible: true);
Logger.Log("trying state " + _stateIndex);
indices.Remove(_stateIndex);
} while (!CurrentStateIsValid() && indices.Count > 0);
if (!CurrentStateIsValid())
{
if (_stateIndex >= 0 && _stateIndex < _states.Length) _states[_stateIndex].SetVisible(visible: false);
_stateIndex = stateIndex;
_states[_stateIndex].SetVisible(visible: true);
return false;
}
}
if (stateIndex != _stateIndex && stateIndex >= 0 && stateIndex < _states.Length)
{
_states[stateIndex].SetVisible(visible: false);
}
_states[_stateIndex].SetVisible(visible: true);
if (_sequential && !_loop && _stateIndex == _states.Length - 1)
{
SetActivation(active: false);
}
return true;
}
public bool CurrentStateIsValid()
{
// This check is stolen from SocketedQuantumObject
//if (!((!IsPlayerEntangled()) ? (CheckIllumination() ? CheckVisibilityInstantly() : CheckPointInside(Locator.GetPlayerCamera().transform.position)) : CheckIllumination()))
//{
// return true; // this is a valid state
//}
var isPlayerEntangled = IsPlayerEntangled();
var illumination = CheckIllumination();
var visibility = CheckVisibilityInstantly();
var playerInside = CheckPointInside(Locator.GetPlayerCamera().transform.position);
var isVisible =
isPlayerEntangled
? illumination
: (
illumination
? visibility
: playerInside
);
Logger.Log($"isPlayerEntangled: {isPlayerEntangled}, illumination: {illumination}, visibility: {visibility}, playerInside: {playerInside}, isVisible: {isVisible}");
if (!isVisible)
{
return true; // this is a valid state
}
return false;
}
public int RollState(int excludeIndex, List<int> indices)
{
var stateIndex = excludeIndex;
// this function constructs a sort of segmented range:
// 0 3 5 6
// +-------------------+-----+--+
// | state 1 | s2 |s3|
// +-------------------+-----+--+
//
// num is the max value of this range (min is always 0)
// num2 is a random point on this range
//
// num3 and num4 track the bounds of the current segment being considered
// num3 is the min value, num4 is the max. for example, if num3=5 then num4=6
//
// the second for looop uses num3 and num4 to figure out which segment num2 landed in
int num = 0;
foreach (int j in indices)
{
if (j != stateIndex)
{
_probabilities[j] = _states[j].GetProbability();
num += _probabilities[j];
}
}
int num2 = UnityEngine.Random.Range(0, num);
int num3 = 0;
int num4 = 0;
foreach (int k in indices)
{
if (k != stateIndex)
{
num3 = num4;
num4 += _probabilities[k];
if (_probabilities[k] > 0 && num2 >= num3 && num2 < num4)
{
return k;
}
}
}
return indices[indices.Count-1];
}
}
}